{
  "markdown": "# @mcp-rating/gateway\n\n**Run MCP servers without handing them your API keys.**\n\nAdding an MCP server to your client today spawns somebody else's code with your\nentire environment attached — `AWS_SECRET_ACCESS_KEY`, `OPENAI_API_KEY`,\n`DATABASE_URL`, everything in your shell. The gateway spawns them with a\nconstructed environment instead: `PATH`, `HOME`, and only the variables you or\nits manifest name. Nothing else is there to read.\n\n<!-- Absolute URL on purpose: relative image paths render on GitHub but break on\n     npmjs.com, which is where anyone arriving via `npx` reads this. -->\n![The same deliberately malicious MCP server, run twice: on a raw spawn it reads every\nvariable in the shell; through the gateway it sees fifteen, none sensitive.](https://raw.githubusercontent.com/mcprating/mcp-gateway/main/demo/sandbox-demo.gif)\n\n*The same malicious server, run twice. Reproduce it yourself: `node demo/run-demo.mjs`\n— it plants two fake credentials and reads your real environment, printing only the\ncount and the planted values.*\n\nIt is also a meta-server: one entry in your config gives you the whole registry,\nconnected on demand rather than pre-loaded.\n\n```json\n{ \"mcpServers\": { \"gateway\": { \"command\": \"npx\", \"args\": [\"-y\", \"@mcp-rating/gateway\"] } } }\n```\n\n## Why it uses less of your context\n\nEvery MCP server you configure statically injects its full tool schema into\nevery turn, whether you use it or not. The gateway exposes 13 meta-tools at a\nfixed cost and loads a server's tools only once you connect to it.\n\n| | measured |\n|---|--:|\n| Mean per real MCP server | **~1,500 tokens** |\n| 10 servers configured statically | **~15,100 tokens, every turn** |\n| Gateway, flat | **~2,800 tokens** |\n\nRoughly **5× less** standing overhead at ten servers, and the gap widens with\neach one you add.\n\n*Honest about the method:* measured from 6 servers this project connected to and\nintrospected, sized as `chars / 4`. It is an estimate from a small sample, not a\nbenchmark. And it is standing overhead only — connecting to a server pays that\nserver's schema cost at connect time. The saving is real precisely because most\nconfigured servers sit unused in most conversations.\n\n## How It Works\n\n```\n┌────────────────────┐       ┌──────────────┐       ┌──────────────────┐\n│  Claude Desktop /  │ stdio │              │ stdio  │ MCP Server A     │\n│  Cursor / Windsurf │◄─────►│  MCP Gateway │◄──────►│ (e.g. filesystem)│\n│  (host client)     │       │              │◄──┐    └──────────────────┘\n└────────────────────┘       └──────────────┘   │    ┌──────────────────┐\n                                    │           └───►│ MCP Server B     │\n                                    ▼                │ (e.g. github)    │\n                             ┌──────────────┐        └──────────────────┘\n                             │ MCP-Rating   │\n                             │ Registry API │\n                             └──────────────┘\n```\n\nInstead of manually configuring each MCP server in your client, the Gateway:\n\n1. **Discovers** servers via the MCP-Rating registry\n2. **Connects** to them on-demand (spawns as child processes)\n3. **Proxies** their tools through namespaced names (`servername__toolname`)\n4. **Notifies** your client when tools are added/removed\n\n## Quick Start\n\n### With Claude Desktop\n\nAdd to your `claude_desktop_config.json`:\n\n```json\n{\n  \"mcpServers\": {\n    \"gateway\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@mcp-rating/gateway\"]\n    }\n  }\n}\n```\n\nThen ask Claude:\n- *\"Search for MCP servers that work with databases\"* (uses `mcp_discover`)\n- *\"Connect to the sqlite server\"* (uses `mcp_connect`)\n- *\"Query my database\"* (calls the proxied tool directly)\n\n### Cursor\n\n`~/.cursor/mcp.json` (or `.cursor/mcp.json` in a project):\n\n```json\n{\n  \"mcpServers\": {\n    \"gateway\": { \"command\": \"npx\", \"args\": [\"-y\", \"@mcp-rating/gateway\"] }\n  }\n}\n```\n\n### Claude Code\n\n```bash\nclaude mcp add gateway -- npx -y @mcp-rating/gateway\n```\n\n### Windsurf\n\n`~/.codeium/windsurf/mcp_config.json`, same shape as Cursor:\n\n```json\n{\n  \"mcpServers\": {\n    \"gateway\": { \"command\": \"npx\", \"args\": [\"-y\", \"@mcp-rating/gateway\"] }\n  }\n}\n```\n\n### Any other MCP client\n\n```json\n{ \"command\": \"npx\", \"args\": [\"-y\", \"@mcp-rating/gateway\"] }\n```\n\nRestart the client after editing its config — most read it only at startup.\n\n## Meta-Tools\n\nThe gateway exposes 13 built-in tools:\n\n| Tool | Description |\n|------|-------------|\n| `mcp_discover` | Search the MCP-Rating registry for MCP servers |\n| `mcp_connect` | Connect to a server and make its tools available |\n| `mcp_disconnect` | Disconnect a server and remove its tools |\n| `mcp_list_active` | List connected servers and their tools |\n| `mcp_server_info` | Detailed info about a server, from the registry or a live connection |\n| `mcp_call_tool` | Call a tool on a connected server |\n| `mcp_gateway_health` | Diagnostics: version, uptime, connection and registry status |\n| `mcp_sandbox` | View or customise a server's sandbox manifest (env/network/filesystem) |\n| `mcp_audit` | The safety audit trail — what sandboxed servers actually did |\n| `mcp_profiles` | Named connection profiles (work, personal, …) |\n| `mcp_groups` | Atomic connect/disconnect of server sets |\n| `mcp_usage` | Call counts, latency and error rates for connected servers |\n| `mcp_recommend` | Server recommendations based on usage |\n\n## Trust Tiers\n\nEvery connected server is labeled with a trust tier based on its MCP-Rating quality score:\n\n- **[Verified]** — High quality + officially verified\n- **[Trusted]** — Good quality with repository and install command\n- **[Community]** — Listed in registry with basic quality\n- **[Unverified]** — Unknown origin (manually connected)\n\n## Configuration\n\nThe gateway reads config from `~/.mcp-gateway/config.json`:\n\n```json\n{\n  \"registryApiUrl\": \"https://mcprating.io/api/v1\",\n  \"proxyTimeoutMs\": 30000,\n  \"maxConnections\": 10,\n  \"logLevel\": \"info\"\n}\n```\n\n### Environment Variables\n\n| Variable | Description | Default |\n|----------|-------------|---------|\n| `MCP_GATEWAY_REGISTRY_URL` | MCP-Rating API base URL | `https://mcprating.io/api/v1` |\n| `MCP_GATEWAY_TIMEOUT` | Proxy timeout (ms) | `30000` |\n| `MCP_GATEWAY_MAX_CONNECTIONS` | Max simultaneous connections | `10` |\n| `MCP_GATEWAY_LOG_LEVEL` | Log level (debug/info/warn/error) | `info` |\n| `MCP_GATEWAY_CONTAINER_ISOLATION` | Force L2 container isolation on/off | manifest decides |\n| `MCP_GATEWAY_AUDIT_LOG` | Path for the forensic audit log | disabled |\n| `MCP_GATEWAY_PARTNER_KEY` | Partner attribution key — **enables ad telemetry** | unset |\n| `MCP_GATEWAY_AD_TRACKING` | Set to `false` to disable ad telemetry outright | unset |\n| `MCP_GATEWAY_HTTP_TOKEN` | Bearer token for HTTP daemon mode | unset |\n\n## Security model\n\nThe gateway exists because plain MCP hands every server your whole environment.\nTwo layers push back, and it is worth being precise about what each one does and\ndoes not do.\n\n### L1 — environment scoping (always on, for stdio servers)\n\nA downstream server receives `PATH`, `HOME` and friends, plus only the variable\n**names** its manifest allowlists or you pass at connect time. Everything else in\nthe parent environment — `AWS_*`, `OPENAI_API_KEY`, `DATABASE_URL` — is withheld.\nExported shell functions (`BASH_FUNC_*`) are dropped rather than forwarded.\n\nThis is genuine enforcement: the child process is spawned with a constructed\nenvironment, so there is nothing to opt out of or bypass.\n\n### L2 — container isolation (opt-in)\n\nWhen a manifest requests it, or `MCP_GATEWAY_CONTAINER_ISOLATION=true`, the\nserver runs under `docker`/`podman` with an ephemeral container.\n\n### Network allowlists: read this before relying on them\n\n`network: \"allowlist\"` starts an in-process forward proxy and points the child at\nit via `HTTP_PROXY`/`HTTPS_PROXY`.\n\n**This filters proxy-aware clients only.** Node's fetch/undici, axios, and Python\nrequests all honour those variables, which covers most real servers. A program\nthat opens raw TCP sockets, or a compiled binary that ignores proxy environment\nvariables, **is not filtered**. Treat allowlists in L1 as a guard rail against\nhonest code, not a containment boundary against hostile code — for that you need\nL2 with container network namespacing.\n\nAllowlist patterns fail **closed**: a malformed pattern such as `*example.com`\n(missing dot) matches nothing rather than everything. The gateway warns at\nstartup about patterns that will not do what their author intended, including\nover-broad ones like `*.com`.\n\n### What is not covered\n\nIf the host client is `SIGKILL`ed, the gateway cannot run its shutdown path and\nspawned child processes may be left behind. `SIGINT`/`SIGTERM` are handled and\ndisconnect everything cleanly; `SIGKILL` is untrappable by definition.\n\n## Telemetry\n\n**Off unless you turn it on.** The ad tracker is constructed only when\n`MCP_GATEWAY_PARTNER_KEY` is set — with no partner key there is no partner\ntelemetry, and nothing is posted about your connects or tool calls.\n\nIf a partner key is set (you are earning attribution revenue), connect and\ntool-execution events are sent to mcprating.io. Disable it while keeping the key\nwith `MCP_GATEWAY_AD_TRACKING=false`.\n\nSeparately, the gateway calls the MCP-Rating registry API for `mcp_discover` and\n`mcp_recommend` — that is the lookup you asked for, not background reporting.\nUsage analytics (`mcp_usage`) are an in-memory ring buffer and never leave the\nprocess.\n\n## Development\n\n```bash\nnpm install\nnpm run dev        # watch mode\nnpm run typecheck\nnpm run build\nnpm test           # sandbox unit tests (env scoping + egress allowlist)\n```\n\n## Architecture\n\nThe gateway is built on the [MCP SDK](https://github.com/modelcontextprotocol/typescript-sdk) and uses:\n\n- **StdioServerTransport** — communicates with the host client\n- **StdioClientTransport** — spawns and communicates with downstream servers\n- **Dynamic tool registration** — `McpServer.registerTool()` + `sendToolListChanged()`\n- **Tool namespacing** — `slug__toolname` pattern prevents collisions\n- **Passthrough Zod schemas** — preserves parameter names for host client UI while letting downstream servers validate\n\n## License\n\nISC\n",
  "bytes": 10176,
  "sha": "69b35e9a64ec172f3736d318a4c65f69efd1f0cfddf8da2ebe6bda9db01677d2",
  "repo_slug": "mcprating/mcp-gateway",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_mcprating_gateway_d1e416d9/readme"
}