Hosted MCP Server¶
The Contio User API is also available as a hosted Model Context Protocol (MCP) server. Instead of writing REST calls, an MCP-compatible agent can discover Contio tools, invoke them with typed parameters, and subscribe to live workspace events.
Why MCP¶
MCP turns Contio into a first-class agent integration:
- Zero client code — the server exposes every tool, its JSON schema, and descriptions; the agent decides what to call.
- Natural language to action — requests like "list my upcoming meetings" or "create an action item to follow up with the client" map directly to tool calls.
- Live workspace events — cookie-aware clients can subscribe to the
contio-eventsSSE resource; cookie-less clients can receive the same events through theGET /v1/user/eventsSSE endpoint or workspace webhooks. - Same security model — the gateway forwards your bearer token to the Contio API, so workspace roles, scopes, and plan limits are always respected.
Hosted vs. self-hosted¶
Contio runs a public MCP gateway for paid workspaces. Free workspaces keep full API access and can build or self-host their own MCP server.
Hosted MCP Gateway (mcp.contio.ai) | User API + self-hosted MCP | |
|---|---|---|
| Plans | PRO, ELITE, and ENT | Any plan, including FREE |
| Infrastructure | Managed by Contio | You run it (local, VPS, private cloud) |
| Authentication | Your OAuth token, PAT, or SLT | Your OAuth token, PAT, or SLT |
| Events | SSE contio-events with cookies, GET /v1/user/events directly, or workspace webhooks | Depends on your implementation |
| Best for | Quick setup with Claude, Cursor, etc. | Custom caching, VPC rules, or FREE-tier users |
Free plans keep full API access
FREE workspaces are not blocked from the User API. You can still list meetings, create action items, and build automations with the /v1 endpoints and a valid OAuth token. The hosted MCP gateway is a paid convenience for users who want a managed MCP transport.
Endpoint¶
The hosted gateway speaks MCP 2024-11-05 streamable-http:
OAuth discovery is published at:
GET https://mcp.contio.ai/.well-known/oauth-protected-resource
GET https://mcp.contio.ai/.well-known/oauth-authorization-server
GET https://mcp.contio.ai/.well-known/openid-configuration
Connect your MCP client¶
This is the best fit for Contio-owned first-party clients — desktop apps, CLIs, and other tools built or approved by Contio that can open a system browser and listen on a loopback address. The first-party client_id should only be used by Contio-owned clients.
- Point the client at the MCP endpoint
https://mcp.contio.ai/mcp. - If the client discovers OAuth automatically, use the protected-resource metadata at
https://mcp.contio.ai/.well-known/oauth-protected-resource. - Start authorization at
https://app.contio.ai/v1/oauth/authorizewith PKCE (S256) and the scopes you need. - Exchange the code at
https://api.contio.ai/v1/oauth/token. - The client sends the resulting
cto_at_v1_...token on every MCP request:
The gateway forwards the token to the Contio API, so token expiry and refresh are handled through the standard OAuth endpoints.
See the Authentication guide for the full PKCE flow.
For quick, ad hoc MCP sessions, use a short-lived access token (cto_slt_v1_) from the Contio web app. SLTs can be created on all plans and expire within hours, but the hosted MCP gateway itself is a paid feature. FREE users should call the /v1 REST API directly or self-host an MCP server instead. SLTs are shown once at creation.
- Open the Contio app and go to Settings > API Tokens.
- In the Short-lived Access Tokens (SLT) section, click Create SLT.
- Select the scopes you need and choose an expiry.
- Copy the plaintext token immediately — it is shown only once.
- In your MCP client, set:
URL: https://mcp.contio.ai/mcp
Transport: http (streamable-http)
Auth: Bearer cto_slt_v1_<your-token>
The gateway introspects the token and exposes only the tools allowed by the selected scopes. If a tool call returns 403 Insufficient scope or role, reissue the SLT with the missing scope.
See the Authentication guide.
For server-side automation, third-party agents, and MCP clients that run without a browser or do not support Dynamic Client Registration, issue a PAT and configure it once.
- Create a PAT in the Contio app under Settings > Personal Access Tokens (prefix
cto_pat_v1_). PATs cannot be minted through the API. - In your MCP client, set:
URL: https://mcp.contio.ai/mcp
Transport: http (streamable-http)
Auth: Bearer cto_pat_v1_<your-token>
The gateway introspects the token at GET /v1/me and exposes only the tools allowed by the token's scopes and workspace role. Owner or admin tokens also load the admin tool manifest.
See the Personal Access Tokens guide.
You can also POST MCP JSON-RPC messages directly. Most clients perform the initialize handshake automatically, but you can do it manually to test or build a custom integration.
Initialize the session:
curl -X POST https://mcp.contio.ai/mcp \
-H "Authorization: Bearer cto_pat_v1_..." \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2024-11-05",
"capabilities": {},
"clientInfo": {"name": "example", "version": "1.0.0"}
}
}'
After the server responds, call tools/list:
curl -X POST https://mcp.contio.ai/mcp \
-H "Authorization: Bearer cto_pat_v1_..." \
-H "Content-Type: application/json" \
-H "Mcp-Session-Id: <session-id-from-previous-response>" \
-d '{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/list"
}'
Note
Replace cto_pat_v1_... with your PAT or cto_at_v1_... with an OAuth access token. The Mcp-Session-Id header is only needed for stateful sessions; omit it if the gateway is running in stateless mode.
Because the gateway uses cookie-based sticky sessions for SSE, use a cookie jar (curl -c cookies.txt -b cookies.txt) if you want live contio-events. Cookie-less clients can still call tools and receive the same events through GET /v1/user/events or workspace webhooks.
Per-client configuration examples¶
Every MCP client sends the same Authorization header, but the config shape differs. The value must always be Bearer <token> — not Bearer: <token> and not the bare token string. In the JSON snippets below, transport: "http" is the client-side name for the MCP streamable-http transport used by the gateway.
Use a space, not a colon, after Bearer
The correct header value is Bearer cto_slt_v1_... or Bearer cto_pat_v1_.... Some clients expose the scheme and token separately; if you paste the token into a "Bearer token" field, omit the Bearer prefix.
Add to mcpServers in the client's MCP settings:
Add the server and keep the secret in the local (gitignored) config:
Then add the token to .devin/config.local.json:
Test with curl:
curl -X POST https://mcp.contio.ai/mcp \
-H "Authorization: Bearer cto_pat_v1_..." \
-H "Accept: application/json, text/event-stream" \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2024-11-05",
"capabilities": {},
"clientInfo": {"name": "example", "version": "1.0.0"}
}
}'
Continue the session with the Mcp-Session-Id returned in the response.
Session affinity and cookies¶
The hosted gateway runs more than one task. To keep a stateful session on the same task, the gateway uses cookie-based sticky sessions in addition to the mcp-session-id header. Your HTTP client must preserve and resend the AWS ALB sticky-session cookie on every request if you want live contio-events through the MCP gateway.
Not all MCP SDK clients do this by default — the official Node SDK uses raw fetch and does not store or send cookies. With those clients, the gateway still works:
- Tool calls are handled statelessly, one request at a time, with no cookie required.
- Live events through
contio-eventsrequire the sticky cookie.
Choosing a live-event delivery option¶
Pick the option that matches your client and infrastructure:
| Option | What you implement | Best for | Requires cookies? | Who can use |
|---|---|---|---|---|
MCP resources/subscribe to mcp://contio/events | The MCP host preserves and resends the ALB sticky cookie on every request. | Claude Desktop, Cursor, VS Code, or any MCP host with cookie support. | Yes | Any user with a valid token and read scope |
GET /v1/user/events | Your code holds a long-lived HTTP connection, parses SSE, and resumes with Last-Event-ID. | Your own long-running service, script, or agent runtime. | No | Any user with a valid read scope |
| Workspace webhooks | Your public HTTPS endpoint receives signed POST callbacks, validates signatures, and parses payloads. | Server-side automations, bots, or integrations that do not need a live connection. | No | Workspace admins only |
Consumer MCP hosts usually cannot receive webhooks
Webhooks require a publicly routable HTTPS endpoint. A desktop MCP client like Claude Desktop or Cursor cannot receive them. If your consumer MCP client does not preserve cookies, live events are not available through that client. Use GET /v1/user/events from your own code, or poll resources/read on mcp://contio/events.
If a cookie-aware client receives 404 Session not found, its session was lost (for example, during a deployment or task replacement). Re-initialize and re-subscribe to contio-events.
We plan to remove this cookie dependency with a distributed-session architecture. Until then, use the option above that matches your runtime.
Subscribing to contio-events¶
The hosted MCP gateway exposes workspace events as an MCP resource at mcp://contio/events, not as a tool. To receive live events:
- Complete the
initializehandshake. - Call
resources/subscribewith the resource URI. - Keep the
streamable-httpSSE stream open to receivenotifications/resources/updated.
{
"jsonrpc": "2.0",
"id": 3,
"method": "resources/subscribe",
"params": {
"uri": "mcp://contio/events"
}
}
When the gateway receives a workspace event, it sends a notification like:
{
"jsonrpc": "2.0",
"method": "notifications/resources/updated",
"params": {
"uri": "mcp://contio/events"
}
}
Call resources/read with the same URI to fetch the latest event payload. You can also call resources/read without subscribing to see the most recent event at any time.
Requires a stateful, cookie-aware session
contio-events only works when the MCP session is pinned to a single gateway task. See the Session affinity and cookies section above. Cookie-less clients can consume GET /v1/user/events directly or use workspace webhooks.
Idempotent tool calls¶
Mutating tools (createMeeting, createActionItem, addMeetingParticipants, etc.) support the Idempotency-Key argument. If you provide one, the Contio API replays the original 2xx response when the same key is reused with the same payload, so retries are safe.
- If you do not supply
Idempotency-Key, the hosted gateway automatically generates one for supported operations. The same key is reused across the gateway's internal 5xx/network retries, so a transient upstream failure does not accidentally run the mutation twice. - If you supply your own
Idempotency-Key, the gateway forwards it unchanged. Reuse the same key if your MCP client retries the tool call from its side.
See the Reliability guide for retry behavior and the Errors guide for idempotency error codes.
Scopes¶
The hosted gateway requests these User API scopes during OAuth:
meetings:readmeetings:writeaction-items:readaction-items:writecalendar:readworkspace:readworkspace:write
PATs are created with the subset you choose, so the gateway only registers tools your grants allow.
Admin tools¶
If your token belongs to a workspace owner or admin — or carries the workspace:write scope — the gateway also registers tools from admin-mcp.json for workspace management. Regular user tokens only see the user-level tools.
MCP client OAuth compatibility¶
The hosted MCP gateway supports two ways to authenticate:
- OAuth 2.1 + PKCE — interactive sign-in for Contio-owned first-party desktop agents and CLIs.
- Bearer token — a Personal Access Token (PAT), ideal for third-party agents and MCP clients that do not support Dynamic Client Registration.
Some MCP clients require the server to support Dynamic Client Registration, which lets the client register itself automatically during setup. Contio's hosted MCP gateway does not currently support this registration step, so those clients may show an error like "This server did not advertise a supported OAuth flow" when you try to connect.
Use a Bearer token instead¶
If you see that error, use a PAT:
- Create a PAT in the Contio app under Settings > Personal Access Tokens. PATs start with
cto_pat_v1_and cannot be minted through the API. - In your MCP client, add the server URL:
- When the client asks how to authenticate, choose Bearer token or Authentication header and enter:
The gateway will introspect the token and expose only the tools allowed by the token's scopes.
If your client does not support Bearer-token auth and requires OAuth, let us know through support or your account team so we can prioritize Dynamic Client Registration support.
Self-hosting your own MCP server¶
If you are on a FREE plan or need a private instance inside your own infrastructure, you can build your own MCP server using the same published manifests:
mcp.json— user-level toolsadmin-mcp.json— workspace admin toolsoperations.json— per-operation metadata (parameters, body schema, scopes)
Call the underlying /v1 endpoints at https://api.contio.ai/v1 with your PAT or OAuth token. Because the /v1 endpoints are available to every plan, a FREE workspace can use them directly. See the Agent Integration guide for how to consume the manifests and a comparison of the available artifacts.