Advertise your existing MCP server's tools via WebMCP on your website so any browsing agent can use them.
WebMCP Proxy connects to a remote MCP server, discovers its tools, and registers them with the browser's navigator.modelContext API. When a browsing agent invokes a tool, the call is proxied to your MCP server and the result forwarded back.
npm install webmcp-proxyimport { createWebMcpProxy } from "webmcp-proxy";
const proxy = await createWebMcpProxy({
url: "https://mcp.example.com/mcp",
});
console.log("Registered tools:", proxy.tools);
// Later, to clean up:
await proxy.disconnect();import { WebMCPProxy } from "webmcp-proxy/react";
export default function App() {
return (
<>
<WebMCPProxy url="https://mcp.example.com/mcp" />
{/* Your app content */}
</>
);
}<script setup>
import { WebMCPProxy } from "webmcp-proxy/vue";
</script>
<template>
<WebMCPProxy url="https://mcp.example.com/mcp" />
<!-- Your app content -->
</template>All variants accept the same core options:
| Option | Type | Required | Description |
|---|---|---|---|
url |
string |
Yes | URL of the remote MCP server |
headers |
Record<string, string> |
No | Additional headers sent with every request (e.g. Authorization) |
sequenceDiagram
participant Page as Your Page
participant Proxy as webmcp-proxy
participant MCP as Remote MCP Server
participant Agent as Browsing Agent
Page->>Proxy: createWebMcpProxy({ url })
rect rgb(240, 240, 240)
note right of Proxy: Streamable HTTP, fallback to SSE
Proxy->>MCP: initialize
MCP-->>Proxy: capabilities
Proxy->>MCP: tools/list
MCP-->>Proxy: available tools
end
loop For each tool
Proxy->>Page: navigator.modelContext.registerTool()
end
Agent->>Page: Discovers tools via WebMCP
Agent->>Page: Calls a tool
Page->>Proxy: execute(args)
Proxy->>MCP: tools/call
MCP-->>Proxy: result
Proxy-->>Page: result
Page-->>Agent: result
WebMCP Proxy uses registerTool rather than provideContext to manage tools. This means it will not overwrite other tools the page registers on its own — as long as those also use registerTool. Proxy tools and page-local tools coexist safely side by side.
Tool unregistration is handled via AbortSignal (the recommended approach starting from Chrome 148). For backward compatibility with older browsers, unregisterTool() is also called when available.
A live demo is hosted at webmcp.netlify.app.
The demo/ folder contains a standalone React + Vite app that lets you enter an MCP server URL, connect to it, and see the tools it exposes — all registered via WebMCP in the browser.
To run the demo locally:
pnpm run demoThis starts the Vite dev server with a built-in CORS proxy so you can connect to any MCP server without cross-origin issues.
- The remote MCP server must support Streamable HTTP or SSE transport
- The MCP server must allow CORS requests from the browser origin
- The browser must support the WebMCP API (
navigator.modelContext) — if unavailable, the proxy logs a warning and becomes a no-op
ISC