Static review of public source at commit 603217008710. No traffic was sent to any MCP environment.
createMcpHandler intentionally performs no Host/Origin (or token) checks — documented in the JSDoc and in docs/serving/http.md. Framework helpers (createMcpExpressApp / Hono / Fastify) arm those checks for loopback. The bare fetch entry does not:
packages/server/src/server/createMcpHandler.ts (doc comment on the export):
* When mounting bare on a fetch-native runtime,
* put Origin/Host validation in front of the handler — the entry itself is
* deliberately validation-free:
*
* const rejected =
* hostHeaderValidationResponse(request, localhostAllowedHostnames()) ??
* originValidationResponse(request, localhostAllowedOrigins());
* return rejected ?? handler.fetch(request);
On Workers / Deno / Bun, export default handler (as shown earlier in the same guide for “Mount it on your runtime”) is a one-liner that never installs those guards unless the reader continues to the later section. That is a footgun relative to the Express path, where loopback protection is automatic.
Suggested change:
- Offer
createMcpHandler(factory, { allowedHosts, allowedOrigins }) (or a withLocalhostProtection(handler) wrapper) that applies hostHeaderValidationResponse / originValidationResponse before fetch.
- Or make the quickstart
export default example always show the validation wrapper first.
- Keep a documented escape hatch for authenticated reverse-proxy deployments.
Severity: low–medium / API footgun and defense-in-depth (complements finding #1 on non-loopback Express/Hono binds). No proof-of-concept.
Happy to send a focused PR if useful.
Static review of public source at commit
603217008710. No traffic was sent to any MCP environment.createMcpHandlerintentionally performs no Host/Origin (or token) checks — documented in the JSDoc and indocs/serving/http.md. Framework helpers (createMcpExpressApp/ Hono / Fastify) arm those checks for loopback. The bare fetch entry does not:packages/server/src/server/createMcpHandler.ts(doc comment on the export):On Workers / Deno / Bun,
export default handler(as shown earlier in the same guide for “Mount it on your runtime”) is a one-liner that never installs those guards unless the reader continues to the later section. That is a footgun relative to the Express path, where loopback protection is automatic.Suggested change:
createMcpHandler(factory, { allowedHosts, allowedOrigins })(or awithLocalhostProtection(handler)wrapper) that applieshostHeaderValidationResponse/originValidationResponsebeforefetch.export defaultexample always show the validation wrapper first.Severity: low–medium / API footgun and defense-in-depth (complements finding #1 on non-loopback Express/Hono binds). No proof-of-concept.
Happy to send a focused PR if useful.