Skip to content
Chatto v0.5.0

Model Context Protocol

Chatto can expose a small tool catalog through the Model Context Protocol (MCP). The optional MCP integration uses the same public HTTP server, OAuth implementation, and version as the rest of Chatto.

The endpoint supports stateless MCP 2026-07-28. Hosts that start with initialize cannot connect. See the MCP Reference for tools, search arguments, response schemas, and retry rules.

Add this section to chatto.toml:

[mcp]
enabled = true

Chatto mounts /mcp and /.well-known/oauth-protected-resource/mcp on its existing public HTTP server. It uses the webserver.url origin and each exact non-wildcard origin in webserver.allowed_origins. For example, a server at https://chat.example has the MCP endpoint https://chat.example/mcp.

Each endpoint is a separate OAuth resource. A human access token for one origin does not work on another origin. The authorization server always uses the canonical webserver.url origin as its issuer. Bot API keys work on each configured endpoint. A reverse proxy needs no separate MCP upstream.

Human users authorize an MCP client through OAuth Authorization Code with S256 PKCE. Chatto resolves the client’s Client ID Metadata Document (CIMD), shows the requested scope capabilities on the consent page, and issues an access token bound to the exact MCP resource and approved scopes. A first-party Chatto bearer token without this resource and grant cannot use MCP.

Request only the scopes your host needs. Chatto accepts any nonempty subset of these scopes. A write scope does not include read access.

ScopeTools
chatto:rooms:readlist_rooms
chatto:rooms:writejoin_room, leave_room
chatto:messages:readlist_room_messages, search_messages (when search is enabled)
chatto:messages:writepost_message

Any valid grant also permits discovery, get_server_info, and get_current_user. tools/list shows only the tools covered by your grant. Initial discovery requests room-read access, so the default grant has three tools. A host that needs message reads or writes must request those scopes. Additional scopes require fresh consent. Refresh keeps the approved scope set; the token response reports it in scope. Existing full grants still work.

Native hosts must publish client metadata with application_type: native and an exact callback. Runtime callback ports require literal loopback IP addresses. Named localhost callbacks must use the registered port.

An unattended integration can send a current bot API key as its bearer token. The bot acts as its own account. Its explicit permission allowlist and its owner’s current permission ceiling still apply. See Bot Accounts.

  1. Give your agent host the public Chatto URL with the /mcp path.
  2. Let the host read protected-resource and authorization-server metadata.
  3. Complete the Chatto consent screen when the host opens it.
  4. Confirm that the host discovers the tools covered by your grant.
  5. Ask the host to identify the server. Confirm that it reports the expected name and public URL.
  6. Ask the host to identify the connected account and list its visible rooms.
  7. To test all tools, approve all four scopes. In a test room, ask the host to join, post a unique test message, read the message, and leave.

The setup below was tested with Codex CLI 0.160.1:

Terminal window
codex mcp add chatto --url https://chat.example.com/mcp
codex mcp login chatto --oauth-client-registration cimd

Complete sign-in and consent in the browser. Then start Codex and use the identity and room checks above. Codex identifies itself with its public CIMD document. You do not need a client secret or a first-party Chatto token.

To grant all available tools, request all four scopes explicitly:

Terminal window
codex mcp login chatto --oauth-client-registration cimd \
--scopes chatto:rooms:read,chatto:rooms:write,chatto:messages:read,chatto:messages:write

For a diagnostic client, see MCP Inspector.

FailureAction
/mcp returns 404Enable [mcp].enabled and check the public URL and reverse proxy.
initialize returns method not foundUse a host with stateless 2026-07-28 support. In Inspector, select the modern protocol era.
Consent rejects redirect_uriCheck the client’s CIMD document. Runtime ports require a native client and a literal loopback IP callback. Named localhost callbacks must match exactly.
A tool request returns 401Authorize the exact MCP URL again. Check grant expiry, client blocking, and the valid MCP scopes. A first-party token or a grant for another origin cannot be used.
A tool is absent or returns 403 insufficient_scopeRequest its scope in a new OAuth consent flow. The Bearer challenge identifies the required scope. Keep any existing scopes that the host still needs.
search_messages is absent with message-read accessAsk the operator to check that search is enabled on the server.
Inspector --use-stored-auth reports no_stored_tokenUse --stored-auth-only. This Inspector version can fail to load its stored credentials through the older flag.

Claude Code 2.1.291 fails callback validation with its current CIMD document. That document omits application_type: native, while the client requests a callback with a runtime port. Use another tested host until the client and its metadata document agree. Do not disable callback validation.

An operation needs both the relevant OAuth scope and normal Chatto permissions and room membership. A scope error requires fresh consent; an account permission error requires a change to that account’s access. A bot also needs its owner’s current authority. See the MCP error reference for response fields and retry rules.

Set [mcp].enabled = false and restart Chatto to remove the MCP routes. You can also block an OAuth client in Server Admin or rotate a bot API key. These actions invalidate the related authority without changing other Chatto clients.

Removing Chatto from an agent host or deleting its local credentials does not guarantee that its server-side grant is revoked. Ask a server administrator to block that OAuth client when you must terminate its access. A revoked grant or blocked client cannot start another MCP request or refresh its credential, also when the request reaches another Chatto replica.

The network MCP server does not expose the Operator API, bootstrap, password reset, account management, or server management. Use the local Operator API for root-equivalent recovery tasks.