Skip to content

Run the tools in the browser via WebMCP - #32

Merged
benbalter merged 2 commits into
mainfrom
webmcp-browser
Oct 20, 2026
Merged

benbalter merged 2 commits into
mainfrom
webmcp-browser

Conversation

@benbalter

@benbalter benbalter commented Oct 20, 2026 •

Copy link
Copy Markdown
Member

Adds @open-and-async/mcp/browser, an entry point that registers the same 11 tools with a page's WebMCP model context. An agent in a WebMCP browser can then call them on open-and-async.com with nothing to install.

Why

The tools are pure functions over the bundled summaries (template formatting, lookups, keyword ranking). Nothing about them needs a local Node process, so running them in the page is the cheapest way to reach people who will never run npx. There's no server endpoint and nothing extra to deploy.

How

  • One source of truth for tools. src/book.js holds the runtime-neutral helpers plus a createBook() factory. src/data.js keeps every export it had, but is now just the Node loader for data/book.json.br. registerContentTools(server, data) takes the book as a parameter rather than importing data.js, so the tool modules never touch node: APIs.
  • src/browser.js collects the existing registerTool calls with a stand-in server (the same trick test/helpers.js already uses) and passes them to modelContext.registerTool():
    • Input is validated with each tool's own zod schema before the handler runs, the way McpServer does for stdio, so search_principles' limit bounds and the optional fields behave the same.
    • inputSchema comes from z.toJSONSchema(..., { io: "input" }).
    • zod runs jitless: its new Function probe otherwise logs a CSP violation on pages without 'unsafe-eval'.
    • A tool the browser rejects (say, a name clash) is skipped with a warning instead of failing the rest.
  • The page supplies the book data. Browsers can't decompress Brotli streams yet (Chrome 155's DecompressionStream has no 'brotli' format), and where the data lives is the page's call. The site gzips the package's .br at build time.
  • src/browser.d.ts types the entry point. The new exports map lists ./browser, ./data/book.json.br, and ./package.json. Nothing could import the package root before (no main, no root index.js), and npx/the bin aren't affected.
  • Bumps to 1.1.0 (new entry point) in all four version spots. The manifest.json tool list is unchanged.

What WebMCP doesn't carry

Tools only. There's no channel for the server instructions, resources, or prompts, so the once-per-session funnel line in tool output is the only attribution that reaches the agent. In the browser, each page load is one session.

Verification

  • Installed into the site from an npm pack tarball (so the files and exports filters apply): the site's build and CSP suites pass.
  • npm test: 54 pass on Node 24 and Node 18. The new test/browser.test.js:
    • walks the browser import graph for node: imports;
    • checks the WebMCP tool list matches the stdio server's exactly;
    • covers input validation, the skip-on-reject path, and the per-registration funnel.
  • End to end, in a real WebMCP browser: Playwright's Chromium 153 with --enable-experimental-web-platform-features exposes a native model context. Against a local build of the site, all 11 tools registered, triage_sync_vs_async executed, and there were no CSP violations once zod was jitless.

For the owner: data license

The site serves a gzip re-encoding of book.json.br at /webmcp/book.json.gz so the browser tools can read it. DATA-LICENSE.md permits use "solely as part of operating the @open-and-async/mcp software", which this arguably is, but it's still a second hosted copy. As the licensor, you may want the license to name the site explicitly. The README now says the browser entry point exists for open-and-async.com and that the license doesn't cover other sites hosting the data.

Releasing

The site PR depends on 1.1.0 being on npm. Publishing still goes through the tag and the release approvals. Nothing here tags or publishes.

🤖 Generated with Claude Code

benbalter and others added 2 commits October 20, 2026 13:32
WebMCP lets a page register tools with the browser so an in-page agent can
call them. These tools are pure functions over the bundled summaries, so
there's no reason they need a local Node process: open-and-async.com can
offer them to any visitor whose browser exposes a model context, with
nothing to install.

To share one set of tool definitions between stdio and the browser:

- src/book.js holds the runtime-neutral helpers and a createBook() factory.
  data.js keeps its exports but is now just the Node loader for
  data/book.json.br.
- registerContentTools takes the book as a parameter instead of importing
  data.js, so the tool modules never touch node: APIs.
- src/browser.js (@open-and-async/mcp/browser) collects the same
  registrations and hands them to registerTool(). Each call is validated
  with the tool's own zod schema first, the way McpServer does for stdio,
  so defaults and min/max limits still apply. zod runs jitless there:
  its eval probe otherwise logs a CSP violation on strict-CSP pages.

The page supplies the parsed book data rather than this module fetching
it, because browsers can't decompress Brotli streams yet and where the
data lives is the page's call.

test/browser.test.js walks the browser import graph for node: imports
and checks the WebMCP tool list matches the stdio server's.

Adds an exports map (./browser, the data file, package.json) and bumps
to 1.1.0 for the new entry point.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The data license only allows using book.json.br to operate this package.
A generic "pass in the book data" snippet read like an invitation for any
site to host it, so say the browser entry point exists for
open-and-async.com. Also say that the data has to be decoded first:
browsers can't decompress Brotli streams, which is why the site re-encodes
it as gzip.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@benbalter
benbalter merged commit 66c777d into main Oct 20, 2026
8 checks passed
@benbalter
benbalter deleted the webmcp-browser branch October 20, 2026 19:05
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