MCP proxy: security model
The proxy sits in front of every entity_type=mcp-server listing. It exists
so consumers don't have to track upstream URL changes — and so the registry
can apply consistent abuse + safety checks across the catalog.
What we forward
POST /mcp/<publisher>/<name>— JSON-RPC over HTTP (the streamable HTTP transport modern MCP clients use).POST /mcp/<publisher>/<name>/<version>— pinned variant for consumers that need a known build.GETequivalents for SSE-only clients.
Trust-tier gating
| Tier | Proxied? | Notes |
|---|---|---|
unverified | ❌ default | Returns 403; consumers can install the publisher's URL directly. |
verified | ✅ | Domain-verified publishers. |
official | ✅ | Anthropic, registry team, etc. |
Self-hosted deployments can flip the default by setting
AMITTE_MCP_PROXY_ALLOW_UNVERIFIED=1.
Rate limits
Per-IP × per-skill, dedicated bucket. Default 60 requests/minute. Submit
patterns that exceed the bucket get a Retry-After header and a JSON-RPC
-32000 error envelope so MCP clients render a clean failure toast.
SSRF guard
Upstream URLs are validated at submit time and on every proxy request — URLs may have changed between submit and now. Rejected ranges:
127.0.0.0/8(loopback)10.0.0.0/8,172.16.0.0/12,192.168.0.0/16(RFC 1918)169.254.0.0/16(link-local, including the cloud metadata IP)::1,fe80::/10,fc00::/7(IPv6 loopback / link-local / unique-local)
The same guard runs in the intent grounding fetcher; both share the
@amitte-ai/shared/ssrf helper so the rules can't drift.
Health probes
A 60-second TTL'd probe (OPTIONS request, fallback HEAD) populates the
mcp_server_health table. Consumers see the result on the detail page and
via GET /mcp/health/<publisher>/<name>. Three consecutive failures emails
the publisher; the listing stays in catalog with the unhealthy badge.
Telemetry
Every forwarded request increments proxy_hits_daily(version_id, day).
Publishers see their per-day count on /me; admins see global totals on
/admin.
Out of scope (for now)
- Hosting publisher MCP server code (registry-hosted mode is v2+).
- Stdio-transport proxying (impossible without shipping a binary;
npx <package>is the install path for stdio servers). - Active malware scanning of MCP responses. Document as known gap; rely on
community flagging via
/policy.