OneSay documentation

Documentation

MCP Guide

Preview: features and APIs may change.

PDF uses your browser’s print dialog. It is not a hosted export service.

The OneSay MCP server lets an AI client read your OneSay Projects, Devices, Rooms, Tasks, logs and Usage, and ask for a few bounded changes, through the Model Context Protocol. It is a thin layer over the public Control API: every tool calls a public API operation or Action, and the Control API decides what your account may do. The server is available on Staging; see Availability.

MCP never carries audio. Voice goes through the SDKs: Task voice over the OneSay Realtime WebSocket, or Realtime RTC.

Connect#

  • Endpoint: https://<mcp host>/mcp, one per environment. On Staging it is https://mcp.staging.onesay.com/mcp.
  • Transport: stateless Streamable HTTP. The server keeps no session between requests.
  • Protocol: MCP 2026-07-28 only. Every request sends Mcp-Protocol-Version: 2026-07-28; another version is refused with mcp_protocol_version_unsupported, naming the supported one.
  • Request headers: Mcp-Method must equal the body's method, and for tools/call, prompts/get and resources/read Mcp-Name must equal the tool name, prompt name or resource URI. A mismatch is answered with HTTP 400 and JSON-RPC error -32020 before any token is read.

Sign in#

The server is an OAuth 2.1 protected resource. Its Protected Resource Metadata is served at /.well-known/oauth-protected-resource (and at /.well-known/oauth-protected-resource/mcp), and it names the environment's authorization server.

  • No token is needed for public discovery: the R0 tools, the quickstart resources, the prompts and the tool, resource and prompt lists.
  • Account data needs a token. An R1 or R2 tool, or a resource other than a quickstart, needs a Bearer access token whose audience is this MCP resource. Without one the server answers HTTP 401 with a WWW-Authenticate challenge that points to the metadata. The body is a JSON-RPC error carrying your request id, with the oauth_resource_invalid error envelope as its data.
  • Your token never reaches the Control API. For each Control API call the server exchanges it (OAuth 2.0 Token Exchange, RFC 8693) for a short-lived token whose subject is you and whose actor is the MCP service. No exchange is made after your token expires, and no token is logged or returned.

Tools#

Each tool has a risk class. Read-only tools are marked read-only to the client; rooms.close and tasks.cancel are marked destructive.

RiskToolsNeeds
R0onesay.capabilities.list, onesay.capabilities.get, onesay.quickstarts.getNothing: public metadata
R1onesay.projects.list, onesay.projects.get, onesay.applications.list, onesay.devices.list, onesay.devices.get, onesay.devices.diagnose, onesay.rooms.get, onesay.tasks.get, onesay.logs.search, onesay.logs.timeline, onesay.usage.summaryA token and the Grants the matching API operation requires
R2onesay.rooms.create, onesay.rooms.close, onesay.tasks.cancelA token, the Grant and the human's consent

An R2 tool runs its Action only after the human has consented in OneSay. Without that consent the call answers mcp_confirmation_required, and nothing changes. On Staging the R2 tools are switched off for now: they answer mcp_tool_not_exposed and change nothing.

Resources#

URI templateReads
onesay://projects/{project_id}The Project, like onesay.projects.get
onesay://devices/{device_id}The Device's state, like onesay.devices.get
onesay://tasks/{task_id}The Task's state, like onesay.tasks.get
onesay://docs/quickstarts/{name}A quickstart page (javascript or esp32); public

The server lists templates only. Every read result has ttlMs 0, so a client treats it as immediately stale.

Prompts#

Errors#

A tool error carries the OneSay error envelope, the same as the Control API's:

CodeMeaning
oauth_resource_invalidThe token is missing, invalid, for another resource, or was refused by the token exchange.
capability_authority_unavailableOneSay could not check your access right now. Retry.
mcp_confirmation_requiredAn R2 call has no human consent yet.
consent_requiredThe Control API needs a Consent the account has not given.
mcp_tool_input_invalidAn argument is missing or does not match the tool's schema.
mcp_tool_not_exposedThe tool is not enabled on this server.
mcp_tool_output_invalidThe Control API answered with something the tool cannot return.

Errors from the Control API itself, such as a missing Grant or an unknown resource, are passed through with their own codes. The Canonical Reference lists every code.

Availability#

  • The server runs on Staging at https://mcp.staging.onesay.com/mcp. Production is not available yet.
  • On Staging the R2 tools are switched off and answer mcp_tool_not_exposed.
  • Tools, prompts and resources are fixed per release, so the server sends no list-changed notifications.
View original Markdown
# MCP Guide

