Skip to content

Routing

mcpr parses every JSON-RPC 2.0 message and routes it based on the protocol, not the URL path.

Each proxy instance fronts one upstream MCP app.

Request typeBehavior
JSON-RPC (tools/call, resources/read, etc.)Classified, forwarded to the upstream MCP server, response is recorded
Everything elseForwarded as-is — mcpr never blocks traffic
mcp = "http://localhost:9000"

To proxy multiple MCP servers, write one mcpr.toml per upstream and launch each with mcpr proxy run <path>.

mcpr classifies 25+ MCP methods for routing, observability, and CSP rewriting:

CategoryMethodsProxy Behavior
Lifecycleinitialize, notifications/initialized, pingExtracts client info, tracks session state
Toolstools/list, tools/call, notifications/tools/list_changedCSP rewriting, per-tool metrics, schema capture
Resourcesresources/list, resources/templates/list, resources/read, resources/subscribe, resources/unsubscribeCSP rewriting, resource URI logging
Promptsprompts/list, prompts/getPrompt name extraction
Utilitylogging/setLevel, completion/complete, notifications/cancelled, notifications/progressForwarded, classified for logging

Unknown methods are forwarded as-is — mcpr never blocks traffic. See Supported MCP Methods for the full reference.

Each tool gets its own metrics automatically: call count, error rate, p95/max latency, bytes in/out. No configuration needed — mcpr extracts the tool name from every tools/call request.

Inspect locally with sqlite3 ~/.mcpr/store.db, or stream to mcpr Cloud for per-tool tables, slow-call detection, and latency percentiles.

MCP Apps (ChatGPT Apps, Claude connectors) render widgets in sandboxed iframes with strict CSP. ChatGPT reads openai/widgetCSP, Claude reads ui.csp, and each interprets domain lists differently. mcpr handles this automatically:

  • Rewrites CSP domain arrays in tools/list, tools/call, resources/list, resources/templates/list, and resources/read responses
  • Replaces localhost/upstream URLs with the proxy domain
  • Emits the CSP shape each platform expects
  • Deep-scans nested structures for CSP arrays

CSP has three independent directives — connectDomains (fetch / WebSocket), resourceDomains (scripts, styles, images), and frameDomains (iframes) — each with its own mode: extend (merge with upstream) or replace (use only declared domains). Widget entries layer glob-matched overrides on top of the global policy.

[csp.connectDomains]
domains = ["api.example.com"]
mode = "extend"
[csp.resourceDomains]
domains = ["cdn.example.com"]
mode = "extend"
[csp.frameDomains]
domains = []
mode = "replace"
[[csp.widget]]
match = "ui://widget/payment*"
connectDomains = ["api.stripe.com"]
connectDomainsMode = "extend"

mcpr passively captures your server’s tools, resources, and prompts by intercepting discovery responses. No extra requests, no added latency. Captured schemas land in the local SQLite store and stream to mcpr Cloud, where added/modified/removed entries and unused tools surface in the Tools tab.

See Events for the full event and capture system.

  • Multi-server routing — route to multiple upstream MCP backends
  • Multiple proxies in one process — single binary serving several upstreams ([[proxy]] config array)