Make MCP server browser-portable with a Web-standard handler#136
Conversation
Replace the Hono-only Node handler with a Fetch-API handler that runs on Node, Bun, Deno, Cloudflare Workers, and in-page Web Workers. Restructure @eclipse-glsp/server-mcp into a browser/common/node split mirroring @eclipse-glsp/server. - New browser entry point with a Web Worker integration helper. - VS Code web-extension bundle no longer transitively pulls Node-only deps. - Mutating tools report dispatched-command counts for cross-call undo / redo. - Port-agnostic Host-header validation — matches the SDK's older Express middleware that the Fetch transport regressed. - Workflow example ships an end-to-end browser demo of the portable handler in its own private `workflow-server-mcp-demo` workspace; `workflow-server-bundled-web` stays narrow and ships only the worker bundle. The Service Worker scaffolding lives with the demo, not as a published asset of `@eclipse-glsp/server-mcp`. - Root `start:mcp-demo` script builds the worker bundle and launches the demo in one step. - Non-loopback auth and shared session state remain adopter responsibility. - ARCHITECTURE.md refreshed for the portable handler and for the IDE integrations that now register the GLSP MCP server with the host IDE. Part of eclipse-glsp/glsp#1546
e8e54a1 to
544b7f8
Compare
tortmayr
left a comment
There was a problem hiding this comment.
Changes look good to me.
Clean split into browser/node entrypoints.
And the MCP browser demo is very nice 👍🏼
| export async function launch(argv?: string[]): Promise<void> { | ||
| export async function launch(_argv?: string[]): Promise<void> { | ||
| // Bridge must be created before any await so postMessages that arrive on the next event-loop | ||
| // tick aren't dropped. Requests pile up on the bridge's internal `launcherReady` until the |
There was a problem hiding this comment.
Keep concise. First sentence is enough
There was a problem hiding this comment.
Good call, trimmed to the first sentence.
|
|
||
| ```bash | ||
| yarn workspace @eclipse-glsp-examples/workflow-server build | ||
| yarn workspace @eclipse-glsp-examples/workflow-server-mcp-demo start |
There was a problem hiding this comment.
yarn start:mcp-demo should be fine here right?
There was a problem hiding this comment.
Yep, switched to yarn start:mcp-demo. Thanks!
|
|
||
| /** | ||
| * Browser-compatible {@link McpRequestContext}. Single mutable slot — concurrent requests on | ||
| * the same session overwrite each other's frame. Hosts must serialise handler chains. |
There was a problem hiding this comment.
The comment says "hosts must serialise
handler chains" and the McpWorkerBridge does this via dispatchChain. This is correct but fragile — if an adopter uses
BrowserMcpServerModule directly without the bridge's serialization, concurrent requests will silently corrupt the context.
Consider logging a warning or documenting this more prominently.
There was a problem hiding this comment.
Good point. Added a one-shot console.warn when run() is entered while another context is still active, and expanded the doc comment to point adopters at McpWorkerBridge (or an equivalent queue around launcher.handleRequest) so the fix is obvious from the warning as well.
| status: response.status, | ||
| statusText: response.statusText, | ||
| headers, | ||
| body: response.body |
There was a problem hiding this comment.
The type says ReadableStream | null
and it's passed as a Transferable in reply(). However, ReadableStream is only transferable in Chromium (Firefox and Safari
don't support it). The README already says "Chromium-based browser" but this limits portability.
There was a problem hiding this comment.
Nice catch! Added a feature-detect so that Firefox/Safari fall back to buffering the body into an ArrayBuffer (still transferable) with a warn-once.
- Trim verbose comment in browser workflow example. - Use `yarn start:mcp-demo` shortcut in demo README. - Warn once on concurrent BrowserMcpRequestContext.run(). - Feature-detect transferable ReadableStream in McpWorkerBridge; buffer to ArrayBuffer (with warn-once) on browsers without support.
|
@tortmayr Great, thank you! I pushed a follow-up commit to address your concerns |
What it does
Replace the Hono-only Node handler with a Fetch-API handler that runs on Node, Bun, Deno, Cloudflare Workers, and in-page Web Workers. Restructure @eclipse-glsp/server-mcp into a browser/common/node split mirroring @eclipse-glsp/server.
Part of eclipse-glsp/glsp#1546
How to test
Follow-ups
Changelog