LAYER 3 · THE MCP GATEWAY
Gateway reference
Endpoints, the call-log row schema, gateway status codes, and the two knobs that tune the hot path.
Endpoints
| Endpoint | Auth | What it does |
|---|---|---|
ANY /proxy/{server}/{path} | Agent token | The data path. All HTTP methods (GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS) forward to the registered upstream after identity, revocation, and policy checks. Agent tokens only — org API keys and user sessions are not valid here. |
POST /mcp-servers | security role | Register an upstream: {"name", "upstream_url"}. Upsert on name — re-posting updates the upstream. Returns the proxy_path. |
GET /mcp-servers | viewer role | List the org's registered servers with upstream URLs and creation dates. |
GET /mcp-calls | viewer role | Durable call history, newest first. Filters: agent_id, would_block, status; paging via limit (default 100, max 1000) and offset. |
GET /mcp-calls/export.csv | viewer role | SIEM-ready CSV of the last days days (default 30). Same fields as the API minus raw params. |
GET /cimd/{agent_id}.json | public | The agent's resolvable identity document — name, owner, environment, risk level, status, allowed servers. Metadata only, never secrets; unknown ids get an indistinguishable 404. |
WS /ws/calls?key=… | org API key only | Live call feed, events pushed under a second after logging. Auth is the API key as a query param (browsers cannot set WS headers); a wrong key closes with code 4401. Lossy tail: slow consumers drop oldest events. |
Call-log row fields
| Field | Type | Meaning |
|---|---|---|
agent_id | text | The verified layer-1 identity that made the call. |
mcp_server | text | The registered server name from the proxy path. |
tool_name | text | Tool from JSON-RPC tools/call; otherwise the RPC method or request path. |
params | jsonb | The tool arguments as sent. API only — excluded from the CSV export. |
duration_ms | integer | Upstream round-trip time; 0 for calls that never reached the upstream. |
status | permitted | blocked | error | What happened. blocked is written only by layer-4 enforcement; error covers unreachable upstreams and 5xx responses. |
would_block | boolean | True when the policy verdict was deny — regardless of whether it was enforced. The enforcement dress-rehearsal flag. |
blast_radius | numeric(3,2) | The policy engine's 0–1 risk score for this server + tool, when defined. |
violation_reason | text | The rule and reason behind a denied verdict; null on clean passes. |
Every row also carries its own id, an org scope, and a timestamp set when the call is logged.
Gateway status codes
| Status | Cause |
|---|---|
401 | Missing bearer token, invalid signature, revoked/rotated token, or an unknown agent. Also what a user-session token gets — only agent tokens work at the proxy. |
404 | The server name in the path is not registered for the agent's org. |
502 | Upstream unreachable — logged as status=error with the reason. |
Observe mode never returns
403. That code — a machine-readable blocked_by_sentnelops refusal — arrives only when layer 4 enforcement or approvals are switched on, using layer-2 policy verdicts unchanged.Configuration
| Setting (env var) | Default | Effect |
|---|---|---|
SNOPS_PROXY_IDENTITY_TTL_SECONDS | 5.0 | TTL for both hot-path caches (identity+upstream resolution, token revocation). It is the staleness bound: a revocation or suspension takes effect within this many seconds. 0 disables caching — every call pays a database round trip. |
SNOPS_RATE_LIMIT_PER_MINUTE | 600 | Per-key fixed-window limit (60 s window), applied API-wide including the proxy. Keyed by credential hash — floods with invalid keys are rejected before any database lookup. |
Operational behavior when the gateway itself degrades — fail-open logging, feed loss, deploy shape — is covered in Trust & reliability.