The OneSay MCP server lets an AI client read your OneSay Projects, Devices,
Rooms, Tasks, logs and Usage, and ask for a few bounded changes, through the
Model Context Protocol. It is a thin layer over the public Control API: every
tool calls a public API operation or Action, and the Control API decides what
your account may do. The server is available on Staging; see
[Availability](#availability).

MCP never carries audio. Voice goes through the SDKs: Task voice over the OneSay
Realtime WebSocket, or Realtime RTC.

## Connect

- **Endpoint:** `https://<mcp host>/mcp`, one per environment. On Staging it is
  `https://mcp.staging.onesay.com/mcp`.
- **Transport:** stateless Streamable HTTP. The server keeps no session between
  requests.
- **Protocol:** MCP `2026-07-28` only. Every request sends
  `Mcp-Protocol-Version: 2026-07-28`; another version is refused with
  `mcp_protocol_version_unsupported`, naming the supported one.
- **Request headers:** `Mcp-Method` must equal the body's method, and for
  `tools/call`, `prompts/get` and `resources/read` `Mcp-Name` must equal the tool
  name, prompt name or resource URI. A mismatch is answered with HTTP 400 and
  JSON-RPC error `-32020` before any token is read.

## Sign in

The server is an OAuth 2.1 protected resource. Its Protected Resource Metadata
is served at `/.well-known/oauth-protected-resource` (and at
`/.well-known/oauth-protected-resource/mcp`), and it names the environment's
authorization server.

- **No token** is needed for public discovery: the R0 tools, the quickstart
  resources, the prompts and the tool, resource and prompt lists.
- **Account data needs a token.** An R1 or R2 tool, or a resource other than a
  quickstart, needs a Bearer access token whose audience is this MCP resource.
  Without one the server answers HTTP 401 with a `WWW-Authenticate` challenge
  that points to the metadata. The body is a JSON-RPC error carrying your
  request id, with the `oauth_resource_invalid` error envelope as its data.
- **Your token never reaches the Control API.** For each Control API call the
  server exchanges it (OAuth 2.0 Token Exchange, RFC 8693) for a short-lived
  token whose subject is you and whose actor is the MCP service. No exchange is
  made after your token expires, and no token is logged or returned.

## Tools

Each tool has a risk class. Read-only tools are marked read-only to the client;
`rooms.close` and `tasks.cancel` are marked destructive.

| Risk | Tools | Needs |
|---|---|---|
| R0 | `onesay.capabilities.list`, `onesay.capabilities.get`, `onesay.quickstarts.get` | Nothing: public metadata |
| R1 | `onesay.projects.list`, `onesay.projects.get`, `onesay.applications.list`, `onesay.devices.list`, `onesay.devices.get`, `onesay.devices.diagnose`, `onesay.rooms.get`, `onesay.tasks.get`, `onesay.logs.search`, `onesay.logs.timeline`, `onesay.usage.summary` | A token and the Grants the matching API operation requires |
| R2 | `onesay.rooms.create`, `onesay.rooms.close`, `onesay.tasks.cancel` | A token, the Grant and the human's consent |

An R2 tool runs its Action only after the human has consented in OneSay. Without
that consent the call answers `mcp_confirmation_required`, and nothing changes.
On Staging the R2 tools are switched off for now: they answer
`mcp_tool_not_exposed` and change nothing.

## Resources

| URI template | Reads |
|---|---|
| `onesay://projects/{project_id}` | The Project, like `onesay.projects.get` |
| `onesay://devices/{device_id}` | The Device's state, like `onesay.devices.get` |
| `onesay://tasks/{task_id}` | The Task's state, like `onesay.tasks.get` |
| `onesay://docs/quickstarts/{name}` | A quickstart page (`javascript` or `esp32`); public |

The server lists templates only. Every read result has `ttlMs` 0, so a client
treats it as immediately stale.

## Prompts

- `build_voice_app` follows the [JavaScript Quickstart](JAVASCRIPT_QUICKSTART.md).
- `diagnose_device` follows the [Device Diagnostics](DEVICE_DIAGNOSTICS.md) guide.

## Errors

A tool error carries the OneSay error envelope, the same as the Control API's:

| Code | Meaning |
|---|---|
| `oauth_resource_invalid` | The token is missing, invalid, for another resource, or was refused by the token exchange. |
| `capability_authority_unavailable` | OneSay could not check your access right now. Retry. |
| `mcp_confirmation_required` | An R2 call has no human consent yet. |
| `consent_required` | The Control API needs a Consent the account has not given. |
| `mcp_tool_input_invalid` | An argument is missing or does not match the tool's schema. |
| `mcp_tool_not_exposed` | The tool is not enabled on this server. |
| `mcp_tool_output_invalid` | The Control API answered with something the tool cannot return. |

Errors from the Control API itself, such as a missing Grant or an unknown
resource, are passed through with their own codes. The
[Canonical Reference](../reference/generated/catalog.md) lists every code.

## Availability

- The server runs on Staging at `https://mcp.staging.onesay.com/mcp`. Production
  is not available yet.
- On Staging the R2 tools are switched off and answer `mcp_tool_not_exposed`.
- Tools, prompts and resources are fixed per release, so the server sends no
  list-changed notifications.