Documentation: all sections

MCP Gateway

The MCP server at POST /v1/mcp exposes Saxeo as tools. The MCP Gateway is the other direction: you register someone else's MCP server, and Saxeo hands you a proxy URL that governs, meters, and receipts every tool call your agent makes through it.

It is a tool firewall with a ledger. An agent pointed at the proxy URL can only call the tools you allowed, spends against a budget you set, and leaves a signed record of every call it made.

What it does, and what it does not

Every tools/call through the proxy is:

  1. Allowlist-checked before the upstream is dialed. A refused tool never reaches the third-party server — the refusal is a 403 with policy_denied, decided at the gateway.
  2. Metered. One mcp_call usage event per call, debited at the server's per-call price. It counts against the key's spend cap, its circuit breaker, and any mandate it was minted under, because it goes through the same billing path as everything else.
  3. Receipted. A signed, metadata-only receipt of kind mcp_call carrying the tool name, a sha256 fingerprint of the arguments, a fingerprint of the result, the latency, and the policy stamp — verifiable through the public POST /v1/receipts/verify.

What it is not: Saxeo governs and receipts the call. It does not sandbox the upstream server, cannot see what that server does with the arguments once they arrive, and cannot verify that its result is correct. The proof it gives you is "this tool was called with these arguments, under these rules, and cost this much" — not "the tool behaved."

Register a server

Registration is session-authed (it stores a credential). The auth_header you give is the header the upstream wants, and is AES-GCM sealed at rest — Saxeo opens it only at dial time, never logs it, and destroys it when you deregister.

curl https://www.saxeonetwork.tech/__api/v1/mcp-servers \
-H "authorization: Bearer $SAXEO_SESSION" \
-H 'content-type: application/json' \
-d '{
  "name": "github-tools",
  "url": "https://example.com/mcp",
  "auth_header": "Bearer ghp_your_upstream_token",
  "allowed_tools": ["search_issues", "read_file"],
  "price_micro_usd_per_call": 200
}'

The response carries a proxy_url:

{
  "id": "mcp_9f2c…",
  "name": "github-tools",
  "allowed_tools": ["search_issues", "read_file"],
  "price_micro_usd_per_call": 200,
  "enabled": true,
  "proxy_url": "https://www.saxeonetwork.tech/__api/v1/mcp/servers/mcp_9f2c…"
}

Omit allowed_tools and every tool the upstream lists is permitted — the allowlist is the point of the feature, so set one. price_micro_usd_per_call defaults to the deployment's SAXEO_MCP_PROXY_MICRO_USD_PER_CALL (100 µ$ = $0.0001) and can only be raised above it, so an expensive upstream tool shows up honestly in budgets.

Check it works before pointing an agent at it — POST /v1/mcp-servers/:id/test runs initialize + tools/list against the upstream and returns the tool names it advertises, plus which of them your allowlist permits.

Connect an agent

The proxy path is API-key authed, not session-authed. That is deliberate: it is what puts every call under a specific sk-sable_ key's budget, policy, circuit breaker, and the account kill switch.

claude mcp add --transport http sable-github \
https://www.saxeonetwork.tech/__api/v1/mcp/servers/mcp_9f2c… \
--header "authorization: Bearer $SAXEO_API_KEY"

tools/list through the proxy is filtered to the effective allowlist, so an agent never even sees a tool it may not call.

Two allowlists, intersected

A call is permitted only if the tool is in both:

not setKey policy allowed_toolsnot setEffectiveevery tool the upstream lists
[a, b]Key policy allowed_toolsnot setEffective[a, b]
not setKey policy allowed_tools[b, c]Effective[b, c]
[a, b]Key policy allowed_tools[b, c]Effective[b]
[a]Key policy allowed_tools[c]Effectivenothing — every call refused

A policy with no allowed_tools rule (only a token ceiling, say) contributes nothing: a policy about token limits must not silently become an empty tool list.

The receipt

{
  "v": 1,
  "kind": "mcp_call",
  "request_id": "mcp_5c1b…",
  "server_id": "mcp_9f2c…",
  "tool": "search_issues",
  "unit": "calls",
  "quantity": 1,
  "status": "ok",
  "is_error": false,
  "latency_ms": 412,
  "cost_micro_usd": 200,
  "actions": {
    "count": 1,
    "root": "3f9a…",
    "calls": [{ "tool": "search_issues", "args_fp": "8c21…", "args_len": 48 }]
  },
  "result_fp": "a70e…",
  "result_len": 1264,
  "policy": { "id": "pol_…", "sha256": "…" },
  "node_id": "gateway",
  "created_at": "2026-09-04T10:31:02Z"
}

It comes back three ways: the x-sable-receipt, x-sable-receipt-sig and x-sable-receipt-signer response headers, and inside the JSON-RPC result at result._meta.sable_receipt.

actions is the same action attestation shape the chat path uses — the tool name plus a sha256 prefix of name|arguments. Anyone holding the same arguments recomputes the fingerprint; nobody holding only the receipt can recover them. result_fp does the same for what came back. Tag a call into an agent run by putting sable_run_id in the request's params._meta; Saxeo strips it before forwarding.

Metering and status

status on the usage event and the receipt is one of:

okMeaningThe upstream returned a result.Billedyes
tool_errorMeaningThe upstream returned a result with isError: true — the tool ran and failed.Billedyes
upstream_errorMeaningThe upstream returned a JSON-RPC error object.Billedyes
errorMeaningSaxeo could not reach the upstream, it timed out, or its answer was unusable.Billedno

The first three are billed because the upstream did the work; a transport failure is recorded at zero cost so the attempt is visible without charging for it.

Methods

tools/callBehaviorAllowlist-checked, metered, receipted.
tools/listBehaviorForwarded unmetered; the result is filtered to the effective allowlist.
initialize, ping, notifications/*, prompts/list, prompts/get, resources/list, resources/read, resources/templates/listBehaviorForwarded unmetered.
everything else (sampling/*, roots/*, elicitation/*, logging/*, completion/*)BehaviorRefused with JSON-RPC -32601.

The proxy governs tool calls; forwarding the rest blind would be a different, ungoverned product.

Limits and honest caveats

Endpoints

POSTPath/v1/mcp-serversAuthsession
GETPath/v1/mcp-serversAuthsession
PATCHPath/v1/mcp-servers/:idAuthsession
DELETEPath/v1/mcp-servers/:idAuthsession
POSTPath/v1/mcp-servers/:id/testAuthsession
POSTPath/v1/mcp/servers/:idAuthsk-sable_ key

Manage them in the portal at Portal → MCP Gateway.