Browse guides · API reference

API reference

Choose what you want to build. Each example shows the token and request you need.

Base URL: https://closedmcp.com. Use your company’s address if it differs.

An access token lets an AI app call ClosedMCP. A tool identity token tells a connected server who is calling. Use the access token when calling ClosedMCP. Your tool receives a separate identity token to identify the person.

Sign-in steps

  1. Register your app. Save the client_id and use your registered return URL.
  2. Sign in the user. Make a random PKCE verifier. Send its SHA-256 base64url hash as code_challenge. Keep the verifier private. Make a random state value and check it on return.
  3. Get a token. Exchange the returned code with the original verifier. Save the access token securely. Use the refresh token to renew it.

Follow the endpoints below in order. ClosedMCP handles the permission form; your app opens its URL.

Discover the sign-in server

GET/.well-known/oauth-protected-resource

Tells an AI app where to sign in. Also at /.well-known/oauth-protected-resource/mcp.

Authentication: None.

Copy request
Terminal
curl "$BASE/.well-known/oauth-protected-resource"
View response
Successful response
{
  "resource": "https://closedmcp.com/mcp",
  "authorization_servers": [
    "https://closedmcp.com"
  ],
  "scopes_supported": [
    "mcp:tools",
    "mcp:list"
  ],
  "bearer_methods_supported": [
    "header"
  ]
}
Notes and errors

Errors: No endpoint-specific error response.

Read sign-in settings

GET/.well-known/oauth-authorization-server

Lists the sign-in, registration and token URLs, supported settings and the public key URL. Also at /.well-known/oauth-authorization-server/mcp and /.well-known/openid-configuration.

Authentication: None.

Copy request
Terminal
curl "$BASE/.well-known/oauth-authorization-server"
View response
Successful response
{
  "issuer": "https://closedmcp.com",
  "authorization_endpoint": "https://closedmcp.com/oauth/authorize",
  "token_endpoint": "https://closedmcp.com/oauth/token",
  "registration_endpoint": "https://closedmcp.com/oauth/register",
  "code_challenge_methods_supported": [
    "S256"
  ],
  "jwks_uri": "https://closedmcp.com/.well-known/jwks.json"
}
Notes and errors

Excerpt. The response also lists supported grants, scopes and response types.

Errors: No endpoint-specific error response.

Register an AI app

POST/oauth/register

Registers an AI app and its return URLs. Send JSON. The answer includes a client_id. No client secret is needed.

Authentication: None.

Copy request
Terminal
curl "$BASE/oauth/register" \
  -H 'Content-Type: application/json' \
  -d '{"client_name":"My app",
    "redirect_uris":["https://my-app.example/callback"]}'
View response
Successful response
{
  "client_name": "My app",
  "redirect_uris": [
    "https://my-app.example/callback"
  ],
  "client_id": "cm_example",
  "client_id_issued_at": 1791504000,
  "token_endpoint_auth_method": "none"
}
Notes and errors

Errors: HTTP 400, invalid_redirect_uri: missing or unsupported return URL.

Open the sign-in and permission page

GET/oauth/authorize

Opens the sign-in and permission page in a browser. Use the registered client_id and return URL with a PKCE S256 challenge. To ask for a tool identity token for your own MCP server, add its exact URL as resource. Replace the placeholder values, then open this URL in a browser.

Authentication: Google sign-in in the browser.

Copy request
URL
https://closedmcp.com/oauth/authorize
  ?response_type=code
  &client_id=<client_id>
  &redirect_uri=https%3A%2F%2Fmy-app.example%2Fcallback
  &code_challenge=<S256_challenge>
  &code_challenge_method=S256
  &state=<random_state>
View response
Successful response
HTTP 200: sign-in or permission page.
After approval: HTTP 302 to your return URL.
https://my-app.example/callback?code=example&state=example
Notes and errors

Errors: HTTP 400: invalid authorization parameters. User denial returns access_denied to a validated return URL.

Submit the permission decision

POST/oauth/authorize

Sends the person’s choice from the permission page. Needs the signed-in browser session and a request from the same site.

Authentication: Signed-in browser session. Same-origin request.

Copy request
Form body
rid=<request_id>&decision=allow
View response
Successful response
HTTP 302
Location: https://my-app.example/callback?code=example&state=example
Notes and errors

The Location header is a single-line URL. This endpoint serves the permission form; apps should open GET /oauth/authorize.

Errors: HTTP 403: cross-site request. HTTP 400: invalid or expired request.

Get an access token

POST/oauth/token

Swaps a sign-in code and its PKCE verifier for a bearer token. Send form data. To renew a token, send grant_type=refresh_token and refresh_token instead. Keep client_id when renewing an access token.

Authentication: Registered client_id and PKCE verifier. No client secret.

Copy request
Terminal
curl "$BASE/oauth/token" \
  -d grant_type=authorization_code \
  -d 'code=<code>' \
  -d 'code_verifier=<verifier>' \
  -d 'client_id=<client_id>' \
  -d redirect_uri=https%3A%2F%2Fmy-app.example%2Fcallback
View response
Successful response
{
  "access_token": "cmcp_at_example",
  "refresh_token": "cmcp_rt_example",
  "token_type": "Bearer",
  "expires_in": 2592000,
  "scope": "mcp:tools mcp:list"
}
Notes and errors

Errors: HTTP 400: invalid_grant for a bad, expired or reused code, mismatched client, or invalid verifier. invalid_target for an unsupported resource. invalid_request for repeated parameters.

Continue: start a session →