@mcp-b/webmcp-ts-sdk 6.0.0-beta.20261001010549 → 6.0.0
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 +4 -0
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -160,6 +160,10 @@ var BrowserMcpServer = class extends EventTarget {
|
|
|
160
160
|
} catch (error) {
|
|
161
161
|
controller.abort();
|
|
162
162
|
if (this.nativeToolAbortControllers.get(tool.name) === controller) this.nativeToolAbortControllers.delete(tool.name);
|
|
163
|
+
if (error instanceof DOMException && error.name === "NotAllowedError") {
|
|
164
|
+
console.warn(`[BrowserMcpServer] Tool "${tool.name}" is available over MCP only: ${error.message}. Grant allow="tools" on the iframe to expose it to WebMCP.`);
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
163
167
|
throw error;
|
|
164
168
|
}
|
|
165
169
|
if (this.nativeToolAbortControllers.get(tool.name) === controller) this.removingNativeTools.delete(tool.name);
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../src/browser-server.ts"],"sourcesContent":["import type { WebMCP } from 'webmcp-types';\nimport { installWebMCP } from '@mcp-b/webmcp-polyfill';\nimport {\n coerceWebMcpToolDescriptor,\n createInvalidStateError,\n isPlainObject,\n serializeInputSchema,\n type ToolRegistrationDictionary,\n} from './normalize.js';\nimport {\n isMcpStandardSchema,\n normalizeInputSchema,\n normalizeToolResponse,\n type NormalizedInputSchema,\n} from './schema.js';\nimport type {\n ModelContext,\n ModelContextGetToolOptions,\n ModelContextRegisterToolOptions,\n ModelContextWithExtensions,\n RegisteredTool,\n} from './model-context.js';\nimport type {\n CallToolResult,\n InputSchema,\n RegistrationHandle,\n WebMcpToolInput,\n WebMcpToolObjectInput,\n} from './common.js';\nimport type { ModelContextTool, ToolDescriptor, ToolListItem } from './tool.js';\nimport {\n fromJsonSchema,\n isInputRequiredResult,\n McpServer,\n mergeCapabilities,\n ResourceTemplate,\n type GetPromptResult,\n type Implementation,\n type ReadResourceResult,\n type ResourceMetadata,\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 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\nexport interface PeerOriginTransport extends Transport {\n clientOrigin?: string | undefined;\n onclientorigin?: ((origin: string) => void) | undefined;\n}\n\nfunction isPeerOriginTransport(transport: Transport): transport is PeerOriginTransport {\n return (\n 'clientOrigin' in transport &&\n (transport.clientOrigin === undefined || typeof transport.clientOrigin === 'string') &&\n (!('onclientorigin' in transport) ||\n transport.onclientorigin === undefined ||\n typeof transport.onclientorigin === 'function')\n );\n}\n\ninterface RegisteredWebMcpTool {\n item: ToolListItem;\n mcpHandle: McpRegisteredTool | undefined;\n exposedTo?: readonly string[];\n abortSignal?: AbortSignal;\n abortListener?: () => void;\n}\n\ntype McpRegistration = McpRegisteredPrompt | McpRegisteredResource | McpRegisteredResourceTemplate;\ntype ModelContextEventHandler = ModelContext['ontoolchange'];\n\nexport interface BrowserMcpServerOptions extends ServerOptions {\n /** Underlying context. Defaults to document.modelContext, installing upstream if needed. */\n native?: ModelContext;\n}\n\ninterface NativeBackfilledTool {\n source: RegisteredTool;\n item: ToolListItem;\n fingerprint: string;\n}\n\nfunction parseNativeToolResult(serialized: string): CallToolResult | WebMcpToolObjectInput {\n let result: unknown;\n try {\n result = JSON.parse(serialized);\n } catch {\n // Native declarative tools return plain text for string responses.\n result = serialized;\n }\n if (isPlainObject(result)) return result;\n // Strings cross as their content; every other value keeps its original text.\n return { content: [{ type: 'text', text: typeof result === 'string' ? result : serialized }] };\n}\n\n/** Runs `operation` in a microtask; rejects with the reason as soon as `signal` aborts. */\nfunction withAbortSignal<T>(operation: () => T | PromiseLike<T>, signal: AbortSignal): Promise<T> {\n return new Promise<T>((resolve, reject) => {\n signal.throwIfAborted();\n const onAbort = () => reject(signal.reason);\n signal.addEventListener('abort', onAbort, { once: true });\n Promise.resolve()\n .then(operation)\n .then(resolve, reject)\n .finally(() => signal.removeEventListener('abort', onAbort));\n });\n}\n\nfunction toMcpInputSchema(\n normalized: NormalizedInputSchema\n): StandardSchemaWithJSON<WebMcpToolObjectInput> {\n // normalizeInputSchema() keeps the caller's Standard Schema validator on the converted\n // schema, so reuse it instead of recompiling the JSON Schema projection.\n if (isMcpStandardSchema(normalized.inputSchema)) return normalized.inputSchema;\n // SAFETY: normalizeInputSchema returns a plain JSON object whose keywords may exceed the SDK's\n // declared JSON Schema type; fromJsonSchema compiles it and validates its dialect at runtime.\n return fromJsonSchema<WebMcpToolObjectInput>(\n normalized.inputSchema as Parameters<typeof fromJsonSchema>[0]\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 extends the upstream WebMCP context with MCP capabilities.\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 stopObservingPeerOrigin: (() => void) | 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 readonly nativeToolChangeListener: () => void;\n private closed = false;\n private closePromise: Promise<void> | undefined;\n private readonly eventHandlers = new Map<string, NonNullable<ModelContextEventHandler>>();\n private readonly eventHandlerListener: EventListener = (event) => {\n this.eventHandlers.get(event.type)?.call(this, event);\n };\n // Lifecycle events fire at the underlying context; listeners on the extended\n // document context see them through this target.\n private readonly nativeLifecycleListener: EventListener = (event) => {\n if (this.closed) return;\n const mirrored = new Event(event.type);\n if ('toolName' in event) {\n Object.defineProperty(mirrored, 'toolName', { enumerable: true, value: event.toolName });\n }\n this.dispatchEvent(mirrored);\n };\n\n constructor(serverInfo: Implementation, options: BrowserMcpServerOptions = {}) {\n super();\n const { native: suppliedContext, ...serverOptions } = options;\n if (!suppliedContext && !globalThis.document?.modelContext) installWebMCP();\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 // Outside a secure document no context exists; the server then serves MCP only.\n this.native = suppliedContext ?? globalThis.document?.modelContext;\n this.ownerDocument = globalThis.document ?? null;\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 this.native?.addEventListener('toolchange', this.nativeToolChangeListener);\n this.native?.addEventListener('toolactivated', this.nativeLifecycleListener);\n this.native?.addEventListener('toolcancel', this.nativeLifecycleListener);\n }\n\n private getEventHandler(type: string): ModelContextEventHandler {\n return this.eventHandlers.get(type) ?? null;\n }\n\n private setEventHandler(type: string, handler: ModelContextEventHandler): void {\n if (typeof handler === 'function') {\n if (!this.eventHandlers.has(type)) super.addEventListener(type, this.eventHandlerListener);\n this.eventHandlers.set(type, handler);\n } else if (this.eventHandlers.delete(type)) {\n super.removeEventListener(type, this.eventHandlerListener);\n }\n }\n\n get ontoolchange(): ModelContextEventHandler {\n return this.getEventHandler('toolchange');\n }\n\n set ontoolchange(handler: ModelContextEventHandler) {\n this.setEventHandler('toolchange', handler);\n }\n\n get ontoolactivated(): ModelContextEventHandler {\n return this.getEventHandler('toolactivated');\n }\n\n set ontoolactivated(handler: ModelContextEventHandler) {\n this.setEventHandler('toolactivated', handler);\n }\n\n get ontoolcancel(): ModelContextEventHandler {\n return this.getEventHandler('toolcancel');\n }\n\n set ontoolcancel(handler: ModelContextEventHandler) {\n this.setEventHandler('toolcancel', handler);\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 async registerNativeToolMirror(\n tool: ToolDescriptor<WebMcpToolInput>,\n normalized: NormalizedInputSchema,\n options: ModelContextRegisterToolOptions,\n execute: ModelContextTool<WebMcpToolInput>['execute'],\n controller: AbortController\n ): Promise<void> {\n const native = this.native;\n if (!native) return;\n const signal = options.signal\n ? AbortSignal.any([options.signal, controller.signal])\n : controller.signal;\n const nativeTool: WebMCP.ModelContextTool = {\n name: tool.name,\n description: tool.description,\n execute,\n };\n if (tool.title !== undefined) nativeTool.title = tool.title;\n if (normalized.registeredInputSchema !== undefined) {\n const inputSchema: unknown = JSON.parse(normalized.registeredInputSchema);\n if (!isPlainObject(inputSchema)) throw new TypeError('inputSchema must be an object');\n nativeTool.inputSchema = inputSchema;\n }\n if (tool.annotations) nativeTool.annotations = tool.annotations;\n\n this.nativeToolAbortControllers.set(tool.name, controller);\n try {\n await native.registerTool(nativeTool, { ...options, signal });\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 registerToolInMcp(\n tool: ToolDescriptor<WebMcpToolInput>,\n normalized: NormalizedInputSchema,\n executeTool: ModelContextTool<WebMcpToolInput>['execute'],\n exposedTo?: readonly string[]\n ): RegisteredWebMcpTool {\n const item: ToolListItem = {\n name: tool.name,\n description: tool.description,\n inputSchema: normalized.inputSchema,\n };\n if (tool.title !== undefined) item.title = tool.title;\n if (tool.outputSchema !== undefined) item.outputSchema = structuredClone(tool.outputSchema);\n if (tool.annotations) item.annotations = tool.annotations;\n\n const config: Omit<Parameters<McpServer['registerTool']>[1], 'inputSchema' | 'outputSchema'> & {\n inputSchema?: ReturnType<typeof toMcpInputSchema>;\n outputSchema?: ReturnType<typeof fromJsonSchema>;\n } = {\n description: tool.description,\n };\n if (item.outputSchema !== undefined) config.outputSchema = fromJsonSchema(item.outputSchema);\n if (tool.title !== undefined) config.title = tool.title;\n if (tool.annotations) {\n const { untrustedContentHint: _untrustedContentHint, ...annotations } = tool.annotations;\n config.annotations = annotations;\n }\n let mcpHandle: McpRegisteredTool | undefined;\n if (normalized.inputSchema.type === undefined || normalized.inputSchema.type === 'object') {\n config.inputSchema = toMcpInputSchema(normalized);\n mcpHandle = this.mcpServer.registerTool(tool.name, config, async (args, context) => {\n const result = await executeTool(args, { signal: 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 // A tool is never observable on the wire before it is published: the handle is\n // disabled here, in the same synchronous step that created it, and only\n // applyToolExposure enables it.\n mcpHandle.disable();\n } else {\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 registered: RegisteredWebMcpTool = { item, mcpHandle };\n if (exposedTo?.length) registered.exposedTo = exposedTo;\n return registered;\n }\n\n readonly registerTool: ModelContextWithExtensions['registerTool'] = async (\n toolValue: ToolRegistrationDictionary,\n optionsValue: ModelContextRegisterToolOptions | null = {}\n ): Promise<void> => {\n const { signal, exposedTo } = optionsValue ?? {};\n const options: ModelContextRegisterToolOptions = {};\n if (signal) options.signal = signal;\n if (exposedTo) options.exposedTo = [...exposedTo];\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 // Upstream keys names per document, so only local and pending registrations\n // collide; a mirror of another document's tool yields once native accepts.\n if (\n (this.tools.has(tool.name) && !this.nativeBackfilledTools.has(tool.name)) ||\n this.pendingTools.has(tool.name)\n ) {\n throw createInvalidStateError(`Tool already registered: ${tool.name}`);\n }\n const normalized = normalizeInputSchema(tool.inputSchema);\n options.signal?.throwIfAborted();\n const callback = tool.execute;\n const execute: ModelContextTool<WebMcpToolInput>['execute'] = (args, options) =>\n withAbortSignal(() => callback(args, options), options.signal);\n const controller = new AbortController();\n // An unparsable entry reaches the context, which rejects it with its own error.\n const exposedOrigins = options.exposedTo?.map((origin) => URL.parse(origin)?.origin ?? origin);\n // `registered` owns the MCP handle until the tool is published or the handle is released.\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 registered?.mcpHandle?.remove();\n this.abortNativeToolMirror(tool.name, controller);\n }\n registered = undefined;\n };\n options.signal?.addEventListener('abort', abort, { once: true });\n this.pendingTools.set(tool.name, controller);\n try {\n // The MCP side compiles before other frames can see the tool. A mirror of\n // another document's tool keeps the MCP name until native accepts this one.\n if (!this.nativeBackfilledTools.has(tool.name)) {\n registered = this.registerToolInMcp(tool, normalized, execute, exposedOrigins);\n }\n options.signal?.throwIfAborted();\n await this.registerNativeToolMirror(tool, normalized, options, execute, controller);\n if (this.closed) throw createInvalidStateError('BrowserMcpServer is closed');\n options.signal?.throwIfAborted();\n this.removeTool(tool.name, { skipNative: true });\n registered ??= this.registerToolInMcp(tool, normalized, execute, exposedOrigins);\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 registered?.mcpHandle?.remove();\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 await this.nativeToolChangeQueue;\n }\n if (this.closed) throw createInvalidStateError('BrowserMcpServer is closed');\n options.signal?.throwIfAborted();\n };\n\n private removeTool(name: string, options?: { skipNative?: 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 }\n if (!options?.skipNative) this.abortNativeToolMirror(name);\n }\n\n syncNativeTools(): Promise<void> {\n const native = this.native;\n const sync = this.nativeSyncQueue.then(async () => {\n if (this.closed || !native) return;\n 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: ModelContext): Promise<void> {\n // A top-level server serves its subtree; a framed one serves only its own\n // document, so an embedder cannot reach same-origin children through the\n // framed page, and ancestor or sibling tools never feed iframe bridges back\n // into their source.\n const ownerWindow = this.ownerDocument?.defaultView;\n const tools = (await native.getTools()).filter((tool) => {\n if (tool.window === ownerWindow) return true;\n if (ownerWindow?.parent !== ownerWindow) return false;\n let frame = tool.window;\n while (frame) {\n if (frame === ownerWindow) return true;\n const parent = frame.parent;\n if (parent === frame) break;\n frame = parent;\n }\n return false;\n });\n if (this.closed) return;\n // A removal completes once this document no longer registers the name; a\n // descendant's same-named tool is mirrored afterwards.\n for (const name of this.removingNativeTools) {\n if (!tools.some((tool) => tool.name === name && tool.window === ownerWindow)) {\n this.removingNativeTools.delete(name);\n }\n }\n const nextTools = new Map<string, NativeBackfilledTool>();\n for (const tool of tools) {\n // MCP tool names are global, so the first visible tool with a name wins.\n if (\n nextTools.has(tool.name) ||\n this.pendingTools.has(tool.name) ||\n this.removingNativeTools.has(tool.name)\n ) {\n continue;\n }\n // Detach the schema from the page; a value that cannot cross JSON stays undefined.\n let inputSchema: unknown;\n try {\n inputSchema = JSON.parse(serializeInputSchema(tool.inputSchema ?? DEFAULT_INPUT_SCHEMA));\n } catch {}\n if (!isPlainObject(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 = { name: tool.name, description: tool.description, inputSchema };\n if (tool.title !== undefined) item.title = tool.title;\n if (tool.annotations) item.annotations = tool.annotations;\n nextTools.set(tool.name, { source: tool, item, fingerprint: JSON.stringify(item) });\n }\n\n for (const [name, current] of this.nativeBackfilledTools) {\n const next = nextTools.get(name);\n if (next?.fingerprint === current.fingerprint) this.nativeBackfilledTools.set(name, next);\n else this.removeTool(name, { skipNative: true });\n }\n\n for (const [name, next] of nextTools) {\n if (this.tools.has(name)) continue;\n const execute: ModelContextTool<WebMcpToolInput>['execute'] = async (args, options) => {\n const currentTool = this.nativeBackfilledTools.get(name)?.source;\n if (!currentTool) throw new Error(`Native tool not found: ${name}`);\n try {\n return parseNativeToolResult(await native.executeTool(currentTool, args, options));\n } catch (error) {\n // Upstream fires no toolchange when a frame is removed, so a failed call\n // into a closed window is the first signal to drop its mirrors.\n if (currentTool.window.closed) this.nativeToolChangeListener();\n throw error;\n }\n };\n const tool = { ...next.item, execute };\n try {\n // Native getTools() does not report a tool's exposedTo allowlist, so a\n // backfilled mirror is exposed to every MCP peer.\n const normalized = normalizeInputSchema(tool.inputSchema);\n this.tools.set(name, this.registerToolInMcp(tool, normalized, execute));\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 this.applyToolExposure();\n }\n\n registerResource(descriptor: ResourceDescriptor): RegistrationHandle {\n if (this.closed) throw createInvalidStateError('BrowserMcpServer is closed');\n const registeredDescriptor = { ...descriptor };\n const config: ResourceMetadata = {};\n if (registeredDescriptor.description !== undefined) {\n config.description = registeredDescriptor.description;\n }\n if (registeredDescriptor.mimeType !== undefined)\n config.mimeType = registeredDescriptor.mimeType;\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 = { ...descriptor };\n if (descriptor.argsSchema !== undefined) {\n registeredDescriptor.argsSchema = structuredClone(descriptor.argsSchema);\n }\n const argsSchema =\n registeredDescriptor.argsSchema === undefined\n ? undefined\n : fromJsonSchema<Record<string, string>>(\n // SAFETY: PromptDescriptor accepts WebMCP's JSON schema shape; the MCP schema\n // compiler validates supported keywords and values at this boundary.\n registeredDescriptor.argsSchema as Parameters<typeof fromJsonSchema>[0]\n );\n const config: Omit<Parameters<McpServer['registerPrompt']>[1], 'argsSchema'> & {\n argsSchema?: NonNullable<typeof argsSchema>;\n } = {};\n if (registeredDescriptor.description !== undefined) {\n config.description = registeredDescriptor.description;\n }\n if (argsSchema) config.argsSchema = argsSchema;\n const mcpHandle = this.mcpServer.registerPrompt(\n registeredDescriptor.name,\n config,\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 if (this.closed) throw createInvalidStateError('BrowserMcpServer is closed');\n if (!this.native) throw createInvalidStateError('BrowserMcpServer has no WebMCP context');\n return this.native.getTools(options);\n }\n\n async executeTool(...args: Parameters<ModelContext['executeTool']>): Promise<string> {\n if (this.closed) throw createInvalidStateError('BrowserMcpServer is closed');\n if (!this.native) throw createInvalidStateError('BrowserMcpServer has no WebMCP context');\n return this.native.executeTool(...args);\n }\n\n /**\n * Re-evaluate which registered tools may appear on the wire.\n *\n * A published tool without `exposedTo` is enabled. `exposedTo` narrows a tool to named\n * embedder origins. The peer origin is only known once a transport that reports one has\n * heard from its peer, so a restricted tool stays disabled until then — and stays\n * disabled forever on transports that cannot name a peer at all. Failing closed keeps a\n * tool that asked for a narrow audience from reaching a wider one.\n */\n private applyToolExposure(): void {\n for (const { exposedTo, mcpHandle } of this.tools.values()) {\n if (!mcpHandle) continue;\n // Opaque origins serialize identically and cannot identify an allowed peer.\n const visible =\n !exposedTo?.length ||\n (this.peerOrigin !== undefined &&\n this.peerOrigin !== 'null' &&\n 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 this.stopObservingPeerOrigin?.();\n this.stopObservingPeerOrigin = undefined;\n this.peerOrigin = undefined;\n this.applyToolExposure();\n if (!isPeerOriginTransport(transport)) return;\n const peered = transport;\n this.peerOrigin = peered.clientOrigin;\n this.applyToolExposure();\n const previous = peered.onclientorigin;\n let observing = true;\n const onclientorigin = (origin: string) => {\n previous?.(origin);\n if (!observing) return;\n this.peerOrigin = origin;\n this.applyToolExposure();\n };\n peered.onclientorigin = onclientorigin;\n this.stopObservingPeerOrigin = () => {\n observing = false;\n if (peered.onclientorigin === onclientorigin) peered.onclientorigin = previous;\n };\n }\n\n async connect(transport: Transport): Promise<void> {\n if (this.closed) throw createInvalidStateError('BrowserMcpServer is closed');\n if (this.mcpServer.server.transport) {\n throw createInvalidStateError('BrowserMcpServer is already connected');\n }\n this.observePeerOrigin(transport);\n const stopObserving = this.stopObservingPeerOrigin;\n try {\n await this.mcpServer.connect(transport);\n } catch (error) {\n if (this.stopObservingPeerOrigin === stopObserving) {\n stopObserving?.();\n this.stopObservingPeerOrigin = undefined;\n this.peerOrigin = undefined;\n this.applyToolExposure();\n }\n if (this.mcpServer.server.transport === transport) await this.mcpServer.close();\n throw error;\n }\n }\n\n close(): Promise<void> {\n if (this.closePromise) return this.closePromise;\n this.closed = true;\n this.stopObservingPeerOrigin?.();\n this.stopObservingPeerOrigin = undefined;\n this.closePromise = (async () => {\n this.native?.removeEventListener('toolchange', this.nativeToolChangeListener);\n this.native?.removeEventListener('toolactivated', this.nativeLifecycleListener);\n this.native?.removeEventListener('toolcancel', this.nativeLifecycleListener);\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);\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 type { WebMCP } from 'webmcp-types';\nimport { installWebMCP } from '@mcp-b/webmcp-polyfill';\nimport {\n coerceWebMcpToolDescriptor,\n createInvalidStateError,\n isPlainObject,\n serializeInputSchema,\n type ToolRegistrationDictionary,\n} from './normalize.js';\nimport {\n isMcpStandardSchema,\n normalizeInputSchema,\n normalizeToolResponse,\n type NormalizedInputSchema,\n} from './schema.js';\nimport type {\n ModelContext,\n ModelContextGetToolOptions,\n ModelContextRegisterToolOptions,\n ModelContextWithExtensions,\n RegisteredTool,\n} from './model-context.js';\nimport type {\n CallToolResult,\n InputSchema,\n RegistrationHandle,\n WebMcpToolInput,\n WebMcpToolObjectInput,\n} from './common.js';\nimport type { ModelContextTool, ToolDescriptor, ToolListItem } from './tool.js';\nimport {\n fromJsonSchema,\n isInputRequiredResult,\n McpServer,\n mergeCapabilities,\n ResourceTemplate,\n type GetPromptResult,\n type Implementation,\n type ReadResourceResult,\n type ResourceMetadata,\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 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\nexport interface PeerOriginTransport extends Transport {\n clientOrigin?: string | undefined;\n onclientorigin?: ((origin: string) => void) | undefined;\n}\n\nfunction isPeerOriginTransport(transport: Transport): transport is PeerOriginTransport {\n return (\n 'clientOrigin' in transport &&\n (transport.clientOrigin === undefined || typeof transport.clientOrigin === 'string') &&\n (!('onclientorigin' in transport) ||\n transport.onclientorigin === undefined ||\n typeof transport.onclientorigin === 'function')\n );\n}\n\ninterface RegisteredWebMcpTool {\n item: ToolListItem;\n mcpHandle: McpRegisteredTool | undefined;\n exposedTo?: readonly string[];\n abortSignal?: AbortSignal;\n abortListener?: () => void;\n}\n\ntype McpRegistration = McpRegisteredPrompt | McpRegisteredResource | McpRegisteredResourceTemplate;\ntype ModelContextEventHandler = ModelContext['ontoolchange'];\n\nexport interface BrowserMcpServerOptions extends ServerOptions {\n /** Underlying context. Defaults to document.modelContext, installing upstream if needed. */\n native?: ModelContext;\n}\n\ninterface NativeBackfilledTool {\n source: RegisteredTool;\n item: ToolListItem;\n fingerprint: string;\n}\n\nfunction parseNativeToolResult(serialized: string): CallToolResult | WebMcpToolObjectInput {\n let result: unknown;\n try {\n result = JSON.parse(serialized);\n } catch {\n // Native declarative tools return plain text for string responses.\n result = serialized;\n }\n if (isPlainObject(result)) return result;\n // Strings cross as their content; every other value keeps its original text.\n return { content: [{ type: 'text', text: typeof result === 'string' ? result : serialized }] };\n}\n\n/** Runs `operation` in a microtask; rejects with the reason as soon as `signal` aborts. */\nfunction withAbortSignal<T>(operation: () => T | PromiseLike<T>, signal: AbortSignal): Promise<T> {\n return new Promise<T>((resolve, reject) => {\n signal.throwIfAborted();\n const onAbort = () => reject(signal.reason);\n signal.addEventListener('abort', onAbort, { once: true });\n Promise.resolve()\n .then(operation)\n .then(resolve, reject)\n .finally(() => signal.removeEventListener('abort', onAbort));\n });\n}\n\nfunction toMcpInputSchema(\n normalized: NormalizedInputSchema\n): StandardSchemaWithJSON<WebMcpToolObjectInput> {\n // normalizeInputSchema() keeps the caller's Standard Schema validator on the converted\n // schema, so reuse it instead of recompiling the JSON Schema projection.\n if (isMcpStandardSchema(normalized.inputSchema)) return normalized.inputSchema;\n // SAFETY: normalizeInputSchema returns a plain JSON object whose keywords may exceed the SDK's\n // declared JSON Schema type; fromJsonSchema compiles it and validates its dialect at runtime.\n return fromJsonSchema<WebMcpToolObjectInput>(\n normalized.inputSchema as Parameters<typeof fromJsonSchema>[0]\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 extends the upstream WebMCP context with MCP capabilities.\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 stopObservingPeerOrigin: (() => void) | 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 readonly nativeToolChangeListener: () => void;\n private closed = false;\n private closePromise: Promise<void> | undefined;\n private readonly eventHandlers = new Map<string, NonNullable<ModelContextEventHandler>>();\n private readonly eventHandlerListener: EventListener = (event) => {\n this.eventHandlers.get(event.type)?.call(this, event);\n };\n // Lifecycle events fire at the underlying context; listeners on the extended\n // document context see them through this target.\n private readonly nativeLifecycleListener: EventListener = (event) => {\n if (this.closed) return;\n const mirrored = new Event(event.type);\n if ('toolName' in event) {\n Object.defineProperty(mirrored, 'toolName', { enumerable: true, value: event.toolName });\n }\n this.dispatchEvent(mirrored);\n };\n\n constructor(serverInfo: Implementation, options: BrowserMcpServerOptions = {}) {\n super();\n const { native: suppliedContext, ...serverOptions } = options;\n if (!suppliedContext && !globalThis.document?.modelContext) installWebMCP();\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 // Outside a secure document no context exists; the server then serves MCP only.\n this.native = suppliedContext ?? globalThis.document?.modelContext;\n this.ownerDocument = globalThis.document ?? null;\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 this.native?.addEventListener('toolchange', this.nativeToolChangeListener);\n this.native?.addEventListener('toolactivated', this.nativeLifecycleListener);\n this.native?.addEventListener('toolcancel', this.nativeLifecycleListener);\n }\n\n private getEventHandler(type: string): ModelContextEventHandler {\n return this.eventHandlers.get(type) ?? null;\n }\n\n private setEventHandler(type: string, handler: ModelContextEventHandler): void {\n if (typeof handler === 'function') {\n if (!this.eventHandlers.has(type)) super.addEventListener(type, this.eventHandlerListener);\n this.eventHandlers.set(type, handler);\n } else if (this.eventHandlers.delete(type)) {\n super.removeEventListener(type, this.eventHandlerListener);\n }\n }\n\n get ontoolchange(): ModelContextEventHandler {\n return this.getEventHandler('toolchange');\n }\n\n set ontoolchange(handler: ModelContextEventHandler) {\n this.setEventHandler('toolchange', handler);\n }\n\n get ontoolactivated(): ModelContextEventHandler {\n return this.getEventHandler('toolactivated');\n }\n\n set ontoolactivated(handler: ModelContextEventHandler) {\n this.setEventHandler('toolactivated', handler);\n }\n\n get ontoolcancel(): ModelContextEventHandler {\n return this.getEventHandler('toolcancel');\n }\n\n set ontoolcancel(handler: ModelContextEventHandler) {\n this.setEventHandler('toolcancel', handler);\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 async registerNativeToolMirror(\n tool: ToolDescriptor<WebMcpToolInput>,\n normalized: NormalizedInputSchema,\n options: ModelContextRegisterToolOptions,\n execute: ModelContextTool<WebMcpToolInput>['execute'],\n controller: AbortController\n ): Promise<void> {\n const native = this.native;\n if (!native) return;\n const signal = options.signal\n ? AbortSignal.any([options.signal, controller.signal])\n : controller.signal;\n const nativeTool: WebMCP.ModelContextTool = {\n name: tool.name,\n description: tool.description,\n execute,\n };\n if (tool.title !== undefined) nativeTool.title = tool.title;\n if (normalized.registeredInputSchema !== undefined) {\n const inputSchema: unknown = JSON.parse(normalized.registeredInputSchema);\n if (!isPlainObject(inputSchema)) throw new TypeError('inputSchema must be an object');\n nativeTool.inputSchema = inputSchema;\n }\n if (tool.annotations) nativeTool.annotations = tool.annotations;\n\n this.nativeToolAbortControllers.set(tool.name, controller);\n try {\n await native.registerTool(nativeTool, { ...options, signal });\n } catch (error) {\n controller.abort();\n if (this.nativeToolAbortControllers.get(tool.name) === controller) {\n this.nativeToolAbortControllers.delete(tool.name);\n }\n // A frame without allow=\"tools\" can still serve the tool over MCP, as in 5.x.\n if (error instanceof DOMException && error.name === 'NotAllowedError') {\n console.warn(\n `[BrowserMcpServer] Tool \"${tool.name}\" is available over MCP only: ${error.message}. Grant allow=\"tools\" on the iframe to expose it to WebMCP.`\n );\n return;\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 registerToolInMcp(\n tool: ToolDescriptor<WebMcpToolInput>,\n normalized: NormalizedInputSchema,\n executeTool: ModelContextTool<WebMcpToolInput>['execute'],\n exposedTo?: readonly string[]\n ): RegisteredWebMcpTool {\n const item: ToolListItem = {\n name: tool.name,\n description: tool.description,\n inputSchema: normalized.inputSchema,\n };\n if (tool.title !== undefined) item.title = tool.title;\n if (tool.outputSchema !== undefined) item.outputSchema = structuredClone(tool.outputSchema);\n if (tool.annotations) item.annotations = tool.annotations;\n\n const config: Omit<Parameters<McpServer['registerTool']>[1], 'inputSchema' | 'outputSchema'> & {\n inputSchema?: ReturnType<typeof toMcpInputSchema>;\n outputSchema?: ReturnType<typeof fromJsonSchema>;\n } = {\n description: tool.description,\n };\n if (item.outputSchema !== undefined) config.outputSchema = fromJsonSchema(item.outputSchema);\n if (tool.title !== undefined) config.title = tool.title;\n if (tool.annotations) {\n const { untrustedContentHint: _untrustedContentHint, ...annotations } = tool.annotations;\n config.annotations = annotations;\n }\n let mcpHandle: McpRegisteredTool | undefined;\n if (normalized.inputSchema.type === undefined || normalized.inputSchema.type === 'object') {\n config.inputSchema = toMcpInputSchema(normalized);\n mcpHandle = this.mcpServer.registerTool(tool.name, config, async (args, context) => {\n const result = await executeTool(args, { signal: 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 // A tool is never observable on the wire before it is published: the handle is\n // disabled here, in the same synchronous step that created it, and only\n // applyToolExposure enables it.\n mcpHandle.disable();\n } else {\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 registered: RegisteredWebMcpTool = { item, mcpHandle };\n if (exposedTo?.length) registered.exposedTo = exposedTo;\n return registered;\n }\n\n readonly registerTool: ModelContextWithExtensions['registerTool'] = async (\n toolValue: ToolRegistrationDictionary,\n optionsValue: ModelContextRegisterToolOptions | null = {}\n ): Promise<void> => {\n const { signal, exposedTo } = optionsValue ?? {};\n const options: ModelContextRegisterToolOptions = {};\n if (signal) options.signal = signal;\n if (exposedTo) options.exposedTo = [...exposedTo];\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 // Upstream keys names per document, so only local and pending registrations\n // collide; a mirror of another document's tool yields once native accepts.\n if (\n (this.tools.has(tool.name) && !this.nativeBackfilledTools.has(tool.name)) ||\n this.pendingTools.has(tool.name)\n ) {\n throw createInvalidStateError(`Tool already registered: ${tool.name}`);\n }\n const normalized = normalizeInputSchema(tool.inputSchema);\n options.signal?.throwIfAborted();\n const callback = tool.execute;\n const execute: ModelContextTool<WebMcpToolInput>['execute'] = (args, options) =>\n withAbortSignal(() => callback(args, options), options.signal);\n const controller = new AbortController();\n // An unparsable entry reaches the context, which rejects it with its own error.\n const exposedOrigins = options.exposedTo?.map((origin) => URL.parse(origin)?.origin ?? origin);\n // `registered` owns the MCP handle until the tool is published or the handle is released.\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 registered?.mcpHandle?.remove();\n this.abortNativeToolMirror(tool.name, controller);\n }\n registered = undefined;\n };\n options.signal?.addEventListener('abort', abort, { once: true });\n this.pendingTools.set(tool.name, controller);\n try {\n // The MCP side compiles before other frames can see the tool. A mirror of\n // another document's tool keeps the MCP name until native accepts this one.\n if (!this.nativeBackfilledTools.has(tool.name)) {\n registered = this.registerToolInMcp(tool, normalized, execute, exposedOrigins);\n }\n options.signal?.throwIfAborted();\n await this.registerNativeToolMirror(tool, normalized, options, execute, controller);\n if (this.closed) throw createInvalidStateError('BrowserMcpServer is closed');\n options.signal?.throwIfAborted();\n this.removeTool(tool.name, { skipNative: true });\n registered ??= this.registerToolInMcp(tool, normalized, execute, exposedOrigins);\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 registered?.mcpHandle?.remove();\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 await this.nativeToolChangeQueue;\n }\n if (this.closed) throw createInvalidStateError('BrowserMcpServer is closed');\n options.signal?.throwIfAborted();\n };\n\n private removeTool(name: string, options?: { skipNative?: 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 }\n if (!options?.skipNative) this.abortNativeToolMirror(name);\n }\n\n syncNativeTools(): Promise<void> {\n const native = this.native;\n const sync = this.nativeSyncQueue.then(async () => {\n if (this.closed || !native) return;\n 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: ModelContext): Promise<void> {\n // A top-level server serves its subtree; a framed one serves only its own\n // document, so an embedder cannot reach same-origin children through the\n // framed page, and ancestor or sibling tools never feed iframe bridges back\n // into their source.\n const ownerWindow = this.ownerDocument?.defaultView;\n const tools = (await native.getTools()).filter((tool) => {\n if (tool.window === ownerWindow) return true;\n if (ownerWindow?.parent !== ownerWindow) return false;\n let frame = tool.window;\n while (frame) {\n if (frame === ownerWindow) return true;\n const parent = frame.parent;\n if (parent === frame) break;\n frame = parent;\n }\n return false;\n });\n if (this.closed) return;\n // A removal completes once this document no longer registers the name; a\n // descendant's same-named tool is mirrored afterwards.\n for (const name of this.removingNativeTools) {\n if (!tools.some((tool) => tool.name === name && tool.window === ownerWindow)) {\n this.removingNativeTools.delete(name);\n }\n }\n const nextTools = new Map<string, NativeBackfilledTool>();\n for (const tool of tools) {\n // MCP tool names are global, so the first visible tool with a name wins.\n if (\n nextTools.has(tool.name) ||\n this.pendingTools.has(tool.name) ||\n this.removingNativeTools.has(tool.name)\n ) {\n continue;\n }\n // Detach the schema from the page; a value that cannot cross JSON stays undefined.\n let inputSchema: unknown;\n try {\n inputSchema = JSON.parse(serializeInputSchema(tool.inputSchema ?? DEFAULT_INPUT_SCHEMA));\n } catch {}\n if (!isPlainObject(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 = { name: tool.name, description: tool.description, inputSchema };\n if (tool.title !== undefined) item.title = tool.title;\n if (tool.annotations) item.annotations = tool.annotations;\n nextTools.set(tool.name, { source: tool, item, fingerprint: JSON.stringify(item) });\n }\n\n for (const [name, current] of this.nativeBackfilledTools) {\n const next = nextTools.get(name);\n if (next?.fingerprint === current.fingerprint) this.nativeBackfilledTools.set(name, next);\n else this.removeTool(name, { skipNative: true });\n }\n\n for (const [name, next] of nextTools) {\n if (this.tools.has(name)) continue;\n const execute: ModelContextTool<WebMcpToolInput>['execute'] = async (args, options) => {\n const currentTool = this.nativeBackfilledTools.get(name)?.source;\n if (!currentTool) throw new Error(`Native tool not found: ${name}`);\n try {\n return parseNativeToolResult(await native.executeTool(currentTool, args, options));\n } catch (error) {\n // Upstream fires no toolchange when a frame is removed, so a failed call\n // into a closed window is the first signal to drop its mirrors.\n if (currentTool.window.closed) this.nativeToolChangeListener();\n throw error;\n }\n };\n const tool = { ...next.item, execute };\n try {\n // Native getTools() does not report a tool's exposedTo allowlist, so a\n // backfilled mirror is exposed to every MCP peer.\n const normalized = normalizeInputSchema(tool.inputSchema);\n this.tools.set(name, this.registerToolInMcp(tool, normalized, execute));\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 this.applyToolExposure();\n }\n\n registerResource(descriptor: ResourceDescriptor): RegistrationHandle {\n if (this.closed) throw createInvalidStateError('BrowserMcpServer is closed');\n const registeredDescriptor = { ...descriptor };\n const config: ResourceMetadata = {};\n if (registeredDescriptor.description !== undefined) {\n config.description = registeredDescriptor.description;\n }\n if (registeredDescriptor.mimeType !== undefined)\n config.mimeType = registeredDescriptor.mimeType;\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 = { ...descriptor };\n if (descriptor.argsSchema !== undefined) {\n registeredDescriptor.argsSchema = structuredClone(descriptor.argsSchema);\n }\n const argsSchema =\n registeredDescriptor.argsSchema === undefined\n ? undefined\n : fromJsonSchema<Record<string, string>>(\n // SAFETY: PromptDescriptor accepts WebMCP's JSON schema shape; the MCP schema\n // compiler validates supported keywords and values at this boundary.\n registeredDescriptor.argsSchema as Parameters<typeof fromJsonSchema>[0]\n );\n const config: Omit<Parameters<McpServer['registerPrompt']>[1], 'argsSchema'> & {\n argsSchema?: NonNullable<typeof argsSchema>;\n } = {};\n if (registeredDescriptor.description !== undefined) {\n config.description = registeredDescriptor.description;\n }\n if (argsSchema) config.argsSchema = argsSchema;\n const mcpHandle = this.mcpServer.registerPrompt(\n registeredDescriptor.name,\n config,\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 if (this.closed) throw createInvalidStateError('BrowserMcpServer is closed');\n if (!this.native) throw createInvalidStateError('BrowserMcpServer has no WebMCP context');\n return this.native.getTools(options);\n }\n\n async executeTool(...args: Parameters<ModelContext['executeTool']>): Promise<string> {\n if (this.closed) throw createInvalidStateError('BrowserMcpServer is closed');\n if (!this.native) throw createInvalidStateError('BrowserMcpServer has no WebMCP context');\n return this.native.executeTool(...args);\n }\n\n /**\n * Re-evaluate which registered tools may appear on the wire.\n *\n * A published tool without `exposedTo` is enabled. `exposedTo` narrows a tool to named\n * embedder origins. The peer origin is only known once a transport that reports one has\n * heard from its peer, so a restricted tool stays disabled until then — and stays\n * disabled forever on transports that cannot name a peer at all. Failing closed keeps a\n * tool that asked for a narrow audience from reaching a wider one.\n */\n private applyToolExposure(): void {\n for (const { exposedTo, mcpHandle } of this.tools.values()) {\n if (!mcpHandle) continue;\n // Opaque origins serialize identically and cannot identify an allowed peer.\n const visible =\n !exposedTo?.length ||\n (this.peerOrigin !== undefined &&\n this.peerOrigin !== 'null' &&\n 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 this.stopObservingPeerOrigin?.();\n this.stopObservingPeerOrigin = undefined;\n this.peerOrigin = undefined;\n this.applyToolExposure();\n if (!isPeerOriginTransport(transport)) return;\n const peered = transport;\n this.peerOrigin = peered.clientOrigin;\n this.applyToolExposure();\n const previous = peered.onclientorigin;\n let observing = true;\n const onclientorigin = (origin: string) => {\n previous?.(origin);\n if (!observing) return;\n this.peerOrigin = origin;\n this.applyToolExposure();\n };\n peered.onclientorigin = onclientorigin;\n this.stopObservingPeerOrigin = () => {\n observing = false;\n if (peered.onclientorigin === onclientorigin) peered.onclientorigin = previous;\n };\n }\n\n async connect(transport: Transport): Promise<void> {\n if (this.closed) throw createInvalidStateError('BrowserMcpServer is closed');\n if (this.mcpServer.server.transport) {\n throw createInvalidStateError('BrowserMcpServer is already connected');\n }\n this.observePeerOrigin(transport);\n const stopObserving = this.stopObservingPeerOrigin;\n try {\n await this.mcpServer.connect(transport);\n } catch (error) {\n if (this.stopObservingPeerOrigin === stopObserving) {\n stopObserving?.();\n this.stopObservingPeerOrigin = undefined;\n this.peerOrigin = undefined;\n this.applyToolExposure();\n }\n if (this.mcpServer.server.transport === transport) await this.mcpServer.close();\n throw error;\n }\n }\n\n close(): Promise<void> {\n if (this.closePromise) return this.closePromise;\n this.closed = true;\n this.stopObservingPeerOrigin?.();\n this.stopObservingPeerOrigin = undefined;\n this.closePromise = (async () => {\n this.native?.removeEventListener('toolchange', this.nativeToolChangeListener);\n this.native?.removeEventListener('toolactivated', this.nativeLifecycleListener);\n this.native?.removeEventListener('toolcancel', this.nativeLifecycleListener);\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);\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":";;;;;AAkDA,MAAM,uBAAuB,qBAAqB,MAAS,EAAE;AAC7D,MAAM,yBAAyB;AAE/B,SAAgB,mBAAmB,SAA+C;CAChF,OACE,OAAO,YAAY,YACnB,YAAY,QACZ,0BAA0B,WAC1B,QAAQ,4BAA4B;AAExC;AAOA,SAAS,sBAAsB,WAAwD;CACrF,OACE,kBAAkB,cACjB,UAAU,iBAAiB,UAAa,OAAO,UAAU,iBAAiB,cAC1E,EAAE,oBAAoB,cACrB,UAAU,mBAAmB,UAC7B,OAAO,UAAU,mBAAmB;AAE1C;AAwBA,SAAS,sBAAsB,YAA4D;CACzF,IAAI;CACJ,IAAI;EACF,SAAS,KAAK,MAAM,UAAU;CAChC,QAAQ;EAEN,SAAS;CACX;CACA,IAAI,cAAc,MAAM,GAAG,OAAO;CAElC,OAAO,EAAE,SAAS,CAAC;EAAE,MAAM;EAAQ,MAAM,OAAO,WAAW,WAAW,SAAS;CAAW,CAAC,EAAE;AAC/F;;AAGA,SAAS,gBAAmB,WAAqC,QAAiC;CAChG,OAAO,IAAI,SAAY,SAAS,WAAW;EACzC,OAAO,eAAe;EACtB,MAAM,gBAAgB,OAAO,OAAO,MAAM;EAC1C,OAAO,iBAAiB,SAAS,SAAS,EAAE,MAAM,KAAK,CAAC;EACxD,QAAQ,QAAQ,EACb,KAAK,SAAS,EACd,KAAK,SAAS,MAAM,EACpB,cAAc,OAAO,oBAAoB,SAAS,OAAO,CAAC;CAC/D,CAAC;AACH;AAEA,SAAS,iBACP,YAC+C;CAG/C,IAAI,oBAAoB,WAAW,WAAW,GAAG,OAAO,WAAW;CAGnE,OAAO,eACL,WAAW,WACb;AACF;;;;;;;AAQA,IAAa,mBAAb,cAAsC,YAAkD;CACtF,CAAU,0BAA0B;CACpC,AAAS;CAET,AAAiB;CACjB,AAAiB;CACjB,AAAiB,wBAAQ,IAAI,IAAkC;CAC/D,AAAQ;CACR,AAAQ;CACR,AAAiB,gCAAgB,IAAI,IAAqB;CAC1D,AAAiB,6CAA6B,IAAI,IAA6B;CAC/E,AAAiB,wCAAwB,IAAI,IAAkC;CAC/E,AAAiB,+BAAe,IAAI,IAA6B;CACjE,AAAiB,sCAAsB,IAAI,IAAY;CACvD,AAAQ,kBAAiC,QAAQ,QAAQ;CACzD,AAAQ,wBAAuC,QAAQ,QAAQ;CAC/D,AAAiB;CACjB,AAAQ,SAAS;CACjB,AAAQ;CACR,AAAiB,gCAAgB,IAAI,IAAmD;CACxF,AAAiB,wBAAuC,UAAU;EAChE,KAAK,cAAc,IAAI,MAAM,IAAI,GAAG,KAAK,MAAM,KAAK;CACtD;CAGA,AAAiB,2BAA0C,UAAU;EACnE,IAAI,KAAK,QAAQ;EACjB,MAAM,WAAW,IAAI,MAAM,MAAM,IAAI;EACrC,IAAI,cAAc,OAChB,OAAO,eAAe,UAAU,YAAY;GAAE,YAAY;GAAM,OAAO,MAAM;EAAS,CAAC;EAEzF,KAAK,cAAc,QAAQ;CAC7B;CAEA,YAAY,YAA4B,UAAmC,CAAC,GAAG;EAC7E,MAAM;EACN,MAAM,EAAE,QAAQ,iBAAiB,GAAG,kBAAkB;EACtD,IAAI,CAAC,mBAAmB,CAAC,WAAW,UAAU,cAAc,cAAc;EAC1E,KAAK,YAAY,IAAI,UAAU,YAAY;GACzC,GAAG;GACH,cAAc,kBAAkB,cAAc,gBAAgB,CAAC,GAAG;IAChE,OAAO,EAAE,aAAa,KAAK;IAC3B,WAAW,EAAE,aAAa,KAAK;IAC/B,SAAS,EAAE,aAAa,KAAK;GAC/B,CAAC;EACH,CAAC;EAED,KAAK,SAAS,mBAAmB,WAAW,UAAU;EACtD,KAAK,gBAAgB,WAAW,YAAY;EAC5C,KAAK,iCAAiC;GACpC,IAAI,KAAK,QAAQ;GACjB,KAAK,wBAAwB,KAAK,sBAAsB,KAAK,YAAY;IACvE,IAAI;KACF,MAAM,KAAK,gBAAgB;IAC7B,SAAS,OAAO;KACd,QAAQ,KAAK,gEAAgE,KAAK;IACpF;IACA,MAAM,KAAK,2BAA2B;GACxC,CAAC;EACH;EACA,KAAK,QAAQ,iBAAiB,cAAc,KAAK,wBAAwB;EACzE,KAAK,QAAQ,iBAAiB,iBAAiB,KAAK,uBAAuB;EAC3E,KAAK,QAAQ,iBAAiB,cAAc,KAAK,uBAAuB;CAC1E;CAEA,AAAQ,gBAAgB,MAAwC;EAC9D,OAAO,KAAK,cAAc,IAAI,IAAI,KAAK;CACzC;CAEA,AAAQ,gBAAgB,MAAc,SAAyC;EAC7E,IAAI,OAAO,YAAY,YAAY;GACjC,IAAI,CAAC,KAAK,cAAc,IAAI,IAAI,GAAG,MAAM,iBAAiB,MAAM,KAAK,oBAAoB;GACzF,KAAK,cAAc,IAAI,MAAM,OAAO;EACtC,OAAO,IAAI,KAAK,cAAc,OAAO,IAAI,GACvC,MAAM,oBAAoB,MAAM,KAAK,oBAAoB;CAE7D;CAEA,IAAI,eAAyC;EAC3C,OAAO,KAAK,gBAAgB,YAAY;CAC1C;CAEA,IAAI,aAAa,SAAmC;EAClD,KAAK,gBAAgB,cAAc,OAAO;CAC5C;CAEA,IAAI,kBAA4C;EAC9C,OAAO,KAAK,gBAAgB,eAAe;CAC7C;CAEA,IAAI,gBAAgB,SAAmC;EACrD,KAAK,gBAAgB,iBAAiB,OAAO;CAC/C;CAEA,IAAI,eAAyC;EAC3C,OAAO,KAAK,gBAAgB,YAAY;CAC1C;CAEA,IAAI,aAAa,SAAmC;EAClD,KAAK,gBAAgB,cAAc,OAAO;CAC5C;CAEA,MAAc,6BAA4C;EACxD,IAAI,KAAK,QAAQ;EAEjB,MAAM,IAAI,SAAS,YAAY,WAAW,SAAS,CAAC,CAAC;EACrD,IAAI,CAAC,KAAK,QAAQ,KAAK,cAAc,IAAI,MAAM,YAAY,CAAC;CAC9D;CAEA,MAAc,yBACZ,MACA,YACA,SACA,SACA,YACe;EACf,MAAM,SAAS,KAAK;EACpB,IAAI,CAAC,QAAQ;EACb,MAAM,SAAS,QAAQ,SACnB,YAAY,IAAI,CAAC,QAAQ,QAAQ,WAAW,MAAM,CAAC,IACnD,WAAW;EACf,MAAM,aAAsC;GAC1C,MAAM,KAAK;GACX,aAAa,KAAK;GAClB;EACF;EACA,IAAI,KAAK,UAAU,QAAW,WAAW,QAAQ,KAAK;EACtD,IAAI,WAAW,0BAA0B,QAAW;GAClD,MAAM,cAAuB,KAAK,MAAM,WAAW,qBAAqB;GACxE,IAAI,CAAC,cAAc,WAAW,GAAG,MAAM,IAAI,UAAU,+BAA+B;GACpF,WAAW,cAAc;EAC3B;EACA,IAAI,KAAK,aAAa,WAAW,cAAc,KAAK;EAEpD,KAAK,2BAA2B,IAAI,KAAK,MAAM,UAAU;EACzD,IAAI;GACF,MAAM,OAAO,aAAa,YAAY;IAAE,GAAG;IAAS;GAAO,CAAC;EAC9D,SAAS,OAAO;GACd,WAAW,MAAM;GACjB,IAAI,KAAK,2BAA2B,IAAI,KAAK,IAAI,MAAM,YACrD,KAAK,2BAA2B,OAAO,KAAK,IAAI;GAGlD,IAAI,iBAAiB,gBAAgB,MAAM,SAAS,mBAAmB;IACrE,QAAQ,KACN,4BAA4B,KAAK,KAAK,gCAAgC,MAAM,QAAQ,4DACtF;IACA;GACF;GACA,MAAM;EACR;EACA,IAAI,KAAK,2BAA2B,IAAI,KAAK,IAAI,MAAM,YACrD,KAAK,oBAAoB,OAAO,KAAK,IAAI;CAE7C;CAEA,AAAQ,sBACN,MACA,aAAa,KAAK,2BAA2B,IAAI,IAAI,GAC/C;EACN,IAAI,CAAC,cAAc,KAAK,2BAA2B,IAAI,IAAI,MAAM,YAAY;EAC7E,KAAK,oBAAoB,IAAI,IAAI;EACjC,WAAW,MAAM;EACjB,KAAK,2BAA2B,OAAO,IAAI;CAC7C;CAEA,AAAQ,kBACN,MACA,YACA,aACA,WACsB;EACtB,MAAM,OAAqB;GACzB,MAAM,KAAK;GACX,aAAa,KAAK;GAClB,aAAa,WAAW;EAC1B;EACA,IAAI,KAAK,UAAU,QAAW,KAAK,QAAQ,KAAK;EAChD,IAAI,KAAK,iBAAiB,QAAW,KAAK,eAAe,gBAAgB,KAAK,YAAY;EAC1F,IAAI,KAAK,aAAa,KAAK,cAAc,KAAK;EAE9C,MAAM,SAGF,EACF,aAAa,KAAK,YACpB;EACA,IAAI,KAAK,iBAAiB,QAAW,OAAO,eAAe,eAAe,KAAK,YAAY;EAC3F,IAAI,KAAK,UAAU,QAAW,OAAO,QAAQ,KAAK;EAClD,IAAI,KAAK,aAAa;GACpB,MAAM,EAAE,sBAAsB,uBAAuB,GAAG,gBAAgB,KAAK;GAC7E,OAAO,cAAc;EACvB;EACA,IAAI;EACJ,IAAI,WAAW,YAAY,SAAS,UAAa,WAAW,YAAY,SAAS,UAAU;GACzF,OAAO,cAAc,iBAAiB,UAAU;GAChD,YAAY,KAAK,UAAU,aAAa,KAAK,MAAM,QAAQ,OAAO,MAAM,YAAY;IAClF,MAAM,SAAS,MAAM,YAAY,MAAM,EAAE,QAAQ,QAAQ,OAAO,OAAO,CAAC;IACxE,IAAI,sBAAsB,MAAM,GAC9B,MAAM,IAAI,MACR,gBAAgB,KAAK,KAAK,qGAC5B;IAEF,OAAO,sBAAsB,MAAM;GACrC,CAAC;GAID,UAAU,QAAQ;EACpB,OACE,QAAQ,KACN,4BAA4B,KAAK,KAAK,oHACxC;EAGF,MAAM,aAAmC;GAAE;GAAM;EAAU;EAC3D,IAAI,WAAW,QAAQ,WAAW,YAAY;EAC9C,OAAO;CACT;CAEA,AAAS,eAA2D,OAClE,WACA,eAAuD,CAAC,MACtC;EAClB,MAAM,EAAE,QAAQ,cAAc,gBAAgB,CAAC;EAC/C,MAAM,UAA2C,CAAC;EAClD,IAAI,QAAQ,QAAQ,SAAS;EAC7B,IAAI,WAAW,QAAQ,YAAY,CAAC,GAAG,SAAS;EAChD,IAAI,KAAK,QAAQ,MAAM,wBAAwB,4BAA4B;EAC3E,IAAI,CAAC,cAAc,SAAS,GAC1B,MAAM,IAAI,UAAU,2CAA2C;EAEjE,MAAM,OAAO,2BAA2B,SAAS;EAGjD,IACG,KAAK,MAAM,IAAI,KAAK,IAAI,KAAK,CAAC,KAAK,sBAAsB,IAAI,KAAK,IAAI,KACvE,KAAK,aAAa,IAAI,KAAK,IAAI,GAE/B,MAAM,wBAAwB,4BAA4B,KAAK,MAAM;EAEvE,MAAM,aAAa,qBAAqB,KAAK,WAAW;EACxD,QAAQ,QAAQ,eAAe;EAC/B,MAAM,WAAW,KAAK;EACtB,MAAM,WAAyD,MAAM,YACnE,sBAAsB,SAAS,MAAM,OAAO,GAAG,QAAQ,MAAM;EAC/D,MAAM,aAAa,IAAI,gBAAgB;EAEvC,MAAM,iBAAiB,QAAQ,WAAW,KAAK,WAAW,IAAI,MAAM,MAAM,GAAG,UAAU,MAAM;EAE7F,IAAI;EACJ,MAAM,cAAc;GAClB,IAAI,KAAK,aAAa,IAAI,KAAK,IAAI,MAAM,YACvC,KAAK,aAAa,OAAO,KAAK,IAAI;GAEpC,IAAI,cAAc,KAAK,MAAM,IAAI,KAAK,IAAI,MAAM,YAC9C,KAAK,WAAW,KAAK,IAAI;QACpB;IACL,YAAY,WAAW,OAAO;IAC9B,KAAK,sBAAsB,KAAK,MAAM,UAAU;GAClD;GACA,aAAa;EACf;EACA,QAAQ,QAAQ,iBAAiB,SAAS,OAAO,EAAE,MAAM,KAAK,CAAC;EAC/D,KAAK,aAAa,IAAI,KAAK,MAAM,UAAU;EAC3C,IAAI;GAGF,IAAI,CAAC,KAAK,sBAAsB,IAAI,KAAK,IAAI,GAC3C,aAAa,KAAK,kBAAkB,MAAM,YAAY,SAAS,cAAc;GAE/E,QAAQ,QAAQ,eAAe;GAC/B,MAAM,KAAK,yBAAyB,MAAM,YAAY,SAAS,SAAS,UAAU;GAClF,IAAI,KAAK,QAAQ,MAAM,wBAAwB,4BAA4B;GAC3E,QAAQ,QAAQ,eAAe;GAC/B,KAAK,WAAW,KAAK,MAAM,EAAE,YAAY,KAAK,CAAC;GAC/C,eAAe,KAAK,kBAAkB,MAAM,YAAY,SAAS,cAAc;GAC/E,KAAK,MAAM,IAAI,KAAK,MAAM,UAAU;GACpC,KAAK,kBAAkB;GACvB,IAAI,QAAQ,QAAQ,SAAS;IAC3B,MAAM;IACN,QAAQ,OAAO,eAAe;GAChC;EACF,SAAS,OAAO;GACd,YAAY,WAAW,OAAO;GAC9B,KAAK,sBAAsB,KAAK,MAAM,UAAU;GAChD,QAAQ,QAAQ,oBAAoB,SAAS,KAAK;GAClD,QAAQ,QAAQ,eAAe;GAC/B,MAAM;EACR,UAAU;GACR,IAAI,KAAK,aAAa,IAAI,KAAK,IAAI,MAAM,YACvC,KAAK,aAAa,OAAO,KAAK,IAAI;EAEtC;EACA,IAAI,QAAQ,QAAQ;GAClB,WAAW,cAAc,QAAQ;GACjC,WAAW,gBAAgB;EAC7B;EACA,IAAI,KAAK,MAAM,IAAI,KAAK,IAAI,MAAM,YAChC,MAAM,KAAK;EAEb,IAAI,KAAK,QAAQ,MAAM,wBAAwB,4BAA4B;EAC3E,QAAQ,QAAQ,eAAe;CACjC;CAEA,AAAQ,WAAW,MAAc,SAA0C;EACzE,MAAM,aAAa,KAAK,MAAM,IAAI,IAAI;EACtC,IAAI,YAAY;GACd,IAAI,WAAW,eAAe,WAAW,eACvC,WAAW,YAAY,oBAAoB,SAAS,WAAW,aAAa;GAE9E,KAAK,MAAM,OAAO,IAAI;GACtB,KAAK,sBAAsB,OAAO,IAAI;GACtC,WAAW,WAAW,OAAO;EAC/B;EACA,IAAI,CAAC,SAAS,YAAY,KAAK,sBAAsB,IAAI;CAC3D;CAEA,kBAAiC;EAC/B,MAAM,SAAS,KAAK;EACpB,MAAM,OAAO,KAAK,gBAAgB,KAAK,YAAY;GACjD,IAAI,KAAK,UAAU,CAAC,QAAQ;GAC5B,MAAM,KAAK,4BAA4B,MAAM;EAC/C,CAAC;EACD,KAAK,kBAAkB,KAAK,WACpB,cACA,MACR;EACA,OAAO;CACT;CAEA,MAAc,4BAA4B,QAAqC;EAK7E,MAAM,cAAc,KAAK,eAAe;EACxC,MAAM,SAAS,MAAM,OAAO,SAAS,GAAG,QAAQ,SAAS;GACvD,IAAI,KAAK,WAAW,aAAa,OAAO;GACxC,IAAI,aAAa,WAAW,aAAa,OAAO;GAChD,IAAI,QAAQ,KAAK;GACjB,OAAO,OAAO;IACZ,IAAI,UAAU,aAAa,OAAO;IAClC,MAAM,SAAS,MAAM;IACrB,IAAI,WAAW,OAAO;IACtB,QAAQ;GACV;GACA,OAAO;EACT,CAAC;EACD,IAAI,KAAK,QAAQ;EAGjB,KAAK,MAAM,QAAQ,KAAK,qBACtB,IAAI,CAAC,MAAM,MAAM,SAAS,KAAK,SAAS,QAAQ,KAAK,WAAW,WAAW,GACzE,KAAK,oBAAoB,OAAO,IAAI;EAGxC,MAAM,4BAAY,IAAI,IAAkC;EACxD,KAAK,MAAM,QAAQ,OAAO;GAExB,IACE,UAAU,IAAI,KAAK,IAAI,KACvB,KAAK,aAAa,IAAI,KAAK,IAAI,KAC/B,KAAK,oBAAoB,IAAI,KAAK,IAAI,GAEtC;GAGF,IAAI;GACJ,IAAI;IACF,cAAc,KAAK,MAAM,qBAAqB,KAAK,eAAe,oBAAoB,CAAC;GACzF,QAAQ,CAAC;GACT,IAAI,CAAC,cAAc,WAAW,GAAG;IAC/B,QAAQ,KACN,mCAAmC,KAAK,KAAK,kEAC/C;IACA;GACF;GACA,MAAM,OAAqB;IAAE,MAAM,KAAK;IAAM,aAAa,KAAK;IAAa;GAAY;GACzF,IAAI,KAAK,UAAU,QAAW,KAAK,QAAQ,KAAK;GAChD,IAAI,KAAK,aAAa,KAAK,cAAc,KAAK;GAC9C,UAAU,IAAI,KAAK,MAAM;IAAE,QAAQ;IAAM;IAAM,aAAa,KAAK,UAAU,IAAI;GAAE,CAAC;EACpF;EAEA,KAAK,MAAM,CAAC,MAAM,YAAY,KAAK,uBAAuB;GACxD,MAAM,OAAO,UAAU,IAAI,IAAI;GAC/B,IAAI,MAAM,gBAAgB,QAAQ,aAAa,KAAK,sBAAsB,IAAI,MAAM,IAAI;QACnF,KAAK,WAAW,MAAM,EAAE,YAAY,KAAK,CAAC;EACjD;EAEA,KAAK,MAAM,CAAC,MAAM,SAAS,WAAW;GACpC,IAAI,KAAK,MAAM,IAAI,IAAI,GAAG;GAC1B,MAAM,UAAwD,OAAO,MAAM,YAAY;IACrF,MAAM,cAAc,KAAK,sBAAsB,IAAI,IAAI,GAAG;IAC1D,IAAI,CAAC,aAAa,MAAM,IAAI,MAAM,0BAA0B,MAAM;IAClE,IAAI;KACF,OAAO,sBAAsB,MAAM,OAAO,YAAY,aAAa,MAAM,OAAO,CAAC;IACnF,SAAS,OAAO;KAGd,IAAI,YAAY,OAAO,QAAQ,KAAK,yBAAyB;KAC7D,MAAM;IACR;GACF;GACA,MAAM,OAAO;IAAE,GAAG,KAAK;IAAM;GAAQ;GACrC,IAAI;IAGF,MAAM,aAAa,qBAAqB,KAAK,WAAW;IACxD,KAAK,MAAM,IAAI,MAAM,KAAK,kBAAkB,MAAM,YAAY,OAAO,CAAC;IACtE,KAAK,sBAAsB,IAAI,MAAM,IAAI;GAC3C,SAAS,OAAO;IACd,QAAQ,KACN,mCAAmC,KAAK,uEACxC,KACF;GACF;EACF;EACA,KAAK,kBAAkB;CACzB;CAEA,iBAAiB,YAAoD;EACnE,IAAI,KAAK,QAAQ,MAAM,wBAAwB,4BAA4B;EAC3E,MAAM,uBAAuB,EAAE,GAAG,WAAW;EAC7C,MAAM,SAA2B,CAAC;EAClC,IAAI,qBAAqB,gBAAgB,QACvC,OAAO,cAAc,qBAAqB;EAE5C,IAAI,qBAAqB,aAAa,QACpC,OAAO,WAAW,qBAAqB;EACzC,MAAM,WAAW,qBAAqB,IAAI,SAAS,GAAG,IAClD,IAAI,iBAAiB,qBAAqB,KAAK,EAAE,MAAM,OAAU,CAAC,IAClE;EACJ,MAAM,YAAY,WACd,KAAK,UAAU,iBACb,qBAAqB,MACrB,UACA,QACA,OAAO,KAAK,cAAc,qBAAqB,KAAK,KAAK,SAAS,CACpE,IACA,KAAK,UAAU,iBACb,qBAAqB,MACrB,qBAAqB,KACrB,QACA,OAAO,QAAQ,qBAAqB,KAAK,GAAG,CAC9C;EACJ,KAAK,cAAc,IAAI,SAAS;EAChC,OAAO,EACL,kBAAkB;GAChB,IAAI,KAAK,cAAc,OAAO,SAAS,GAAG,UAAU,OAAO;EAC7D,EACF;CACF;CAEA,eAAe,YAAkD;EAC/D,IAAI,KAAK,QAAQ,MAAM,wBAAwB,4BAA4B;EAC3E,MAAM,uBAAuB,EAAE,GAAG,WAAW;EAC7C,IAAI,WAAW,eAAe,QAC5B,qBAAqB,aAAa,gBAAgB,WAAW,UAAU;EAEzE,MAAM,aACJ,qBAAqB,eAAe,SAChC,SACA,eAGE,qBAAqB,UACvB;EACN,MAAM,SAEF,CAAC;EACL,IAAI,qBAAqB,gBAAgB,QACvC,OAAO,cAAc,qBAAqB;EAE5C,IAAI,YAAY,OAAO,aAAa;EACpC,MAAM,YAAY,KAAK,UAAU,eAC/B,qBAAqB,MACrB,QACA,OAAO,SAAS,qBAAqB,IAAI,QAAQ,CAAC,CAAC,CACrD;EACA,KAAK,cAAc,IAAI,SAAS;EAChC,OAAO,EACL,kBAAkB;GAChB,IAAI,KAAK,cAAc,OAAO,SAAS,GAAG,UAAU,OAAO;EAC7D,EACF;CACF;CAEA,YAA4B;EAC1B,OAAO,gBAAgB,CAAC,GAAG,KAAK,MAAM,OAAO,CAAC,EAAE,KAAK,EAAE,WAAW,IAAI,CAAC;CACzE;CAEA,MAAM,SAAS,SAAiE;EAC9E,IAAI,KAAK,QAAQ,MAAM,wBAAwB,4BAA4B;EAC3E,IAAI,CAAC,KAAK,QAAQ,MAAM,wBAAwB,wCAAwC;EACxF,OAAO,KAAK,OAAO,SAAS,OAAO;CACrC;CAEA,MAAM,YAAY,GAAG,MAAgE;EACnF,IAAI,KAAK,QAAQ,MAAM,wBAAwB,4BAA4B;EAC3E,IAAI,CAAC,KAAK,QAAQ,MAAM,wBAAwB,wCAAwC;EACxF,OAAO,KAAK,OAAO,YAAY,GAAG,IAAI;CACxC;;;;;;;;;;CAWA,AAAQ,oBAA0B;EAChC,KAAK,MAAM,EAAE,WAAW,eAAe,KAAK,MAAM,OAAO,GAAG;GAC1D,IAAI,CAAC,WAAW;GAEhB,MAAM,UACJ,CAAC,WAAW,UACX,KAAK,eAAe,UACnB,KAAK,eAAe,UACpB,UAAU,SAAS,KAAK,UAAU;GACtC,IAAI,YAAY,UAAU,SAAS;GACnC,IAAI,SAAS,UAAU,OAAO;QACzB,UAAU,QAAQ;EACzB;CACF;;;;;;;CAQA,AAAQ,kBAAkB,WAA4B;EACpD,KAAK,0BAA0B;EAC/B,KAAK,0BAA0B;EAC/B,KAAK,aAAa;EAClB,KAAK,kBAAkB;EACvB,IAAI,CAAC,sBAAsB,SAAS,GAAG;EACvC,MAAM,SAAS;EACf,KAAK,aAAa,OAAO;EACzB,KAAK,kBAAkB;EACvB,MAAM,WAAW,OAAO;EACxB,IAAI,YAAY;EAChB,MAAM,kBAAkB,WAAmB;GACzC,WAAW,MAAM;GACjB,IAAI,CAAC,WAAW;GAChB,KAAK,aAAa;GAClB,KAAK,kBAAkB;EACzB;EACA,OAAO,iBAAiB;EACxB,KAAK,gCAAgC;GACnC,YAAY;GACZ,IAAI,OAAO,mBAAmB,gBAAgB,OAAO,iBAAiB;EACxE;CACF;CAEA,MAAM,QAAQ,WAAqC;EACjD,IAAI,KAAK,QAAQ,MAAM,wBAAwB,4BAA4B;EAC3E,IAAI,KAAK,UAAU,OAAO,WACxB,MAAM,wBAAwB,uCAAuC;EAEvE,KAAK,kBAAkB,SAAS;EAChC,MAAM,gBAAgB,KAAK;EAC3B,IAAI;GACF,MAAM,KAAK,UAAU,QAAQ,SAAS;EACxC,SAAS,OAAO;GACd,IAAI,KAAK,4BAA4B,eAAe;IAClD,gBAAgB;IAChB,KAAK,0BAA0B;IAC/B,KAAK,aAAa;IAClB,KAAK,kBAAkB;GACzB;GACA,IAAI,KAAK,UAAU,OAAO,cAAc,WAAW,MAAM,KAAK,UAAU,MAAM;GAC9E,MAAM;EACR;CACF;CAEA,QAAuB;EACrB,IAAI,KAAK,cAAc,OAAO,KAAK;EACnC,KAAK,SAAS;EACd,KAAK,0BAA0B;EAC/B,KAAK,0BAA0B;EAC/B,KAAK,gBAAgB,YAAY;GAC/B,KAAK,QAAQ,oBAAoB,cAAc,KAAK,wBAAwB;GAC5E,KAAK,QAAQ,oBAAoB,iBAAiB,KAAK,uBAAuB;GAC9E,KAAK,QAAQ,oBAAoB,cAAc,KAAK,uBAAuB;GAC3E,KAAK,MAAM,QAAQ,KAAK,2BAA2B,KAAK,GACtD,KAAK,sBAAsB,IAAI;GAEjC,KAAK,MAAM,QAAQ,KAAK,MAAM,KAAK,GACjC,KAAK,WAAW,IAAI;GAEtB,KAAK,MAAM,UAAU,KAAK,eAAe,OAAO,OAAO;GACvD,KAAK,cAAc,MAAM;GACzB,KAAK,sBAAsB,MAAM;GACjC,KAAK,oBAAoB,MAAM;GAC/B,MAAM,KAAK,UAAU,MAAM;EAC7B,GAAG;EACH,OAAO,KAAK;CACd;AACF"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mcp-b/webmcp-ts-sdk",
|
|
3
|
-
"version": "6.0.0
|
|
3
|
+
"version": "6.0.0",
|
|
4
4
|
"description": "WebMCP browser adapter extending the upstream API with MCP capabilities",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"adapter",
|
|
@@ -65,7 +65,7 @@
|
|
|
65
65
|
"@modelcontextprotocol/server": "2.0.0",
|
|
66
66
|
"@standard-schema/spec": "^1.1.0",
|
|
67
67
|
"webmcp-types": "0.1.9",
|
|
68
|
-
"@mcp-b/webmcp-polyfill": "6.0.0
|
|
68
|
+
"@mcp-b/webmcp-polyfill": "6.0.0"
|
|
69
69
|
},
|
|
70
70
|
"devDependencies": {
|
|
71
71
|
"@modelcontextprotocol/client": "2.0.0",
|