Skip to main content
@mcp-b/webmcp-ts-sdk exports BrowserMcpServer, a WebMCP adapter that composes the official MCP TypeScript SDK v2 McpServer.
Most applications should use @mcp-b/global, which creates and installs the adapter on document.modelContext.

Minimal example

BrowserMcpServer

Constructor

BrowserMcpServerOptions extends the upstream ServerOptions type. The constructor uses document.modelContext, installing the bundled @mcp-b/webmcp-polyfill (about 28 KB minified) when needed. It leaves that document property pointing to the underlying context. Use @mcp-b/global to install the extended API on the document and connect its default transport. Without a WebMCP context, which is the case with no document (server-side module evaluation) or on an insecure page (the polyfill does not install), the constructor still succeeds and the server serves MCP only: registerTool(), registerPrompt(), registerResource(), listTools(), connect(), and close() work, tools are not mirrored to a browser context, getTools() and executeTool() reject with InvalidStateError, syncNativeTools() resolves without effect, and no toolchange events fire. In service workers or Node.js, use the official McpServer directly. The constructor passes the remaining options to McpServer and enables list-change support for tools, resources, and prompts.

mcpServer

The composed official server. Use it for upstream registration APIs and other MCP SDK v2 features that BrowserMcpServer does not wrap. Protocol-owned sampling and elicitation APIs are not direct BrowserMcpServer methods. Legacy push-style calls live on browserServer.mcpServer.server and depend on the negotiated protocol revision. WebMCP descriptor callbacks are single-round over MCP. An input_required result becomes a tool error. Register multi-round tools directly with browserServer.mcpServer.registerTool() so the official handler context owns the interaction.

WebMCP tool surface

The WebMCP Community Group draft is authoritative for the proposed browser API.

registerTool(tool, options?)

Registers a WebMCP descriptor and its MCP representation. Registration succeeds only after the upstream context accepts the tool. A tool registered with a non-empty exposedTo is advertised only while the connected peer’s origin appears in that list. BrowserMcpServer reads the origin from transports that report one, such as IframeChildTransport. Restricted tools fail closed: they stay hidden before the first peer origin arrives, and on transports that never report one. The supplied WebMCP context also validates the origin list before the tool is published. The vendored polyfill rejects opaque origins and browser-specific extension schemes. exposedTo only narrows. The child transport’s allowedOrigins still decides who may connect, and enforcement is the page’s own JavaScript rather than the user agent. See Bridge tools across iframes for the end-to-end setup. Invalid descriptors, duplicate names, blocked Permissions Policy, and pre-aborted signals reject the returned promise. Duplicate names count only this document’s registrations: a name held by a mirrored child-frame tool passes to the local registration once the upstream context accepts it.

getTools(options?)

Delegates to native.getTools(options). The supplied context owns discovery, frame access, and Permissions Policy checks.

executeTool(tool, input, options?)

Executes a descriptor returned by getTools() with an input object and returns the underlying context’s result string: JSON for imperative tools, plain text for native declarative tools. The optional signal aborts the call.

Lifecycle events

BrowserMcpServer extends EventTarget and exposes ontoolchange, ontoolactivated, and ontoolcancel. A native toolchange event triggers reconciliation before the adapter dispatches its own toolchange; a local registration produces one only after the underlying context reports it. The adapter re-dispatches the underlying context’s toolactivated and toolcancel events on itself as plain Event objects that carry the same toolName, so listeners on document.modelContext see them when @mcp-b/global is installed.

MCP-B extensions

isBrowserMcpServer(context)

Narrows an installed document.modelContext without changing the package’s global declaration or creating a second runtime handle.

listTools()

Returns a clone of the adapter’s MCP-B tool metadata, including outputSchema when registered.

syncNativeTools()

