{"id":47641493,"url":"https://github.com/cptrodgers/mcpr","last_synced_at":"2026-04-21T02:16:04.810Z","repository":{"id":346160634,"uuid":"1188744865","full_name":"cptrodgers/mcpr","owner":"cptrodgers","description":"MCPR is a reverse proxy for MCP Apps/Servers — operating at the JSON-RPC layer to route, authenticate, observe, and secure MCP traffic. Written in Rust, with under 0.3ms overhead.","archived":false,"fork":false,"pushed_at":"2026-04-17T10:24:57.000Z","size":27989,"stargazers_count":26,"open_issues_count":5,"forks_count":1,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-17T11:11:37.175Z","etag":null,"topics":["mcp","mcp-gateway","mcp-proxy","rust"],"latest_commit_sha":null,"homepage":"https://mcpr.app","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cptrodgers.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-03-22T14:26:07.000Z","updated_at":"2026-04-17T10:25:00.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/cptrodgers/mcpr","commit_stats":null,"previous_names":["cptrodgers/mcpr"],"tags_count":47,"template":false,"template_full_name":null,"purl":"pkg:github/cptrodgers/mcpr","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cptrodgers%2Fmcpr","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cptrodgers%2Fmcpr/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cptrodgers%2Fmcpr/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cptrodgers%2Fmcpr/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cptrodgers","download_url":"https://codeload.github.com/cptrodgers/mcpr/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cptrodgers%2Fmcpr/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32073509,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-21T01:35:38.224Z","status":"online","status_checked_at":"2026-04-21T02:00:06.111Z","response_time":128,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["mcp","mcp-gateway","mcp-proxy","rust"],"created_at":"2026-04-02T00:58:16.369Z","updated_at":"2026-04-21T02:16:04.802Z","avatar_url":"https://github.com/cptrodgers.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# mcpr\n\n[![CI](https://github.com/cptrodgers/mcpr/actions/workflows/check.yml/badge.svg)](https://github.com/cptrodgers/mcpr/actions/workflows/check.yml)\n[![codecov](https://codecov.io/gh/cptrodgers/mcpr/branch/main/graph/badge.svg)](https://codecov.io/gh/cptrodgers/mcpr)\n[![License](https://img.shields.io/badge/license-Apache--2.0-blue)](LICENSE)\n\n**A proxy for MCP Apps/Servers.** mcpr parses JSON-RPC messages to route, serve widgets, observe, authenticate, and secure MCP traffic. Written in Rust and built for minimal overhead — [under 1ms p99](benches/reports/v0.4.42-post-refactor.md).\n\n![mcpr TUI dashboard showing information](docs/assets/mcpr-demo.gif)\n\n### Why I build mcpr\n\nMost MCP proxies sit on the client side, aggregating multiple servers for a single client. mcpr sits on the server side — in front of your MCP app — handling JSON-RPC routing, widget serving, CSP configuration, OAuth 2.1, and per-tool/per-resource observability. Your application code stays focused on business logic while mcpr absorbs the policy differences between AI clients (ChatGPT, Claude, Copilot, etc.).\n\nStatus: Under active development — already running in front of my own MCP App (https://mcp.usestudykit.com/mcp)\n\n### Highlight Features\n\n- **Routing** — forwards `tools/call` and `resources/*` traffic with minimal overhead ([under 1ms p99](benches/reports/v0.4.42-post-refactor.md)), plus CSP rewriting that stays compatible across AI clients (ChatGPT, Claude, etc.).\n- **Observability** — per-method stats: tool calls, prompt usage, slow calls, error rates. [Dashboard demo](docs/assets/cloud-dashboard.png) · [proxy demo](docs/assets/proxy-status.png)\n- **Sessions capture** — see how each AI client and user interacts with your MCP: client info, call flow, and the full sequence of tool calls within every session.\n- **Schema capture** — records the MCP schema as it flows through, tracks changes over time, and flags tools that are registered but never called.\n- **Authentication** *(coming soon)* — OAuth 2.1 integration with common providers, plus support for bring-your-own auth that meets the 2.1 spec. Open an issue if your provider isn't covered.\n\n### Quickstart\n\nWrite a config:\n\n```toml\n# mcpr.toml\nmcp = \"http://localhost:9000\"\nport = 3000\n```\n\n**Run by mcpr** (recommended for local development):\n\n```bash\ncurl -fsSL https://mcpr.app/install.sh | sh\nmcpr proxy run\n```\n\nDocker support is in beta — see [docs/DOCKER.md](docs/DOCKER.md) for volumes, health probes, and compose/Kubernetes examples. Feedback welcome.\n\n---\n\n## Route\n\nmcpr inspects each JSON-RPC body to classify the MCP method. Requests route to the MCP backend. Non-JSON-RPC requests (HTML, JS, CSS, images) route to the widget server if configured.\n\n```toml\nmcp = \"http://localhost:9000\"\nwidgets = \"http://localhost:4444\" # Optional for MCP server (no Apps)\n```\n\n### Widget CSP\n\nMCP Apps (ChatGPT Apps, Claude connectors) render widgets in sandboxed iframes with CSP rules. ChatGPT reads `openai/widgetCSP`, Claude reads `ui.csp`. Each platform interprets domain lists differently.\n\nmcpr rewrites CSP domain arrays in `tools/list`, `tools/call`, `resources/list`, `resources/templates/list`, and `resources/read` responses. It replaces localhost URLs with the proxy's public domain, merges configured domains, and emits the CSP shape each client expects.\n\nCSP has three independent directives — `connectDomains` (fetch / WebSocket), `resourceDomains` (scripts, styles, images), and `frameDomains` (iframes) — each with its own `mode` (`extend` or `replace`). Widget entries layer glob-matched overrides on top of the global policy.\n\n```toml\n[csp.connectDomains]\ndomains = [\"api.example.com\"]\nmode    = \"extend\"\n\n[csp.resourceDomains]\ndomains = [\"cdn.example.com\"]\nmode    = \"extend\"\n\n[csp.frameDomains]\ndomains = []\nmode    = \"replace\"\n\n[[csp.widget]]\nmatch              = \"ui://widget/payment*\"\nconnectDomains     = [\"api.stripe.com\"]\nconnectDomainsMode = \"extend\"\n```\n\n---\n\n## Observe\n\nmcpr records every MCP request to a local SQLite database — tool name, latency, status, error code, request/response size, session ID. All `mcpr proxy` commands read from this store and work whether or not the daemon is running.\n\n### Per-tool metrics\n\n```bash\n$ mcpr proxy status\nSTATUS — localhost-9000 — last 1h\n\n  Total requests:    1,284\n  Error rate:        2.3%\n  Sessions:          12 total   3 active\n\n  TOOL                  CALLS      AVG      P95      MAX   ERRORS   BYTES IN  BYTES OUT\n  get_weather             412    45ms    120ms    340ms      0%     48.2 KB    196.8 KB\n  search_docs             389    82ms    210ms    890ms     1.5%    92.1 KB    1.2 MB\n  run_query               156   240ms    890ms   2.40s      8.3%   128.4 KB    2.8 MB\n```\n\n### Request logs\n\n```bash\nmcpr proxy logs --tool search_docs --status error    # failed calls to search_docs\nmcpr proxy logs --follow                             # live tail (polls every 500ms)\nmcpr proxy logs --session abc123                     # filter by session (prefix match)\nmcpr proxy logs --method tools/call                  # filter by MCP method\nmcpr proxy logs --since 30m --tail 100               # last 30 minutes, 100 rows\n```\n\n### Slow calls\n\n```bash\n$ mcpr proxy slow --threshold 500ms\n  TOOL              LATENCY    TIME                   STATUS\n  run_query          2.40s     2025-04-10 14:20:12    ok\n  run_query          1.80s     2025-04-10 14:18:45    ok\n  search_docs         890ms    2025-04-10 14:15:33    error\n```\n\n### Schema capture\n\nmcpr intercepts `tools/list`, `resources/list`, and `prompts/list` responses as they pass through. It stores the server's schema and records each change.\n\n```bash\n$ mcpr proxy schema\nServer: my-mcp-server v1.2.0 (MCP 2025-03-26)\nCapabilities: tools, resources\nSchema: complete\nLast captured: 2026-04-12 14:30:00\n\n── tools/list ──\n  Tools (3):\n    search_products  —  Search the product catalog by keyword\n    get_product      —  Get product details by ID\n    create_order     —  Create a new order\n```\n\n```bash\n$ mcpr proxy schema --changes\n  TIME                  METHOD        CHANGE           ITEM\n  2026-04-12 14:30:00   tools/list    tool_added       send_email\n  2026-04-10 09:15:00   tools/list    tool_modified    search_products\n```\n\n`mcpr proxy schema --unused` compares listed tools against actual call logs to find tools that are registered but never called.\n\n### Sessions and clients\n\n```bash\n$ mcpr proxy sessions\n  SESSION    CLIENT                 STARTED         CALLS   ERRS\n  a1b2c3d4   claude-desktop 1.2.0   Apr 10 14:20      45      2\n  e5f6g7h8   cursor 0.48.0          Apr 10 14:15      23      0\n\n$ mcpr proxy clients\n  CLIENT              VERSION    PLATFORM   SESSIONS    CALLS   ERRORS\n  claude-desktop      1.2.0      claude           12    4,201        8\n  cursor              0.44.1     cursor            3      891        0\n```\n\n---\n\n## Authenticate\n\n*Coming soon.*\n\nmcpr will handle MCP OAuth 2.1 and API key auth at the proxy layer. The MCP Apps (server) receives a verified `x-user-id` header instead of implementing its own auth flow.\n\n---\n\n## Secure\n\n*Coming soon.*\n\nmcpr will provide request validation, per-tool ACLs, and IP whitelisting at the proxy layer.\n\n---\n\n## Reference\n\n- Configuration — [docs/proxy/PROXY_CONFIGURATION.md](docs/proxy/PROXY_CONFIGURATION.md) (upstream URL, port, tunnel, CSP, cloud sync, logging, limits)\n- CLI — [docs/CLI.md](docs/CLI.md) (daemon, proxies, relay, and SQLite queries)\n- Docker — [docs/DOCKER.md](docs/DOCKER.md) (volumes, health probes, compose/Kubernetes)\n\n---\n\n## Roadmap\n\n**Routing \u0026 Network**\n- [x] JSON-RPC routing \n- [x] Content Security Policy (CSP) rewriting\n- [ ] Widgets mode (Server endpoint, statics)\n\n**Observability**\n- [x] MCP request logs, session tracking, AI client tracking\n- [x] MCP schema capture with change tracking\n- [x] Per-tool metrics (calls, error%, p50, p95, max, request size, response size)\n- [x] Cloud dashboard sync ([mcpr.app](https://cloud.mcpr.app))\n\n**Auth**\n- [ ] OAuth 2.1 for Auth Provider\n- [ ] OAuth 2.1 for legacy auth (non oauth standard)\n- [ ] Token API auth\n- [ ] Multiple Auth Mode for one server\n\n**Security**\n- [ ] Per-tool access control\n- [ ] Rate limiting and circuit breaker\n- [ ] IP whitelist\n\n**Tunnel/Relay**\n- [x] Built-in tunnel client and self-hosted relay server\n- [x] Standalone `mcpr relay` CLI with daemon lifecycle\n- [x] Daemon mode, graceful shutdown\n\n## License\n\nApache 2.0\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcptrodgers%2Fmcpr","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcptrodgers%2Fmcpr","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcptrodgers%2Fmcpr/lists"}