Skip to content

Latest commit

 

History

History
167 lines (120 loc) · 4.72 KB

File metadata and controls

167 lines (120 loc) · 4.72 KB

Usage

HTTP mode

Start the gateway:

./arbitus gateway.yml
# or explicitly:
./arbitus start gateway.yml

Agents 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 gone

Rate-limit headers

Every tools/call response includes standard rate-limit headers:

X-RateLimit-Limit: 60
X-RateLimit-Remaining: 57
X-RateLimit-Reset: 42

When the limit is exceeded, the response also includes Retry-After:

HTTP/1.1 200 OK
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 38
Retry-After: 38

X-RateLimit-Reset and Retry-After are in seconds until the oldest request in the window ages out (max 60).

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:

# Approve
curl -X POST http://localhost:4000/approvals/appr-abc-123/approve \
  -H "Authorization: Bearer admin-secret"

# Reject with reason
curl -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

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

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-server

To sign a binary with cosign (keyless, via GitHub Actions OIDC):

cosign sign-blob --bundle server.bundle /usr/local/bin/mcp-server

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: endpoint
data: /mcp

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

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.