Skip to main content
The MCP server is an OAuth-protected resource. Compliant clients handle everything below automatically. You only need this page if you’re building your own client or debugging a connection.

Discovery flow

  1. The client POSTs to /api/mcp without a token and receives 401 Unauthorized with a WWW-Authenticate header pointing at https://mcp.mavel.ai/.well-known/oauth-protected-resource (RFC 9728).
  2. That document names the authorization server; the client then fetches /.well-known/oauth-authorization-server (RFC 8414) for the endpoints: authorize, token, register, revoke. The flow is authorization-code + PKCE (S256), public clients only.
  3. The client self-registers (RFC 7591 dynamic client registration), runs the PKCE flow (you approve on the Mavel consent page), and retries with Authorization: Bearer <token>.

Scopes

Registering a client (RFC 7591)

  • redirect_uris: 1-10 URIs; https:// only, except http://localhost / http://127.0.0.1. URIs are matched on scheme + host + path (query and fragment ignored).
  • Only public clients are issued. There is no client_secret, and token_endpoint_auth_method is always none.

Tokens

  • Access tokens expire after 1 hour (expires_in: 3600).
  • Refresh tokens live 90 days; each refresh rotates the pair (the consumed refresh token is revoked and a fresh access + refresh pair is issued).
  • Revoke with POST /api/mcp/oauth/revoke using either token: both belong to the same grant, so revoking one kills both (RFC 7009 semantics: HTTP 200 regardless).

Protocol surface

POST /api/mcp accepts JSON-RPC 2.0 (single object or batch array). Supported methods: initialize, tools/list, prompts/list, tools/call, prompts/get. Add Accept: text/event-stream only if your client requires SSE responses. Rate limit: 200 requests / minute / authenticated user; exceeding it returns HTTP 429 with X-RateLimit-* headers.

Error codes

Strict argument validation

tools/call checks the top-level keys of arguments against the tool’s declared schema before running it. An argument key the schema doesn’t list (a typo like offfset for offset, for example) used to be silently dropped; it now fails the whole call with -32602. The error message itself names every offending key and the tool’s legal argument names, for example unknown argument "offfset" for tool "list_chats" (valid: project_id, date_from, ...), so the guidance holds even on clients that strip error.data. The same list is also available structured, as error.data.valid_keys. If a key you’re sure is spelled correctly still gets rejected, your cached tool schema may be stale: re-fetch tools/list (see Server version below for how to detect a stale cache automatically).

Server version

serverInfo.version, returned at initialize and by an unauthenticated GET request to the server URL, is the deployed commit SHA. Every non-array tools/call result also carries that same value as a plain server_version field in its response body, alongside _meta.server_version (the MCP-spec channel): the body field is the reliable one, since some MCP clients strip _meta (and error.data) before the model ever sees them. -32601 / -32602 errors carry server_version in error.data too, for clients that do deliver it, so even a failed call can tell you which deploy answered it. Compare the stamp across calls in the same session: if it changes, the server redeployed and the tool catalog may have changed underneath you, so re-fetch tools/list. There’s no push notification for this (capabilities.tools.listChanged is false by design, since this is a stateless request/response transport with no server-to-client channel to push on), so comparing the version yourself is the only way to detect a mid-session deploy.