Reconciles the adapter with tools already visible through native.getTools(). A top-level document mirrors its own tools and those of same-origin descendant frames; a framed document (window.parent !== window) mirrors only its own tools. Backfill uses the native context’s executeTool() with object input. Over MCP, a native result that parses to a JSON object becomes structured content (an MCP result envelope passes through unchanged); any other result, including numbers, quoted strings, booleans, null, and arrays, is returned as text exactly as the context produced it. Later native toolchange events reconcile additions, metadata changes, and removals; when a mirrored frame is removed, the first failed call to one of its tools drops the stale mirrors. Use the Model Context Tool Inspector recommended by Chrome’s WebMCP documentation to inspect native and mirrored tools.

registerResource(descriptor)

Registers a fixed URI or URI template with the composed McpServer. The returned handle removes the registration through unregister(). A URI containing { registers a ResourceTemplate; its variables are passed to read as params. Other URIs register fixed resources.

registerPrompt(descriptor)

Registers a prompt with the composed McpServer. The returned handle removes the registration through unregister(). Prompt and resource discovery and invocation use MCP. Connect an MCP client; BrowserMcpServer does not duplicate the official list, read, or get methods. See Register prompts and resources for usage.

Transport lifecycle

connect(transport)

Connects the composed server. Custom tab and iframe transports use SDK v2’s legacy 2025-era route; see the upstream protocol revision guide.

close()

Stops native reconciliation, aborts native mirrors, removes registrations, and closes mcpServer. Repeated calls return the same promise.

Schema boundary

BrowserMcpServer normalizes JSON Schema and Standard JSON Schema inputs with normalizeInputSchema(). If the schema also supplies ~standard.validate(), the adapter preserves it for the composed McpServer. Otherwise the MCP server uses its fromJsonSchema adapter. This validation runs on MCP client calls. Direct executeTool() calls and native mirrors execute the browser callback without passing through MCP validation. Validate in the callback when both paths can call a tool, and pass plain JSON metadata so the MCP server does not also apply the vendor transforms. The schema guide demonstrates this pattern; @mcp-b/react-webmcp applies it for React registrations. A callback result is passed through as an MCP result only when it is a valid CallToolResult whose content items use the MCP content types; any other object, such as a rich-text document with its own type and content fields, becomes text plus structuredContent. outputSchema is enforced by the official MCP server on MCP calls. Direct browser calls do not perform that check. PromptDescriptor.argsSchema accepts InputSchema. Direct upstream server registrations support Zod 4.2 or newer and the official fromJsonSchema helper; Zod 3 is unsupported. MCP requires object-root tool input schemas. An array-root WebMCP tool remains available through WebMCP but is omitted from MCP discovery with a warning.

Exports

The root exports BrowserMcpServer, BrowserMcpServerOptions, isBrowserMcpServer, PromptDescriptor, ResourceDescriptor, ModelContext, ModelContextGetToolOptions, ModelContextRegisterToolOptions, RegisteredTool, ModelContextExtensions, ModelContextWithExtensions, ModelContextTool, InputSchema, WebMcpToolInput, WebMcpToolObjectInput, ToolDescriptor, ToolDescriptorFromSchema, ToolListItem, ToolAnnotations, MaybePromise, RegistrationHandle, JsonSchemaForInference, InferJsonSchema, InferArgsFromInputSchema, and ToolResultFromOutputSchema. The MCP result types CallToolResult, ContentBlock, TextContent, JsonObject, and JsonValue are re-exported from @modelcontextprotocol/server. WebMCP is the upstream namespace from webmcp-types, re-exported through @mcp-b/webmcp-polyfill so that the polyfill’s SubmitEvent and global ModelContext declarations reach consumers that import only this package. Import MCP clients, protocol schemas, transports, and validators from their official @modelcontextprotocol/* packages. The @mcp-b/webmcp-ts-sdk/schema subpath exports normalizeInputSchema(), normalizeToolResponse(), isMcpStandardSchema(), and the ToolInputSchema and NormalizedInputSchema types. The @mcp-b/transports reference documents browser transports. WebMCP and MCP-B extensions defines the boundary between the proposal and this adapter.