Register an MCP endpoint
const url = 'https://example.com/v1/mcp/endpoints';const options = { method: 'POST', headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'}, body: '{"endpointId":"example","name":"example","transport":"stdio","config":{"transport":"stdio","command":"example","args":["example"],"env":{"additionalProperty":"example"}},"secretRef":{"envName":"example","name":"example"},"auth":{"scheme":"basic","username":"example","secretRef":{"envName":"example","name":"example"}},"instructions":"example","metadata":{},"sendTraceparent":true,"scopeKind":"tenant","scopeId":"example"}'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request POST \ --url https://example.com/v1/mcp/endpoints \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data '{ "endpointId": "example", "name": "example", "transport": "stdio", "config": { "transport": "stdio", "command": "example", "args": [ "example" ], "env": { "additionalProperty": "example" } }, "secretRef": { "envName": "example", "name": "example" }, "auth": { "scheme": "basic", "username": "example", "secretRef": { "envName": "example", "name": "example" } }, "instructions": "example", "metadata": {}, "sendTraceparent": true, "scopeKind": "tenant", "scopeId": "example" }'Body is a full MCPEndpoint plus the scope to register it in (scopeKind + scopeId); authorization checks that scope. Server validates the closed transport enum + the config.transport matches transport guardrail + per-variant required fields (command for stdio; url for http-sse / streamable-http), and refuses unknown fields. secretRef names a secret in the deployment’s store — plaintext secrets never cross the wire — and never a model provider’s key (400 provider-key-refused). Where each secret it names is read is recorded on it now (secretScopes): the first of its own scope, its project’s org and the tenant that has the secret and that the caller administers, else the broadest they administer; the runtime reads it there only. A deployment with KINDGI_TENANT_HOST_ACCESS=deployed (the default outside development) refuses a stdio endpoint, which would run a command on the server’s host: 403 host-access-denied.
Authorizations
Section titled “Authorizations”Parameters
Section titled “Parameters”Header Parameters
Section titled “Header Parameters”Caller-supplied idempotency key, scoped to the caller: the same key from someone else in the tenant is their own request (from 0.1.5). Retries with the same key return the original response byte-identical (per docs/API-ROUTE-CONVENTIONS.md §3.1). A retry sent while the first request still runs is answered 409 idempotency-key-in-flight with Retry-After, on a runtime whose store holds keys (from 0.1.5); retry after it, and you get the first request’s answer. An answer that carries a secret (a new API key or public run token, a session token, a generated signing secret) isn’t kept: a retry gets 409 idempotency-key-replay-withheld, with the first request’s status and when it succeeded (from 0.1.5).
Request Bodyrequired
Section titled “Request Bodyrequired”object
No .: an MCP tool’s id is <endpointId>.<tool name>, so it splits at its first .. An endpoint registered with one before keeps it.
Human-readable display name.
MCP transport variant. stdio — local subprocess (spawn a command). http-sse — the older MCP HTTP+SSE transport (separate POST + SSE endpoints). streamable-http — the Streamable HTTP transport (single endpoint, session id via header).
object
object
object
Optional distinct SSE endpoint if the server splits them.
Headers sent with every request, as given. Not for a credential: a header named Authorization, Proxy-Authorization or Cookie, or with a -/_-separated part token, secret, password, passwd, apikey, credential, credentials, signature, session, auth, authorization or authentication, or the parts api-key, access-key, private-key, auth-key, subscription-key, functions-key, application-key, app-key, master-key, client-key or partner-key (X-Api-Key, X-Auth-Token), is refused (invalid-mcp-endpoint, reason credential-in-headers). Send it by reference: auth with scheme: header, or secretRef for a bearer. An endpoint registered with one before keeps working, and its value reads back as [redacted].
object
object
Headers sent with every request, as given. Not for a credential: a header named Authorization, Proxy-Authorization or Cookie, or with a -/_-separated part token, secret, password, passwd, apikey, credential, credentials, signature, session, auth, authorization or authentication, or the parts api-key, access-key, private-key, auth-key, subscription-key, functions-key, application-key, app-key, master-key, client-key or partner-key (X-Api-Key, X-Auth-Token), is refused (invalid-mcp-endpoint, reason credential-in-headers). Send it by reference: auth with scheme: header, or secretRef for a bearer. An endpoint registered with one before keeps working, and its value reads back as [redacted].
object
The secret an MCP endpoint authenticates with: a name in the deployment’s secrets store, resolved at the endpoint’s tenant scope by the runtime (the shape webhooks and providers use). As the endpoint’s own secretRef, it is sent as its bearer; inside auth, it is the scheme’s password, client secret or header value. The endpoint keeps only this reference.
object
HTTP Basic: the runtime sends Authorization: Basic base64(<username>:<secret>), with the secret secretRef names (a WordPress Application Password, for one).
object
The user name. Not a secret, and without :.
The secret an MCP endpoint authenticates with: a name in the deployment’s secrets store, resolved at the endpoint’s tenant scope by the runtime (the shape webhooks and providers use). As the endpoint’s own secretRef, it is sent as its bearer; inside auth, it is the scheme’s password, client secret or header value. The endpoint keeps only this reference.
object
OAuth 2 client credentials: the runtime asks tokenUrl for an access token (grant_type=client_credentials) as clientId, with the client secret secretRef names, sends it as the endpoint’s bearer, and asks for a new one before it expires (Drupal’s Simple OAuth, for one). The token is never stored.
object
The token endpoint: https, or http to a loopback host (localhost, 127.0.0.1, [::1]).
The secret an MCP endpoint authenticates with: a name in the deployment’s secrets store, resolved at the endpoint’s tenant scope by the runtime (the shape webhooks and providers use). As the endpoint’s own secretRef, it is sent as its bearer; inside auth, it is the scheme’s password, client secret or header value. The endpoint keeps only this reference.
object
The scopes to ask for, space-separated, sent as-is. Absent: none asked for.
An audience parameter, for identity providers that need one. Absent: none sent.
How the client authenticates to the token endpoint (RFC 6749 §2.3.1): client_secret_basic (an Authorization: Basic header, the default) or client_secret_post (client_id and client_secret in the form).
Headers of the server’s own, each with a secret: an API key in X-Api-Key, a key and a secret in two headers, or Authorization with a prefix other than Bearer (Token …). The runtime resolves each secretRef when it connects, and refuses to follow a redirect with them, as it does for every auth.
object
One header a header auth sends: <name>: <prefix><secret>.
object
An HTTP header name, once per auth (case-insensitive). Not one the MCP transport or HTTP sets itself (Host, Content-Type, Content-Length, Accept, Connection, Mcp-Session-Id, Mcp-Protocol-Version, Last-Event-ID, traceparent, tracestate, …): reason invalid-auth.
The secret an MCP endpoint authenticates with: a name in the deployment’s secrets store, resolved at the endpoint’s tenant scope by the runtime (the shape webhooks and providers use). As the endpoint’s own secretRef, it is sent as its bearer; inside auth, it is the scheme’s password, client secret or header value. The endpoint keeps only this reference.
object
Text sent before the secret, such as Token or ApiKey , without control characters. Absent: none. Not a secret: it reads back as registered.
Optional pass-through to the MCP client serverInfo.instructions.
Optional caller-defined metadata bag.
object
Send the W3C traceparent of the run calling a tool to this endpoint, as a request header, so the server’s logs can be matched to the run. Ids only, never content. Default false. HTTP transports only: true on a stdio endpoint is refused (invalid-mcp-endpoint, reason invalid-send-traceparent). An older runtime ignores it and sends none.
Discriminator for the ?scopeKind + ?scopeId + ?inherit triplet. Tenant carries no id (implicit from session); org/project require scopeId.
Required when scopeKind is org or project; absent for tenant (implicit from the session).
Responses
Section titled “Responses”MCP endpoint registered.
object
Examplegenerated
{ "endpointId": "example"}Validation failed (see details.reason). Or provider-key-refused: secretRef names a model provider’s key (details.secret, details.providerId).
object
object
Stable machine-readable discriminant. Values match domain error codes (see docs/API-ROUTE-CONVENTIONS.md §4.3).
Optional, kind-specific.
object
Server-assigned request id; also echoed via X-Request-Id header.
Examplegenerated
{ "error": { "code": "example", "message": "example", "details": {}, "requestId": "example" }}Missing / malformed / expired / revoked bearer token.
object
object
Stable machine-readable discriminant. Values match domain error codes (see docs/API-ROUTE-CONVENTIONS.md §4.3).
Optional, kind-specific.
object
Server-assigned request id; also echoed via X-Request-Id header.
Examplegenerated
{ "error": { "code": "example", "message": "example", "details": {}, "requestId": "example" }}host-access-denied: a stdio endpoint on a deployment that refuses commands on its host (KINDGI_TENANT_HOST_ACCESS=deployed or isolated); or authz-denied.
object
object
Stable machine-readable discriminant. Values match domain error codes (see docs/API-ROUTE-CONVENTIONS.md §4.3).
Optional, kind-specific.
object
Server-assigned request id; also echoed via X-Request-Id header.
Examplegenerated
{ "error": { "code": "example", "message": "example", "details": {}, "requestId": "example" }}MCP endpoint already registered at that id. Or env-not-served: this runtime keeps every value under the env it serves (whoami’s servedEnv, with refusesOtherEnvs), and the secret reference names another. Name it under details.servedEnv. Nothing is stored.
object
object
Stable machine-readable discriminant. Values match domain error codes (see docs/API-ROUTE-CONVENTIONS.md §4.3).
Optional, kind-specific.
object
Server-assigned request id; also echoed via X-Request-Id header.
Examplegenerated
{ "error": { "code": "example", "message": "example", "details": {}, "requestId": "example" }}The request body is over the API’s limit (request-too-large; details.maxBytes says how much).
object
object
Stable machine-readable discriminant. Values match domain error codes (see docs/API-ROUTE-CONVENTIONS.md §4.3).
Optional, kind-specific.
object
Server-assigned request id; also echoed via X-Request-Id header.
Examplegenerated
{ "error": { "code": "example", "message": "example", "details": {}, "requestId": "example" }}rate-limit-exceeded with details.limit: "schema-compile-time", on a server with a compile budget (Kindgi Cloud): this tenant’s schemas spent details.budgetMs compiling in the last 60 seconds. Nothing was stored; Retry-After says when to send it again.
object
object
Stable machine-readable discriminant. Values match domain error codes (see docs/API-ROUTE-CONVENTIONS.md §4.3).
Optional, kind-specific.
object
Server-assigned request id; also echoed via X-Request-Id header.
Examplegenerated
{ "error": { "code": "example", "message": "example", "details": {}, "requestId": "example" }}Server error (unmapped domain code or framework crash).
object
object
Stable machine-readable discriminant. Values match domain error codes (see docs/API-ROUTE-CONVENTIONS.md §4.3).
Optional, kind-specific.
object
Server-assigned request id; also echoed via X-Request-Id header.
Examplegenerated
{ "error": { "code": "example", "message": "example", "details": {}, "requestId": "example" }}See also
GET /v1/mcp/endpoints: List MCP endpointsGET /v1/mcp/endpoints/{endpointId}: Fetch an MCP endpointPOST /v1/mcp/endpoints/{endpointId}/unregister: Unregister an MCP endpointGET /v1/mcp/endpoints/{endpointId}/resources: List resources at a remote MCP endpoint- Kindgi 0.1.9
- Error code
authz-denied - Error code
env-not-served - Error code
host-access-denied - Error code
provider-key-refused - Error code
rate-limit-exceeded - Error code
request-too-large - Every error code