An authless, public MCP server that tunnels to multiple upstream MCP providers — each of which may require its own token (like Context7). Callers hit one endpoint with no auth; the gateway injects each provider's secret server-side.
Rendering mermaid diagram...
Add this val's live /mcp endpoint as a remote Streamable HTTP MCP server
in any MCP-compatible client (Claude Code, Cursor, etc.). No headers or API
keys required on the client side.
Visit the homepage (/) to see configured providers and the live aggregated
tool list.
| File | Responsibility |
|---|---|
providers.ts | Config for each upstream provider: URL + which env var holds its secret |
mcpClient.ts | A minimal MCP client — speaks the Streamable HTTP handshake (initialize → notifications/initialized → tools/list/tools/call) to upstream providers |
registry.ts | Aggregates tools from all providers into one namespace (prefixed <provider>__<tool>), caches tools/list briefly, and dispatches tools/call to the right upstream |
mcpServer.ts | The public-facing MCP server — JSON-RPC 2.0 method handling for initialize, tools/list, tools/call |
index.tsx | Hono app: POST /mcp (the protocol endpoint) + a homepage documenting providers/tools |
Tools are namespaced so multiple providers can coexist without collisions,
e.g. context7__resolve-library-id and context7__query-docs.
- Add an entry to the
providersarray inproviders.ts:{ id: "firecrawl", name: "Firecrawl", url: "https://mcp.firecrawl.dev/mcp", authEnvVar: "FIRECRAWL_API_KEY", authHeader: "Authorization", authPrefix: "Bearer ", } - Add the corresponding env var to this val (see below).
- That's it — its tools show up automatically in
tools/list, prefixedfirecrawl__....
Only needed for providers that require a token. Context7 works without one at
lower rate limits; set CONTEXT7_API_KEY for higher limits.
👉 Add CONTEXT7_API_KEY here: https://www.val.town/x/thevt1/mcp-gateway/environment-variables?key=CONTEXT7_API_KEY
- Each
tools/callre-runs the upstreaminitializehandshake (stateless, simple, robust — no session expiry bugs).tools/listresults are cached in-memory for 5 minutes per warm instance. - This server doesn't push server-initiated events, so
GET /mcp(the optional SSE-stream half of the Streamable HTTP spec) returns 405. - Because the gateway itself is authless, treat it as semi-public: anyone who
can reach
/mcpcan spend your upstream providers' rate limits/quota. Put it behind Val Town's restricted HTTP privacy or a bypass token if you need to lock it down.