feat(nitro)!: build on h3-mcp instead of the MCP SDK - #305
Draft
HugoRCD wants to merge 1 commit into
Draft
Conversation
The SDK was the only reason the runtime touched a Node built-in: it hands a handler no request, so the context travelled through `AsyncLocalStorage`, and a `WeakMap` could not stand in because the SDK does not give back the `Request` it was given. h3-mcp passes the `H3Event` straight through, so `node:async_hooks` goes, and with it the `nodejs_compat` flag Cloudflare needed. An app with five tools, four resources and two prompts drops from 974 kB to 321 kB (220 kB to 72.1 kB gzip), and the Cloudflare build carries no `node:` import at all. The official client still drives every test, so conformance is judged by something that is not the engine under test. Breaking, and the package is alpha: `ResourceTemplate` and `completable` are gone — a templated resource takes `uriTemplate`, and a prompt argument declares its own `complete` — `ctx.auth` is read off `ctx.event` like anything a middleware leaves, and `legacy`/`responseMode` became `era`. Two things the engine does not cover yet are ours: the MRTR builders (`inputRequired`, `inputResponse`, `acceptedContent`), and the `origin` default. The engine trusts no browser origin until one is listed, which locks out a page the app serves to itself — the inspector, in practice. The handler therefore accepts same-origin requests on a loopback host, which is sound where a bare same-origin check is not: `Host` is a header the caller sets, and DNS rebinding sets it to the attacker's own name, matching its `Origin`.
Contributor
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Contributor
|
Thank you for following the naming conventions! 🙏 |
commit: |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The SDK was the only reason the runtime touched a Node built-in: it hands a handler no request, so the context travelled through
AsyncLocalStorage, and aWeakMapcould not stand in because the SDK does not give back theRequestit was given. h3-mcp passes theH3Eventstraight through, sonode:async_hooksgoes, and with it thenodejs_compatflag Cloudflare needed.An app with five tools, four resources and two prompts drops from 974 kB to 321 kB (220 kB to 72.1 kB gzip), and the Cloudflare build carries no
node:import at all. The official client still drives every test, so conformance is judged by something that is not the engine under test.Breaking, and the package is alpha:
ResourceTemplateandcompletableare gone — a templated resource takesuriTemplate, and a prompt argument declares its owncomplete—ctx.authis read offctx.eventlike anything a middleware leaves, andlegacy/responseModebecameera.Two things the engine does not cover yet are ours: the MRTR builders (
inputRequired,inputResponse,acceptedContent), and theorigindefault. The engine trusts no browser origin until one is listed, which locks out a page the app serves to itself — the inspector, in practice. The handler therefore accepts same-origin requests on a loopback host, which is sound where a bare same-origin check is not:Hostis a header the caller sets, and DNS rebinding sets it to the attacker's own name, matching itsOrigin.🔗 Linked issue
📚 Description
📝 Checklist