MCP Gateway
Run Veto as a managed or self-hosted MCP policy gateway.
Veto MCP Gateway lets you enforce Veto policies on MCP tools/call traffic while preserving normal MCP JSON-RPC behavior.
Architecture
Veto MCP Gateway has two launch paths:
- Managed gateway in
veto-server:- Configure upstreams in the dashboard.
- Call
POST /v1/mcp/:slug(and optionalGET /v1/mcp/:slugSSE stream). - Data path auth uses your Veto API key.
- Self-hosted gateway in CLI:
- Run
veto mcp serve. - Route MCP requests to configured upstreams from
veto/mcp.config.yaml. - Supports
mcp-sseandmcp-stdio.
- Run
Policy decisions map to JSON-RPC responses:
allow: upstream call is forwarded.deny: JSON-RPC error-32001.require_approval: JSON-RPC error-32002.
Self-hosted quickstart
Initialize config:
veto mcp initGenerated file:
listen:
host: 127.0.0.1
port: 8799
policy:
serverUrl: http://localhost:3001
apiKey: veto_replace_me
upstreams:
- name: default
transport: mcp-sse
url: http://localhost:3000/mcp
timeoutMs: 30000Run diagnostics:
veto mcp doctor
veto mcp doctor --jsonStart gateway:
veto mcp serve --config ./veto/mcp.config.yamlYou can also run without a config file for simple SSE setups:
veto mcp serve \
--upstream http://localhost:3000/mcp \
--api-key veto_xxx \
--policy-server http://localhost:3001Managed quickstart
- Open dashboard settings and go to MCP Gateway.
- Add an upstream slug and transport (
mcp-ssein managed mode). - Test connectivity from the UI.
- Send MCP JSON-RPC to:
curl -X POST https://api.veto.so/v1/mcp/default \
-H 'X-Veto-API-Key: veto_xxx' \
-H 'content-type: application/json' \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'Native Charter MCP
Veto also exposes Charter as a native MCP JSON-RPC surface. This is not an upstream proxy; it is Veto Cloud's own policy agent for Claude Code, Cursor, and other MCP-capable agents.
Endpoint:
POST https://api.veto.so/v1/mcp/charterList tools:
curl -X POST https://api.veto.so/v1/mcp/charter \
-H 'X-Veto-API-Key: veto_xxx' \
-H 'content-type: application/json' \
-d '{"jsonrpc":"2.0","id":"tools","method":"tools/list"}'Available tools:
veto_charter_turn, run a Charter turn withmode: auto | chat | compileveto_charter_chat, ask grounded questions about registered tools, policies, and runtime contextveto_charter_compile, draft policies and return Veto verification links before anything goes liveveto_list_tools, list the tools Charter can compile againstveto_register_tools, register an agent's callable tools before Charter compiles policies
Register the tools your agent can call, then compile against that exact inventory:
curl -X POST https://api.veto.so/v1/mcp/charter \
-H 'X-Veto-API-Key: veto_xxx' \
-H 'content-type: application/json' \
-d '{
"jsonrpc": "2.0",
"id": "register-tools",
"method": "tools/call",
"params": {
"name": "veto_register_tools",
"arguments": {
"tools": [
{
"name": "issue_refund",
"description": "Issue a customer refund",
"parameters": [
{ "name": "amount_usd", "type": "number", "required": true },
{ "name": "ticket_age_days", "type": "number", "required": true }
]
}
]
}
}
}'Example compile call:
curl -X POST https://api.veto.so/v1/mcp/charter \
-H 'X-Veto-API-Key: veto_xxx' \
-H 'content-type: application/json' \
-d '{
"jsonrpc": "2.0",
"id": "compile-refunds",
"method": "tools/call",
"params": {
"name": "veto_charter_compile",
"arguments": {
"message": "Refunds over $200 require support lead approval."
}
}
}'Policy-changing responses include structuredContent.verification. A policy draft is not live until the returned Veto verification link is approved.
Operational smoke check:
VETO_API_KEY=veto_xxx node ops/smoke/charter-agent-surfaces.mjsBy default, the script verifies read-only Charter MCP discovery. Set VETO_CHARTER_SMOKE_WRITE=1 to also register a probe tool, and VETO_CHARTER_SMOKE_COMPILE=1 to verify compile returns a review link.
Managed vs self-hosted transport support
- Managed v1 supports:
mcp-sse. - Self-hosted supports:
mcp-sse,mcp-stdio.
If you need stdio for local process adapters, run self-hosted veto mcp serve.
Troubleshooting
SSE upstream timeouts
Symptoms:
Upstream timeoutNo response in SSE stream
Checks:
- Increase
timeoutMsfor the upstream. - Verify upstream endpoint accepts JSON-RPC
POSTpayloads. - Confirm upstream returns matching JSON-RPC
idin responses.
Policy server unreachable
Symptoms:
Policy server unreachable- doctor reports policy server probe failure.
Checks:
- Verify
policy.serverUrl. - Verify
policy.apiKeystarts withveto_and is valid. - Confirm
POST /v1/validateis reachable from gateway runtime.
Stdio differences
Symptoms:
- Managed upstream creation rejected for
mcp-stdio.
Cause:
- Managed v1 intentionally blocks stdio transports.
Resolution:
- Move that upstream to self-hosted
veto mcp serve.
Related
- CLI reference
- MCP API reference
- MCP SDK integration
- Polymarket With Veto MCP, guarded MCP sidecar for Polymarket trading
OpenClaw Finance Quickstart
Go from zero to a financially accountable OpenClaw agent. Research runs freely; every money-moving action is gated by explicit approval rules you control.
Polymarket With Veto MCP
Run a guarded MCP sidecar for Polymarket trading. Every mutating tool call is validated against YAML policy rules before execution.

