Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.cometly.com/llms.txt

Use this file to discover all available pages before exploring further.

TL;DR

You don’t need to manage anything by hand. MCP-aware clients walk the full OAuth flow themselves the first time they hit the Cometly MCP endpoint:
  1. The client sees a 401 Unauthorized with a WWW-Authenticate header pointing at our OAuth discovery URL.
  2. The client registers itself dynamically (RFC 7591).
  3. The client opens your browser to the Cometly authorization page.
  4. You log in, pick which Space to grant access to, and click Approve.
  5. The client exchanges the resulting code for an access token bound to that Space.
After that the client just sends Authorization: Bearer <token> on every tool call. If you want the gritty detail — or you’re building a custom MCP client — keep reading.

Endpoints

Cometly is its own authorization server. There’s no third-party identity provider in the middle.
EndpointURL
Protected resource metadata (RFC 9728)https://app.cometly.com/.well-known/oauth-protected-resource/{path}
Authorization server metadata (RFC 8414)https://app.cometly.com/.well-known/oauth-authorization-server/{path}
Dynamic client registrationPOST https://app.cometly.com/mcp/oauth/register
Authorization (browser)GET https://app.cometly.com/mcp/oauth/authorize
Token exchangePOST https://app.cometly.com/mcp/oauth/token
MCP server (resource)https://app.cometly.com/mcp/{space_id}/public-api
We expose both the path-prefix (RFC 9728) and path-suffix (RFC 8414) .well-known URL variants because different clients implement different revisions of the spec. Claude Desktop uses the prefix form; Cursor uses the suffix form. Both resolve to the same metadata.

Discovery metadata

Hitting the auth-server metadata endpoint returns:
{
  "issuer": "https://app.cometly.com",
  "authorization_endpoint": "https://app.cometly.com/mcp/oauth/authorize",
  "token_endpoint": "https://app.cometly.com/mcp/oauth/token",
  "registration_endpoint": "https://app.cometly.com/mcp/oauth/register",
  "response_types_supported": ["code"],
  "code_challenge_methods_supported": ["S256"],
  "scopes_supported": ["mcp:use"],
  "grant_types_supported": ["authorization_code"]
}
PKCE with S256 is required. There’s no implicit grant, no password grant, no client-credentials grant — just authorization code with PKCE.

Dynamic client registration

POST /mcp/oauth/register with the client’s metadata. Minimal example:
{
  "client_name": "My MCP Client",
  "redirect_uris": ["http://127.0.0.1:33333/callback"],
  "token_endpoint_auth_method": "none"
}
Returns a client_id you’ll use for the authorization request. There is no client_secret — Cometly’s MCP server treats every client as a public client and relies on PKCE for security.

Accepted redirect_uris

The redirect URI is the primary security boundary for an unauthenticated client (RFC 7591), so the registration endpoint enforces a strict policy. URIs that don’t match one of the categories below are rejected with 400 invalid_redirect_uri.
CategoryExamplesNotes
Loopback over http/httpshttp://127.0.0.1:33333/callback, http://localhost/cb, http://[::1]/cbRecommended for native clients. The port is matched loosely so reconnects on a different ephemeral port still work.
https to a registered hosthttps://callbacks.example.com/oauthOnly hosts on the operator’s explicit allowlist (MCP_ALLOWED_REDIRECT_HOSTS). No wildcards, no subdomain matching. Exact host match, case-insensitive.
Approved custom schemecursor://..., vscode://..., claude-desktop://...A published allowlist of well-known native MCP client schemes.
Reverse-DNS custom schemecom.example.app:/oauth2redirectLets published native apps register their own bundle identifier. Each segment must start with a letter and contain only a-z, 0-9, or -.
Other patterns — non-loopback http://, arbitrary https:// hosts, single-word custom schemes (evil://), URIs with fragments, and javascript:/data:/file: URIs — are always rejected.

Accepted client_name

client_name is shown verbatim on the consent screen, so it’s validated to prevent impersonation and UI hijacking:
  • Maximum 120 characters.
  • No control characters (\x00–\x1f, \x7f).
  • Names that contain cometly as a standalone word (case-insensitive, word/whitespace/hyphen/underscore boundaries) are rejected to keep malicious clients from passing themselves off as Cometly itself.

Rate limits

POST /mcp/oauth/register is throttled to 10 registrations per hour per IP. Legitimate clients register once per install, so this leaves plenty of headroom for retries while making it impractical to flood the registration table. Exceeded requests return 429 temporarily_unavailable with an RFC 7591 error body.

Authorization flow

  1. Generate a PKCE code_verifier and the matching code_challenge (SHA256(verifier), base64url, no padding).
  2. Redirect the user (in their browser) to:
    https://app.cometly.com/mcp/oauth/authorize
      ?response_type=code
      &client_id={client_id}
      &redirect_uri={redirect_uri}
      &code_challenge={code_challenge}
      &code_challenge_method=S256
      &state={random}
      &scope=mcp:use
    
  3. The user logs in (if not already), then picks the Space and clicks Approve.
  4. Cometly redirects back to your redirect_uri with ?code={code}&state={state}.
  5. Exchange the code:
    curl -X POST https://app.cometly.com/mcp/oauth/token \
      -H "Content-Type: application/x-www-form-urlencoded" \
      -d "grant_type=authorization_code" \
      -d "code={code}" \
      -d "redirect_uri={redirect_uri}" \
      -d "client_id={client_id}" \
      -d "code_verifier={code_verifier}"
    
    Response:
    {
      "access_token": "1|abc...",
      "token_type": "Bearer",
      "expires_in": null,
      "scope": "mcp_space:42"
    }
    

Calling the MCP server

Once you have an access token, every JSON-RPC call to the MCP endpoint carries it:
curl -X POST https://app.cometly.com/mcp/42/public-api \
  -H "Authorization: Bearer 1|abc..." \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
The Space ID in the URL must match the Space the token was approved for — Cometly checks the token’s mcp_space:{id} ability against the route param on every request and returns 403 if they disagree.

Scopes

There’s a single MCP scope today:
ScopeWhat it grants
mcp_space:{id}Call any read-only tool against Space {id}. The Space ID is bound into the scope string — a token approved for Space 42 cannot read Space 43.
When you click Approve in the consent UI, the token’s ability is set to exactly one mcp_space:{id} value. There’s no broader “all spaces” scope, by design.

Revoking access

You can revoke a connected MCP client at any time:
  1. Open Settings → API Tokens in your Cometly dashboard.
  2. Find the token whose name matches the MCP client (e.g. MCP — Claude Desktop).
  3. Click Revoke.
The next tool call from that client gets 401 Unauthorized and the client will walk the auth flow again on next launch (or you can just remove it from the client’s MCP settings). Removing a user from a Space also immediately revokes any MCP tokens they have for that Space — there’s no separate cleanup step.

Common errors

StatusMeaningRecovery
401No / invalid / expired token.Walk the OAuth flow again. The WWW-Authenticate header includes the discovery URL.
403Token’s mcp_space:{id} doesn’t match the URL’s Space ID, or the user no longer has API permission in that Space.Re-authorize with the correct Space.
403 (subscription)The Space’s team doesn’t have an active Public API subscription.Reach out to your Cometly admin or contact sales.
429Rate limit exceeded.Back off. See Rate Limits & Errors.