Skip to content

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-events SSE resource; cookie-less clients can receive the same events through the GET /v1/user/events SSE 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:

https://mcp.contio.ai/mcp

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.

  1. Point the client at the MCP endpoint https://mcp.contio.ai/mcp.
  2. If the client discovers OAuth automatically, use the protected-resource metadata at https://mcp.contio.ai/.well-known/oauth-protected-resource.
  3. Start authorization at https://app.contio.ai/v1/oauth/authorize with PKCE (S256) and the scopes you need.
  4. Exchange the code at https://api.contio.ai/v1/oauth/token.
  5. The client sends the resulting cto_at_v1_... token on every MCP request:
Authorization: Bearer cto_at_v1_...

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.

  1. Open the Contio app and go to Settings > API Tokens.
  2. In the Short-lived Access Tokens (SLT) section, click Create SLT.
  3. Select the scopes you need and choose an expiry.
  4. Copy the plaintext token immediately — it is shown only once.
  5. 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.

  1. Create a PAT in the Contio app under Settings > Personal Access Tokens (prefix cto_pat_v1_). PATs cannot be minted through the API.
  2. 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:

{
  "mcpServers": {
    "contio": {
      "url": "https://mcp.contio.ai/mcp",
      "transport": "http",
      "headers": {
        "Authorization": "Bearer cto_pat_v1_<your-token>"
      }
    }
  }
}

Add the server and keep the secret in the local (gitignored) config:

devin mcp add contio https://mcp.contio.ai/mcp

Then add the token to .devin/config.local.json:

{
  "mcpServers": {
    "contio": {
      "url": "https://mcp.contio.ai/mcp",
      "transport": "http",
      "headers": {
        "Authorization": "Bearer cto_pat_v1_<your-token>"
      }
    }
  }
}

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-events require 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:

  1. Complete the initialize handshake.
  2. Call resources/subscribe with the resource URI.
  3. Keep the streamable-http SSE stream open to receive notifications/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:read
  • meetings:write
  • action-items:read
  • action-items:write
  • calendar:read
  • workspace:read
  • workspace: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:

  1. 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.
  2. In your MCP client, add the server URL:
    https://mcp.contio.ai/mcp
    
  3. When the client asks how to authenticate, choose Bearer token or Authentication header and enter:
    Bearer cto_pat_v1_<your-token>
    

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:

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.

Next steps