Usage
HTTP mode
Section titled “HTTP mode”Start the gateway:
./arbitus gateway.yml# or explicitly:./arbitus start gateway.ymlAgents connect to http://localhost:4000/mcp. The gateway forwards allowed requests to the upstream MCP server.
Session management follows the MCP spec: the gateway assigns a Mcp-Session-Id on initialize and uses it to identify the agent on subsequent requests. Requests with a missing or expired session ID receive 404.
To explicitly end a session, send DELETE /mcp with the session header:
curl -X DELETE http://localhost:4000/mcp -H "Mcp-Session-Id: <id>"# 204 No Content on success, 404 if the session is already goneRate-limit headers
Section titled “Rate-limit headers”Every tools/call response includes standard rate-limit headers:
X-RateLimit-Limit: 60X-RateLimit-Remaining: 57X-RateLimit-Reset: 42When the limit is exceeded, the response also includes Retry-After:
HTTP/1.1 200 OKX-RateLimit-Limit: 60X-RateLimit-Remaining: 0X-RateLimit-Reset: 38Retry-After: 38X-RateLimit-Reset and Retry-After are in seconds until the oldest request in the window ages out (max 60).
Human-in-the-Loop (HITL)
Section titled “Human-in-the-Loop (HITL)”Tools listed in approval_required are suspended until an operator takes action. The gateway holds the request open and waits up to hitl_timeout_secs (default: 60) before auto-rejecting.
List pending approvals:
curl http://localhost:4000/approvals \ -H "Authorization: Bearer admin-secret"[ { "id": "appr-abc-123", "agent_id": "cursor", "tool_name": "delete_file", "arguments": {"path": "/data/important.db"}, "created_at": 1743375600 }]Approve or reject:
# Approvecurl -X POST http://localhost:4000/approvals/appr-abc-123/approve \ -H "Authorization: Bearer admin-secret"
# Reject with reasoncurl -X POST http://localhost:4000/approvals/appr-abc-123/reject \ -H "Authorization: Bearer admin-secret" \ -H "Content-Type: application/json" \ -d '{"reason": "not authorized during off-hours"}'Both endpoints return 204 No Content on success, 404 if the approval ID is unknown or already resolved.
Shadow mode
Section titled “Shadow mode”Tools listed in shadow_tools are intercepted after all middleware passes. The gateway logs them as shadowed, returns a mock success response to the agent, and does not forward the call to the upstream server.
This is useful for observing what a new agent would do with dangerous tools before granting real access.
agents: new-agent: shadow_tools: - delete_file - "exec_*"The agent receives:
{ "jsonrpc": "2.0", "id": 1, "result": { "content": [{"type": "text", "text": "[shadow] call intercepted — not forwarded to upstream"}] }}Shadowed calls appear in the audit log with outcome: shadowed.
Supply-chain security
Section titled “Supply-chain security”When using stdio transport, verify the MCP server binary before spawning it:
transport: type: stdio server: ["/usr/local/bin/mcp-server", "--data-dir", "/data"] verify: sha256: "e3b0c44298fc1c149afbf4c8996fb924..." # hex SHA-256 of the binary cosign_bundle: "/etc/mcp/server.bundle" # cosign bundle produced by `cosign sign-blob` cosign_identity: "ci@example.com" # expected signer identity (keyless) cosign_issuer: "https://token.actions.githubusercontent.com"Both sha256 and cosign_bundle are optional and independent — configure one or both. If either check fails, the gateway aborts at startup before spawning the process.
To generate a sha256 for your binary:
sha256sum /usr/local/bin/mcp-serverTo sign a binary with cosign (keyless, via GitHub Actions OIDC):
cosign sign-blob --bundle server.bundle /usr/local/bin/mcp-serverSSE streaming
Section titled “SSE streaming”Once a session is established, open a server-sent event stream to receive server-pushed notifications:
curl -N http://localhost:4000/mcp \ -H "Accept: text/event-stream" \ -H "Mcp-Session-Id: <id>"The gateway proxies the upstream SSE stream and applies block_patterns to each event before forwarding it to the client.
Without a session, GET /mcp returns an endpoint event (legacy HTTP+SSE transport):
event: endpointdata: /mcpOpenAI Tools Bridge
Section titled “OpenAI Tools Bridge”GET /openai/v1/tools and POST /openai/v1/execute let OpenAI function-calling clients use arbitus without refactoring. All requests still pass through the full security pipeline (auth, rate limiting, payload filtering, audit).
Tool Federation
Section titled “Tool Federation”Agents with federate: true aggregate tools from all named upstreams into a single merged view. Colliding tool names are prefixed with <upstream>__. tools/call is transparently routed to the correct upstream. Discovery has a 10-second global timeout to prevent slow upstreams from stalling the gateway.