{"id":49543094,"url":"https://github.com/pragmalabs-tech/mcpr","last_synced_at":"2026-05-02T16:07:36.892Z","repository":{"id":346160634,"uuid":"1188744865","full_name":"pragmalabs-tech/mcpr","owner":"pragmalabs-tech","description":"Observability-first proxy for MCP servers","archived":false,"fork":false,"pushed_at":"2026-05-02T06:05:12.000Z","size":29352,"stargazers_count":28,"open_issues_count":3,"forks_count":1,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-02T07:29:35.411Z","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/pragmalabs-tech.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-05-02T06:02:24.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/pragmalabs-tech/mcpr","commit_stats":null,"previous_names":["cptrodgers/mcpr","pragmalabs-tech/mcpr"],"tags_count":52,"template":false,"template_full_name":null,"purl":"pkg:github/pragmalabs-tech/mcpr","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pragmalabs-tech%2Fmcpr","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pragmalabs-tech%2Fmcpr/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pragmalabs-tech%2Fmcpr/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pragmalabs-tech%2Fmcpr/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pragmalabs-tech","download_url":"https://codeload.github.com/pragmalabs-tech/mcpr/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pragmalabs-tech%2Fmcpr/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32540164,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-02T12:25:33.646Z","status":"ssl_error","status_checked_at":"2026-05-02T12:24:51.733Z","response_time":132,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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-05-02T16:07:36.190Z","updated_at":"2026-05-02T16:07:36.886Z","avatar_url":"https://github.com/pragmalabs-tech.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n\n\u003cimg src=\"docs/assets/logo.png\" alt=\"mcpr logo\" width=\"120\" /\u003e\n\n# mcpr\n\n[![CI](https://github.com/pragmalabs-tech/mcpr/actions/workflows/check.yml/badge.svg)](https://github.com/pragmalabs-tech/mcpr/actions/workflows/check.yml)\n[![codecov](https://codecov.io/gh/pragmalabs-tech/mcpr/branch/main/graph/badge.svg)](https://codecov.io/gh/pragmalabs-tech/mcpr)\n[![License](https://img.shields.io/badge/license-Apache--2.0-blue)](LICENSE)\n\n**Observability-first proxy for MCP servers.** A single Rust binary that sits in front of your MCP app and records every JSON-RPC call to a local SQLite store: per-tool latency, session traces, schema diffs, client breakdowns. \n\n\u003c/div\u003e\n\n## Quickstart\n\n### Install\n\n```bash\ncurl -fsSL https://mcpr.app/install.sh | sh\n```\n\nDetects your OS and architecture, downloads the latest release from GitHub, installs to `$HOME/.local/bin/mcpr`, and adds that directory to your shell PATH. Override the destination with `MCPR_INSTALL_DIR=/usr/local/bin` if you prefer. Linux (x86_64, aarch64) and macOS (Intel, Apple Silicon) are supported. Manual tarballs are attached to every [GitHub release](https://github.com/pragmalabs-tech/mcpr/releases).\n\n### Run\n\n```bash\ncat \u003e mcpr.toml \u003c\u003c'EOF'\nmcp = \"http://localhost:9000\"\nport = 3000\nEOF\n\nmcpr proxy run mcpr.toml\n```\n\nTraffic flows through `http://localhost:3000`. `mcpr proxy run` is a foreground process: your supervisor (systemd, Docker, `child_process.spawn`) owns the lifecycle. SIGTERM drains gracefully.\n\nTo stream events into the cloud dashboard, run `mcpr proxy setup` once.\n\n### Docker\n\n```bash\ncat \u003e mcpr.toml \u003c\u003c'EOF'\nmcp = \"http://host.docker.internal:9000\"\nport = 3000\nEOF\n\ndocker run -d --name mcpr \\\n  -v \"$(pwd)/mcpr.toml:/etc/mcpr/mcpr.toml:ro\" \\\n  -v mcpr-state:/var/lib/mcpr \\\n  -p 3000:3000 \\\n  ghcr.io/pragmalabs-tech/mcpr:latest\n```\n\nSee [docs/DOCKER.md](docs/DOCKER.md) for volumes, environment variables, and compose / Kubernetes examples, and [`docker-compose.yml`](docker-compose.yml) for the sidecar pattern.\n\n---\n\n## What mcpr does\n\nmcpr sits in front of your MCP app and does three things, in order of how much work each one saves you:\n\n1. **Observe**: records every `tools/call`, `resources/*`, and `prompts/*` request to a local SQLite store. Per-tool p50/p95/max latency, error rates, session traces, client breakdowns, and schema diffs over time. No instrumentation in your app.\n2. **Route**: one upstream per proxy today. JSON-RPC classification, and CSP rewriting that emits the shape each AI client (ChatGPT, Claude, Copilot) expects.\n3. **Authenticate** *(in progress)*: OAuth 2.1 and API key handling at the proxy layer. Your app receives a verified `x-user-id` header instead of implementing auth flows itself.\n\nRunning in front of [mcp.usestudykit.com/mcp](https://mcp.usestudykit.com/mcp) today.\n\n---\n\n## Observe\n\nEvery JSON-RPC request that flows through mcpr lands in `~/.mcpr/store.db`: tool name, latency, status, error code, request/response size, session ID, server/client info captured on `initialize`, and full `tools/list` / `resources/list` / `prompts/list` responses for schema tracking.\n\n### Local SQLite\n\nThe store at `~/.mcpr/store.db` is the source of truth. Inspect it directly with the `sqlite3` CLI for ad-hoc analysis, or use:\n\n```bash\nmcpr store stats             # row counts, oldest/newest events, db size\nmcpr store vacuum            # delete old records and reclaim disk\n```\n\nSchema is documented in [docs/CLI.md](docs/CLI.md).\n\n---\n\n## Route\n\nEach proxy instance fronts one upstream MCP app. mcpr classifies requests by JSON-RPC shape: MCP methods go to the backend; anything else is forwarded upstream as-is.\n\n```toml\nmcp = \"http://localhost:9000\"\n```\n\nTo proxy multiple MCP servers, write one `mcpr.toml` per upstream and launch each with `mcpr proxy run --config \u003cpath\u003e`.\n\n### Widget CSP\n\nmcpr applies widget CSP in both shapes (the legacy OpenAI per-widget format and the current MCP standard), so a single config block works for both Claude and ChatGPT.\n\n```toml\n[csp]\n# Public host the proxy is reachable on. Written into the OpenAI\n# `widgetDomain` field. `_meta.ui.domain` is left to Claude, which\n# derives that field from the proxy URL itself and rejects values\n# supplied by anything in front of it.\ndomain = \"widgets.example.com\"\n\n# Lands in `connect-src` (fetch / WebSocket / EventSource targets).\n# `extend` merges with whatever the upstream MCP server declared;\n# `replace` ignores upstream.\n[csp.connectDomains]\ndomains = [\"api.example.com\"]\nmode    = \"extend\"\n\n# Lands in `script-src`, `style-src`, `img-src`, `font-src`, `media-src`:\n# one bucket for everything the widget loads. Same merge semantics.\n[csp.resourceDomains]\ndomains = [\"cdn.example.com\"]\nmode    = \"extend\"\n\n# Lands in `frame-src` (nested iframes). Defaults to `replace` so\n# upstream cannot silently widen this directive.\n[csp.frameDomains]\ndomains = []\nmode    = \"replace\"\n\n# Per-widget override, matched by URI pattern (glob). Only the\n# payment widget gets `connect-src` to Stripe.\n[[csp.widget]]\nmatch              = \"ui://widget/payment*\"\nconnectDomains     = [\"api.stripe.com\"]\nconnectDomainsMode = \"extend\"\n```\n\n---\n\n## Authenticate\n\n*In progress.* mcpr will handle MCP OAuth 2.1 and API key auth at the proxy layer, so your MCP app receives a verified `x-user-id` header instead of implementing auth flows itself. Planned config:\n\n```toml\n[auth]\nmode = \"oauth2.1\"           # or \"api_key\"\nprovider = \"google\"         # google, github, bring-your-own\n```\n\nTrack progress in the [Roadmap](#roadmap) below. Open an issue if your provider isn't covered.\n\n---\n\n## Reference\n\n- Configuration: [docs/proxy/PROXY_CONFIGURATION.md](docs/proxy/PROXY_CONFIGURATION.md) (upstream URL, port, CSP, cloud sync, logging, limits)\n- CLI: [docs/CLI.md](docs/CLI.md) (`proxy run/stop/list/delete/setup`, `store stats/vacuum`)\n- Docker: [docs/DOCKER.md](docs/DOCKER.md) (volumes, health probes, compose/Kubernetes)\n- Bench harness: [benches/README.md](benches/README.md) (initialize + tools/call latency, direct vs proxied)\n\n---\n\n## Roadmap\n\n**Observability**\n- [x] Per-tool metrics (calls, error%, p50, p95, max, request/response size)\n- [x] Request logs, session tracking, AI client tracking\n- [x] Schema capture with change tracking\n- [x] Cloud dashboard sync ([cloud.mcpr.app](https://cloud.mcpr.app))\n\n**Routing \u0026 Network**\n- [x] JSON-RPC routing (single upstream per proxy)\n- [x] CSP rewriting\n- [ ] Multi-upstream routing from one port\n\n**Auth**\n- [ ] OAuth 2.1 for standard providers\n- [ ] OAuth 2.1 for legacy (non-standard) auth\n- [ ] API token auth\n- [ ] Multiple auth modes per server\n\n**Security**\n- [ ] Per-tool access control\n- [ ] Rate limiting and circuit breaker\n- [ ] IP whitelist\n\n## License\n\nApache 2.0\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpragmalabs-tech%2Fmcpr","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpragmalabs-tech%2Fmcpr","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpragmalabs-tech%2Fmcpr/lists"}