Skip to content

Prototype WebMCP for View-exposed tools, to illustrate #797 - #798

Draft
ochafik wants to merge 7 commits into
modelcontextprotocol:mainfrom
ochafik:webmcp-soft-deprecate-app-tools
Draft

ochafik wants to merge 7 commits into
modelcontextprotocol:mainfrom
ochafik:webmcp-soft-deprecate-app-tools

Conversation

@ochafik

@ochafik ochafik commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Prototype of one option discussed in #797: make WebMCP (document.modelContext) how a View exposes tools, deprecating app.registerTool and View-handled tools/list. The issue is undecided, so this is meant to make that option concrete for discussion, not to merge as-is. Related: #796, #691.

AppBridge injects a small polyfill into the View HTML (a native implementation wins). The sandbox proxy, the only party same-origin with the View, reads the tools with a new createModelContextRelay and answers reserved messages; Hosts call new listWebMcpTools() / callWebMcpTool(). Results are {content: [], structuredContent: value}. Spec, basic-host, four examples and a v3 migration guide follow. The last commit (docker e2e script) is independent and can be dropped.

Breaking: a View using registerTool exposes no tools on a Host without the injection and relay. It needs a major release; no version bump here.

Test plan

bun test src examples passes (558); tsc and typedoc are clean. npm run test:e2e:docker shows the same 24 failures as a clean origin/main run (font rendering on arm64 Docker, PDF servers not starting) plus 3 new passing WebMCP tests, which also pass in Chrome 154 with native WebMCP. Not verified: other browsers, real third-party Hosts.

Known limits: no image results, no size caps in the relay, native quirks handled for current Chrome only.

cc/ @liady @idosal @domfarolino

Adds ui/sandbox-list-tools, ui/sandbox-call-tool and
ui/notifications/sandbox-tools-changed to the draft specification: the
Sandbox proxy, which is the only party same-origin with the View, reads
the tools the View registers with WebMCP (document.modelContext) and
answers the Host itself. The standard tools/list and tools/call are
untouched and keep reaching Views that answer them.

The `tools` app capability and the View-handled tools/list, tools/call
and notifications/tools/list_changed are marked deprecated in favor of
WebMCP. Includes the matching spec types and regenerated schemas.

Illustrates one of the options discussed in modelcontextprotocol#797.
App.registerTool() becomes a deprecated wrapper over
document.modelContext.registerTool(): the App no longer serves the tool
over tools/list / tools/call and no longer declares the `tools`
capability on its behalf. A callback's structuredContent (or its
content) becomes the WebMCP result; isError rejects. App.oncalltool,
App.onlisttools and App.sendToolListChanged are deprecated too, and the
first two warn once per App.

Host side, AppBridge.sendSandboxResourceReady() injects a small
document.modelContext polyfill into the View HTML by default
(`modelContextPolyfill: false` opts out; a native implementation wins).
createModelContextRelay() is the helper a Sandbox proxy uses to read the
View's tools and answer the new reserved messages, and AppBridge gains
listWebMcpTools(), callWebMcpTool() and onwebmcptoolschange. listTools()
and callTool() are deprecated.

A tool result is {content: [], structuredContent: value}; a tool that
throws is an isError result.

