Skip to main content

Onboarding: one URL

The hosted MCP door is Streamable HTTP at:
Paste that URL into Claude, Cursor, Codex, or ChatGPT. The client runs OAuth 2.1 with PKCE, you sign in with Google or your email and password, and the agent can list models, send a test chat after you Allow it, and read credits. Use the mcp.kymaapi.com host: https://kymaapi.com/mcp is a web page, not the MCP endpoint. Do not put a secret in the path. Manage keys on Integrations.

Auth

  1. OAuth — default for Claude, Cursor, Codex, ChatGPT. Dynamic client registration + PKCE.
  2. Authorization: Bearer — if the header is present, OAuth is skipped. Use this for Grok or Perplexity when they cannot complete OAuth. The token is a dedicated MCP key (km-…), not a REST kyma- key and not a path token.
Unsigned /mcp returns 401, not 404, with WWW-Authenticate pointing at resource metadata.

For client authors

The authorization server is OAuth 2.1 with PKCE (S256 only). Metadata lives at https://mcp.kymaapi.com/.well-known/oauth-authorization-server, and the protected resource metadata at /.well-known/oauth-protected-resource (the read-only door publishes its own at /.well-known/oauth-protected-resource/mcp/readonly).
  • Client ID Metadata Documents are accepted. client_id_metadata_document_supported is true, so you can pass an HTTPS URL as your client_id instead of registering. The document must be served directly as application/json (no redirects), its client_id must equal the URL exactly, and every redirect_uri you use must be listed in it. Loopback redirects match on any port. Dynamic client registration at /mcp/oauth/register keeps working unchanged.
  • Send the resource parameter. On /authorize and /token, resource must name one of the two doors: https://mcp.kymaapi.com/mcp or https://mcp.kymaapi.com/mcp/readonly (RFC 8707). The bare origin https://mcp.kymaapi.com counts as the main door, with or without a trailing slash, so mcp-remote --resource https://mcp.kymaapi.com works as sent. A resource this server does not host comes back as error=invalid_target on your redirect_uri. The issued token is bound to it: a token minted for the read-only door is refused at the main door with 401 and error="invalid_token". Omitting resource keeps the old behaviour, so existing clients are unaffected.
  • Browser clients need an allowed origin. Cross-origin requests are answered only for https://kymaapi.com, https://www.kymaapi.com, https://mcp.kymaapi.com, loopback (the MCP Inspector), and preview deployments. Any other Origin gets 403 on the preflight and on the request. Clients that send no Origin header, which is every non-browser client, are unaffected.

MCP keys

OAuth and the dashboard issue a dedicated key labeled Kyma MCP: <client>.
  • Spend cap default **10per30days∗∗perconnectedclient,adjustablefrom10 per 30 days** per connected client, adjustable from 1 to $500 on Integrations; the window resets 30 days after it starts
  • OAuth connections (Claude, Cursor, ChatGPT) refresh themselves while in use; hand-issued keys (Grok, Perplexity, scripts) last 30 days and can be extended from Integrations
  • SHA-256 at rest
  • Revoke on Integrations without rotating REST keys on /keys
OAuth clients also receive a rotating refresh_token (90 days), so Claude, Cursor, Codex, and ChatGPT renew silently — no weekly re-login. Refreshing keeps the same key: the spend cap never resets. Manual Bearer keys have no refresh; issue a new one when they expire. An expired or revoked MCP key returns 401. Hitting the spend cap refuses send_message with spend_cap_reached; a single call priced above what is left of the cap is refused with estimate_exceeds_remaining.

Tools

Default tools only. Every tool advertises MCP annotations (title, readOnlyHint, destructiveHint, idempotentHint, openWorldHint) so clients can auto-allow reads. Tools are grouped by scope: models.read (catalog, pricing, cost estimates, docs), usage.read (balance, this key’s budget, your usage and requests, transactions, top-up link) and chat.completions (the one tool that spends credits). All three are granted by default; keys.read and billing.alerts are optional boxes on the Allow screen; a tool called without its scope answers HTTP 403 with the missing scope in WWW-Authenticate. Default chat model is qwen-3.6-plus. initialize and tools/list do not charge. max_cost_usd is a spend ceiling for one call, and it is enforced by turning money into tokens: Kyma prices your input from the live catalog, works out how many output tokens still fit under the ceiling, and sends that as max_tokens. The reply is cut at that length rather than allowed to run to the model’s own limit. If even a one-token reply is above the ceiling, the call is refused as estimate_exceeds_max and nothing is charged. Set your own max_tokens and it takes precedence, with the estimate priced against it. The ceiling binds the length, so the price follows the published rate for that length. What you are billed is what the upstream invoice says: for most models that is the catalog rate you were quoted, and for the few billed from an invoice rather than the rate card the settled cost can land a little either side. Every send_message is also checked against what this key has left in its 30-day cap. Above it, the call is refused as estimate_exceeds_remaining with the quote, whether or not you set a ceiling; that is a different answer from spend_cap_reached, which means the cap is already spent and nothing more goes out until the window resets. A model with no published price cannot be priced. Without max_cost_usd the call proceeds rather than being refused on a number nobody has; with max_cost_usd it is refused as unpriceable_model, because a ceiling that cannot be worked out cannot be held to. estimate_cost runs the same arithmetic on its own, so you can price a call without touching the spend tool. send_message also returns structuredContent: generation_id, model_requested, model_served, routes_tried (null where the path does not report it), cost_usd, cap_remaining_usd and max_tokens_sent. The same facts are in the text block. get_usage and get_request cover the whole account, every key and every client, not just this connection. get_spend is the per-connection number: the cap, spend and remaining budget of this MCP key alone. There are no keys.write, billing.write, or admin tools. Image and audio tools are not on this door yet.

Stdio clients: @kyma-api/mcp-server

For clients that can launch stdio servers but cannot speak Streamable HTTP, @kyma-api/mcp-server is a thin bridge to the same hosted URL (it runs mcp-remote against https://mcp.kymaapi.com/mcp). The tools are exactly the hosted ones, it needs network access to Kyma, and it has no API key of its own.
The first tool call opens a browser to sign in (OAuth 2.1 with PKCE). To run without a browser, for example in CI, create an MCP key on Integrations and pass it as KYMA_MCP_KEY:
KYMA_MCP_KEY must be an MCP key (km-…); the bridge exits with an error if it gets a REST API key (kyma-…). KYMA_API_KEY is not read. Extra arguments are passed through to mcp-remote.
Class onboarding is one URL: https://mcp.kymaapi.com/mcp. The live model list is GET /v1/models.

Install in Cursor

One click: Add to Cursor, or add {"mcpServers": {"kyma": {"url": "https://mcp.kymaapi.com/mcp"}}} to .cursor/mcp.json. The plugin bundle (Agent Plugins spec and Claude Code format) is open source at github.com/kyma-api/kyma-mcp-plugin.