MCP endpoint
The MCP endpoint is where MCP clients (Claude Code, Cursor, Claude.ai, ChatGPT and your own code) list and call Mandatum's tools. It speaks the MCP Streamable HTTP transport, and it is sessionless: every request stands alone.
For the tools themselves, read the tool catalogue. For tokens and scopes, read Authentication. For the REST equivalent, read the REST API.
Endpoint #
POST https://mandatum.intergentech.ai/api/mcp
The transport is WebStandardStreamableHTTPServerTransport, sessionless, answering with JSON (enableJsonResponse: true). The protocol revisions it accepts are listed under Protocol revisions.
Authentication #
Every request must include a valid Authorization: Bearer <token> header. Tokens are either:
- Mandatum API keys (
mdt_live_…ormdt_test_…), or - OAuth 2.1 access tokens issued through
/api/oauth/token.
Every request is authenticated and authorised before any MCP method runs. A request that fails the check never reaches a tool.
WWW-Authenticate header cases #
Case 1: missing or invalid Authorization header #
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer resource_metadata="https://<APP_URL>/.well-known/oauth-protected-resource"The <APP_URL> comes from the server's configuration, never from the request Host header, so a caller cannot change the address advertised. This is the discovery challenge that connected apps follow to start OAuth.
Case 2: authenticated but insufficient scope #
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer error="insufficient_scope", scope="<required-scope>"This case carries no resource_metadata parameter. It tells the client which scope to request.
Case 3: other authentication failures #
HTTP/1.1 401 Unauthorized
Content-Type: application/jsonNo WWW-Authenticate header is sent, and no resource_metadata either.
Methods #
| HTTP method | Behaviour |
|---|---|
POST |
JSON-RPC 2.0 requests. This is where every MCP method is handled. |
DELETE |
Accepted as a no-op session terminate. It is still authenticated. |
GET |
405 Method Not Allowed with Allow: POST, DELETE. The check runs first, so an unauthenticated GET still gets the 401 discovery challenge. The endpoint never serves a standalone event stream, and a refused GET writes no audit or usage row. |
The JSON-RPC methods the server answers:
| Method | Description |
|---|---|
initialize |
Negotiates the protocol revision (see below). |
tools/list |
Returns the tools the caller's scopes permit. Filtered on every request. |
tools/call |
Runs one tool from the catalogue. The scope check runs again before the call. |
Per-request tool filtering #
tools/list shows only the tools the token's scopes unlock. A key with citation:verify and nothing else sees the three citation tools and no others. A tools/call for a tool outside those scopes is refused with a scope error, even if a client names the tool directly. The check is the same in both places, so a client cannot widen its access by asking.
Tool annotations #
Every tool in tools/list carries MCP annotations: readOnlyHint, idempotentHint, destructiveHint and openWorldHint. The values for each tool are in the tool catalogue. Annotations are hints for the client. Do not rely on them for a security decision; the server enforces scopes whatever the client does with them.
Protocol revisions #
The MCP-Protocol-Version header is checked against the revisions the endpoint supports. A present but unlisted version gets 400. A missing header is accepted.
| Revision | Accepted in header | initialize answers with |
Notes |
|---|---|---|---|
2026-07-28 |
Only on initialize. Other requests carrying it get 400 from the transport's version check. |
2025-11-25 |
The modern, per-request _meta era. The endpoint's pinned SDK does not implement it, so clients that send _meta without initialize are not served, and server/discover is not implemented. |
2025-11-25 |
Yes | 2025-11-25 |
Current legacy revision. |
2025-06-18 |
Yes | 2025-06-18 |
Legacy. The revision the endpoint was built against. |
2025-03-26 |
Yes | 2025-03-26 |
Legacy. The default when the header is absent. |
2024-11-05, 2024-10-07 |
Yes | The same revision | Legacy. |
The endpoint is initialise-based. A client that supports both eras falls back to initialize and negotiates 2025-11-25. The endpoint is not a dual-era server. The table is checked by the protocol-revision integration test in the repository.
Stateless transport #
No session is created, and no state is kept between requests. Each request builds a fresh MCP server and transport, handles the request, and closes them when it finishes. Concurrent requests never share a transport, so one client's request cannot close another's.
Origin validation #
The endpoint validates the Origin header, which blocks DNS-rebinding attacks from a web page.
No token forwarding #
The endpoint never forwards the caller's token to any other service. Outbound calls use the server's own credentials, limited to what the call needs.
Connecting a client #
The connect guides show the configuration for Claude Code, Cursor, Claude.ai and ChatGPT. For a key-based client, send the key as the bearer token. For a connected app, the client runs the OAuth flow described in Authentication.