@mcp-b/webmcp-ts-sdk 5.0.0 → 5.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -84,7 +84,7 @@ var BrowserMcpServer = class extends EventTarget {
|
|
|
84
84
|
});
|
|
85
85
|
this.native = native;
|
|
86
86
|
this.ownerDocument = globalThis.document ?? null;
|
|
87
|
-
if (native) {
|
|
87
|
+
if (native && typeof native.addEventListener === "function" && typeof native.removeEventListener === "function") {
|
|
88
88
|
this.nativeToolChangeListener = () => {
|
|
89
89
|
if (this.closed) return;
|
|
90
90
|
this.nativeToolChangeQueue = this.nativeToolChangeQueue.then(async () => {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../src/browser-server.ts"],"sourcesContent":["import {\n coerceWebMcpToolDescriptor,\n createInvalidStateError,\n createToolInvocationFailedError,\n createUnknownError,\n isPlainObject,\n normalizeToolResponse,\n normalizeInputSchema,\n parseChromeToolInput,\n serializeChromeToolResult,\n toWebMcpAnnotations,\n validateExecutableOrigin,\n validatePotentiallyTrustworthyOrigins,\n validateWebMcpAccess,\n validateWebMcpToolDescriptor,\n withAbortSignal,\n} from '@mcp-b/webmcp-polyfill/schema';\nimport type { NormalizedInputSchema } from '@mcp-b/webmcp-polyfill/schema';\nimport type {\n ChromeModelContextExecuteToolOptions,\n ChromeModelContextExtensions,\n InputSchema,\n ModelContext,\n ModelContextGetToolOptions,\n ModelContextRegisterToolOptions,\n ModelContextTool,\n ModelContextWithExtensions,\n RegistrationHandle,\n RegisteredTool,\n ToolAnnotations,\n ToolDescriptor,\n ToolListItem,\n WebMcpToolInput,\n} from '@mcp-b/webmcp-types';\nimport {\n fromJsonSchema,\n isInputRequiredResult,\n McpServer,\n mergeCapabilities,\n ResourceTemplate,\n type GetPromptResult,\n type Implementation,\n type ReadResourceResult,\n type RegisteredPrompt as McpRegisteredPrompt,\n type RegisteredResource as McpRegisteredResource,\n type RegisteredResourceTemplate as McpRegisteredResourceTemplate,\n type RegisteredTool as McpRegisteredTool,\n type ServerOptions,\n type StandardSchemaWithJSON,\n type ToolAnnotations as McpToolAnnotations,\n type Transport,\n type Variables,\n} from '@modelcontextprotocol/server';\n\nconst DEFAULT_INPUT_SCHEMA = normalizeInputSchema(undefined).inputSchema;\nconst SERVER_MARKER_PROPERTY = '__isBrowserMcpServer' as const;\n\nexport function isBrowserMcpServer(context: unknown): context is BrowserMcpServer {\n return (\n typeof context === 'object' &&\n context !== null &&\n SERVER_MARKER_PROPERTY in context &&\n context[SERVER_MARKER_PROPERTY] === true\n );\n}\n\ninterface RegisteredWebMcpTool {\n item: ToolListItem;\n registeredInputSchema?: string;\n execute: (args: WebMcpToolInput, signal?: AbortSignal) => Promise<unknown>;\n mcpHandle: McpRegisteredTool | undefined;\n exposedTo?: readonly string[];\n abortSignal?: AbortSignal;\n abortListener?: () => void;\n}\n\ntype McpRegistration = McpRegisteredPrompt | McpRegisteredResource | McpRegisteredResourceTemplate;\n\nexport interface BrowserMcpServerOptions extends ServerOptions {\n native?: ModelContext;\n}\n\ntype NativeStandardToolsApi = ModelContext & {\n executeTool: NonNullable<ChromeModelContextExtensions['executeTool']>;\n};\ntype NativeRegisterToolFn = (\n tool: ModelContextTool<WebMcpToolInput>,\n options?: ModelContextRegisterToolOptions\n) => Promise<void>;\n\ninterface NativeBackfilledTool {\n source: RegisteredTool;\n item: ToolListItem;\n fingerprint: string;\n}\n\nfunction parseNativeToolResult(serialized: string | null): unknown {\n if (serialized === null) {\n return {\n content: [{ type: 'text', text: 'Tool execution interrupted by navigation' }],\n isError: true,\n };\n }\n\n let result: unknown;\n try {\n result = JSON.parse(serialized);\n } catch {\n return normalizeToolResponse(serialized);\n }\n return isInputRequiredResult(result) ? result : normalizeToolResponse(result);\n}\n\nfunction toMcpInputSchema(\n normalized: NormalizedInputSchema\n): StandardSchemaWithJSON<Record<string, unknown>> {\n // normalizeInputSchema() attaches a non-enumerable `~standard` when the caller supplied a\n // Standard Schema validator, so reuse it instead of recompiling the JSON Schema projection.\n const standardSchema = Object.getOwnPropertyDescriptor(normalized.inputSchema, '~standard');\n return standardSchema && !standardSchema.enumerable\n ? (normalized.inputSchema as unknown as StandardSchemaWithJSON<Record<string, unknown>>)\n : fromJsonSchema<Record<string, unknown>>(\n normalized.inputSchema as Parameters<typeof fromJsonSchema>[0]\n );\n}\n\nfunction toMcpAnnotations(\n annotations: ToolAnnotations | undefined\n): McpToolAnnotations | undefined {\n if (!annotations) return undefined;\n const { untrustedContentHint: _untrustedContentHint, ...mcpAnnotations } = annotations;\n return mcpAnnotations;\n}\n\nfunction toNativeTool(\n tool: ToolDescriptor<WebMcpToolInput>,\n inputSchema: InputSchema | undefined,\n execute: ModelContextTool<WebMcpToolInput>['execute']\n): ModelContextTool<WebMcpToolInput> {\n const annotations = tool.annotations ? toWebMcpAnnotations(tool.annotations) : undefined;\n return {\n name: tool.name,\n ...(tool.title !== undefined ? { title: tool.title } : {}),\n description: tool.description,\n ...(inputSchema !== undefined ? { inputSchema } : {}),\n ...(annotations ? { annotations } : {}),\n execute,\n };\n}\n\n/**\n * Thin WebMCP-to-MCP v2 adapter.\n *\n * The official v2 `McpServer` owns MCP registration, validation, and transport\n * behavior. This class only adds the document-facing WebMCP contract and native\n * Chrome mirroring.\n */\nexport class BrowserMcpServer extends EventTarget implements ModelContextWithExtensions {\n readonly [SERVER_MARKER_PROPERTY] = true as const;\n readonly mcpServer: McpServer;\n\n private readonly native: ModelContext | undefined;\n private readonly ownerDocument: Document | null;\n private readonly tools = new Map<string, RegisteredWebMcpTool>();\n private peerOrigin: string | undefined;\n private readonly registrations = new Set<McpRegistration>();\n private readonly nativeToolAbortControllers = new Map<string, AbortController>();\n private readonly nativeBackfilledTools = new Map<string, NativeBackfilledTool>();\n private readonly pendingTools = new Map<string, AbortController>();\n private readonly removingNativeTools = new Set<string>();\n private nativeSyncQueue: Promise<void> = Promise.resolve();\n private nativeToolChangeQueue: Promise<void> = Promise.resolve();\n private nativeToolChangeListener: EventListener | undefined;\n private closed = false;\n private closePromise: Promise<void> | undefined;\n private ontoolchangeHandler: ((this: ModelContext, event: Event) => unknown) | null = null;\n private readonly ontoolchangeListener: EventListener = (event) => {\n this.ontoolchangeHandler?.call(this, event);\n };\n\n constructor(serverInfo: Implementation, options: BrowserMcpServerOptions = {}) {\n super();\n const { native, ...serverOptions } = options;\n this.mcpServer = new McpServer(serverInfo, {\n ...serverOptions,\n capabilities: mergeCapabilities(serverOptions.capabilities ?? {}, {\n tools: { listChanged: true },\n resources: { listChanged: true },\n prompts: { listChanged: true },\n }),\n });\n this.native = native;\n this.ownerDocument = globalThis.document ?? null;\n if (native) {\n this.nativeToolChangeListener = () => {\n if (this.closed) return;\n this.nativeToolChangeQueue = this.nativeToolChangeQueue.then(async () => {\n try {\n await this.syncNativeTools();\n } catch (error) {\n console.warn('[BrowserMcpServer] Native WebMCP tool reconciliation failed:', error);\n }\n await this.notifyProducerToolsChanged();\n });\n };\n native.addEventListener('toolchange', this.nativeToolChangeListener);\n }\n }\n\n get ontoolchange(): ((this: ModelContext, event: Event) => unknown) | null {\n return this.ontoolchangeHandler;\n }\n\n set ontoolchange(handler: ((this: ModelContext, event: Event) => unknown) | null) {\n const listener = typeof handler === 'function' ? handler : null;\n if (listener === null) {\n this.ontoolchangeHandler = null;\n super.removeEventListener('toolchange', this.ontoolchangeListener);\n return;\n }\n\n if (this.ontoolchangeHandler === null) {\n super.addEventListener('toolchange', this.ontoolchangeListener);\n }\n this.ontoolchangeHandler = listener;\n }\n\n private async notifyProducerToolsChanged(): Promise<void> {\n if (this.closed) return;\n // Preserve task ordering because WebMCP does not expose its platform task source.\n await new Promise((resolve) => setTimeout(resolve, 0));\n if (!this.closed) this.dispatchEvent(new Event('toolchange'));\n }\n\n private getNativeStandardToolsApi(): NativeStandardToolsApi | undefined {\n const candidate: (ModelContext & Partial<ChromeModelContextExtensions>) | undefined =\n this.native;\n return candidate && typeof candidate.executeTool === 'function'\n ? (candidate as NativeStandardToolsApi)\n : undefined;\n }\n\n private async registerNativeToolMirror(\n tool: ToolDescriptor<WebMcpToolInput>,\n normalized: NormalizedInputSchema,\n options: ModelContextRegisterToolOptions,\n execute: RegisteredWebMcpTool['execute'],\n controller: AbortController\n ): Promise<void> {\n if (!this.native) return;\n\n // The overload set keys on a statically known inputSchema; mirrored tools carry a dynamic one.\n const nativeRegister = this.native.registerTool as unknown as NativeRegisterToolFn;\n const signal = options.signal\n ? AbortSignal.any([options.signal, controller.signal])\n : controller.signal;\n\n const nativeInputSchema =\n normalized.registeredInputSchema === undefined\n ? undefined\n : (JSON.parse(normalized.registeredInputSchema) as InputSchema);\n this.nativeToolAbortControllers.set(tool.name, controller);\n try {\n await nativeRegister.call(\n this.native,\n toNativeTool(tool, nativeInputSchema, (input) => execute(input)),\n { ...options, signal }\n );\n } catch (error) {\n controller.abort();\n if (this.nativeToolAbortControllers.get(tool.name) === controller) {\n this.nativeToolAbortControllers.delete(tool.name);\n }\n throw error;\n }\n if (this.nativeToolAbortControllers.get(tool.name) === controller) {\n this.removingNativeTools.delete(tool.name);\n }\n }\n\n private abortNativeToolMirror(\n name: string,\n controller = this.nativeToolAbortControllers.get(name)\n ): void {\n if (!controller || this.nativeToolAbortControllers.get(name) !== controller) return;\n this.removingNativeTools.add(name);\n controller.abort();\n this.nativeToolAbortControllers.delete(name);\n }\n\n private validateToolDescriptor(tool: ToolDescriptor<WebMcpToolInput>): NormalizedInputSchema {\n validateWebMcpToolDescriptor(tool);\n if (this.tools.has(tool.name) || this.pendingTools.has(tool.name)) {\n throw createInvalidStateError(`Tool already registered: ${tool.name}`);\n }\n return normalizeInputSchema(tool.inputSchema);\n }\n\n private registerToolInMcp(\n tool: ToolDescriptor<WebMcpToolInput>,\n normalized: NormalizedInputSchema,\n executeTool: RegisteredWebMcpTool['execute'],\n exposedTo: readonly string[] | undefined\n ): RegisteredWebMcpTool {\n const outputSchema =\n tool.outputSchema === undefined ? undefined : structuredClone(tool.outputSchema);\n const mcpOutputSchema =\n outputSchema === undefined\n ? undefined\n : fromJsonSchema(outputSchema as Parameters<typeof fromJsonSchema>[0]);\n const mcpAnnotations = toMcpAnnotations(tool.annotations);\n const mcpCompatibleInput =\n normalized.inputSchema.type === undefined || normalized.inputSchema.type === 'object';\n const mcpHandle = mcpCompatibleInput\n ? this.mcpServer.registerTool(\n tool.name,\n {\n ...(tool.title !== undefined ? { title: tool.title } : {}),\n description: tool.description,\n inputSchema: toMcpInputSchema(normalized),\n ...(mcpOutputSchema ? { outputSchema: mcpOutputSchema } : {}),\n ...(mcpAnnotations ? { annotations: mcpAnnotations } : {}),\n },\n async (args, context) => {\n const result = await executeTool(args, context.mcpReq.signal);\n if (isInputRequiredResult(result)) {\n throw new Error(\n `WebMCP tool \"${tool.name}\" returned input_required. Multi-round tool flows require BrowserMcpServer.mcpServer.registerTool().`\n );\n }\n return normalizeToolResponse(result);\n }\n )\n : undefined;\n // A restricted tool is never observable on the wire before its audience is\n // checked: the handle is disabled here, in the same synchronous step that created\n // it, and only applyToolExposure re-enables it.\n if (exposedTo?.length) mcpHandle?.disable();\n\n if (!mcpCompatibleInput) {\n console.warn(\n `[BrowserMcpServer] Tool \"${tool.name}\" remains available through WebMCP but cannot be exposed over MCP because MCP input schemas require an object root.`\n );\n }\n\n const item: ToolListItem = {\n name: tool.name,\n ...(tool.title !== undefined ? { title: tool.title } : {}),\n description: tool.description,\n inputSchema: normalized.inputSchema,\n ...(outputSchema === undefined ? {} : { outputSchema }),\n ...(tool.annotations ? { annotations: tool.annotations } : {}),\n };\n return {\n item,\n ...(normalized.registeredInputSchema !== undefined\n ? { registeredInputSchema: normalized.registeredInputSchema }\n : {}),\n execute: executeTool,\n mcpHandle,\n ...(exposedTo?.length ? { exposedTo } : {}),\n };\n }\n\n readonly registerTool: ModelContextWithExtensions['registerTool'] = async (\n toolValue: unknown,\n optionsValue: ModelContextRegisterToolOptions | null = {}\n ): Promise<void> => {\n const options = optionsValue ?? {};\n validateWebMcpAccess(this.ownerDocument);\n if (this.closed) throw createInvalidStateError('BrowserMcpServer is closed');\n if (!isPlainObject(toolValue)) {\n throw new TypeError('registerTool(tool) requires a tool object');\n }\n const tool = coerceWebMcpToolDescriptor(toolValue);\n const normalized = this.validateToolDescriptor(tool);\n options.signal?.throwIfAborted();\n validatePotentiallyTrustworthyOrigins(options.exposedTo);\n options.signal?.throwIfAborted();\n const execute: RegisteredWebMcpTool['execute'] = async (args, signal) => {\n signal?.throwIfAborted();\n return withAbortSignal(\n Promise.resolve().then(() => Reflect.apply(tool.execute, undefined, [args])),\n signal\n );\n };\n const controller = new AbortController();\n let registered: RegisteredWebMcpTool | undefined;\n const abort = () => {\n if (this.pendingTools.get(tool.name) === controller) {\n this.pendingTools.delete(tool.name);\n }\n if (registered && this.tools.get(tool.name) === registered) {\n this.removeTool(tool.name);\n } else {\n this.abortNativeToolMirror(tool.name, controller);\n }\n };\n options.signal?.addEventListener('abort', abort, { once: true });\n this.pendingTools.set(tool.name, controller);\n try {\n await this.registerNativeToolMirror(tool, normalized, options, execute, controller);\n if (this.closed) throw createInvalidStateError('BrowserMcpServer is closed');\n options.signal?.throwIfAborted();\n registered = this.registerToolInMcp(tool, normalized, execute, options.exposedTo);\n this.tools.set(tool.name, registered);\n this.applyToolExposure();\n if (options.signal?.aborted) {\n abort();\n options.signal.throwIfAborted();\n }\n } catch (error) {\n this.abortNativeToolMirror(tool.name, controller);\n options.signal?.removeEventListener('abort', abort);\n options.signal?.throwIfAborted();\n throw error;\n } finally {\n if (this.pendingTools.get(tool.name) === controller) {\n this.pendingTools.delete(tool.name);\n }\n }\n if (options.signal) {\n registered.abortSignal = options.signal;\n registered.abortListener = abort;\n }\n if (this.tools.get(tool.name) === registered) {\n if (this.native) await this.nativeToolChangeQueue;\n else await this.notifyProducerToolsChanged();\n }\n if (this.closed) throw createInvalidStateError('BrowserMcpServer is closed');\n options.signal?.throwIfAborted();\n };\n\n private removeTool(name: string, options?: { skipNative?: boolean; notify?: boolean }): void {\n const registered = this.tools.get(name);\n if (registered) {\n if (registered.abortSignal && registered.abortListener) {\n registered.abortSignal.removeEventListener('abort', registered.abortListener);\n }\n this.tools.delete(name);\n this.nativeBackfilledTools.delete(name);\n registered.mcpHandle?.remove();\n if ((options?.notify ?? true) && !this.native) {\n void this.notifyProducerToolsChanged();\n }\n }\n if (!options?.skipNative) this.abortNativeToolMirror(name);\n }\n\n syncNativeTools(): Promise<void> {\n const sync = this.nativeSyncQueue.then(async () => {\n if (this.closed) return;\n const native = this.getNativeStandardToolsApi();\n if (native) await this.backfillNativeStandardTools(native);\n });\n this.nativeSyncQueue = sync.then(\n () => undefined,\n () => undefined\n );\n return sync;\n }\n\n private async backfillNativeStandardTools(native: NativeStandardToolsApi): Promise<void> {\n const tools = await native.getTools();\n if (this.closed) return;\n const nextTools = new Map<string, NativeBackfilledTool>();\n const nativeNames = new Set(tools.map(({ name }) => name));\n for (const name of this.removingNativeTools) {\n if (!nativeNames.has(name)) this.removingNativeTools.delete(name);\n }\n for (const tool of tools) {\n // ponytail: MCP tool names are global, so keep the first valid visible tool.\n // Add origin-qualified aliases if MCP gains scoped tool identity.\n if (\n nextTools.has(tool.name) ||\n this.pendingTools.has(tool.name) ||\n this.removingNativeTools.has(tool.name)\n ) {\n continue;\n }\n let inputSchema: InputSchema | undefined = DEFAULT_INPUT_SCHEMA;\n if (tool.inputSchema !== undefined) {\n try {\n // An object since webmcp#241; a serialized string from older Chrome. The\n // round-trip detaches the object from the page's graph and rejects non-JSON.\n const serialized =\n typeof tool.inputSchema === 'string'\n ? tool.inputSchema\n : JSON.stringify(tool.inputSchema);\n const parsed: unknown = JSON.parse(serialized);\n inputSchema = isPlainObject(parsed) ? (parsed as InputSchema) : undefined;\n } catch {\n inputSchema = undefined;\n }\n }\n if (!inputSchema) {\n console.warn(\n `[BrowserMcpServer] Native tool \"${tool.name}\" was not exposed over MCP because its input schema is malformed.`\n );\n continue;\n }\n const item: ToolListItem = {\n name: tool.name,\n ...(tool.title !== undefined ? { title: tool.title } : {}),\n description: tool.description,\n inputSchema,\n ...(tool.annotations ? { annotations: tool.annotations } : {}),\n };\n nextTools.set(tool.name, {\n source: tool,\n item,\n fingerprint: JSON.stringify(item),\n });\n }\n\n for (const [name, current] of this.nativeBackfilledTools) {\n const next = nextTools.get(name);\n if (!next || next.fingerprint !== current.fingerprint) {\n this.removeTool(name, { skipNative: true, notify: false });\n continue;\n }\n this.nativeBackfilledTools.set(name, next);\n }\n\n for (const [name, next] of nextTools) {\n if (this.tools.has(name)) continue;\n const execute = async (args: WebMcpToolInput, signal?: AbortSignal) => {\n const currentTool = this.nativeBackfilledTools.get(name)?.source;\n if (!currentTool) throw new Error(`Native tool not found: ${name}`);\n const input = JSON.stringify(args);\n return parseNativeToolResult(\n signal\n ? await native.executeTool.call(this.native, currentTool, input, { signal })\n : await native.executeTool.call(this.native, currentTool, input)\n );\n };\n const tool: ToolDescriptor<WebMcpToolInput> = {\n name,\n ...(next.item.title !== undefined ? { title: next.item.title } : {}),\n description: next.item.description,\n inputSchema: next.item.inputSchema,\n ...(next.item.annotations ? { annotations: next.item.annotations } : {}),\n execute: (args) => execute(args),\n };\n try {\n const normalized = this.validateToolDescriptor(tool);\n // Native getTools() does not report the allowlist a tool registered with, so a\n // backfilled mirror carries none and stays as widely exposed as it is today.\n this.tools.set(tool.name, this.registerToolInMcp(tool, normalized, execute, undefined));\n this.nativeBackfilledTools.set(name, next);\n } catch (error) {\n console.warn(\n `[BrowserMcpServer] Native tool \"${name}\" was not exposed over MCP because its schema could not be compiled:`,\n error\n );\n }\n }\n }\n\n registerResource(descriptor: ResourceDescriptor): RegistrationHandle {\n if (this.closed) throw createInvalidStateError('BrowserMcpServer is closed');\n const registeredDescriptor = { ...descriptor };\n const config = {\n ...(registeredDescriptor.description !== undefined\n ? { description: registeredDescriptor.description }\n : {}),\n ...(registeredDescriptor.mimeType !== undefined\n ? { mimeType: registeredDescriptor.mimeType }\n : {}),\n };\n const template = registeredDescriptor.uri.includes('{')\n ? new ResourceTemplate(registeredDescriptor.uri, { list: undefined })\n : undefined;\n const mcpHandle = template\n ? this.mcpServer.registerResource(\n registeredDescriptor.name,\n template,\n config,\n async (uri, variables) => registeredDescriptor.read(uri, variables)\n )\n : this.mcpServer.registerResource(\n registeredDescriptor.name,\n registeredDescriptor.uri,\n config,\n async (uri) => registeredDescriptor.read(uri)\n );\n this.registrations.add(mcpHandle);\n return {\n unregister: () => {\n if (this.registrations.delete(mcpHandle)) mcpHandle.remove();\n },\n };\n }\n\n registerPrompt(descriptor: PromptDescriptor): RegistrationHandle {\n if (this.closed) throw createInvalidStateError('BrowserMcpServer is closed');\n const registeredDescriptor = {\n ...descriptor,\n ...(descriptor.argsSchema === undefined\n ? {}\n : { argsSchema: structuredClone(descriptor.argsSchema) }),\n };\n const argsSchema =\n registeredDescriptor.argsSchema === undefined\n ? undefined\n : fromJsonSchema<Record<string, string>>(\n registeredDescriptor.argsSchema as Parameters<typeof fromJsonSchema>[0]\n );\n const mcpHandle = this.mcpServer.registerPrompt(\n registeredDescriptor.name,\n {\n ...(registeredDescriptor.description !== undefined\n ? { description: registeredDescriptor.description }\n : {}),\n ...(argsSchema ? { argsSchema } : {}),\n },\n async (args) => registeredDescriptor.get(args ?? {})\n );\n this.registrations.add(mcpHandle);\n return {\n unregister: () => {\n if (this.registrations.delete(mcpHandle)) mcpHandle.remove();\n },\n };\n }\n\n listTools(): ToolListItem[] {\n return structuredClone([...this.tools.values()].map(({ item }) => item));\n }\n\n async getTools(options?: ModelContextGetToolOptions): Promise<RegisteredTool[]> {\n validateWebMcpAccess(this.ownerDocument);\n if (this.closed) throw createInvalidStateError('BrowserMcpServer is closed');\n if (this.native) {\n return this.native.getTools(options);\n }\n validatePotentiallyTrustworthyOrigins(options?.fromOrigins);\n if (options?.fromOrigins?.length) {\n throw new DOMException(\n 'Cross-document tool discovery requires native WebMCP',\n 'NotSupportedError'\n );\n }\n\n const origin = globalThis.location?.origin ?? '';\n const currentWindow = globalThis.window;\n\n const tools = [...this.tools.values()]\n .map(({ item, registeredInputSchema }) => {\n // A fresh object per call, aligned with the polyfill's post-webmcp#241\n // shape. A custom toJSON can serialize to non-object JSON; omit those\n // rather than emit a value consumers would mistake for a pre-154\n // serialized string.\n const parsed: unknown =\n registeredInputSchema === undefined ? undefined : JSON.parse(registeredInputSchema);\n return {\n name: item.name,\n title: item.title ?? '',\n description: item.description,\n ...(isPlainObject(parsed) ? { inputSchema: parsed } : {}),\n origin,\n window: currentWindow,\n ...(item.annotations ? { annotations: toWebMcpAnnotations(item.annotations) } : {}),\n };\n })\n .sort((a, b) => (a.name < b.name ? -1 : a.name > b.name ? 1 : 0));\n await new Promise((resolve) => setTimeout(resolve, 0));\n return tools;\n }\n\n async executeTool(\n tool: RegisteredTool,\n inputArgsJson: string,\n options?: ChromeModelContextExecuteToolOptions\n ): Promise<string | null> {\n validateWebMcpAccess(this.ownerDocument);\n if (this.closed) throw createInvalidStateError('BrowserMcpServer is closed');\n const native = this.getNativeStandardToolsApi();\n if (native) {\n return native.executeTool.call(this.native, tool, inputArgsJson, options);\n }\n\n if (tool === null || typeof tool !== 'object') {\n throw new TypeError('RegisteredTool must be an object');\n }\n for (const required of ['name', 'description', 'window', 'origin'] as const) {\n if (!(required in tool)) {\n throw new TypeError(`RegisteredTool.${required} is required`);\n }\n }\n validateExecutableOrigin(tool.origin);\n const origin = globalThis.location?.origin ?? '';\n const currentWindow = globalThis.window;\n if (tool.origin !== origin || tool.window !== currentWindow) {\n throw createUnknownError(`Native tool not found: ${tool.name}`);\n }\n options?.signal?.throwIfAborted();\n const registered = this.tools.get(tool.name);\n if (!registered) throw createUnknownError(`Tool not found: ${tool.name}`);\n const args = parseChromeToolInput(inputArgsJson);\n try {\n const result = await withAbortSignal(\n registered.execute(args, options?.signal),\n registered.abortSignal,\n () => createUnknownError('Tool unregistered')\n );\n return serializeChromeToolResult(result);\n } catch (error) {\n if (options?.signal?.aborted && error === options.signal.reason) throw error;\n if (registered.abortSignal?.aborted) throw error;\n throw createToolInvocationFailedError(error);\n }\n }\n\n /**\n * Re-evaluate which registered tools may appear on the wire.\n *\n * `exposedTo` narrows a tool to named embedder origins. The peer origin is only known\n * once a transport that reports one has heard from its peer, so a restricted tool stays\n * disabled until then — and stays disabled forever on transports that cannot name a peer\n * at all. Failing closed keeps a tool that asked for a narrow audience from reaching a\n * wider one; unrestricted tools are untouched and behave exactly as before.\n */\n private applyToolExposure(): void {\n for (const { exposedTo, mcpHandle } of this.tools.values()) {\n if (!exposedTo?.length || !mcpHandle) continue;\n const visible = this.peerOrigin !== undefined && exposedTo.includes(this.peerOrigin);\n if (visible === mcpHandle.enabled) continue;\n if (visible) mcpHandle.enable();\n else mcpHandle.disable();\n }\n }\n\n /**\n * Follow the peer origin of transports that report one, so `exposedTo` can be scoped to\n * the embedder actually connected. Duck-typed rather than imported: the SDK must not take\n * a build dependency on `@mcp-b/transports`, and transports that never name a peer simply\n * leave every restricted tool disabled.\n */\n private observePeerOrigin(transport: Transport): void {\n if (!('clientOrigin' in transport)) return;\n const peered = transport as Transport & {\n clientOrigin?: string;\n onclientorigin?: (origin: string) => void;\n };\n this.peerOrigin = peered.clientOrigin;\n this.applyToolExposure();\n const previous = peered.onclientorigin;\n peered.onclientorigin = (origin) => {\n previous?.(origin);\n this.peerOrigin = origin;\n this.applyToolExposure();\n };\n }\n\n connect(transport: Transport): Promise<void> {\n if (this.closed) return Promise.reject(createInvalidStateError('BrowserMcpServer is closed'));\n this.observePeerOrigin(transport);\n return this.mcpServer.connect(transport);\n }\n\n close(): Promise<void> {\n if (this.closePromise) return this.closePromise;\n this.closed = true;\n this.closePromise = (async () => {\n if (this.native && this.nativeToolChangeListener) {\n this.native.removeEventListener('toolchange', this.nativeToolChangeListener);\n this.nativeToolChangeListener = undefined;\n }\n for (const name of this.nativeToolAbortControllers.keys()) {\n this.abortNativeToolMirror(name);\n }\n for (const name of this.tools.keys()) {\n this.removeTool(name, { notify: false });\n }\n for (const handle of this.registrations) handle.remove();\n this.registrations.clear();\n this.nativeBackfilledTools.clear();\n this.removingNativeTools.clear();\n await this.mcpServer.close();\n })();\n return this.closePromise;\n }\n}\n\nexport interface ResourceDescriptor {\n uri: string;\n name: string;\n description?: string;\n mimeType?: string;\n read: (uri: URL, params?: Variables) => Promise<ReadResourceResult>;\n}\n\nexport interface PromptDescriptor {\n name: string;\n description?: string;\n argsSchema?: InputSchema;\n get: (args: Record<string, string>) => Promise<GetPromptResult>;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/browser-server.ts"],"sourcesContent":["import {\n coerceWebMcpToolDescriptor,\n createInvalidStateError,\n createToolInvocationFailedError,\n createUnknownError,\n isPlainObject,\n normalizeToolResponse,\n normalizeInputSchema,\n parseChromeToolInput,\n serializeChromeToolResult,\n toWebMcpAnnotations,\n validateExecutableOrigin,\n validatePotentiallyTrustworthyOrigins,\n validateWebMcpAccess,\n validateWebMcpToolDescriptor,\n withAbortSignal,\n} from '@mcp-b/webmcp-polyfill/schema';\nimport type { NormalizedInputSchema } from '@mcp-b/webmcp-polyfill/schema';\nimport type {\n ChromeModelContextExecuteToolOptions,\n ChromeModelContextExtensions,\n InputSchema,\n ModelContext,\n ModelContextGetToolOptions,\n ModelContextRegisterToolOptions,\n ModelContextTool,\n ModelContextWithExtensions,\n RegistrationHandle,\n RegisteredTool,\n ToolAnnotations,\n ToolDescriptor,\n ToolListItem,\n WebMcpToolInput,\n} from '@mcp-b/webmcp-types';\nimport {\n fromJsonSchema,\n isInputRequiredResult,\n McpServer,\n mergeCapabilities,\n ResourceTemplate,\n type GetPromptResult,\n type Implementation,\n type ReadResourceResult,\n type RegisteredPrompt as McpRegisteredPrompt,\n type RegisteredResource as McpRegisteredResource,\n type RegisteredResourceTemplate as McpRegisteredResourceTemplate,\n type RegisteredTool as McpRegisteredTool,\n type ServerOptions,\n type StandardSchemaWithJSON,\n type ToolAnnotations as McpToolAnnotations,\n type Transport,\n type Variables,\n} from '@modelcontextprotocol/server';\n\nconst DEFAULT_INPUT_SCHEMA = normalizeInputSchema(undefined).inputSchema;\nconst SERVER_MARKER_PROPERTY = '__isBrowserMcpServer' as const;\n\nexport function isBrowserMcpServer(context: unknown): context is BrowserMcpServer {\n return (\n typeof context === 'object' &&\n context !== null &&\n SERVER_MARKER_PROPERTY in context &&\n context[SERVER_MARKER_PROPERTY] === true\n );\n}\n\ninterface RegisteredWebMcpTool {\n item: ToolListItem;\n registeredInputSchema?: string;\n execute: (args: WebMcpToolInput, signal?: AbortSignal) => Promise<unknown>;\n mcpHandle: McpRegisteredTool | undefined;\n exposedTo?: readonly string[];\n abortSignal?: AbortSignal;\n abortListener?: () => void;\n}\n\ntype McpRegistration = McpRegisteredPrompt | McpRegisteredResource | McpRegisteredResourceTemplate;\n\nexport interface BrowserMcpServerOptions extends ServerOptions {\n native?: ModelContext;\n}\n\ntype NativeStandardToolsApi = ModelContext & {\n executeTool: NonNullable<ChromeModelContextExtensions['executeTool']>;\n};\ntype NativeRegisterToolFn = (\n tool: ModelContextTool<WebMcpToolInput>,\n options?: ModelContextRegisterToolOptions\n) => Promise<void>;\n\ninterface NativeBackfilledTool {\n source: RegisteredTool;\n item: ToolListItem;\n fingerprint: string;\n}\n\nfunction parseNativeToolResult(serialized: string | null): unknown {\n if (serialized === null) {\n return {\n content: [{ type: 'text', text: 'Tool execution interrupted by navigation' }],\n isError: true,\n };\n }\n\n let result: unknown;\n try {\n result = JSON.parse(serialized);\n } catch {\n return normalizeToolResponse(serialized);\n }\n return isInputRequiredResult(result) ? result : normalizeToolResponse(result);\n}\n\nfunction toMcpInputSchema(\n normalized: NormalizedInputSchema\n): StandardSchemaWithJSON<Record<string, unknown>> {\n // normalizeInputSchema() attaches a non-enumerable `~standard` when the caller supplied a\n // Standard Schema validator, so reuse it instead of recompiling the JSON Schema projection.\n const standardSchema = Object.getOwnPropertyDescriptor(normalized.inputSchema, '~standard');\n return standardSchema && !standardSchema.enumerable\n ? (normalized.inputSchema as unknown as StandardSchemaWithJSON<Record<string, unknown>>)\n : fromJsonSchema<Record<string, unknown>>(\n normalized.inputSchema as Parameters<typeof fromJsonSchema>[0]\n );\n}\n\nfunction toMcpAnnotations(\n annotations: ToolAnnotations | undefined\n): McpToolAnnotations | undefined {\n if (!annotations) return undefined;\n const { untrustedContentHint: _untrustedContentHint, ...mcpAnnotations } = annotations;\n return mcpAnnotations;\n}\n\nfunction toNativeTool(\n tool: ToolDescriptor<WebMcpToolInput>,\n inputSchema: InputSchema | undefined,\n execute: ModelContextTool<WebMcpToolInput>['execute']\n): ModelContextTool<WebMcpToolInput> {\n const annotations = tool.annotations ? toWebMcpAnnotations(tool.annotations) : undefined;\n return {\n name: tool.name,\n ...(tool.title !== undefined ? { title: tool.title } : {}),\n description: tool.description,\n ...(inputSchema !== undefined ? { inputSchema } : {}),\n ...(annotations ? { annotations } : {}),\n execute,\n };\n}\n\n/**\n * Thin WebMCP-to-MCP v2 adapter.\n *\n * The official v2 `McpServer` owns MCP registration, validation, and transport\n * behavior. This class only adds the document-facing WebMCP contract and native\n * Chrome mirroring.\n */\nexport class BrowserMcpServer extends EventTarget implements ModelContextWithExtensions {\n readonly [SERVER_MARKER_PROPERTY] = true as const;\n readonly mcpServer: McpServer;\n\n private readonly native: ModelContext | undefined;\n private readonly ownerDocument: Document | null;\n private readonly tools = new Map<string, RegisteredWebMcpTool>();\n private peerOrigin: string | undefined;\n private readonly registrations = new Set<McpRegistration>();\n private readonly nativeToolAbortControllers = new Map<string, AbortController>();\n private readonly nativeBackfilledTools = new Map<string, NativeBackfilledTool>();\n private readonly pendingTools = new Map<string, AbortController>();\n private readonly removingNativeTools = new Set<string>();\n private nativeSyncQueue: Promise<void> = Promise.resolve();\n private nativeToolChangeQueue: Promise<void> = Promise.resolve();\n private nativeToolChangeListener: EventListener | undefined;\n private closed = false;\n private closePromise: Promise<void> | undefined;\n private ontoolchangeHandler: ((this: ModelContext, event: Event) => unknown) | null = null;\n private readonly ontoolchangeListener: EventListener = (event) => {\n this.ontoolchangeHandler?.call(this, event);\n };\n\n constructor(serverInfo: Implementation, options: BrowserMcpServerOptions = {}) {\n super();\n const { native, ...serverOptions } = options;\n this.mcpServer = new McpServer(serverInfo, {\n ...serverOptions,\n capabilities: mergeCapabilities(serverOptions.capabilities ?? {}, {\n tools: { listChanged: true },\n resources: { listChanged: true },\n prompts: { listChanged: true },\n }),\n });\n this.native = native;\n this.ownerDocument = globalThis.document ?? null;\n if (\n native &&\n typeof native.addEventListener === 'function' &&\n typeof native.removeEventListener === 'function'\n ) {\n this.nativeToolChangeListener = () => {\n if (this.closed) return;\n this.nativeToolChangeQueue = this.nativeToolChangeQueue.then(async () => {\n try {\n await this.syncNativeTools();\n } catch (error) {\n console.warn('[BrowserMcpServer] Native WebMCP tool reconciliation failed:', error);\n }\n await this.notifyProducerToolsChanged();\n });\n };\n native.addEventListener('toolchange', this.nativeToolChangeListener);\n }\n }\n\n get ontoolchange(): ((this: ModelContext, event: Event) => unknown) | null {\n return this.ontoolchangeHandler;\n }\n\n set ontoolchange(handler: ((this: ModelContext, event: Event) => unknown) | null) {\n const listener = typeof handler === 'function' ? handler : null;\n if (listener === null) {\n this.ontoolchangeHandler = null;\n super.removeEventListener('toolchange', this.ontoolchangeListener);\n return;\n }\n\n if (this.ontoolchangeHandler === null) {\n super.addEventListener('toolchange', this.ontoolchangeListener);\n }\n this.ontoolchangeHandler = listener;\n }\n\n private async notifyProducerToolsChanged(): Promise<void> {\n if (this.closed) return;\n // Preserve task ordering because WebMCP does not expose its platform task source.\n await new Promise((resolve) => setTimeout(resolve, 0));\n if (!this.closed) this.dispatchEvent(new Event('toolchange'));\n }\n\n private getNativeStandardToolsApi(): NativeStandardToolsApi | undefined {\n const candidate: (ModelContext & Partial<ChromeModelContextExtensions>) | undefined =\n this.native;\n return candidate && typeof candidate.executeTool === 'function'\n ? (candidate as NativeStandardToolsApi)\n : undefined;\n }\n\n private async registerNativeToolMirror(\n tool: ToolDescriptor<WebMcpToolInput>,\n normalized: NormalizedInputSchema,\n options: ModelContextRegisterToolOptions,\n execute: RegisteredWebMcpTool['execute'],\n controller: AbortController\n ): Promise<void> {\n if (!this.native) return;\n\n // The overload set keys on a statically known inputSchema; mirrored tools carry a dynamic one.\n const nativeRegister = this.native.registerTool as unknown as NativeRegisterToolFn;\n const signal = options.signal\n ? AbortSignal.any([options.signal, controller.signal])\n : controller.signal;\n\n const nativeInputSchema =\n normalized.registeredInputSchema === undefined\n ? undefined\n : (JSON.parse(normalized.registeredInputSchema) as InputSchema);\n this.nativeToolAbortControllers.set(tool.name, controller);\n try {\n await nativeRegister.call(\n this.native,\n toNativeTool(tool, nativeInputSchema, (input) => execute(input)),\n { ...options, signal }\n );\n } catch (error) {\n controller.abort();\n if (this.nativeToolAbortControllers.get(tool.name) === controller) {\n this.nativeToolAbortControllers.delete(tool.name);\n }\n throw error;\n }\n if (this.nativeToolAbortControllers.get(tool.name) === controller) {\n this.removingNativeTools.delete(tool.name);\n }\n }\n\n private abortNativeToolMirror(\n name: string,\n controller = this.nativeToolAbortControllers.get(name)\n ): void {\n if (!controller || this.nativeToolAbortControllers.get(name) !== controller) return;\n this.removingNativeTools.add(name);\n controller.abort();\n this.nativeToolAbortControllers.delete(name);\n }\n\n private validateToolDescriptor(tool: ToolDescriptor<WebMcpToolInput>): NormalizedInputSchema {\n validateWebMcpToolDescriptor(tool);\n if (this.tools.has(tool.name) || this.pendingTools.has(tool.name)) {\n throw createInvalidStateError(`Tool already registered: ${tool.name}`);\n }\n return normalizeInputSchema(tool.inputSchema);\n }\n\n private registerToolInMcp(\n tool: ToolDescriptor<WebMcpToolInput>,\n normalized: NormalizedInputSchema,\n executeTool: RegisteredWebMcpTool['execute'],\n exposedTo: readonly string[] | undefined\n ): RegisteredWebMcpTool {\n const outputSchema =\n tool.outputSchema === undefined ? undefined : structuredClone(tool.outputSchema);\n const mcpOutputSchema =\n outputSchema === undefined\n ? undefined\n : fromJsonSchema(outputSchema as Parameters<typeof fromJsonSchema>[0]);\n const mcpAnnotations = toMcpAnnotations(tool.annotations);\n const mcpCompatibleInput =\n normalized.inputSchema.type === undefined || normalized.inputSchema.type === 'object';\n const mcpHandle = mcpCompatibleInput\n ? this.mcpServer.registerTool(\n tool.name,\n {\n ...(tool.title !== undefined ? { title: tool.title } : {}),\n description: tool.description,\n inputSchema: toMcpInputSchema(normalized),\n ...(mcpOutputSchema ? { outputSchema: mcpOutputSchema } : {}),\n ...(mcpAnnotations ? { annotations: mcpAnnotations } : {}),\n },\n async (args, context) => {\n const result = await executeTool(args, context.mcpReq.signal);\n if (isInputRequiredResult(result)) {\n throw new Error(\n `WebMCP tool \"${tool.name}\" returned input_required. Multi-round tool flows require BrowserMcpServer.mcpServer.registerTool().`\n );\n }\n return normalizeToolResponse(result);\n }\n )\n : undefined;\n // A restricted tool is never observable on the wire before its audience is\n // checked: the handle is disabled here, in the same synchronous step that created\n // it, and only applyToolExposure re-enables it.\n if (exposedTo?.length) mcpHandle?.disable();\n\n if (!mcpCompatibleInput) {\n console.warn(\n `[BrowserMcpServer] Tool \"${tool.name}\" remains available through WebMCP but cannot be exposed over MCP because MCP input schemas require an object root.`\n );\n }\n\n const item: ToolListItem = {\n name: tool.name,\n ...(tool.title !== undefined ? { title: tool.title } : {}),\n description: tool.description,\n inputSchema: normalized.inputSchema,\n ...(outputSchema === undefined ? {} : { outputSchema }),\n ...(tool.annotations ? { annotations: tool.annotations } : {}),\n };\n return {\n item,\n ...(normalized.registeredInputSchema !== undefined\n ? { registeredInputSchema: normalized.registeredInputSchema }\n : {}),\n execute: executeTool,\n mcpHandle,\n ...(exposedTo?.length ? { exposedTo } : {}),\n };\n }\n\n readonly registerTool: ModelContextWithExtensions['registerTool'] = async (\n toolValue: unknown,\n optionsValue: ModelContextRegisterToolOptions | null = {}\n ): Promise<void> => {\n const options = optionsValue ?? {};\n validateWebMcpAccess(this.ownerDocument);\n if (this.closed) throw createInvalidStateError('BrowserMcpServer is closed');\n if (!isPlainObject(toolValue)) {\n throw new TypeError('registerTool(tool) requires a tool object');\n }\n const tool = coerceWebMcpToolDescriptor(toolValue);\n const normalized = this.validateToolDescriptor(tool);\n options.signal?.throwIfAborted();\n validatePotentiallyTrustworthyOrigins(options.exposedTo);\n options.signal?.throwIfAborted();\n const execute: RegisteredWebMcpTool['execute'] = async (args, signal) => {\n signal?.throwIfAborted();\n return withAbortSignal(\n Promise.resolve().then(() => Reflect.apply(tool.execute, undefined, [args])),\n signal\n );\n };\n const controller = new AbortController();\n let registered: RegisteredWebMcpTool | undefined;\n const abort = () => {\n if (this.pendingTools.get(tool.name) === controller) {\n this.pendingTools.delete(tool.name);\n }\n if (registered && this.tools.get(tool.name) === registered) {\n this.removeTool(tool.name);\n } else {\n this.abortNativeToolMirror(tool.name, controller);\n }\n };\n options.signal?.addEventListener('abort', abort, { once: true });\n this.pendingTools.set(tool.name, controller);\n try {\n await this.registerNativeToolMirror(tool, normalized, options, execute, controller);\n if (this.closed) throw createInvalidStateError('BrowserMcpServer is closed');\n options.signal?.throwIfAborted();\n registered = this.registerToolInMcp(tool, normalized, execute, options.exposedTo);\n this.tools.set(tool.name, registered);\n this.applyToolExposure();\n if (options.signal?.aborted) {\n abort();\n options.signal.throwIfAborted();\n }\n } catch (error) {\n this.abortNativeToolMirror(tool.name, controller);\n options.signal?.removeEventListener('abort', abort);\n options.signal?.throwIfAborted();\n throw error;\n } finally {\n if (this.pendingTools.get(tool.name) === controller) {\n this.pendingTools.delete(tool.name);\n }\n }\n if (options.signal) {\n registered.abortSignal = options.signal;\n registered.abortListener = abort;\n }\n if (this.tools.get(tool.name) === registered) {\n if (this.native) await this.nativeToolChangeQueue;\n else await this.notifyProducerToolsChanged();\n }\n if (this.closed) throw createInvalidStateError('BrowserMcpServer is closed');\n options.signal?.throwIfAborted();\n };\n\n private removeTool(name: string, options?: { skipNative?: boolean; notify?: boolean }): void {\n const registered = this.tools.get(name);\n if (registered) {\n if (registered.abortSignal && registered.abortListener) {\n registered.abortSignal.removeEventListener('abort', registered.abortListener);\n }\n this.tools.delete(name);\n this.nativeBackfilledTools.delete(name);\n registered.mcpHandle?.remove();\n if ((options?.notify ?? true) && !this.native) {\n void this.notifyProducerToolsChanged();\n }\n }\n if (!options?.skipNative) this.abortNativeToolMirror(name);\n }\n\n syncNativeTools(): Promise<void> {\n const sync = this.nativeSyncQueue.then(async () => {\n if (this.closed) return;\n const native = this.getNativeStandardToolsApi();\n if (native) await this.backfillNativeStandardTools(native);\n });\n this.nativeSyncQueue = sync.then(\n () => undefined,\n () => undefined\n );\n return sync;\n }\n\n private async backfillNativeStandardTools(native: NativeStandardToolsApi): Promise<void> {\n const tools = await native.getTools();\n if (this.closed) return;\n const nextTools = new Map<string, NativeBackfilledTool>();\n const nativeNames = new Set(tools.map(({ name }) => name));\n for (const name of this.removingNativeTools) {\n if (!nativeNames.has(name)) this.removingNativeTools.delete(name);\n }\n for (const tool of tools) {\n // ponytail: MCP tool names are global, so keep the first valid visible tool.\n // Add origin-qualified aliases if MCP gains scoped tool identity.\n if (\n nextTools.has(tool.name) ||\n this.pendingTools.has(tool.name) ||\n this.removingNativeTools.has(tool.name)\n ) {\n continue;\n }\n let inputSchema: InputSchema | undefined = DEFAULT_INPUT_SCHEMA;\n if (tool.inputSchema !== undefined) {\n try {\n // An object since webmcp#241; a serialized string from older Chrome. The\n // round-trip detaches the object from the page's graph and rejects non-JSON.\n const serialized =\n typeof tool.inputSchema === 'string'\n ? tool.inputSchema\n : JSON.stringify(tool.inputSchema);\n const parsed: unknown = JSON.parse(serialized);\n inputSchema = isPlainObject(parsed) ? (parsed as InputSchema) : undefined;\n } catch {\n inputSchema = undefined;\n }\n }\n if (!inputSchema) {\n console.warn(\n `[BrowserMcpServer] Native tool \"${tool.name}\" was not exposed over MCP because its input schema is malformed.`\n );\n continue;\n }\n const item: ToolListItem = {\n name: tool.name,\n ...(tool.title !== undefined ? { title: tool.title } : {}),\n description: tool.description,\n inputSchema,\n ...(tool.annotations ? { annotations: tool.annotations } : {}),\n };\n nextTools.set(tool.name, {\n source: tool,\n item,\n fingerprint: JSON.stringify(item),\n });\n }\n\n for (const [name, current] of this.nativeBackfilledTools) {\n const next = nextTools.get(name);\n if (!next || next.fingerprint !== current.fingerprint) {\n this.removeTool(name, { skipNative: true, notify: false });\n continue;\n }\n this.nativeBackfilledTools.set(name, next);\n }\n\n for (const [name, next] of nextTools) {\n if (this.tools.has(name)) continue;\n const execute = async (args: WebMcpToolInput, signal?: AbortSignal) => {\n const currentTool = this.nativeBackfilledTools.get(name)?.source;\n if (!currentTool) throw new Error(`Native tool not found: ${name}`);\n const input = JSON.stringify(args);\n return parseNativeToolResult(\n signal\n ? await native.executeTool.call(this.native, currentTool, input, { signal })\n : await native.executeTool.call(this.native, currentTool, input)\n );\n };\n const tool: ToolDescriptor<WebMcpToolInput> = {\n name,\n ...(next.item.title !== undefined ? { title: next.item.title } : {}),\n description: next.item.description,\n inputSchema: next.item.inputSchema,\n ...(next.item.annotations ? { annotations: next.item.annotations } : {}),\n execute: (args) => execute(args),\n };\n try {\n const normalized = this.validateToolDescriptor(tool);\n // Native getTools() does not report the allowlist a tool registered with, so a\n // backfilled mirror carries none and stays as widely exposed as it is today.\n this.tools.set(tool.name, this.registerToolInMcp(tool, normalized, execute, undefined));\n this.nativeBackfilledTools.set(name, next);\n } catch (error) {\n console.warn(\n `[BrowserMcpServer] Native tool \"${name}\" was not exposed over MCP because its schema could not be compiled:`,\n error\n );\n }\n }\n }\n\n registerResource(descriptor: ResourceDescriptor): RegistrationHandle {\n if (this.closed) throw createInvalidStateError('BrowserMcpServer is closed');\n const registeredDescriptor = { ...descriptor };\n const config = {\n ...(registeredDescriptor.description !== undefined\n ? { description: registeredDescriptor.description }\n : {}),\n ...(registeredDescriptor.mimeType !== undefined\n ? { mimeType: registeredDescriptor.mimeType }\n : {}),\n };\n const template = registeredDescriptor.uri.includes('{')\n ? new ResourceTemplate(registeredDescriptor.uri, { list: undefined })\n : undefined;\n const mcpHandle = template\n ? this.mcpServer.registerResource(\n registeredDescriptor.name,\n template,\n config,\n async (uri, variables) => registeredDescriptor.read(uri, variables)\n )\n : this.mcpServer.registerResource(\n registeredDescriptor.name,\n registeredDescriptor.uri,\n config,\n async (uri) => registeredDescriptor.read(uri)\n );\n this.registrations.add(mcpHandle);\n return {\n unregister: () => {\n if (this.registrations.delete(mcpHandle)) mcpHandle.remove();\n },\n };\n }\n\n registerPrompt(descriptor: PromptDescriptor): RegistrationHandle {\n if (this.closed) throw createInvalidStateError('BrowserMcpServer is closed');\n const registeredDescriptor = {\n ...descriptor,\n ...(descriptor.argsSchema === undefined\n ? {}\n : { argsSchema: structuredClone(descriptor.argsSchema) }),\n };\n const argsSchema =\n registeredDescriptor.argsSchema === undefined\n ? undefined\n : fromJsonSchema<Record<string, string>>(\n registeredDescriptor.argsSchema as Parameters<typeof fromJsonSchema>[0]\n );\n const mcpHandle = this.mcpServer.registerPrompt(\n registeredDescriptor.name,\n {\n ...(registeredDescriptor.description !== undefined\n ? { description: registeredDescriptor.description }\n : {}),\n ...(argsSchema ? { argsSchema } : {}),\n },\n async (args) => registeredDescriptor.get(args ?? {})\n );\n this.registrations.add(mcpHandle);\n return {\n unregister: () => {\n if (this.registrations.delete(mcpHandle)) mcpHandle.remove();\n },\n };\n }\n\n listTools(): ToolListItem[] {\n return structuredClone([...this.tools.values()].map(({ item }) => item));\n }\n\n async getTools(options?: ModelContextGetToolOptions): Promise<RegisteredTool[]> {\n validateWebMcpAccess(this.ownerDocument);\n if (this.closed) throw createInvalidStateError('BrowserMcpServer is closed');\n if (this.native) {\n return this.native.getTools(options);\n }\n validatePotentiallyTrustworthyOrigins(options?.fromOrigins);\n if (options?.fromOrigins?.length) {\n throw new DOMException(\n 'Cross-document tool discovery requires native WebMCP',\n 'NotSupportedError'\n );\n }\n\n const origin = globalThis.location?.origin ?? '';\n const currentWindow = globalThis.window;\n\n const tools = [...this.tools.values()]\n .map(({ item, registeredInputSchema }) => {\n // A fresh object per call, aligned with the polyfill's post-webmcp#241\n // shape. A custom toJSON can serialize to non-object JSON; omit those\n // rather than emit a value consumers would mistake for a pre-154\n // serialized string.\n const parsed: unknown =\n registeredInputSchema === undefined ? undefined : JSON.parse(registeredInputSchema);\n return {\n name: item.name,\n title: item.title ?? '',\n description: item.description,\n ...(isPlainObject(parsed) ? { inputSchema: parsed } : {}),\n origin,\n window: currentWindow,\n ...(item.annotations ? { annotations: toWebMcpAnnotations(item.annotations) } : {}),\n };\n })\n .sort((a, b) => (a.name < b.name ? -1 : a.name > b.name ? 1 : 0));\n await new Promise((resolve) => setTimeout(resolve, 0));\n return tools;\n }\n\n async executeTool(\n tool: RegisteredTool,\n inputArgsJson: string,\n options?: ChromeModelContextExecuteToolOptions\n ): Promise<string | null> {\n validateWebMcpAccess(this.ownerDocument);\n if (this.closed) throw createInvalidStateError('BrowserMcpServer is closed');\n const native = this.getNativeStandardToolsApi();\n if (native) {\n return native.executeTool.call(this.native, tool, inputArgsJson, options);\n }\n\n if (tool === null || typeof tool !== 'object') {\n throw new TypeError('RegisteredTool must be an object');\n }\n for (const required of ['name', 'description', 'window', 'origin'] as const) {\n if (!(required in tool)) {\n throw new TypeError(`RegisteredTool.${required} is required`);\n }\n }\n validateExecutableOrigin(tool.origin);\n const origin = globalThis.location?.origin ?? '';\n const currentWindow = globalThis.window;\n if (tool.origin !== origin || tool.window !== currentWindow) {\n throw createUnknownError(`Native tool not found: ${tool.name}`);\n }\n options?.signal?.throwIfAborted();\n const registered = this.tools.get(tool.name);\n if (!registered) throw createUnknownError(`Tool not found: ${tool.name}`);\n const args = parseChromeToolInput(inputArgsJson);\n try {\n const result = await withAbortSignal(\n registered.execute(args, options?.signal),\n registered.abortSignal,\n () => createUnknownError('Tool unregistered')\n );\n return serializeChromeToolResult(result);\n } catch (error) {\n if (options?.signal?.aborted && error === options.signal.reason) throw error;\n if (registered.abortSignal?.aborted) throw error;\n throw createToolInvocationFailedError(error);\n }\n }\n\n /**\n * Re-evaluate which registered tools may appear on the wire.\n *\n * `exposedTo` narrows a tool to named embedder origins. The peer origin is only known\n * once a transport that reports one has heard from its peer, so a restricted tool stays\n * disabled until then — and stays disabled forever on transports that cannot name a peer\n * at all. Failing closed keeps a tool that asked for a narrow audience from reaching a\n * wider one; unrestricted tools are untouched and behave exactly as before.\n */\n private applyToolExposure(): void {\n for (const { exposedTo, mcpHandle } of this.tools.values()) {\n if (!exposedTo?.length || !mcpHandle) continue;\n const visible = this.peerOrigin !== undefined && exposedTo.includes(this.peerOrigin);\n if (visible === mcpHandle.enabled) continue;\n if (visible) mcpHandle.enable();\n else mcpHandle.disable();\n }\n }\n\n /**\n * Follow the peer origin of transports that report one, so `exposedTo` can be scoped to\n * the embedder actually connected. Duck-typed rather than imported: the SDK must not take\n * a build dependency on `@mcp-b/transports`, and transports that never name a peer simply\n * leave every restricted tool disabled.\n */\n private observePeerOrigin(transport: Transport): void {\n if (!('clientOrigin' in transport)) return;\n const peered = transport as Transport & {\n clientOrigin?: string;\n onclientorigin?: (origin: string) => void;\n };\n this.peerOrigin = peered.clientOrigin;\n this.applyToolExposure();\n const previous = peered.onclientorigin;\n peered.onclientorigin = (origin) => {\n previous?.(origin);\n this.peerOrigin = origin;\n this.applyToolExposure();\n };\n }\n\n connect(transport: Transport): Promise<void> {\n if (this.closed) return Promise.reject(createInvalidStateError('BrowserMcpServer is closed'));\n this.observePeerOrigin(transport);\n return this.mcpServer.connect(transport);\n }\n\n close(): Promise<void> {\n if (this.closePromise) return this.closePromise;\n this.closed = true;\n this.closePromise = (async () => {\n if (this.native && this.nativeToolChangeListener) {\n this.native.removeEventListener('toolchange', this.nativeToolChangeListener);\n this.nativeToolChangeListener = undefined;\n }\n for (const name of this.nativeToolAbortControllers.keys()) {\n this.abortNativeToolMirror(name);\n }\n for (const name of this.tools.keys()) {\n this.removeTool(name, { notify: false });\n }\n for (const handle of this.registrations) handle.remove();\n this.registrations.clear();\n this.nativeBackfilledTools.clear();\n this.removingNativeTools.clear();\n await this.mcpServer.close();\n })();\n return this.closePromise;\n }\n}\n\nexport interface ResourceDescriptor {\n uri: string;\n name: string;\n description?: string;\n mimeType?: string;\n read: (uri: URL, params?: Variables) => Promise<ReadResourceResult>;\n}\n\nexport interface PromptDescriptor {\n name: string;\n description?: string;\n argsSchema?: InputSchema;\n get: (args: Record<string, string>) => Promise<GetPromptResult>;\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mcp-b/webmcp-ts-sdk",
|
|
3
|
-
"version": "5.0.
|
|
3
|
+
"version": "5.0.1",
|
|
4
4
|
"description": "Thin WebMCP-to-MCP v2 browser adapter with native Chrome tool mirroring",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"adapter",
|
|
@@ -59,8 +59,8 @@
|
|
|
59
59
|
},
|
|
60
60
|
"dependencies": {
|
|
61
61
|
"@modelcontextprotocol/server": "2.0.0",
|
|
62
|
-
"@mcp-b/webmcp-polyfill": "5.0.
|
|
63
|
-
"@mcp-b/webmcp-types": "5.0.
|
|
62
|
+
"@mcp-b/webmcp-polyfill": "5.0.1",
|
|
63
|
+
"@mcp-b/webmcp-types": "5.0.1"
|
|
64
64
|
},
|
|
65
65
|
"devDependencies": {
|
|
66
66
|
"@modelcontextprotocol/client": "2.0.0",
|