This is a breaking change in behavior: a View on this SDK that uses
registerTool exposes no tools on a Host that has not adopted the
polyfill injection and the relay.
The sandbox proxy uses createModelContextRelay() to answer the Host's
reserved tool messages from the View's document.modelContext, and the
Host lists and calls the tools with listWebMcpTools() / callWebMcpTool()
in a new "App tools (WebMCP)" panel. The sandbox iframe delegates the
`tools` Permissions Policy feature so native WebMCP works too.
Migrates the budget-allocator, map, pdf and debug examples from
app.registerTool() to document.modelContext.registerTool(), typed with
webmcp-types (0.1.10, MIT, no dependencies, pinned). Tools return plain
data, which reaches the Host as structuredContent, and throw to report
errors. debug-server logs its WebMCP calls instead of the raw
oncalltool / onlisttools handlers; three.js no longer declares a `tools`
capability it has no handlers for.
Describes the move to WebMCP for Views, and what Hosts and Sandbox
proxies have to adopt, including the behavior change for Views that
keep using app.registerTool() on a Host without the polyfill injection
and the relay.
Loads the budget-allocator, debug and shadertoy examples in basic-host
and lists and calls their tools end to end: a View registering with
document.modelContext, a throwing tool, and the deprecated
App.registerTool() wrapper (with its single warning).
The docker targets bind-mounted the repo and ran `npm ci` in it, which
left the host with Linux binaries in node_modules, and passed `-it`,
which fails without a terminal. They now share scripts/e2e-docker.sh:
the repo is still mounted (so snapshots are written back) but every
node_modules directory is shadowed by an anonymous volume, and `-it` is
only used when stdin and stdout are terminals.
@pkg-pr-new

pkg-pr-new Bot commented Sep 30, 2026

Copy link
Copy Markdown

Open in StackBlitz

@modelcontextprotocol/ext-apps

npm i https://pkg.pr.new/@modelcontextprotocol/ext-apps@798

@modelcontextprotocol/server-basic-preact

npm i https://pkg.pr.new/@modelcontextprotocol/server-basic-preact@798

@modelcontextprotocol/server-basic-react

npm i https://pkg.pr.new/@modelcontextprotocol/server-basic-react@798

@modelcontextprotocol/server-basic-solid

npm i https://pkg.pr.new/@modelcontextprotocol/server-basic-solid@798

@modelcontextprotocol/server-basic-svelte

npm i https://pkg.pr.new/@modelcontextprotocol/server-basic-svelte@798

@modelcontextprotocol/server-basic-vanillajs

npm i https://pkg.pr.new/@modelcontextprotocol/server-basic-vanillajs@798

@modelcontextprotocol/server-basic-vue

npm i https://pkg.pr.new/@modelcontextprotocol/server-basic-vue@798

@modelcontextprotocol/server-budget-allocator

npm i https://pkg.pr.new/@modelcontextprotocol/server-budget-allocator@798

@modelcontextprotocol/server-cohort-heatmap

npm i https://pkg.pr.new/@modelcontextprotocol/server-cohort-heatmap@798

@modelcontextprotocol/server-customer-segmentation

npm i https://pkg.pr.new/@modelcontextprotocol/server-customer-segmentation@798

@modelcontextprotocol/server-debug

npm i https://pkg.pr.new/@modelcontextprotocol/server-debug@798

@modelcontextprotocol/server-lazy-auth

npm i https://pkg.pr.new/@modelcontextprotocol/server-lazy-auth@798

@modelcontextprotocol/server-map

npm i https://pkg.pr.new/@modelcontextprotocol/server-map@798

@modelcontextprotocol/server-pdf

npm i https://pkg.pr.new/@modelcontextprotocol/server-pdf@798

@modelcontextprotocol/server-scenario-modeler

npm i https://pkg.pr.new/@modelcontextprotocol/server-scenario-modeler@798

@modelcontextprotocol/server-shadertoy

npm i https://pkg.pr.new/@modelcontextprotocol/server-shadertoy@798

@modelcontextprotocol/server-sheet-music

npm i https://pkg.pr.new/@modelcontextprotocol/server-sheet-music@798

@modelcontextprotocol/server-system-monitor

npm i https://pkg.pr.new/@modelcontextprotocol/server-system-monitor@798

@modelcontextprotocol/server-threejs

npm i https://pkg.pr.new/@modelcontextprotocol/server-threejs@798

@modelcontextprotocol/server-transcript

npm i https://pkg.pr.new/@modelcontextprotocol/server-transcript@798

@modelcontextprotocol/server-video-resource

npm i https://pkg.pr.new/@modelcontextprotocol/server-video-resource@798

@modelcontextprotocol/server-wiki-explorer

npm i https://pkg.pr.new/@modelcontextprotocol/server-wiki-explorer@798

commit: efcc19c

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant