feat: experimental WebMCP bridge (mcp-handler/webmcp) - #183
Draft
blurrah wants to merge 3 commits into
Draft
Conversation
Pretty cool as you can use webmcp as easy distribution for your MCP server and use the browser as an authed client with cookies
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.
What this adds
An experimental
mcp-handler/webmcpsubpath export that bridges server-side MCP tools into WebMCP — the W3C proposal (Microsoft + Google) that lets pages expose tools to in-page AI agents vianavigator.modelContext/document.modelContext.The served script is a small dependency-free IIFE: it runs a minimal stateless MCP client against the endpoint (
initialize→tools/list), filters to the allowlist, and registers each tool with the page's WebMCP provider, forwardingexecutetotools/call. No provider in the browser → no-op.Why it's cool
The auth story. Bridged tool calls go through the page's
fetchwithcredentials: "same-origin", so they carry the user's session cookie. An in-page agent (extension, browser built-in) calls your tools as the signed-in user — no OAuth server, no dynamic client registration, no consent redirect, no token storage. Kill the session and the agent's access dies with it.withMcpAuthalready supports this unchanged: its verifier receives the fullRequest, so one endpoint can serve OAuth bearer tokens to remote MCP clients and cookie sessions to the page.Production precedent. Shopify ships this pattern today (
cdn.shopify.com/storefront/webmcp/webmcp-0.1.0.js): catalog/search/product reads go straight to their same-origin Storefront GraphQL API, cart writes route through the theme-integratedwindow.Shopify.actionslayer so the live UI stays in sync. The WebMCP registry is additive, so apps compose the same way here — bridge the server tools with this handler, hand-register client-side tools next to the state they manipulate, and use the allowlist as the partition between the two.Design decisions
toolsallowlist is required. Any script or agent in the page can invoke registered tools with the user's credentials, so exposure is opt-in per tool. The MCP endpoint itself is unaffected — it still serves its full tool set to regular MCP clients.experimental_prefix (same convention asexperimental_withMcpAuth): WebMCP has no shipping browser support yet — this targets polyfills and extension agents, and the API may change with the spec. The subpath staysmcp-handler/webmcpso imports don't move on graduation.<escaped, so the script is safe to inline.GET/HEADonly,Cache-Controlconfigurable.docs/WEBMCP.md: gate cookie auth onSec-Fetch-Site: same-originin the verifier, and use a CSP nonce on the script tag under strict CSP.Docs in
docs/WEBMCP.md, changeset included (minor).