HTTP API reference¶
Every HTTP route mcp-test exposes, beyond the MCP transport itself.
Public routes¶
These are reachable without auth.
| Method | Path | Returns |
|---|---|---|
GET |
/healthz |
200 OK text body. Liveness. |
GET |
/readyz |
200 OK while ready, 503 during shutdown drain. |
GET |
/.well-known/oauth-protected-resource |
RFC 9728 metadata: resource identifier, authorization servers, supported bearer methods. |
GET |
/.well-known/oauth-authorization-server |
Lightweight stub pointing at the upstream OIDC issuer's metadata URL. |
GET |
/portal/ and subpaths |
The embedded React SPA (or a placeholder if make ui wasn't run). |
GET |
/portal/auth/login |
Starts the OIDC PKCE flow. Redirects to the IdP. |
GET |
/portal/auth/callback |
OIDC redirect URI. Exchanges the auth code for tokens, validates the id_token, sets the session cookie. |
POST |
/portal/auth/logout |
Clears the session cookie. |
MCP endpoint¶
Mounted at /. Browser GETs hitting / get a 302 to /portal/; MCP
clients (which send Accept: application/json or
text/event-stream) pass through.
| Method | Path | Returns |
|---|---|---|
POST |
/ |
JSON-RPC requests (initialize, tools/list, tools/call, etc.). |
GET |
/ |
SSE stream for server-initiated messages (after a session is established). |
DELETE |
/ |
Tear down the MCP session. |
All require X-API-Key or Authorization: Bearer <jwt> unless
auth.allow_anonymous is true. 401s carry a WWW-Authenticate: Bearer
realm="mcp-test", resource_metadata="..." header.
Portal API (read-only)¶
Behind the cookie or X-API-Key / Authorization: Bearer.
| Method | Path | Returns |
|---|---|---|
GET |
/api/v1/portal/me |
Resolved Identity object. |
GET |
/api/v1/portal/server |
Build version + sanitized config (secrets redacted). |
GET |
/api/v1/portal/instructions |
The server.instructions text the MCP server hands to clients at initialize time. |
GET |
/api/v1/portal/tools |
List of {name, group, description, input_schema} for every registered tool. |
GET |
/api/v1/portal/tools/{name} |
Same shape, single tool. |
GET |
/api/v1/portal/audit/events |
Paginated audit events. Query: from, to (RFC 3339), tool, user, session, success, q, limit, offset. |
GET |
/api/v1/portal/audit/timeseries |
Bucketed counts. Query: from, to, bucket (Go duration). |
GET |
/api/v1/portal/audit/breakdown |
Group-by aggregations. Query: by (tool/user/success/auth_type). |
GET |
/api/v1/portal/dashboard |
1-hour stats + recent activity. |
GET |
/api/v1/portal/wellknown |
Pretty rendering of the protected-resource metadata. |
Admin API (mutating)¶
Same auth requirements. Per the project decision, any authenticated caller can call these.
| Method | Path | Body | Returns |
|---|---|---|---|
POST |
/api/v1/admin/keys |
{ "name": "...", "description": "..." } |
{ "key": {...}, "plaintext": "mt_..." } (plaintext shown once). |
GET |
/api/v1/admin/keys |
— | { "keys": [...] } (no plaintext). |
DELETE |
/api/v1/admin/keys/{name} |
— | 204 No Content. |
POST |
/api/v1/admin/tryit/{name} |
{ "arguments": { ... } } |
The MCP CallToolResult (content + structuredContent + isError). |
/api/v1/admin/tryit/{name} invokes the named tool through an
in-process MCP client connected to the running server. It writes its
own audit row tagged source=portal-tryit with the portal-
authenticated identity.
Errors¶
All API endpoints return JSON errors:
Standard HTTP codes:
400— malformed body.401— missing or invalid credentials.404— unknown tool / key / resource.503— feature not enabled (e.g. DB API keys whenapi_keys.db.enabledis false).500— unexpected server error.
CORS¶
The mux wraps everything in a permissive CORS handler that:
- Allows any origin (
*). - Allows
GET, POST, DELETE, OPTIONS. - Round-trips
Authorization,Content-Type,X-API-Key,Mcp-Session-Id,Mcp-Protocol-Version,Last-Event-ID. - Exposes
Mcp-Session-Id,Mcp-Protocol-Version.
Tighten this in production by terminating CORS at your ingress.