@mcp-b/global 1.1.3-beta.0 → 1.1.3-beta.3
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/README.md +51 -6
- package/dist/index.d.ts +11 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.iife.js +6 -4
- package/dist/index.js +63 -52
- package/dist/index.js.map +1 -1
- package/package.json +27 -10
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["jsonSchemaToZod","convertJsonSchemaToZod","properties: Record<string, { type: string; description?: string; [key: string]: unknown }>","required: string[]","enumValues: unknown[] | undefined","items: unknown | undefined","propertySchema: { type: string; description?: string; [key: string]: unknown }","validatedTool: ValidatedToolDescriptor","jsonSchemaToZod","args: Record<string, unknown>","templateParams: string[]","argsSchema: InputSchema | undefined","argsValidator: z.ZodType | undefined","paramNames: string[]","params: Record<string, string>","bridge","customTransport: Transport | undefined","McpServer","bridge: MCPBridge","options: WebModelContextInitOptions","tabServerOptions: TabServerConfig"],"sources":["../src/validation.ts","../src/global.ts","../src/index.ts"],"sourcesContent":["import { jsonSchemaToZod as convertJsonSchemaToZod } from '@composio/json-schema-to-zod';\nimport { z } from 'zod';\nimport type { InputSchema } from './types.js';\n\n/**\n * Detect if a schema is a Zod schema object (Record<string, ZodType>)\n * or a JSON Schema object\n */\nexport function isZodSchema(schema: unknown): boolean {\n if (typeof schema !== 'object' || schema === null) {\n return false;\n }\n\n if ('type' in schema && typeof (schema as { type: unknown }).type === 'string') {\n return false;\n }\n\n const values = Object.values(schema);\n if (values.length === 0) {\n return false;\n }\n\n return values.some((val) => val instanceof z.ZodType);\n}\n\n/**\n * Convert JSON Schema to Zod validator\n * Uses @composio/json-schema-to-zod for conversion\n */\nexport function jsonSchemaToZod(jsonSchema: InputSchema): z.ZodType {\n try {\n const zodSchema = convertJsonSchemaToZod(jsonSchema as unknown as object);\n return zodSchema;\n } catch (error) {\n console.warn('[Web Model Context] Failed to convert JSON Schema to Zod:', error);\n return z.object({}).passthrough();\n }\n}\n\n/**\n * Convert Zod schema object to JSON Schema\n * Based on react-webmcp implementation\n */\nexport function zodToJsonSchema(schema: Record<string, z.ZodTypeAny>): InputSchema {\n const properties: Record<string, { type: string; description?: string; [key: string]: unknown }> =\n {};\n const required: string[] = [];\n\n for (const [key, zodType] of Object.entries(schema)) {\n const description = (zodType as { description?: string }).description || undefined;\n\n let type = 'string';\n let enumValues: unknown[] | undefined;\n let items: unknown | undefined;\n\n if (zodType instanceof z.ZodString) {\n type = 'string';\n } else if (zodType instanceof z.ZodNumber) {\n type = 'number';\n } else if (zodType instanceof z.ZodBoolean) {\n type = 'boolean';\n } else if (zodType instanceof z.ZodArray) {\n type = 'array';\n const elementType = (zodType as { element?: z.ZodTypeAny }).element;\n if (elementType instanceof z.ZodString) {\n items = { type: 'string' };\n } else if (elementType instanceof z.ZodNumber) {\n items = { type: 'number' };\n } else if (elementType instanceof z.ZodBoolean) {\n items = { type: 'boolean' };\n } else {\n items = { type: 'string' };\n }\n } else if (zodType instanceof z.ZodObject) {\n type = 'object';\n } else if (zodType instanceof z.ZodEnum) {\n type = 'string';\n const enumDef = (zodType as { _def?: { values?: unknown[] } })._def;\n if (enumDef?.values) {\n enumValues = enumDef.values;\n }\n }\n\n const propertySchema: { type: string; description?: string; [key: string]: unknown } = { type };\n if (description) {\n propertySchema.description = description;\n }\n if (enumValues) {\n propertySchema.enum = enumValues;\n }\n if (items) {\n propertySchema.items = items;\n }\n\n properties[key] = propertySchema;\n\n if (!zodType.isOptional()) {\n required.push(key);\n }\n }\n\n return {\n type: 'object',\n properties,\n ...(required.length > 0 && { required }),\n };\n}\n\n/**\n * Normalize a schema to both JSON Schema and Zod formats\n * Detects which format is provided and converts to the other\n */\nexport function normalizeSchema(schema: InputSchema | Record<string, z.ZodTypeAny>): {\n jsonSchema: InputSchema;\n zodValidator: z.ZodType;\n} {\n const isZod = isZodSchema(schema);\n\n if (isZod) {\n const jsonSchema = zodToJsonSchema(schema as Record<string, z.ZodTypeAny>);\n const zodValidator = z.object(schema as Record<string, z.ZodTypeAny>);\n return { jsonSchema, zodValidator };\n }\n\n const jsonSchema = schema as InputSchema;\n const zodValidator = jsonSchemaToZod(jsonSchema);\n return { jsonSchema, zodValidator };\n}\n\n/**\n * Validate data with Zod schema and return formatted result\n */\nexport function validateWithZod(\n data: unknown,\n validator: z.ZodType\n): { success: true; data: unknown } | { success: false; error: string } {\n const result = validator.safeParse(data);\n\n if (!result.success) {\n const errors = result.error.errors\n .map((err) => ` - ${err.path.join('.') || 'root'}: ${err.message}`)\n .join('\\n');\n return {\n success: false,\n error: `Validation failed:\\n${errors}`,\n };\n }\n\n return {\n success: true,\n data: result.data,\n };\n}\n","import {\n IframeChildTransport,\n type IframeChildTransportOptions,\n TabServerTransport,\n type TabServerTransportOptions,\n} from '@mcp-b/transports';\nimport type {\n Prompt,\n PromptMessage,\n Resource,\n ResourceContents,\n Transport,\n} from '@mcp-b/webmcp-ts-sdk';\nimport {\n CallToolRequestSchema,\n GetPromptRequestSchema,\n ListPromptsRequestSchema,\n ListResourcesRequestSchema,\n ListToolsRequestSchema,\n Server as McpServer,\n ReadResourceRequestSchema,\n} from '@mcp-b/webmcp-ts-sdk';\nimport type { z } from 'zod';\nimport type {\n ElicitationParams,\n ElicitationResult,\n InputSchema,\n InternalModelContext,\n MCPBridge,\n ModelContext,\n ModelContextInput,\n ModelContextTesting,\n PromptDescriptor,\n ResourceDescriptor,\n SamplingRequestParams,\n SamplingResult,\n ToolCallEvent,\n ToolDescriptor,\n ToolResponse,\n ValidatedPromptDescriptor,\n ValidatedResourceDescriptor,\n ValidatedToolDescriptor,\n WebModelContextInitOptions,\n ZodSchemaObject,\n} from './types.js';\nimport { jsonSchemaToZod, normalizeSchema, validateWithZod } from './validation.js';\n\ndeclare global {\n interface Window {\n __webModelContextOptions?: WebModelContextInitOptions;\n }\n}\n\n/**\n * Detect if the native Chromium Web Model Context API is available.\n * Checks for both navigator.modelContext and navigator.modelContextTesting,\n * and verifies they are native implementations (not polyfills) by examining\n * the constructor name.\n *\n * @returns Detection result with flags for native context and testing API availability\n */\nfunction detectNativeAPI(): {\n hasNativeContext: boolean;\n hasNativeTesting: boolean;\n} {\n if (typeof window === 'undefined' || typeof navigator === 'undefined') {\n return { hasNativeContext: false, hasNativeTesting: false };\n }\n\n const modelContext = navigator.modelContext;\n const modelContextTesting = navigator.modelContextTesting;\n\n if (!modelContext || !modelContextTesting) {\n return { hasNativeContext: false, hasNativeTesting: false };\n }\n\n const testingConstructorName = modelContextTesting.constructor?.name || '';\n const isPolyfill = testingConstructorName.includes('WebModelContext');\n\n if (isPolyfill) {\n return { hasNativeContext: false, hasNativeTesting: false };\n }\n\n return { hasNativeContext: true, hasNativeTesting: true };\n}\n\n/**\n * Adapter that wraps the native Chromium Web Model Context API.\n * Synchronizes tool changes from the native API to the MCP bridge,\n * enabling MCP clients to stay in sync with the native tool registry.\n *\n * Key features:\n * - Listens to native tool changes via registerToolsChangedCallback()\n * - Syncs native tools to MCP bridge automatically\n * - Delegates tool execution to native API\n * - Converts native results to MCP ToolResponse format\n *\n * @class NativeModelContextAdapter\n * @implements {InternalModelContext}\n */\nclass NativeModelContextAdapter implements InternalModelContext {\n private nativeContext: ModelContext;\n private nativeTesting: ModelContextTesting;\n private bridge: MCPBridge;\n private syncInProgress = false;\n\n /**\n * Creates a new NativeModelContextAdapter.\n *\n * @param {MCPBridge} bridge - The MCP bridge instance\n * @param {ModelContext} nativeContext - The native navigator.modelContext\n * @param {ModelContextTesting} nativeTesting - The native navigator.modelContextTesting\n */\n constructor(bridge: MCPBridge, nativeContext: ModelContext, nativeTesting: ModelContextTesting) {\n this.bridge = bridge;\n this.nativeContext = nativeContext;\n this.nativeTesting = nativeTesting;\n\n this.nativeTesting.registerToolsChangedCallback(() => {\n console.log('[Native Adapter] Tool change detected from native API');\n this.syncToolsFromNative();\n });\n\n this.syncToolsFromNative();\n }\n\n /**\n * Synchronizes tools from the native API to the MCP bridge.\n * Fetches all tools from navigator.modelContextTesting.listTools()\n * and updates the bridge's tool registry.\n *\n * @private\n */\n private syncToolsFromNative(): void {\n if (this.syncInProgress) {\n return;\n }\n\n this.syncInProgress = true;\n\n try {\n const nativeTools = this.nativeTesting.listTools();\n console.log(`[Native Adapter] Syncing ${nativeTools.length} tools from native API`);\n\n this.bridge.tools.clear();\n\n for (const toolInfo of nativeTools) {\n try {\n const inputSchema = JSON.parse(toolInfo.inputSchema);\n\n const validatedTool: ValidatedToolDescriptor = {\n name: toolInfo.name,\n description: toolInfo.description,\n inputSchema: inputSchema,\n execute: async (args: Record<string, unknown>) => {\n const result = await this.nativeTesting.executeTool(\n toolInfo.name,\n JSON.stringify(args)\n );\n return this.convertToToolResponse(result);\n },\n inputValidator: jsonSchemaToZod(inputSchema),\n };\n\n this.bridge.tools.set(toolInfo.name, validatedTool);\n } catch (error) {\n console.error(`[Native Adapter] Failed to sync tool \"${toolInfo.name}\":`, error);\n }\n }\n\n this.notifyMCPServers();\n } finally {\n this.syncInProgress = false;\n }\n }\n\n /**\n * Converts native API result to MCP ToolResponse format.\n * Native API returns simplified values (string, number, object, etc.)\n * which need to be wrapped in the MCP CallToolResult format.\n *\n * @param {unknown} result - The result from native executeTool()\n * @returns {ToolResponse} Formatted MCP ToolResponse\n * @private\n */\n private convertToToolResponse(result: unknown): ToolResponse {\n if (typeof result === 'string') {\n return { content: [{ type: 'text', text: result }] };\n }\n\n if (result === undefined || result === null) {\n return { content: [{ type: 'text', text: '' }] };\n }\n\n if (typeof result === 'object') {\n return {\n content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],\n structuredContent: result as Record<string, unknown>,\n };\n }\n\n return {\n content: [{ type: 'text', text: String(result) }],\n };\n }\n\n /**\n * Notifies all connected MCP servers that the tools list has changed.\n *\n * @private\n */\n private notifyMCPServers(): void {\n if (this.bridge.tabServer?.notification) {\n this.bridge.tabServer.notification({\n method: 'notifications/tools/list_changed',\n params: {},\n });\n }\n\n if (this.bridge.iframeServer?.notification) {\n this.bridge.iframeServer.notification({\n method: 'notifications/tools/list_changed',\n params: {},\n });\n }\n }\n\n /**\n * Provides context (tools) to AI models via the native API.\n * Delegates to navigator.modelContext.provideContext().\n * Tool change callback will fire and trigger sync automatically.\n *\n * @param {ModelContextInput} context - Context containing tools to register\n */\n provideContext(context: ModelContextInput): void {\n console.log('[Native Adapter] Delegating provideContext to native API');\n this.nativeContext.provideContext(context);\n }\n\n /**\n * Registers a single tool dynamically via the native API.\n * Delegates to navigator.modelContext.registerTool().\n * Tool change callback will fire and trigger sync automatically.\n *\n * @param {ToolDescriptor} tool - The tool descriptor to register\n * @returns {{unregister: () => void}} Object with unregister function\n */\n registerTool<\n TInputSchema extends ZodSchemaObject = Record<string, never>,\n TOutputSchema extends ZodSchemaObject = Record<string, never>,\n >(tool: ToolDescriptor<TInputSchema, TOutputSchema>): { unregister: () => void } {\n console.log(`[Native Adapter] Delegating registerTool(\"${tool.name}\") to native API`);\n const result = this.nativeContext.registerTool(tool);\n return result;\n }\n\n /**\n * Unregisters a tool by name via the native API.\n * Delegates to navigator.modelContext.unregisterTool().\n *\n * @param {string} name - Name of the tool to unregister\n */\n unregisterTool(name: string): void {\n console.log(`[Native Adapter] Delegating unregisterTool(\"${name}\") to native API`);\n this.nativeContext.unregisterTool(name);\n }\n\n /**\n * Clears all registered tools via the native API.\n * Delegates to navigator.modelContext.clearContext().\n */\n clearContext(): void {\n console.log('[Native Adapter] Delegating clearContext to native API');\n this.nativeContext.clearContext();\n }\n\n /**\n * Executes a tool via the native API.\n * Delegates to navigator.modelContextTesting.executeTool() with JSON string args.\n *\n * @param {string} toolName - Name of the tool to execute\n * @param {Record<string, unknown>} args - Arguments to pass to the tool\n * @returns {Promise<ToolResponse>} The tool's response in MCP format\n * @internal\n */\n async executeTool(toolName: string, args: Record<string, unknown>): Promise<ToolResponse> {\n console.log(`[Native Adapter] Executing tool \"${toolName}\" via native API`);\n try {\n const result = await this.nativeTesting.executeTool(toolName, JSON.stringify(args));\n return this.convertToToolResponse(result);\n } catch (error) {\n console.error(`[Native Adapter] Error executing tool \"${toolName}\":`, error);\n return {\n content: [\n {\n type: 'text',\n text: `Error: ${error instanceof Error ? error.message : String(error)}`,\n },\n ],\n isError: true,\n };\n }\n }\n\n /**\n * Lists all registered tools from the MCP bridge.\n * Returns tools synced from the native API.\n *\n * @returns {Array<{name: string, description: string, inputSchema: InputSchema}>} Array of tool descriptors\n */\n listTools() {\n return Array.from(this.bridge.tools.values()).map((tool) => ({\n name: tool.name,\n description: tool.description,\n inputSchema: tool.inputSchema,\n ...(tool.outputSchema && { outputSchema: tool.outputSchema }),\n ...(tool.annotations && { annotations: tool.annotations }),\n }));\n }\n\n // ==================== RESOURCE METHODS (not yet supported by native API) ====================\n\n /**\n * Registers a resource dynamically.\n * Note: Native Chromium API does not yet support resources.\n * This is a polyfill-only feature.\n */\n registerResource(_resource: ResourceDescriptor): { unregister: () => void } {\n console.warn('[Native Adapter] registerResource is not supported by native API');\n return { unregister: () => {} };\n }\n\n /**\n * Unregisters a resource by URI.\n * Note: Native Chromium API does not yet support resources.\n */\n unregisterResource(_uri: string): void {\n console.warn('[Native Adapter] unregisterResource is not supported by native API');\n }\n\n /**\n * Lists all registered resources.\n * Note: Native Chromium API does not yet support resources.\n */\n listResources(): Resource[] {\n return [];\n }\n\n /**\n * Lists all resource templates.\n * Note: Native Chromium API does not yet support resources.\n */\n listResourceTemplates(): Array<{\n uriTemplate: string;\n name: string;\n description?: string;\n mimeType?: string;\n }> {\n return [];\n }\n\n /**\n * Reads a resource by URI.\n * Note: Native Chromium API does not yet support resources.\n * @internal\n */\n async readResource(_uri: string): Promise<{ contents: ResourceContents[] }> {\n throw new Error('[Native Adapter] readResource is not supported by native API');\n }\n\n // ==================== PROMPT METHODS (not yet supported by native API) ====================\n\n /**\n * Registers a prompt dynamically.\n * Note: Native Chromium API does not yet support prompts.\n * This is a polyfill-only feature.\n */\n registerPrompt<TArgsSchema extends ZodSchemaObject = Record<string, never>>(\n _prompt: PromptDescriptor<TArgsSchema>\n ): { unregister: () => void } {\n console.warn('[Native Adapter] registerPrompt is not supported by native API');\n return { unregister: () => {} };\n }\n\n /**\n * Unregisters a prompt by name.\n * Note: Native Chromium API does not yet support prompts.\n */\n unregisterPrompt(_name: string): void {\n console.warn('[Native Adapter] unregisterPrompt is not supported by native API');\n }\n\n /**\n * Lists all registered prompts.\n * Note: Native Chromium API does not yet support prompts.\n */\n listPrompts(): Prompt[] {\n return [];\n }\n\n /**\n * Gets a prompt with arguments.\n * Note: Native Chromium API does not yet support prompts.\n * @internal\n */\n async getPrompt(\n _name: string,\n _args?: Record<string, unknown>\n ): Promise<{ messages: PromptMessage[] }> {\n throw new Error('[Native Adapter] getPrompt is not supported by native API');\n }\n\n /**\n * Adds an event listener for tool call events.\n * Delegates to the native API's addEventListener.\n *\n * @param {'toolcall'} type - Event type\n * @param {(event: ToolCallEvent) => void | Promise<void>} listener - Event handler\n * @param {boolean | AddEventListenerOptions} [options] - Event listener options\n */\n addEventListener(\n type: 'toolcall',\n listener: (event: ToolCallEvent) => void | Promise<void>,\n options?: boolean | AddEventListenerOptions\n ): void {\n this.nativeContext.addEventListener(type, listener, options);\n }\n\n /**\n * Removes an event listener for tool call events.\n * Delegates to the native API's removeEventListener.\n *\n * @param {'toolcall'} type - Event type\n * @param {(event: ToolCallEvent) => void | Promise<void>} listener - Event handler\n * @param {boolean | EventListenerOptions} [options] - Event listener options\n */\n removeEventListener(\n type: 'toolcall',\n listener: (event: ToolCallEvent) => void | Promise<void>,\n options?: boolean | EventListenerOptions\n ): void {\n this.nativeContext.removeEventListener(type, listener, options);\n }\n\n /**\n * Dispatches a tool call event.\n * Delegates to the native API's dispatchEvent.\n *\n * @param {Event} event - The event to dispatch\n * @returns {boolean} False if event was cancelled, true otherwise\n */\n dispatchEvent(event: Event): boolean {\n return this.nativeContext.dispatchEvent(event);\n }\n\n // ==================== SAMPLING METHODS ====================\n\n /**\n * Request an LLM completion from the connected client.\n * Note: Native Chromium API does not yet support sampling.\n * This is handled by the polyfill.\n */\n async createMessage(params: SamplingRequestParams): Promise<SamplingResult> {\n console.log('[Native Adapter] Requesting sampling from client');\n const server = this.bridge.tabServer;\n\n // Access the underlying Server instance to call createMessage\n const underlyingServer = (\n server as unknown as {\n server: { createMessage: (params: unknown) => Promise<SamplingResult> };\n }\n ).server;\n\n if (!underlyingServer?.createMessage) {\n throw new Error('Sampling is not supported: no connected client with sampling capability');\n }\n\n return underlyingServer.createMessage(params);\n }\n\n // ==================== ELICITATION METHODS ====================\n\n /**\n * Request user input from the connected client.\n * Note: Native Chromium API does not yet support elicitation.\n * This is handled by the polyfill.\n */\n async elicitInput(params: ElicitationParams): Promise<ElicitationResult> {\n console.log('[Native Adapter] Requesting elicitation from client');\n const server = this.bridge.tabServer;\n\n // Access the underlying Server instance to call elicitInput\n const underlyingServer = (\n server as unknown as {\n server: { elicitInput: (params: unknown) => Promise<ElicitationResult> };\n }\n ).server;\n\n if (!underlyingServer?.elicitInput) {\n throw new Error(\n 'Elicitation is not supported: no connected client with elicitation capability'\n );\n }\n\n return underlyingServer.elicitInput(params);\n }\n}\n\n/**\n * ToolCallEvent implementation for the Web Model Context API.\n * Represents an event fired when a tool is called, allowing event listeners\n * to intercept and provide custom responses.\n *\n * @class WebToolCallEvent\n * @extends {Event}\n * @implements {ToolCallEvent}\n */\nclass WebToolCallEvent extends Event implements ToolCallEvent {\n public name: string;\n public arguments: Record<string, unknown>;\n private _response: ToolResponse | null = null;\n private _responded = false;\n\n /**\n * Creates a new ToolCallEvent.\n *\n * @param {string} toolName - Name of the tool being called\n * @param {Record<string, unknown>} args - Validated arguments for the tool\n */\n constructor(toolName: string, args: Record<string, unknown>) {\n super('toolcall', { cancelable: true });\n this.name = toolName;\n this.arguments = args;\n }\n\n /**\n * Provides a response for this tool call, preventing the default tool execution.\n *\n * @param {ToolResponse} response - The response to use instead of executing the tool\n * @throws {Error} If a response has already been provided\n */\n respondWith(response: ToolResponse): void {\n if (this._responded) {\n throw new Error('Response already provided for this tool call');\n }\n this._response = response;\n this._responded = true;\n }\n\n /**\n * Gets the response provided via respondWith().\n *\n * @returns {ToolResponse | null} The response, or null if none provided\n */\n getResponse(): ToolResponse | null {\n return this._response;\n }\n\n /**\n * Checks whether a response has been provided for this tool call.\n *\n * @returns {boolean} True if respondWith() was called\n */\n hasResponse(): boolean {\n return this._responded;\n }\n}\n\n/**\n * Time window in milliseconds to detect rapid duplicate tool registrations.\n * Used to filter out double-registrations caused by React Strict Mode.\n */\nconst RAPID_DUPLICATE_WINDOW_MS = 50;\n\n/**\n * Testing API implementation for the Model Context Protocol.\n * Provides debugging, mocking, and testing capabilities for tool execution.\n * Implements both Chromium native methods and polyfill-specific extensions.\n *\n * @class WebModelContextTesting\n * @implements {ModelContextTesting}\n */\nclass WebModelContextTesting implements ModelContextTesting {\n private toolCallHistory: Array<{\n toolName: string;\n arguments: Record<string, unknown>;\n timestamp: number;\n }> = [];\n private mockResponses: Map<string, ToolResponse> = new Map();\n private toolsChangedCallbacks: Set<() => void> = new Set();\n private bridge: MCPBridge;\n\n /**\n * Creates a new WebModelContextTesting instance.\n *\n * @param {MCPBridge} bridge - The MCP bridge instance to test\n */\n constructor(bridge: MCPBridge) {\n this.bridge = bridge;\n }\n\n /**\n * Records a tool call in the history.\n * Called internally by WebModelContext when tools are executed.\n *\n * @param {string} toolName - Name of the tool that was called\n * @param {Record<string, unknown>} args - Arguments passed to the tool\n * @internal\n */\n recordToolCall(toolName: string, args: Record<string, unknown>): void {\n this.toolCallHistory.push({\n toolName,\n arguments: args,\n timestamp: Date.now(),\n });\n }\n\n /**\n * Checks if a mock response is registered for a specific tool.\n *\n * @param {string} toolName - Name of the tool to check\n * @returns {boolean} True if a mock response exists\n * @internal\n */\n hasMockResponse(toolName: string): boolean {\n return this.mockResponses.has(toolName);\n }\n\n /**\n * Retrieves the mock response for a specific tool.\n *\n * @param {string} toolName - Name of the tool\n * @returns {ToolResponse | undefined} The mock response, or undefined if none exists\n * @internal\n */\n getMockResponse(toolName: string): ToolResponse | undefined {\n return this.mockResponses.get(toolName);\n }\n\n /**\n * Notifies all registered callbacks that the tools list has changed.\n * Called internally when tools are registered, unregistered, or cleared.\n *\n * @internal\n */\n notifyToolsChanged(): void {\n for (const callback of this.toolsChangedCallbacks) {\n try {\n callback();\n } catch (error) {\n console.error('[Model Context Testing] Error in tools changed callback:', error);\n }\n }\n }\n\n /**\n * Executes a tool directly with JSON string input (Chromium native API).\n * Parses the JSON input, validates it, and executes the tool.\n *\n * @param {string} toolName - Name of the tool to execute\n * @param {string} inputArgsJson - JSON string of input arguments\n * @returns {Promise<unknown>} The tool's result, or undefined on error\n * @throws {SyntaxError} If the input JSON is invalid\n * @throws {Error} If the tool does not exist\n */\n async executeTool(toolName: string, inputArgsJson: string): Promise<unknown> {\n console.log(`[Model Context Testing] Executing tool: ${toolName}`);\n\n let args: Record<string, unknown>;\n try {\n args = JSON.parse(inputArgsJson);\n } catch (error) {\n throw new SyntaxError(\n `Invalid JSON input: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n\n const tool = this.bridge.tools.get(toolName);\n if (!tool) {\n throw new Error(`Tool not found: ${toolName}`);\n }\n\n const result = await this.bridge.modelContext.executeTool(toolName, args);\n\n if (result.isError) {\n return undefined;\n }\n\n if (result.structuredContent) {\n return result.structuredContent;\n }\n\n if (result.content && result.content.length > 0) {\n const firstContent = result.content[0];\n if (firstContent && firstContent.type === 'text') {\n return firstContent.text;\n }\n }\n\n return undefined;\n }\n\n /**\n * Lists all registered tools with inputSchema as JSON string (Chromium native API).\n * Returns an array of ToolInfo objects where inputSchema is stringified.\n *\n * @returns {Array<{name: string, description: string, inputSchema: string}>} Array of tool information\n */\n listTools(): Array<{ name: string; description: string; inputSchema: string }> {\n const tools = this.bridge.modelContext.listTools();\n return tools.map((tool) => ({\n name: tool.name,\n description: tool.description,\n inputSchema: JSON.stringify(tool.inputSchema),\n }));\n }\n\n /**\n * Registers a callback that fires when the tools list changes (Chromium native API).\n * The callback will be invoked on registerTool, unregisterTool, provideContext, and clearContext.\n *\n * @param {() => void} callback - Function to call when tools change\n */\n registerToolsChangedCallback(callback: () => void): void {\n this.toolsChangedCallbacks.add(callback);\n console.log('[Model Context Testing] Tools changed callback registered');\n }\n\n /**\n * Gets all tool calls that have been recorded (polyfill extension).\n *\n * @returns {Array<{toolName: string, arguments: Record<string, unknown>, timestamp: number}>} Tool call history\n */\n getToolCalls(): Array<{\n toolName: string;\n arguments: Record<string, unknown>;\n timestamp: number;\n }> {\n return [...this.toolCallHistory];\n }\n\n /**\n * Clears the tool call history (polyfill extension).\n */\n clearToolCalls(): void {\n this.toolCallHistory = [];\n console.log('[Model Context Testing] Tool call history cleared');\n }\n\n /**\n * Sets a mock response for a specific tool (polyfill extension).\n * When set, the tool's execute function will be bypassed.\n *\n * @param {string} toolName - Name of the tool to mock\n * @param {ToolResponse} response - The mock response to return\n */\n setMockToolResponse(toolName: string, response: ToolResponse): void {\n this.mockResponses.set(toolName, response);\n console.log(`[Model Context Testing] Mock response set for tool: ${toolName}`);\n }\n\n /**\n * Clears the mock response for a specific tool (polyfill extension).\n *\n * @param {string} toolName - Name of the tool\n */\n clearMockToolResponse(toolName: string): void {\n this.mockResponses.delete(toolName);\n console.log(`[Model Context Testing] Mock response cleared for tool: ${toolName}`);\n }\n\n /**\n * Clears all mock tool responses (polyfill extension).\n */\n clearAllMockToolResponses(): void {\n this.mockResponses.clear();\n console.log('[Model Context Testing] All mock responses cleared');\n }\n\n /**\n * Gets the current tools registered in the system (polyfill extension).\n *\n * @returns {ReturnType<InternalModelContext['listTools']>} Array of registered tools\n */\n getRegisteredTools(): ReturnType<InternalModelContext['listTools']> {\n return this.bridge.modelContext.listTools();\n }\n\n /**\n * Resets the entire testing state (polyfill extension).\n * Clears both tool call history and all mock responses.\n */\n reset(): void {\n this.clearToolCalls();\n this.clearAllMockToolResponses();\n console.log('[Model Context Testing] Testing state reset');\n }\n}\n\n/**\n * ModelContext implementation that bridges to the Model Context Protocol SDK.\n * Implements the W3C Web Model Context API proposal with two-bucket tool management:\n * - Bucket A (provideContextTools): Tools registered via provideContext()\n * - Bucket B (dynamicTools): Tools registered via registerTool()\n *\n * This separation ensures that component-scoped dynamic tools persist across\n * app-level provideContext() calls.\n *\n * @class WebModelContext\n * @implements {InternalModelContext}\n */\nclass WebModelContext implements InternalModelContext {\n private bridge: MCPBridge;\n private eventTarget: EventTarget;\n\n // Tool storage (Bucket A = provideContext, Bucket B = dynamic)\n private provideContextTools: Map<string, ValidatedToolDescriptor>;\n private dynamicTools: Map<string, ValidatedToolDescriptor>;\n\n // Resource storage (Bucket A = provideContext, Bucket B = dynamic)\n private provideContextResources: Map<string, ValidatedResourceDescriptor>;\n private dynamicResources: Map<string, ValidatedResourceDescriptor>;\n\n // Prompt storage (Bucket A = provideContext, Bucket B = dynamic)\n private provideContextPrompts: Map<string, ValidatedPromptDescriptor>;\n private dynamicPrompts: Map<string, ValidatedPromptDescriptor>;\n\n // Registration tracking for duplicate detection\n private toolRegistrationTimestamps: Map<string, number>;\n private resourceRegistrationTimestamps: Map<string, number>;\n private promptRegistrationTimestamps: Map<string, number>;\n\n // Unregister functions for dynamic registrations\n private toolUnregisterFunctions: Map<string, () => void>;\n private resourceUnregisterFunctions: Map<string, () => void>;\n private promptUnregisterFunctions: Map<string, () => void>;\n\n private testingAPI?: WebModelContextTesting;\n\n /**\n * Creates a new WebModelContext instance.\n *\n * @param {MCPBridge} bridge - The MCP bridge to use for communication\n */\n constructor(bridge: MCPBridge) {\n this.bridge = bridge;\n this.eventTarget = new EventTarget();\n\n // Initialize tool storage\n this.provideContextTools = new Map();\n this.dynamicTools = new Map();\n this.toolRegistrationTimestamps = new Map();\n this.toolUnregisterFunctions = new Map();\n\n // Initialize resource storage\n this.provideContextResources = new Map();\n this.dynamicResources = new Map();\n this.resourceRegistrationTimestamps = new Map();\n this.resourceUnregisterFunctions = new Map();\n\n // Initialize prompt storage\n this.provideContextPrompts = new Map();\n this.dynamicPrompts = new Map();\n this.promptRegistrationTimestamps = new Map();\n this.promptUnregisterFunctions = new Map();\n }\n\n /**\n * Sets the testing API instance.\n * Called during initialization to enable testing features.\n *\n * @param {WebModelContextTesting} testingAPI - The testing API instance\n * @internal\n */\n setTestingAPI(testingAPI: WebModelContextTesting): void {\n this.testingAPI = testingAPI;\n }\n\n /**\n * Adds an event listener for tool call events.\n *\n * @param {'toolcall'} type - Event type (only 'toolcall' is supported)\n * @param {(event: ToolCallEvent) => void | Promise<void>} listener - Event handler function\n * @param {boolean | AddEventListenerOptions} [options] - Event listener options\n */\n addEventListener(\n type: 'toolcall',\n listener: (event: ToolCallEvent) => void | Promise<void>,\n options?: boolean | AddEventListenerOptions\n ): void {\n this.eventTarget.addEventListener(type, listener as EventListener, options);\n }\n\n /**\n * Removes an event listener for tool call events.\n *\n * @param {'toolcall'} type - Event type (only 'toolcall' is supported)\n * @param {(event: ToolCallEvent) => void | Promise<void>} listener - Event handler function\n * @param {boolean | EventListenerOptions} [options] - Event listener options\n */\n removeEventListener(\n type: 'toolcall',\n listener: (event: ToolCallEvent) => void | Promise<void>,\n options?: boolean | EventListenerOptions\n ): void {\n this.eventTarget.removeEventListener(type, listener as EventListener, options);\n }\n\n /**\n * Dispatches a tool call event to all registered listeners.\n *\n * @param {Event} event - The event to dispatch\n * @returns {boolean} False if event was cancelled, true otherwise\n */\n dispatchEvent(event: Event): boolean {\n return this.eventTarget.dispatchEvent(event);\n }\n\n /**\n * Provides context (tools, resources, prompts) to AI models by registering base items (Bucket A).\n * Clears and replaces all previously registered base items while preserving\n * dynamic items registered via register* methods.\n *\n * @param {ModelContextInput} context - Context containing tools, resources, and prompts to register\n * @throws {Error} If a name/uri collides with existing dynamic items\n */\n provideContext(context: ModelContextInput): void {\n const toolCount = context.tools?.length ?? 0;\n const resourceCount = context.resources?.length ?? 0;\n const promptCount = context.prompts?.length ?? 0;\n console.log(\n `[Web Model Context] provideContext: ${toolCount} tools, ${resourceCount} resources, ${promptCount} prompts`\n );\n\n // Clear base items (Bucket A)\n this.provideContextTools.clear();\n this.provideContextResources.clear();\n this.provideContextPrompts.clear();\n\n // Register tools\n for (const tool of context.tools ?? []) {\n if (this.dynamicTools.has(tool.name)) {\n throw new Error(\n `[Web Model Context] Tool name collision: \"${tool.name}\" is already registered via registerTool(). ` +\n 'Please use a different name or unregister the dynamic tool first.'\n );\n }\n\n const { jsonSchema: inputJson, zodValidator: inputZod } = normalizeSchema(tool.inputSchema);\n const normalizedOutput = tool.outputSchema ? normalizeSchema(tool.outputSchema) : null;\n\n const validatedTool: ValidatedToolDescriptor = {\n name: tool.name,\n description: tool.description,\n inputSchema: inputJson,\n ...(normalizedOutput && { outputSchema: normalizedOutput.jsonSchema }),\n ...(tool.annotations && { annotations: tool.annotations }),\n execute: tool.execute,\n inputValidator: inputZod,\n ...(normalizedOutput && { outputValidator: normalizedOutput.zodValidator }),\n };\n\n this.provideContextTools.set(tool.name, validatedTool);\n }\n\n // Register resources\n for (const resource of context.resources ?? []) {\n if (this.dynamicResources.has(resource.uri)) {\n throw new Error(\n `[Web Model Context] Resource URI collision: \"${resource.uri}\" is already registered via registerResource(). ` +\n 'Please use a different URI or unregister the dynamic resource first.'\n );\n }\n\n const validatedResource = this.validateResource(resource);\n this.provideContextResources.set(resource.uri, validatedResource);\n }\n\n // Register prompts\n for (const prompt of context.prompts ?? []) {\n if (this.dynamicPrompts.has(prompt.name)) {\n throw new Error(\n `[Web Model Context] Prompt name collision: \"${prompt.name}\" is already registered via registerPrompt(). ` +\n 'Please use a different name or unregister the dynamic prompt first.'\n );\n }\n\n const validatedPrompt = this.validatePrompt(prompt);\n this.provideContextPrompts.set(prompt.name, validatedPrompt);\n }\n\n // Update bridge and notify\n this.updateBridgeTools();\n this.updateBridgeResources();\n this.updateBridgePrompts();\n\n this.notifyToolsListChanged();\n this.notifyResourcesListChanged();\n this.notifyPromptsListChanged();\n }\n\n /**\n * Validates and normalizes a resource descriptor.\n * @private\n */\n private validateResource(resource: ResourceDescriptor): ValidatedResourceDescriptor {\n // Extract template parameters from URI (e.g., \"file://{path}\" -> [\"path\"])\n const templateParamRegex = /\\{([^}]+)\\}/g;\n const templateParams: string[] = [];\n for (const match of resource.uri.matchAll(templateParamRegex)) {\n const paramName = match[1];\n if (paramName) {\n templateParams.push(paramName);\n }\n }\n\n return {\n uri: resource.uri,\n name: resource.name,\n description: resource.description,\n mimeType: resource.mimeType,\n read: resource.read,\n isTemplate: templateParams.length > 0,\n templateParams,\n };\n }\n\n /**\n * Validates and normalizes a prompt descriptor.\n * @private\n */\n private validatePrompt<TArgsSchema extends ZodSchemaObject>(\n prompt: PromptDescriptor<TArgsSchema>\n ): ValidatedPromptDescriptor {\n let argsSchema: InputSchema | undefined;\n let argsValidator: z.ZodType | undefined;\n\n if (prompt.argsSchema) {\n const normalized = normalizeSchema(prompt.argsSchema);\n argsSchema = normalized.jsonSchema;\n argsValidator = normalized.zodValidator;\n }\n\n return {\n name: prompt.name,\n description: prompt.description,\n argsSchema,\n get: prompt.get as (args: Record<string, unknown>) => Promise<{ messages: PromptMessage[] }>,\n argsValidator,\n };\n }\n\n /**\n * Registers a single tool dynamically (Bucket B).\n * Dynamic tools persist across provideContext() calls and can be independently managed.\n *\n * @param {ToolDescriptor} tool - The tool descriptor to register\n * @returns {{unregister: () => void}} Object with unregister function\n * @throws {Error} If tool name collides with existing tools\n */\n registerTool<\n TInputSchema extends ZodSchemaObject = Record<string, never>,\n TOutputSchema extends ZodSchemaObject = Record<string, never>,\n >(tool: ToolDescriptor<TInputSchema, TOutputSchema>): { unregister: () => void } {\n console.log(`[Web Model Context] Registering tool dynamically: ${tool.name}`);\n\n const now = Date.now();\n const lastRegistration = this.toolRegistrationTimestamps.get(tool.name);\n\n if (lastRegistration && now - lastRegistration < RAPID_DUPLICATE_WINDOW_MS) {\n console.warn(\n `[Web Model Context] Tool \"${tool.name}\" registered multiple times within ${RAPID_DUPLICATE_WINDOW_MS}ms. ` +\n 'This is likely due to React Strict Mode double-mounting. Ignoring duplicate registration.'\n );\n\n const existingUnregister = this.toolUnregisterFunctions.get(tool.name);\n if (existingUnregister) {\n return { unregister: existingUnregister };\n }\n }\n\n if (this.provideContextTools.has(tool.name)) {\n throw new Error(\n `[Web Model Context] Tool name collision: \"${tool.name}\" is already registered via provideContext(). ` +\n 'Please use a different name or update your provideContext() call.'\n );\n }\n\n if (this.dynamicTools.has(tool.name)) {\n throw new Error(\n `[Web Model Context] Tool name collision: \"${tool.name}\" is already registered via registerTool(). ` +\n 'Please unregister it first or use a different name.'\n );\n }\n\n const { jsonSchema: inputJson, zodValidator: inputZod } = normalizeSchema(tool.inputSchema);\n\n const normalizedOutput = tool.outputSchema ? normalizeSchema(tool.outputSchema) : null;\n\n const validatedTool: ValidatedToolDescriptor = {\n name: tool.name,\n description: tool.description,\n inputSchema: inputJson,\n ...(normalizedOutput && { outputSchema: normalizedOutput.jsonSchema }),\n ...(tool.annotations && { annotations: tool.annotations }),\n execute: tool.execute as (args: Record<string, unknown>) => Promise<ToolResponse>,\n inputValidator: inputZod,\n ...(normalizedOutput && { outputValidator: normalizedOutput.zodValidator }),\n };\n\n this.dynamicTools.set(tool.name, validatedTool);\n this.toolRegistrationTimestamps.set(tool.name, now);\n this.updateBridgeTools();\n this.notifyToolsListChanged();\n\n const unregisterFn = () => {\n console.log(`[Web Model Context] Unregistering tool: ${tool.name}`);\n\n if (this.provideContextTools.has(tool.name)) {\n throw new Error(\n `[Web Model Context] Cannot unregister tool \"${tool.name}\": ` +\n 'This tool was registered via provideContext(). Use provideContext() to update the base tool set.'\n );\n }\n\n if (!this.dynamicTools.has(tool.name)) {\n console.warn(\n `[Web Model Context] Tool \"${tool.name}\" is not registered, ignoring unregister call`\n );\n return;\n }\n\n this.dynamicTools.delete(tool.name);\n this.toolRegistrationTimestamps.delete(tool.name);\n this.toolUnregisterFunctions.delete(tool.name);\n this.updateBridgeTools();\n this.notifyToolsListChanged();\n };\n\n this.toolUnregisterFunctions.set(tool.name, unregisterFn);\n\n return { unregister: unregisterFn };\n }\n\n // ==================== RESOURCE METHODS ====================\n\n /**\n * Registers a single resource dynamically (Bucket B).\n * Dynamic resources persist across provideContext() calls and can be independently managed.\n *\n * @param {ResourceDescriptor} resource - The resource descriptor to register\n * @returns {{unregister: () => void}} Object with unregister function\n * @throws {Error} If resource URI collides with existing resources\n */\n registerResource(resource: ResourceDescriptor): { unregister: () => void } {\n console.log(`[Web Model Context] Registering resource dynamically: ${resource.uri}`);\n\n const now = Date.now();\n const lastRegistration = this.resourceRegistrationTimestamps.get(resource.uri);\n\n if (lastRegistration && now - lastRegistration < RAPID_DUPLICATE_WINDOW_MS) {\n console.warn(\n `[Web Model Context] Resource \"${resource.uri}\" registered multiple times within ${RAPID_DUPLICATE_WINDOW_MS}ms. ` +\n 'This is likely due to React Strict Mode double-mounting. Ignoring duplicate registration.'\n );\n\n const existingUnregister = this.resourceUnregisterFunctions.get(resource.uri);\n if (existingUnregister) {\n return { unregister: existingUnregister };\n }\n }\n\n if (this.provideContextResources.has(resource.uri)) {\n throw new Error(\n `[Web Model Context] Resource URI collision: \"${resource.uri}\" is already registered via provideContext(). ` +\n 'Please use a different URI or update your provideContext() call.'\n );\n }\n\n if (this.dynamicResources.has(resource.uri)) {\n throw new Error(\n `[Web Model Context] Resource URI collision: \"${resource.uri}\" is already registered via registerResource(). ` +\n 'Please unregister it first or use a different URI.'\n );\n }\n\n const validatedResource = this.validateResource(resource);\n this.dynamicResources.set(resource.uri, validatedResource);\n this.resourceRegistrationTimestamps.set(resource.uri, now);\n this.updateBridgeResources();\n this.notifyResourcesListChanged();\n\n const unregisterFn = () => {\n console.log(`[Web Model Context] Unregistering resource: ${resource.uri}`);\n\n if (this.provideContextResources.has(resource.uri)) {\n throw new Error(\n `[Web Model Context] Cannot unregister resource \"${resource.uri}\": ` +\n 'This resource was registered via provideContext(). Use provideContext() to update the base resource set.'\n );\n }\n\n if (!this.dynamicResources.has(resource.uri)) {\n console.warn(\n `[Web Model Context] Resource \"${resource.uri}\" is not registered, ignoring unregister call`\n );\n return;\n }\n\n this.dynamicResources.delete(resource.uri);\n this.resourceRegistrationTimestamps.delete(resource.uri);\n this.resourceUnregisterFunctions.delete(resource.uri);\n this.updateBridgeResources();\n this.notifyResourcesListChanged();\n };\n\n this.resourceUnregisterFunctions.set(resource.uri, unregisterFn);\n\n return { unregister: unregisterFn };\n }\n\n /**\n * Unregisters a resource by URI.\n * Can unregister resources from either Bucket A (provideContext) or Bucket B (registerResource).\n *\n * @param {string} uri - URI of the resource to unregister\n */\n unregisterResource(uri: string): void {\n console.log(`[Web Model Context] Unregistering resource: ${uri}`);\n\n const inProvideContext = this.provideContextResources.has(uri);\n const inDynamic = this.dynamicResources.has(uri);\n\n if (!inProvideContext && !inDynamic) {\n console.warn(\n `[Web Model Context] Resource \"${uri}\" is not registered, ignoring unregister call`\n );\n return;\n }\n\n if (inProvideContext) {\n this.provideContextResources.delete(uri);\n }\n\n if (inDynamic) {\n this.dynamicResources.delete(uri);\n this.resourceRegistrationTimestamps.delete(uri);\n this.resourceUnregisterFunctions.delete(uri);\n }\n\n this.updateBridgeResources();\n this.notifyResourcesListChanged();\n }\n\n /**\n * Lists all registered resources in MCP format.\n * Returns static resources from both buckets (not templates).\n *\n * @returns {Resource[]} Array of resource descriptors\n */\n listResources(): Resource[] {\n return Array.from(this.bridge.resources.values())\n .filter((r) => !r.isTemplate)\n .map((resource) => ({\n uri: resource.uri,\n name: resource.name,\n description: resource.description,\n mimeType: resource.mimeType,\n }));\n }\n\n /**\n * Lists all registered resource templates.\n * Returns only resources with URI templates (dynamic resources).\n *\n * @returns {Array<{uriTemplate: string, name: string, description?: string, mimeType?: string}>}\n */\n listResourceTemplates(): Array<{\n uriTemplate: string;\n name: string;\n description?: string;\n mimeType?: string;\n }> {\n return Array.from(this.bridge.resources.values())\n .filter((r) => r.isTemplate)\n .map((resource) => ({\n uriTemplate: resource.uri,\n name: resource.name,\n ...(resource.description !== undefined && { description: resource.description }),\n ...(resource.mimeType !== undefined && { mimeType: resource.mimeType }),\n }));\n }\n\n // ==================== PROMPT METHODS ====================\n\n /**\n * Registers a single prompt dynamically (Bucket B).\n * Dynamic prompts persist across provideContext() calls and can be independently managed.\n *\n * @param {PromptDescriptor} prompt - The prompt descriptor to register\n * @returns {{unregister: () => void}} Object with unregister function\n * @throws {Error} If prompt name collides with existing prompts\n */\n registerPrompt<TArgsSchema extends ZodSchemaObject = Record<string, never>>(\n prompt: PromptDescriptor<TArgsSchema>\n ): { unregister: () => void } {\n console.log(`[Web Model Context] Registering prompt dynamically: ${prompt.name}`);\n\n const now = Date.now();\n const lastRegistration = this.promptRegistrationTimestamps.get(prompt.name);\n\n if (lastRegistration && now - lastRegistration < RAPID_DUPLICATE_WINDOW_MS) {\n console.warn(\n `[Web Model Context] Prompt \"${prompt.name}\" registered multiple times within ${RAPID_DUPLICATE_WINDOW_MS}ms. ` +\n 'This is likely due to React Strict Mode double-mounting. Ignoring duplicate registration.'\n );\n\n const existingUnregister = this.promptUnregisterFunctions.get(prompt.name);\n if (existingUnregister) {\n return { unregister: existingUnregister };\n }\n }\n\n if (this.provideContextPrompts.has(prompt.name)) {\n throw new Error(\n `[Web Model Context] Prompt name collision: \"${prompt.name}\" is already registered via provideContext(). ` +\n 'Please use a different name or update your provideContext() call.'\n );\n }\n\n if (this.dynamicPrompts.has(prompt.name)) {\n throw new Error(\n `[Web Model Context] Prompt name collision: \"${prompt.name}\" is already registered via registerPrompt(). ` +\n 'Please unregister it first or use a different name.'\n );\n }\n\n const validatedPrompt = this.validatePrompt(prompt);\n this.dynamicPrompts.set(prompt.name, validatedPrompt);\n this.promptRegistrationTimestamps.set(prompt.name, now);\n this.updateBridgePrompts();\n this.notifyPromptsListChanged();\n\n const unregisterFn = () => {\n console.log(`[Web Model Context] Unregistering prompt: ${prompt.name}`);\n\n if (this.provideContextPrompts.has(prompt.name)) {\n throw new Error(\n `[Web Model Context] Cannot unregister prompt \"${prompt.name}\": ` +\n 'This prompt was registered via provideContext(). Use provideContext() to update the base prompt set.'\n );\n }\n\n if (!this.dynamicPrompts.has(prompt.name)) {\n console.warn(\n `[Web Model Context] Prompt \"${prompt.name}\" is not registered, ignoring unregister call`\n );\n return;\n }\n\n this.dynamicPrompts.delete(prompt.name);\n this.promptRegistrationTimestamps.delete(prompt.name);\n this.promptUnregisterFunctions.delete(prompt.name);\n this.updateBridgePrompts();\n this.notifyPromptsListChanged();\n };\n\n this.promptUnregisterFunctions.set(prompt.name, unregisterFn);\n\n return { unregister: unregisterFn };\n }\n\n /**\n * Unregisters a prompt by name.\n * Can unregister prompts from either Bucket A (provideContext) or Bucket B (registerPrompt).\n *\n * @param {string} name - Name of the prompt to unregister\n */\n unregisterPrompt(name: string): void {\n console.log(`[Web Model Context] Unregistering prompt: ${name}`);\n\n const inProvideContext = this.provideContextPrompts.has(name);\n const inDynamic = this.dynamicPrompts.has(name);\n\n if (!inProvideContext && !inDynamic) {\n console.warn(\n `[Web Model Context] Prompt \"${name}\" is not registered, ignoring unregister call`\n );\n return;\n }\n\n if (inProvideContext) {\n this.provideContextPrompts.delete(name);\n }\n\n if (inDynamic) {\n this.dynamicPrompts.delete(name);\n this.promptRegistrationTimestamps.delete(name);\n this.promptUnregisterFunctions.delete(name);\n }\n\n this.updateBridgePrompts();\n this.notifyPromptsListChanged();\n }\n\n /**\n * Lists all registered prompts in MCP format.\n * Returns prompts from both buckets.\n *\n * @returns {Prompt[]} Array of prompt descriptors\n */\n listPrompts(): Prompt[] {\n return Array.from(this.bridge.prompts.values()).map((prompt) => ({\n name: prompt.name,\n description: prompt.description,\n arguments: prompt.argsSchema?.properties\n ? Object.entries(prompt.argsSchema.properties).map(([name, schema]) => ({\n name,\n description: (schema as { description?: string }).description,\n required: prompt.argsSchema?.required?.includes(name) ?? false,\n }))\n : undefined,\n }));\n }\n\n /**\n * Unregisters a tool by name (Chromium native API).\n * Can unregister tools from either Bucket A (provideContext) or Bucket B (registerTool).\n *\n * @param {string} name - Name of the tool to unregister\n */\n unregisterTool(name: string): void {\n console.log(`[Web Model Context] Unregistering tool: ${name}`);\n\n const inProvideContext = this.provideContextTools.has(name);\n const inDynamic = this.dynamicTools.has(name);\n\n if (!inProvideContext && !inDynamic) {\n console.warn(\n `[Web Model Context] Tool \"${name}\" is not registered, ignoring unregister call`\n );\n return;\n }\n\n if (inProvideContext) {\n this.provideContextTools.delete(name);\n }\n\n if (inDynamic) {\n this.dynamicTools.delete(name);\n this.toolRegistrationTimestamps.delete(name);\n this.toolUnregisterFunctions.delete(name);\n }\n\n this.updateBridgeTools();\n this.notifyToolsListChanged();\n }\n\n /**\n * Clears all registered context from both buckets (Chromium native API).\n * Removes all tools, resources, and prompts registered via provideContext() and register* methods.\n */\n clearContext(): void {\n console.log('[Web Model Context] Clearing all context (tools, resources, prompts)');\n\n // Clear tools\n this.provideContextTools.clear();\n this.dynamicTools.clear();\n this.toolRegistrationTimestamps.clear();\n this.toolUnregisterFunctions.clear();\n\n // Clear resources\n this.provideContextResources.clear();\n this.dynamicResources.clear();\n this.resourceRegistrationTimestamps.clear();\n this.resourceUnregisterFunctions.clear();\n\n // Clear prompts\n this.provideContextPrompts.clear();\n this.dynamicPrompts.clear();\n this.promptRegistrationTimestamps.clear();\n this.promptUnregisterFunctions.clear();\n\n // Update bridge\n this.updateBridgeTools();\n this.updateBridgeResources();\n this.updateBridgePrompts();\n\n // Notify changes\n this.notifyToolsListChanged();\n this.notifyResourcesListChanged();\n this.notifyPromptsListChanged();\n }\n\n /**\n * Updates the bridge tools map with merged tools from both buckets.\n * The final tool list is the union of Bucket A (provideContext) and Bucket B (dynamic).\n *\n * @private\n */\n private updateBridgeTools(): void {\n this.bridge.tools.clear();\n\n for (const [name, tool] of this.provideContextTools) {\n this.bridge.tools.set(name, tool);\n }\n\n for (const [name, tool] of this.dynamicTools) {\n this.bridge.tools.set(name, tool);\n }\n\n console.log(\n `[Web Model Context] Updated bridge with ${this.provideContextTools.size} base tools + ${this.dynamicTools.size} dynamic tools = ${this.bridge.tools.size} total`\n );\n }\n\n /**\n * Notifies all servers and testing callbacks that the tools list has changed.\n * Sends MCP notifications to connected servers and invokes registered testing callbacks.\n *\n * @private\n */\n private notifyToolsListChanged(): void {\n if (this.bridge.tabServer.notification) {\n this.bridge.tabServer.notification({\n method: 'notifications/tools/list_changed',\n params: {},\n });\n }\n\n if (this.bridge.iframeServer?.notification) {\n this.bridge.iframeServer.notification({\n method: 'notifications/tools/list_changed',\n params: {},\n });\n }\n\n if (this.testingAPI && 'notifyToolsChanged' in this.testingAPI) {\n (this.testingAPI as WebModelContextTesting).notifyToolsChanged();\n }\n }\n\n /**\n * Updates the bridge resources map with merged resources from both buckets.\n *\n * @private\n */\n private updateBridgeResources(): void {\n this.bridge.resources.clear();\n\n for (const [uri, resource] of this.provideContextResources) {\n this.bridge.resources.set(uri, resource);\n }\n\n for (const [uri, resource] of this.dynamicResources) {\n this.bridge.resources.set(uri, resource);\n }\n\n console.log(\n `[Web Model Context] Updated bridge with ${this.provideContextResources.size} base resources + ${this.dynamicResources.size} dynamic resources = ${this.bridge.resources.size} total`\n );\n }\n\n /**\n * Notifies all servers that the resources list has changed.\n *\n * @private\n */\n private notifyResourcesListChanged(): void {\n if (this.bridge.tabServer.notification) {\n this.bridge.tabServer.notification({\n method: 'notifications/resources/list_changed',\n params: {},\n });\n }\n\n if (this.bridge.iframeServer?.notification) {\n this.bridge.iframeServer.notification({\n method: 'notifications/resources/list_changed',\n params: {},\n });\n }\n }\n\n /**\n * Updates the bridge prompts map with merged prompts from both buckets.\n *\n * @private\n */\n private updateBridgePrompts(): void {\n this.bridge.prompts.clear();\n\n for (const [name, prompt] of this.provideContextPrompts) {\n this.bridge.prompts.set(name, prompt);\n }\n\n for (const [name, prompt] of this.dynamicPrompts) {\n this.bridge.prompts.set(name, prompt);\n }\n\n console.log(\n `[Web Model Context] Updated bridge with ${this.provideContextPrompts.size} base prompts + ${this.dynamicPrompts.size} dynamic prompts = ${this.bridge.prompts.size} total`\n );\n }\n\n /**\n * Notifies all servers that the prompts list has changed.\n *\n * @private\n */\n private notifyPromptsListChanged(): void {\n if (this.bridge.tabServer.notification) {\n this.bridge.tabServer.notification({\n method: 'notifications/prompts/list_changed',\n params: {},\n });\n }\n\n if (this.bridge.iframeServer?.notification) {\n this.bridge.iframeServer.notification({\n method: 'notifications/prompts/list_changed',\n params: {},\n });\n }\n }\n\n /**\n * Reads a resource by URI (internal use only by MCP bridge).\n * Handles both static resources and URI templates.\n *\n * @param {string} uri - The URI of the resource to read\n * @returns {Promise<{contents: ResourceContents[]}>} The resource contents\n * @throws {Error} If resource is not found\n * @internal\n */\n async readResource(uri: string): Promise<{ contents: ResourceContents[] }> {\n console.log(`[Web Model Context] Reading resource: ${uri}`);\n\n // First, try to find an exact match (static resource)\n const staticResource = this.bridge.resources.get(uri);\n if (staticResource && !staticResource.isTemplate) {\n try {\n const parsedUri = new URL(uri);\n return await staticResource.read(parsedUri);\n } catch (error) {\n console.error(`[Web Model Context] Error reading resource ${uri}:`, error);\n throw error;\n }\n }\n\n // Try to match against URI templates\n for (const resource of this.bridge.resources.values()) {\n if (!resource.isTemplate) continue;\n\n const params = this.matchUriTemplate(resource.uri, uri);\n if (params) {\n try {\n const parsedUri = new URL(uri);\n return await resource.read(parsedUri, params);\n } catch (error) {\n console.error(`[Web Model Context] Error reading resource ${uri}:`, error);\n throw error;\n }\n }\n }\n\n throw new Error(`Resource not found: ${uri}`);\n }\n\n /**\n * Matches a URI against a URI template and extracts parameters.\n *\n * @param {string} template - The URI template (e.g., \"file://{path}\")\n * @param {string} uri - The actual URI to match\n * @returns {Record<string, string> | null} Extracted parameters or null if no match\n * @private\n */\n private matchUriTemplate(template: string, uri: string): Record<string, string> | null {\n // Convert template to regex pattern\n // e.g., \"file://{path}\" -> \"^file://(.+)$\" with capture group for \"path\"\n const paramNames: string[] = [];\n let regexPattern = template.replace(/[.*+?^${}()|[\\]\\\\]/g, (char) => {\n // Don't escape { and } - we'll handle them specially\n if (char === '{' || char === '}') return char;\n return `\\\\${char}`;\n });\n\n // Replace {param} with capture groups\n regexPattern = regexPattern.replace(/\\{([^}]+)\\}/g, (_, paramName) => {\n paramNames.push(paramName);\n return '(.+)';\n });\n\n const regex = new RegExp(`^${regexPattern}$`);\n const match = uri.match(regex);\n\n if (!match) return null;\n\n const params: Record<string, string> = {};\n for (let i = 0; i < paramNames.length; i++) {\n const paramName = paramNames[i];\n const paramValue = match[i + 1];\n if (paramName !== undefined && paramValue !== undefined) {\n params[paramName] = paramValue;\n }\n }\n\n return params;\n }\n\n /**\n * Gets a prompt with arguments (internal use only by MCP bridge).\n *\n * @param {string} name - Name of the prompt\n * @param {Record<string, unknown>} args - Arguments to pass to the prompt\n * @returns {Promise<{messages: PromptMessage[]}>} The prompt messages\n * @throws {Error} If prompt is not found\n * @internal\n */\n async getPrompt(\n name: string,\n args?: Record<string, unknown>\n ): Promise<{ messages: PromptMessage[] }> {\n console.log(`[Web Model Context] Getting prompt: ${name}`);\n\n const prompt = this.bridge.prompts.get(name);\n if (!prompt) {\n throw new Error(`Prompt not found: ${name}`);\n }\n\n // Validate arguments if schema is defined\n if (prompt.argsValidator && args) {\n const validation = validateWithZod(args, prompt.argsValidator);\n if (!validation.success) {\n console.error(\n `[Web Model Context] Argument validation failed for prompt ${name}:`,\n validation.error\n );\n throw new Error(`Argument validation error for prompt \"${name}\":\\n${validation.error}`);\n }\n }\n\n try {\n return await prompt.get(args ?? {});\n } catch (error) {\n console.error(`[Web Model Context] Error getting prompt ${name}:`, error);\n throw error;\n }\n }\n\n /**\n * Executes a tool with validation and event dispatch.\n * Follows this sequence:\n * 1. Validates input arguments against schema\n * 2. Records tool call in testing API (if available)\n * 3. Checks for mock response (if testing)\n * 4. Dispatches 'toolcall' event to listeners\n * 5. Executes tool function if not prevented\n * 6. Validates output (permissive mode - warns only)\n *\n * @param {string} toolName - Name of the tool to execute\n * @param {Record<string, unknown>} args - Arguments to pass to the tool\n * @returns {Promise<ToolResponse>} The tool's response\n * @throws {Error} If tool is not found\n * @internal\n */\n async executeTool(toolName: string, args: Record<string, unknown>): Promise<ToolResponse> {\n const tool = this.bridge.tools.get(toolName);\n if (!tool) {\n throw new Error(`Tool not found: ${toolName}`);\n }\n\n console.log(`[Web Model Context] Validating input for tool: ${toolName}`);\n const validation = validateWithZod(args, tool.inputValidator);\n if (!validation.success) {\n console.error(\n `[Web Model Context] Input validation failed for ${toolName}:`,\n validation.error\n );\n return {\n content: [\n {\n type: 'text',\n text: `Input validation error for tool \"${toolName}\":\\n${validation.error}`,\n },\n ],\n isError: true,\n };\n }\n\n const validatedArgs = validation.data as Record<string, unknown>;\n\n if (this.testingAPI) {\n this.testingAPI.recordToolCall(toolName, validatedArgs);\n }\n\n if (this.testingAPI?.hasMockResponse(toolName)) {\n const mockResponse = this.testingAPI.getMockResponse(toolName);\n if (mockResponse) {\n console.log(`[Web Model Context] Returning mock response for tool: ${toolName}`);\n return mockResponse;\n }\n }\n\n const event = new WebToolCallEvent(toolName, validatedArgs);\n\n this.dispatchEvent(event);\n\n if (event.defaultPrevented && event.hasResponse()) {\n const response = event.getResponse();\n if (response) {\n console.log(`[Web Model Context] Tool ${toolName} handled by event listener`);\n return response;\n }\n }\n\n console.log(`[Web Model Context] Executing tool: ${toolName}`);\n try {\n const response = await tool.execute(validatedArgs);\n\n if (tool.outputValidator && response.structuredContent) {\n const outputValidation = validateWithZod(response.structuredContent, tool.outputValidator);\n if (!outputValidation.success) {\n console.warn(\n `[Web Model Context] Output validation failed for ${toolName}:`,\n outputValidation.error\n );\n }\n }\n\n return response;\n } catch (error) {\n console.error(`[Web Model Context] Error executing tool ${toolName}:`, error);\n return {\n content: [\n {\n type: 'text',\n text: `Error: ${error instanceof Error ? error.message : String(error)}`,\n },\n ],\n isError: true,\n };\n }\n }\n\n /**\n * Lists all registered tools in MCP format.\n * Returns tools from both buckets with full MCP specification including\n * annotations and output schemas.\n *\n * @returns {Array<{name: string, description: string, inputSchema: InputSchema, outputSchema?: InputSchema, annotations?: ToolAnnotations}>} Array of tool descriptors\n */\n listTools() {\n return Array.from(this.bridge.tools.values()).map((tool) => ({\n name: tool.name,\n description: tool.description,\n inputSchema: tool.inputSchema,\n ...(tool.outputSchema && { outputSchema: tool.outputSchema }),\n ...(tool.annotations && { annotations: tool.annotations }),\n }));\n }\n\n // ==================== SAMPLING METHODS ====================\n\n /**\n * Request an LLM completion from the connected client.\n * This sends a sampling request to the connected MCP client.\n *\n * @param {SamplingRequestParams} params - Parameters for the sampling request\n * @returns {Promise<SamplingResult>} The LLM completion result\n */\n async createMessage(params: SamplingRequestParams): Promise<SamplingResult> {\n console.log('[Web Model Context] Requesting sampling from client');\n const server = this.bridge.tabServer;\n\n // Access the underlying Server instance to call createMessage\n const underlyingServer = (\n server as unknown as {\n server: { createMessage: (params: unknown) => Promise<SamplingResult> };\n }\n ).server;\n\n if (!underlyingServer?.createMessage) {\n throw new Error('Sampling is not supported: no connected client with sampling capability');\n }\n\n return underlyingServer.createMessage(params);\n }\n\n // ==================== ELICITATION METHODS ====================\n\n /**\n * Request user input from the connected client.\n * This sends an elicitation request to the connected MCP client.\n *\n * @param {ElicitationParams} params - Parameters for the elicitation request\n * @returns {Promise<ElicitationResult>} The user's response\n */\n async elicitInput(params: ElicitationParams): Promise<ElicitationResult> {\n console.log('[Web Model Context] Requesting elicitation from client');\n const server = this.bridge.tabServer;\n\n // Access the underlying Server instance to call elicitInput\n const underlyingServer = (\n server as unknown as {\n server: { elicitInput: (params: unknown) => Promise<ElicitationResult> };\n }\n ).server;\n\n if (!underlyingServer?.elicitInput) {\n throw new Error(\n 'Elicitation is not supported: no connected client with elicitation capability'\n );\n }\n\n return underlyingServer.elicitInput(params);\n }\n}\n\n/**\n * Initializes the MCP bridge with dual-server support.\n * Creates TabServer for same-window communication and optionally IframeChildServer\n * for parent-child iframe communication.\n *\n * @param {WebModelContextInitOptions} [options] - Configuration options\n * @returns {MCPBridge} The initialized MCP bridge\n */\nfunction initializeMCPBridge(options?: WebModelContextInitOptions): MCPBridge {\n console.log('[Web Model Context] Initializing MCP bridge');\n\n const hostname = window.location.hostname || 'localhost';\n const transportOptions = options?.transport;\n\n const setupServerHandlers = (server: McpServer, bridge: MCPBridge) => {\n // ==================== TOOL HANDLERS ====================\n server.setRequestHandler(ListToolsRequestSchema, async () => {\n console.log('[MCP Bridge] Handling list_tools request');\n return {\n tools: bridge.modelContext.listTools(),\n };\n });\n\n server.setRequestHandler(CallToolRequestSchema, async (request) => {\n console.log(`[MCP Bridge] Handling call_tool request: ${request.params.name}`);\n\n const toolName = request.params.name;\n const args = (request.params.arguments || {}) as Record<string, unknown>;\n\n try {\n const response = await bridge.modelContext.executeTool(toolName, args);\n return {\n content: response.content,\n isError: response.isError,\n };\n } catch (error) {\n console.error(`[MCP Bridge] Error calling tool ${toolName}:`, error);\n throw error;\n }\n });\n\n // ==================== RESOURCE HANDLERS ====================\n server.setRequestHandler(ListResourcesRequestSchema, async () => {\n console.log('[MCP Bridge] Handling list_resources request');\n return {\n resources: bridge.modelContext.listResources(),\n // Note: Resource templates are included in the resources list as the MCP SDK\n // doesn't export ListResourceTemplatesRequestSchema separately.\n // Clients can identify templates by checking for URI patterns containing {param}.\n };\n });\n\n server.setRequestHandler(ReadResourceRequestSchema, async (request) => {\n console.log(`[MCP Bridge] Handling read_resource request: ${request.params.uri}`);\n\n try {\n return await bridge.modelContext.readResource(request.params.uri);\n } catch (error) {\n console.error(`[MCP Bridge] Error reading resource ${request.params.uri}:`, error);\n throw error;\n }\n });\n\n // ==================== PROMPT HANDLERS ====================\n server.setRequestHandler(ListPromptsRequestSchema, async () => {\n console.log('[MCP Bridge] Handling list_prompts request');\n return {\n prompts: bridge.modelContext.listPrompts(),\n };\n });\n\n server.setRequestHandler(GetPromptRequestSchema, async (request) => {\n console.log(`[MCP Bridge] Handling get_prompt request: ${request.params.name}`);\n\n try {\n return await bridge.modelContext.getPrompt(\n request.params.name,\n request.params.arguments as Record<string, unknown> | undefined\n );\n } catch (error) {\n console.error(`[MCP Bridge] Error getting prompt ${request.params.name}:`, error);\n throw error;\n }\n });\n\n // Note: Sampling and elicitation are server-to-client requests.\n // The server calls createMessage() and elicitInput() methods on the Server instance.\n // These are NOT request handlers - the client handles these requests.\n };\n\n const customTransport: Transport | undefined = transportOptions?.create?.();\n\n if (customTransport) {\n console.log('[Web Model Context] Using custom transport');\n\n const server = new McpServer(\n {\n name: hostname,\n version: '1.0.0',\n },\n {\n capabilities: {\n tools: { listChanged: true },\n resources: { listChanged: true },\n prompts: { listChanged: true },\n },\n }\n );\n\n const bridge: MCPBridge = {\n tabServer: server,\n tools: new Map(),\n resources: new Map(),\n prompts: new Map(),\n modelContext: undefined as unknown as InternalModelContext,\n isInitialized: true,\n };\n\n const modelContext = new WebModelContext(bridge);\n bridge.modelContext = modelContext;\n\n setupServerHandlers(server, bridge);\n server.connect(customTransport);\n\n console.log('[Web Model Context] MCP server connected with custom transport');\n return bridge;\n }\n\n console.log('[Web Model Context] Using dual-server mode');\n\n const tabServerEnabled = transportOptions?.tabServer !== false;\n const tabServer = new McpServer(\n {\n name: `${hostname}-tab`,\n version: '1.0.0',\n },\n {\n capabilities: {\n tools: { listChanged: true },\n resources: { listChanged: true },\n prompts: { listChanged: true },\n },\n }\n );\n\n const bridge: MCPBridge = {\n tabServer,\n tools: new Map(),\n resources: new Map(),\n prompts: new Map(),\n modelContext: undefined as unknown as InternalModelContext,\n isInitialized: true,\n };\n\n const modelContext = new WebModelContext(bridge);\n bridge.modelContext = modelContext;\n\n setupServerHandlers(tabServer, bridge);\n\n if (tabServerEnabled) {\n const tabServerOptions: Partial<TabServerTransportOptions> =\n typeof transportOptions?.tabServer === 'object' ? transportOptions.tabServer : {};\n const { allowedOrigins, ...restTabServerOptions } = tabServerOptions;\n\n const tabTransport = new TabServerTransport({\n allowedOrigins: allowedOrigins ?? ['*'],\n ...(restTabServerOptions as Omit<TabServerTransportOptions, 'allowedOrigins'>),\n });\n\n tabServer.connect(tabTransport);\n console.log('[Web Model Context] Tab server connected');\n }\n\n const isInIframe = typeof window !== 'undefined' && window.parent !== window;\n const iframeServerConfig = transportOptions?.iframeServer;\n const iframeServerEnabled =\n iframeServerConfig !== false && (iframeServerConfig !== undefined || isInIframe);\n\n if (iframeServerEnabled) {\n console.log('[Web Model Context] Enabling iframe server');\n\n const iframeServer = new McpServer(\n {\n name: `${hostname}-iframe`,\n version: '1.0.0',\n },\n {\n capabilities: {\n tools: { listChanged: true },\n resources: { listChanged: true },\n prompts: { listChanged: true },\n },\n }\n );\n\n setupServerHandlers(iframeServer, bridge);\n\n const iframeServerOptions: Partial<IframeChildTransportOptions> =\n typeof iframeServerConfig === 'object' ? iframeServerConfig : {};\n const { allowedOrigins, ...restIframeServerOptions } = iframeServerOptions;\n\n const iframeTransport = new IframeChildTransport({\n allowedOrigins: allowedOrigins ?? ['*'],\n ...(restIframeServerOptions as Omit<IframeChildTransportOptions, 'allowedOrigins'>),\n });\n\n iframeServer.connect(iframeTransport);\n bridge.iframeServer = iframeServer;\n\n console.log('[Web Model Context] Iframe server connected');\n }\n\n return bridge;\n}\n\n/**\n * Initializes the Web Model Context API on window.navigator.\n * Creates and exposes navigator.modelContext and navigator.modelContextTesting.\n * Automatically detects and uses native Chromium implementation if available.\n *\n * @param {WebModelContextInitOptions} [options] - Configuration options\n * @throws {Error} If initialization fails\n * @example\n * ```typescript\n * import { initializeWebModelContext } from '@mcp-b/global';\n *\n * initializeWebModelContext({\n * transport: {\n * tabServer: {\n * allowedOrigins: ['https://example.com']\n * }\n * }\n * });\n * ```\n */\nexport function initializeWebModelContext(options?: WebModelContextInitOptions): void {\n if (typeof window === 'undefined') {\n console.warn('[Web Model Context] Not in browser environment, skipping initialization');\n return;\n }\n\n const effectiveOptions = options ?? window.__webModelContextOptions;\n const native = detectNativeAPI();\n\n if (native.hasNativeContext && native.hasNativeTesting) {\n const nativeContext = window.navigator.modelContext;\n const nativeTesting = window.navigator.modelContextTesting;\n\n if (!nativeContext || !nativeTesting) {\n console.error('[Web Model Context] Native API detection mismatch');\n return;\n }\n\n console.log('✅ [Web Model Context] Native Chromium API detected');\n console.log(' Using native implementation with MCP bridge synchronization');\n console.log(' Native API will automatically collect tools from embedded iframes');\n\n try {\n const bridge = initializeMCPBridge(effectiveOptions);\n\n const adapter = new NativeModelContextAdapter(bridge, nativeContext, nativeTesting);\n\n bridge.modelContext = adapter;\n bridge.modelContextTesting = nativeTesting;\n\n Object.defineProperty(window, '__mcpBridge', {\n value: bridge,\n writable: false,\n configurable: true,\n });\n\n console.log('✅ [Web Model Context] MCP bridge synced with native API');\n console.log(' MCP clients will receive automatic tool updates from native registry');\n } catch (error) {\n console.error('[Web Model Context] Failed to initialize native adapter:', error);\n throw error;\n }\n\n return;\n }\n\n if (native.hasNativeContext && !native.hasNativeTesting) {\n console.warn('[Web Model Context] Partial native API detected');\n console.warn(' navigator.modelContext exists but navigator.modelContextTesting is missing');\n console.warn(' Cannot sync with native API. Please enable experimental features:');\n console.warn(' - Navigate to chrome://flags');\n console.warn(' - Enable \"Experimental Web Platform Features\"');\n console.warn(' - Or launch with: --enable-experimental-web-platform-features');\n console.warn(' Skipping initialization to avoid conflicts');\n return;\n }\n\n if (window.navigator.modelContext) {\n console.warn(\n '[Web Model Context] window.navigator.modelContext already exists, skipping initialization'\n );\n return;\n }\n\n console.log('[Web Model Context] Native API not detected, installing polyfill');\n\n try {\n const bridge = initializeMCPBridge(effectiveOptions);\n\n Object.defineProperty(window.navigator, 'modelContext', {\n value: bridge.modelContext,\n writable: false,\n configurable: false,\n });\n\n Object.defineProperty(window, '__mcpBridge', {\n value: bridge,\n writable: false,\n configurable: true,\n });\n\n console.log('✅ [Web Model Context] window.navigator.modelContext initialized successfully');\n\n console.log('[Model Context Testing] Installing polyfill');\n console.log(' 💡 To use the native implementation in Chromium:');\n console.log(' - Navigate to chrome://flags');\n console.log(' - Enable \"Experimental Web Platform Features\"');\n console.log(' - Or launch with: --enable-experimental-web-platform-features');\n\n const testingAPI = new WebModelContextTesting(bridge);\n bridge.modelContextTesting = testingAPI;\n\n (bridge.modelContext as WebModelContext).setTestingAPI(testingAPI);\n\n Object.defineProperty(window.navigator, 'modelContextTesting', {\n value: testingAPI,\n writable: false,\n configurable: true,\n });\n\n console.log(\n '✅ [Model Context Testing] Polyfill installed at window.navigator.modelContextTesting'\n );\n } catch (error) {\n console.error('[Web Model Context] Failed to initialize:', error);\n throw error;\n }\n}\n\n/**\n * Cleans up the Web Model Context API.\n * Closes all MCP servers and removes API from window.navigator.\n * Useful for testing and hot module replacement.\n *\n * @example\n * ```typescript\n * import { cleanupWebModelContext } from '@mcp-b/global';\n *\n * cleanupWebModelContext();\n * ```\n */\nexport function cleanupWebModelContext(): void {\n if (typeof window === 'undefined') return;\n\n if (window.__mcpBridge) {\n try {\n window.__mcpBridge.tabServer.close();\n\n if (window.__mcpBridge.iframeServer) {\n window.__mcpBridge.iframeServer.close();\n }\n } catch (error) {\n console.warn('[Web Model Context] Error closing MCP servers:', error);\n }\n }\n\n delete (window.navigator as unknown as { modelContext?: unknown }).modelContext;\n delete (window.navigator as unknown as { modelContextTesting?: unknown }).modelContextTesting;\n delete (window as unknown as { __mcpBridge?: unknown }).__mcpBridge;\n\n console.log('[Web Model Context] Cleaned up');\n}\n","import { initializeWebModelContext } from './global.js';\nimport type { TransportConfiguration, WebModelContextInitOptions } from './types.js';\n\ntype TabServerConfig = NonNullable<TransportConfiguration['tabServer']>;\n\nfunction mergeTransportOptions(\n base: TransportConfiguration,\n override: TransportConfiguration\n): TransportConfiguration {\n if (!base) {\n return override;\n }\n if (!override) {\n return base;\n }\n\n return {\n ...base,\n ...override,\n tabServer: {\n ...(base.tabServer ?? {}),\n ...(override.tabServer ?? {}),\n },\n };\n}\n\nfunction mergeInitOptions(\n base?: WebModelContextInitOptions,\n override?: WebModelContextInitOptions\n): WebModelContextInitOptions | undefined {\n if (!base) {\n return override;\n }\n if (!override) {\n return base;\n }\n\n return {\n ...base,\n ...override,\n transport: mergeTransportOptions(base.transport ?? {}, override.transport ?? {}),\n };\n}\n\nfunction parseScriptTagOptions(\n script: HTMLScriptElement | null\n): WebModelContextInitOptions | undefined {\n if (!script || !script.dataset) {\n return undefined;\n }\n\n const { dataset } = script;\n\n if (dataset.webmcpOptions) {\n try {\n return JSON.parse(dataset.webmcpOptions) as WebModelContextInitOptions;\n } catch (error) {\n console.error('[Web Model Context] Invalid JSON in data-webmcp-options:', error);\n return undefined;\n }\n }\n\n const options: WebModelContextInitOptions = {};\n let hasOptions = false;\n\n if (dataset.webmcpAutoInitialize !== undefined) {\n options.autoInitialize = dataset.webmcpAutoInitialize !== 'false';\n hasOptions = true;\n }\n\n const tabServerOptions: TabServerConfig = {};\n let hasTabServerOptions = false;\n\n if (dataset.webmcpAllowedOrigins) {\n const origins = dataset.webmcpAllowedOrigins\n .split(',')\n .map((origin) => origin.trim())\n .filter((origin) => origin.length > 0);\n\n if (origins.length > 0) {\n tabServerOptions.allowedOrigins = origins;\n hasOptions = true;\n hasTabServerOptions = true;\n }\n }\n\n if (dataset.webmcpChannelId) {\n tabServerOptions.channelId = dataset.webmcpChannelId;\n hasOptions = true;\n hasTabServerOptions = true;\n }\n\n if (hasTabServerOptions) {\n options.transport = {\n ...(options.transport ?? {}),\n tabServer: {\n ...(options.transport?.tabServer ?? {}),\n ...tabServerOptions,\n },\n };\n }\n\n return hasOptions ? options : undefined;\n}\n\nif (typeof window !== 'undefined' && typeof document !== 'undefined') {\n const globalOptions = window.__webModelContextOptions;\n const scriptElement = document.currentScript as HTMLScriptElement | null;\n const scriptOptions = parseScriptTagOptions(scriptElement);\n const mergedOptions =\n mergeInitOptions(globalOptions, scriptOptions) ?? globalOptions ?? scriptOptions;\n\n if (mergedOptions) {\n window.__webModelContextOptions = mergedOptions;\n }\n\n const shouldAutoInitialize = mergedOptions?.autoInitialize !== false;\n\n try {\n if (shouldAutoInitialize) {\n initializeWebModelContext(mergedOptions);\n }\n } catch (error) {\n console.error('[Web Model Context] Auto-initialization failed:', error);\n }\n}\n\nexport { cleanupWebModelContext, initializeWebModelContext } from './global.js';\nexport type * from './types.js';\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["jsonSchemaToZod","convertJsonSchemaToZod","zodToJsonSchemaLib","validatedTool: ValidatedToolDescriptor","jsonSchemaToZod","args: Record<string, unknown>","templateParams: string[]","argsSchema: InputSchema | undefined","argsValidator: z.ZodType | undefined","_exhaustive: never","paramNames: string[]","params: Record<string, string>","bridge","customTransport: Transport | undefined","McpServer","bridge: MCPBridge","options: WebModelContextInitOptions","tabServerOptions: TabServerConfig"],"sources":["../src/validation.ts","../src/global.ts","../src/index.ts"],"sourcesContent":["import { jsonSchemaToZod as convertJsonSchemaToZod } from '@composio/json-schema-to-zod';\nimport { z } from 'zod';\nimport { zodToJsonSchema as zodToJsonSchemaLib } from 'zod-to-json-schema';\nimport type { InputSchema } from './types.js';\n\n/**\n * Detect if a schema is a Zod schema object (Record<string, ZodType>)\n * or a JSON Schema object\n */\nexport function isZodSchema(schema: unknown): boolean {\n if (typeof schema !== 'object' || schema === null) {\n return false;\n }\n\n if ('type' in schema && typeof (schema as { type: unknown }).type === 'string') {\n return false;\n }\n\n const values = Object.values(schema);\n if (values.length === 0) {\n return false;\n }\n\n return values.some((val) => val instanceof z.ZodType);\n}\n\n/**\n * Convert JSON Schema to Zod validator\n * Uses @composio/json-schema-to-zod for conversion\n */\nexport function jsonSchemaToZod(jsonSchema: InputSchema): z.ZodType {\n try {\n const zodSchema = convertJsonSchemaToZod(jsonSchema as unknown as object);\n return zodSchema;\n } catch (error) {\n console.warn('[Web Model Context] Failed to convert JSON Schema to Zod:', error);\n return z.object({}).passthrough();\n }\n}\n\n/**\n * Convert Zod schema object to JSON Schema\n * Uses zod-to-json-schema package for comprehensive conversion\n *\n * @param schema - Record of Zod type definitions (e.g., { name: z.string(), age: z.number() })\n * @returns JSON Schema object compatible with MCP InputSchema\n */\nexport function zodToJsonSchema(schema: Record<string, z.ZodTypeAny>): InputSchema {\n const zodObject = z.object(schema);\n const jsonSchema = zodToJsonSchemaLib(zodObject, {\n $refStrategy: 'none',\n target: 'jsonSchema7',\n });\n\n // Remove $schema field as it's not needed for MCP\n const { $schema: _, ...rest } = jsonSchema as { $schema?: string } & InputSchema;\n return rest as InputSchema;\n}\n\n/**\n * Normalize a schema to both JSON Schema and Zod formats\n * Detects which format is provided and converts to the other\n */\nexport function normalizeSchema(schema: InputSchema | Record<string, z.ZodTypeAny>): {\n jsonSchema: InputSchema;\n zodValidator: z.ZodType;\n} {\n const isZod = isZodSchema(schema);\n\n if (isZod) {\n const jsonSchema = zodToJsonSchema(schema as Record<string, z.ZodTypeAny>);\n const zodValidator = z.object(schema as Record<string, z.ZodTypeAny>);\n return { jsonSchema, zodValidator };\n }\n\n const jsonSchema = schema as InputSchema;\n const zodValidator = jsonSchemaToZod(jsonSchema);\n return { jsonSchema, zodValidator };\n}\n\n/**\n * Validate data with Zod schema and return formatted result\n */\nexport function validateWithZod(\n data: unknown,\n validator: z.ZodType\n): { success: true; data: unknown } | { success: false; error: string } {\n const result = validator.safeParse(data);\n\n if (!result.success) {\n const errors = result.error.errors\n .map((err) => ` - ${err.path.join('.') || 'root'}: ${err.message}`)\n .join('\\n');\n return {\n success: false,\n error: `Validation failed:\\n${errors}`,\n };\n }\n\n return {\n success: true,\n data: result.data,\n };\n}\n","import {\n IframeChildTransport,\n type IframeChildTransportOptions,\n TabServerTransport,\n type TabServerTransportOptions,\n} from '@mcp-b/transports';\nimport type {\n Prompt,\n PromptMessage,\n Resource,\n ResourceContents,\n Transport,\n} from '@mcp-b/webmcp-ts-sdk';\nimport {\n CallToolRequestSchema,\n GetPromptRequestSchema,\n ListPromptsRequestSchema,\n ListResourcesRequestSchema,\n ListToolsRequestSchema,\n Server as McpServer,\n ReadResourceRequestSchema,\n} from '@mcp-b/webmcp-ts-sdk';\nimport type { z } from 'zod';\nimport type {\n ElicitationParams,\n ElicitationResult,\n InputSchema,\n InternalModelContext,\n MCPBridge,\n ModelContext,\n ModelContextInput,\n ModelContextTesting,\n PromptDescriptor,\n ResourceDescriptor,\n SamplingRequestParams,\n SamplingResult,\n ToolCallEvent,\n ToolDescriptor,\n ToolResponse,\n ValidatedPromptDescriptor,\n ValidatedResourceDescriptor,\n ValidatedToolDescriptor,\n WebModelContextInitOptions,\n ZodSchemaObject,\n} from './types.js';\nimport { jsonSchemaToZod, normalizeSchema, validateWithZod } from './validation.js';\n\ndeclare global {\n interface Window {\n __webModelContextOptions?: WebModelContextInitOptions;\n }\n}\n\n/**\n * Detect if the native Chromium Web Model Context API is available.\n * Checks for both navigator.modelContext and navigator.modelContextTesting,\n * and verifies they are native implementations (not polyfills) by examining\n * the constructor name.\n *\n * @returns Detection result with flags for native context and testing API availability\n */\nfunction detectNativeAPI(): {\n hasNativeContext: boolean;\n hasNativeTesting: boolean;\n} {\n if (typeof window === 'undefined' || typeof navigator === 'undefined') {\n return { hasNativeContext: false, hasNativeTesting: false };\n }\n\n const modelContext = navigator.modelContext;\n const modelContextTesting = navigator.modelContextTesting;\n\n if (!modelContext || !modelContextTesting) {\n return { hasNativeContext: false, hasNativeTesting: false };\n }\n\n const testingConstructorName = modelContextTesting.constructor?.name || '';\n const isPolyfill = testingConstructorName.includes('WebModelContext');\n\n if (isPolyfill) {\n return { hasNativeContext: false, hasNativeTesting: false };\n }\n\n return { hasNativeContext: true, hasNativeTesting: true };\n}\n\n/**\n * Adapter that wraps the native Chromium Web Model Context API.\n * Synchronizes tool changes from the native API to the MCP bridge,\n * enabling MCP clients to stay in sync with the native tool registry.\n *\n * Key features:\n * - Listens to native tool changes via registerToolsChangedCallback()\n * - Syncs native tools to MCP bridge automatically\n * - Delegates tool execution to native API\n * - Converts native results to MCP ToolResponse format\n *\n * @class NativeModelContextAdapter\n * @implements {InternalModelContext}\n */\nclass NativeModelContextAdapter implements InternalModelContext {\n private nativeContext: ModelContext;\n private nativeTesting: ModelContextTesting;\n private bridge: MCPBridge;\n private syncInProgress = false;\n\n /**\n * Creates a new NativeModelContextAdapter.\n *\n * @param {MCPBridge} bridge - The MCP bridge instance\n * @param {ModelContext} nativeContext - The native navigator.modelContext\n * @param {ModelContextTesting} nativeTesting - The native navigator.modelContextTesting\n */\n constructor(bridge: MCPBridge, nativeContext: ModelContext, nativeTesting: ModelContextTesting) {\n this.bridge = bridge;\n this.nativeContext = nativeContext;\n this.nativeTesting = nativeTesting;\n\n this.nativeTesting.registerToolsChangedCallback(() => {\n console.log('[Native Adapter] Tool change detected from native API');\n this.syncToolsFromNative();\n });\n\n this.syncToolsFromNative();\n }\n\n /**\n * Synchronizes tools from the native API to the MCP bridge.\n * Fetches all tools from navigator.modelContextTesting.listTools()\n * and updates the bridge's tool registry.\n *\n * @private\n */\n private syncToolsFromNative(): void {\n if (this.syncInProgress) {\n return;\n }\n\n this.syncInProgress = true;\n\n try {\n const nativeTools = this.nativeTesting.listTools();\n console.log(`[Native Adapter] Syncing ${nativeTools.length} tools from native API`);\n\n this.bridge.tools.clear();\n\n for (const toolInfo of nativeTools) {\n try {\n const inputSchema = JSON.parse(toolInfo.inputSchema);\n\n const validatedTool: ValidatedToolDescriptor = {\n name: toolInfo.name,\n description: toolInfo.description,\n inputSchema: inputSchema,\n execute: async (args: Record<string, unknown>) => {\n const result = await this.nativeTesting.executeTool(\n toolInfo.name,\n JSON.stringify(args)\n );\n return this.convertToToolResponse(result);\n },\n inputValidator: jsonSchemaToZod(inputSchema),\n };\n\n this.bridge.tools.set(toolInfo.name, validatedTool);\n } catch (error) {\n console.error(`[Native Adapter] Failed to sync tool \"${toolInfo.name}\":`, error);\n }\n }\n\n this.notifyMCPServers();\n } finally {\n this.syncInProgress = false;\n }\n }\n\n /**\n * Converts native API result to MCP ToolResponse format.\n * Native API returns simplified values (string, number, object, etc.)\n * which need to be wrapped in the MCP CallToolResult format.\n *\n * @param {unknown} result - The result from native executeTool()\n * @returns {ToolResponse} Formatted MCP ToolResponse\n * @private\n */\n private convertToToolResponse(result: unknown): ToolResponse {\n if (typeof result === 'string') {\n return { content: [{ type: 'text', text: result }] };\n }\n\n if (result === undefined || result === null) {\n return { content: [{ type: 'text', text: '' }] };\n }\n\n if (typeof result === 'object') {\n return {\n content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],\n structuredContent: result as Record<string, unknown>,\n };\n }\n\n return {\n content: [{ type: 'text', text: String(result) }],\n };\n }\n\n /**\n * Notifies all connected MCP servers that the tools list has changed.\n *\n * @private\n */\n private notifyMCPServers(): void {\n if (this.bridge.tabServer?.notification) {\n this.bridge.tabServer.notification({\n method: 'notifications/tools/list_changed',\n params: {},\n });\n }\n\n if (this.bridge.iframeServer?.notification) {\n this.bridge.iframeServer.notification({\n method: 'notifications/tools/list_changed',\n params: {},\n });\n }\n }\n\n /**\n * Provides context (tools) to AI models via the native API.\n * Delegates to navigator.modelContext.provideContext().\n * Tool change callback will fire and trigger sync automatically.\n *\n * @param {ModelContextInput} context - Context containing tools to register\n */\n provideContext(context: ModelContextInput): void {\n console.log('[Native Adapter] Delegating provideContext to native API');\n this.nativeContext.provideContext(context);\n }\n\n /**\n * Registers a single tool dynamically via the native API.\n * Delegates to navigator.modelContext.registerTool().\n * Tool change callback will fire and trigger sync automatically.\n *\n * @param {ToolDescriptor} tool - The tool descriptor to register\n * @returns {{unregister: () => void}} Object with unregister function\n */\n registerTool<\n TInputSchema extends ZodSchemaObject = Record<string, never>,\n TOutputSchema extends ZodSchemaObject = Record<string, never>,\n >(tool: ToolDescriptor<TInputSchema, TOutputSchema>): { unregister: () => void } {\n console.log(`[Native Adapter] Delegating registerTool(\"${tool.name}\") to native API`);\n const result = this.nativeContext.registerTool(tool);\n return result;\n }\n\n /**\n * Unregisters a tool by name via the native API.\n * Delegates to navigator.modelContext.unregisterTool().\n *\n * @param {string} name - Name of the tool to unregister\n */\n unregisterTool(name: string): void {\n console.log(`[Native Adapter] Delegating unregisterTool(\"${name}\") to native API`);\n this.nativeContext.unregisterTool(name);\n }\n\n /**\n * Clears all registered tools via the native API.\n * Delegates to navigator.modelContext.clearContext().\n */\n clearContext(): void {\n console.log('[Native Adapter] Delegating clearContext to native API');\n this.nativeContext.clearContext();\n }\n\n /**\n * Executes a tool via the native API.\n * Delegates to navigator.modelContextTesting.executeTool() with JSON string args.\n *\n * @param {string} toolName - Name of the tool to execute\n * @param {Record<string, unknown>} args - Arguments to pass to the tool\n * @returns {Promise<ToolResponse>} The tool's response in MCP format\n * @internal\n */\n async executeTool(toolName: string, args: Record<string, unknown>): Promise<ToolResponse> {\n console.log(`[Native Adapter] Executing tool \"${toolName}\" via native API`);\n try {\n const result = await this.nativeTesting.executeTool(toolName, JSON.stringify(args));\n return this.convertToToolResponse(result);\n } catch (error) {\n console.error(`[Native Adapter] Error executing tool \"${toolName}\":`, error);\n return {\n content: [\n {\n type: 'text',\n text: `Error: ${error instanceof Error ? error.message : String(error)}`,\n },\n ],\n isError: true,\n };\n }\n }\n\n /**\n * Lists all registered tools from the MCP bridge.\n * Returns tools synced from the native API.\n *\n * @returns {Array<{name: string, description: string, inputSchema: InputSchema}>} Array of tool descriptors\n */\n listTools() {\n return Array.from(this.bridge.tools.values()).map((tool) => ({\n name: tool.name,\n description: tool.description,\n inputSchema: tool.inputSchema,\n ...(tool.outputSchema && { outputSchema: tool.outputSchema }),\n ...(tool.annotations && { annotations: tool.annotations }),\n }));\n }\n\n // ==================== RESOURCE METHODS (not yet supported by native API) ====================\n\n /**\n * Registers a resource dynamically.\n * Note: Native Chromium API does not yet support resources.\n * This is a polyfill-only feature.\n */\n registerResource(_resource: ResourceDescriptor): { unregister: () => void } {\n console.warn('[Native Adapter] registerResource is not supported by native API');\n return { unregister: () => {} };\n }\n\n /**\n * Unregisters a resource by URI.\n * Note: Native Chromium API does not yet support resources.\n */\n unregisterResource(_uri: string): void {\n console.warn('[Native Adapter] unregisterResource is not supported by native API');\n }\n\n /**\n * Lists all registered resources.\n * Note: Native Chromium API does not yet support resources.\n */\n listResources(): Resource[] {\n return [];\n }\n\n /**\n * Lists all resource templates.\n * Note: Native Chromium API does not yet support resources.\n */\n listResourceTemplates(): Array<{\n uriTemplate: string;\n name: string;\n description?: string;\n mimeType?: string;\n }> {\n return [];\n }\n\n /**\n * Reads a resource by URI.\n * Note: Native Chromium API does not yet support resources.\n * @internal\n */\n async readResource(_uri: string): Promise<{ contents: ResourceContents[] }> {\n throw new Error('[Native Adapter] readResource is not supported by native API');\n }\n\n // ==================== PROMPT METHODS (not yet supported by native API) ====================\n\n /**\n * Registers a prompt dynamically.\n * Note: Native Chromium API does not yet support prompts.\n * This is a polyfill-only feature.\n */\n registerPrompt<TArgsSchema extends ZodSchemaObject = Record<string, never>>(\n _prompt: PromptDescriptor<TArgsSchema>\n ): { unregister: () => void } {\n console.warn('[Native Adapter] registerPrompt is not supported by native API');\n return { unregister: () => {} };\n }\n\n /**\n * Unregisters a prompt by name.\n * Note: Native Chromium API does not yet support prompts.\n */\n unregisterPrompt(_name: string): void {\n console.warn('[Native Adapter] unregisterPrompt is not supported by native API');\n }\n\n /**\n * Lists all registered prompts.\n * Note: Native Chromium API does not yet support prompts.\n */\n listPrompts(): Prompt[] {\n return [];\n }\n\n /**\n * Gets a prompt with arguments.\n * Note: Native Chromium API does not yet support prompts.\n * @internal\n */\n async getPrompt(\n _name: string,\n _args?: Record<string, unknown>\n ): Promise<{ messages: PromptMessage[] }> {\n throw new Error('[Native Adapter] getPrompt is not supported by native API');\n }\n\n /**\n * Adds an event listener for tool call events.\n * Delegates to the native API's addEventListener.\n *\n * @param {'toolcall'} type - Event type\n * @param {(event: ToolCallEvent) => void | Promise<void>} listener - Event handler\n * @param {boolean | AddEventListenerOptions} [options] - Event listener options\n */\n addEventListener(\n type: 'toolcall',\n listener: (event: ToolCallEvent) => void | Promise<void>,\n options?: boolean | AddEventListenerOptions\n ): void {\n this.nativeContext.addEventListener(type, listener, options);\n }\n\n /**\n * Removes an event listener for tool call events.\n * Delegates to the native API's removeEventListener.\n *\n * @param {'toolcall'} type - Event type\n * @param {(event: ToolCallEvent) => void | Promise<void>} listener - Event handler\n * @param {boolean | EventListenerOptions} [options] - Event listener options\n */\n removeEventListener(\n type: 'toolcall',\n listener: (event: ToolCallEvent) => void | Promise<void>,\n options?: boolean | EventListenerOptions\n ): void {\n this.nativeContext.removeEventListener(type, listener, options);\n }\n\n /**\n * Dispatches a tool call event.\n * Delegates to the native API's dispatchEvent.\n *\n * @param {Event} event - The event to dispatch\n * @returns {boolean} False if event was cancelled, true otherwise\n */\n dispatchEvent(event: Event): boolean {\n return this.nativeContext.dispatchEvent(event);\n }\n\n // ==================== SAMPLING METHODS ====================\n\n /**\n * Request an LLM completion from the connected client.\n * Note: Native Chromium API does not yet support sampling.\n * This is handled by the polyfill.\n */\n async createMessage(params: SamplingRequestParams): Promise<SamplingResult> {\n console.log('[Native Adapter] Requesting sampling from client');\n const server = this.bridge.tabServer;\n\n // Access the underlying Server instance to call createMessage\n const underlyingServer = (\n server as unknown as {\n server: { createMessage: (params: unknown) => Promise<SamplingResult> };\n }\n ).server;\n\n if (!underlyingServer?.createMessage) {\n throw new Error('Sampling is not supported: no connected client with sampling capability');\n }\n\n return underlyingServer.createMessage(params);\n }\n\n // ==================== ELICITATION METHODS ====================\n\n /**\n * Request user input from the connected client.\n * Note: Native Chromium API does not yet support elicitation.\n * This is handled by the polyfill.\n */\n async elicitInput(params: ElicitationParams): Promise<ElicitationResult> {\n console.log('[Native Adapter] Requesting elicitation from client');\n const server = this.bridge.tabServer;\n\n // Access the underlying Server instance to call elicitInput\n const underlyingServer = (\n server as unknown as {\n server: { elicitInput: (params: unknown) => Promise<ElicitationResult> };\n }\n ).server;\n\n if (!underlyingServer?.elicitInput) {\n throw new Error(\n 'Elicitation is not supported: no connected client with elicitation capability'\n );\n }\n\n return underlyingServer.elicitInput(params);\n }\n}\n\n/**\n * ToolCallEvent implementation for the Web Model Context API.\n * Represents an event fired when a tool is called, allowing event listeners\n * to intercept and provide custom responses.\n *\n * @class WebToolCallEvent\n * @extends {Event}\n * @implements {ToolCallEvent}\n */\nclass WebToolCallEvent extends Event implements ToolCallEvent {\n public name: string;\n public arguments: Record<string, unknown>;\n private _response: ToolResponse | null = null;\n private _responded = false;\n\n /**\n * Creates a new ToolCallEvent.\n *\n * @param {string} toolName - Name of the tool being called\n * @param {Record<string, unknown>} args - Validated arguments for the tool\n */\n constructor(toolName: string, args: Record<string, unknown>) {\n super('toolcall', { cancelable: true });\n this.name = toolName;\n this.arguments = args;\n }\n\n /**\n * Provides a response for this tool call, preventing the default tool execution.\n *\n * @param {ToolResponse} response - The response to use instead of executing the tool\n * @throws {Error} If a response has already been provided\n */\n respondWith(response: ToolResponse): void {\n if (this._responded) {\n throw new Error('Response already provided for this tool call');\n }\n this._response = response;\n this._responded = true;\n }\n\n /**\n * Gets the response provided via respondWith().\n *\n * @returns {ToolResponse | null} The response, or null if none provided\n */\n getResponse(): ToolResponse | null {\n return this._response;\n }\n\n /**\n * Checks whether a response has been provided for this tool call.\n *\n * @returns {boolean} True if respondWith() was called\n */\n hasResponse(): boolean {\n return this._responded;\n }\n}\n\n/**\n * Time window in milliseconds to detect rapid duplicate tool registrations.\n * Used to filter out double-registrations caused by React Strict Mode.\n */\nconst RAPID_DUPLICATE_WINDOW_MS = 50;\n\n/**\n * Types of lists that can trigger change notifications.\n * Single source of truth for notification batching logic.\n */\ntype ListChangeType = 'tools' | 'resources' | 'prompts';\n\n/**\n * Testing API implementation for the Model Context Protocol.\n * Provides debugging, mocking, and testing capabilities for tool execution.\n * Implements both Chromium native methods and polyfill-specific extensions.\n *\n * @class WebModelContextTesting\n * @implements {ModelContextTesting}\n */\nclass WebModelContextTesting implements ModelContextTesting {\n private toolCallHistory: Array<{\n toolName: string;\n arguments: Record<string, unknown>;\n timestamp: number;\n }> = [];\n private mockResponses: Map<string, ToolResponse> = new Map();\n private toolsChangedCallbacks: Set<() => void> = new Set();\n private bridge: MCPBridge;\n\n /**\n * Creates a new WebModelContextTesting instance.\n *\n * @param {MCPBridge} bridge - The MCP bridge instance to test\n */\n constructor(bridge: MCPBridge) {\n this.bridge = bridge;\n }\n\n /**\n * Records a tool call in the history.\n * Called internally by WebModelContext when tools are executed.\n *\n * @param {string} toolName - Name of the tool that was called\n * @param {Record<string, unknown>} args - Arguments passed to the tool\n * @internal\n */\n recordToolCall(toolName: string, args: Record<string, unknown>): void {\n this.toolCallHistory.push({\n toolName,\n arguments: args,\n timestamp: Date.now(),\n });\n }\n\n /**\n * Checks if a mock response is registered for a specific tool.\n *\n * @param {string} toolName - Name of the tool to check\n * @returns {boolean} True if a mock response exists\n * @internal\n */\n hasMockResponse(toolName: string): boolean {\n return this.mockResponses.has(toolName);\n }\n\n /**\n * Retrieves the mock response for a specific tool.\n *\n * @param {string} toolName - Name of the tool\n * @returns {ToolResponse | undefined} The mock response, or undefined if none exists\n * @internal\n */\n getMockResponse(toolName: string): ToolResponse | undefined {\n return this.mockResponses.get(toolName);\n }\n\n /**\n * Notifies all registered callbacks that the tools list has changed.\n * Called internally when tools are registered, unregistered, or cleared.\n *\n * @internal\n */\n notifyToolsChanged(): void {\n for (const callback of this.toolsChangedCallbacks) {\n try {\n callback();\n } catch (error) {\n console.error('[Model Context Testing] Error in tools changed callback:', error);\n }\n }\n }\n\n /**\n * Executes a tool directly with JSON string input (Chromium native API).\n * Parses the JSON input, validates it, and executes the tool.\n *\n * @param {string} toolName - Name of the tool to execute\n * @param {string} inputArgsJson - JSON string of input arguments\n * @returns {Promise<unknown>} The tool's result, or undefined on error\n * @throws {SyntaxError} If the input JSON is invalid\n * @throws {Error} If the tool does not exist\n */\n async executeTool(toolName: string, inputArgsJson: string): Promise<unknown> {\n console.log(`[Model Context Testing] Executing tool: ${toolName}`);\n\n let args: Record<string, unknown>;\n try {\n args = JSON.parse(inputArgsJson);\n } catch (error) {\n throw new SyntaxError(\n `Invalid JSON input: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n\n const tool = this.bridge.tools.get(toolName);\n if (!tool) {\n throw new Error(`Tool not found: ${toolName}`);\n }\n\n const result = await this.bridge.modelContext.executeTool(toolName, args);\n\n if (result.isError) {\n return undefined;\n }\n\n if (result.structuredContent) {\n return result.structuredContent;\n }\n\n if (result.content && result.content.length > 0) {\n const firstContent = result.content[0];\n if (firstContent && firstContent.type === 'text') {\n return firstContent.text;\n }\n }\n\n return undefined;\n }\n\n /**\n * Lists all registered tools with inputSchema as JSON string (Chromium native API).\n * Returns an array of ToolInfo objects where inputSchema is stringified.\n *\n * @returns {Array<{name: string, description: string, inputSchema: string}>} Array of tool information\n */\n listTools(): Array<{ name: string; description: string; inputSchema: string }> {\n const tools = this.bridge.modelContext.listTools();\n return tools.map((tool) => ({\n name: tool.name,\n description: tool.description,\n inputSchema: JSON.stringify(tool.inputSchema),\n }));\n }\n\n /**\n * Registers a callback that fires when the tools list changes (Chromium native API).\n * The callback will be invoked on registerTool, unregisterTool, provideContext, and clearContext.\n *\n * @param {() => void} callback - Function to call when tools change\n */\n registerToolsChangedCallback(callback: () => void): void {\n this.toolsChangedCallbacks.add(callback);\n console.log('[Model Context Testing] Tools changed callback registered');\n }\n\n /**\n * Gets all tool calls that have been recorded (polyfill extension).\n *\n * @returns {Array<{toolName: string, arguments: Record<string, unknown>, timestamp: number}>} Tool call history\n */\n getToolCalls(): Array<{\n toolName: string;\n arguments: Record<string, unknown>;\n timestamp: number;\n }> {\n return [...this.toolCallHistory];\n }\n\n /**\n * Clears the tool call history (polyfill extension).\n */\n clearToolCalls(): void {\n this.toolCallHistory = [];\n console.log('[Model Context Testing] Tool call history cleared');\n }\n\n /**\n * Sets a mock response for a specific tool (polyfill extension).\n * When set, the tool's execute function will be bypassed.\n *\n * @param {string} toolName - Name of the tool to mock\n * @param {ToolResponse} response - The mock response to return\n */\n setMockToolResponse(toolName: string, response: ToolResponse): void {\n this.mockResponses.set(toolName, response);\n console.log(`[Model Context Testing] Mock response set for tool: ${toolName}`);\n }\n\n /**\n * Clears the mock response for a specific tool (polyfill extension).\n *\n * @param {string} toolName - Name of the tool\n */\n clearMockToolResponse(toolName: string): void {\n this.mockResponses.delete(toolName);\n console.log(`[Model Context Testing] Mock response cleared for tool: ${toolName}`);\n }\n\n /**\n * Clears all mock tool responses (polyfill extension).\n */\n clearAllMockToolResponses(): void {\n this.mockResponses.clear();\n console.log('[Model Context Testing] All mock responses cleared');\n }\n\n /**\n * Gets the current tools registered in the system (polyfill extension).\n *\n * @returns {ReturnType<InternalModelContext['listTools']>} Array of registered tools\n */\n getRegisteredTools(): ReturnType<InternalModelContext['listTools']> {\n return this.bridge.modelContext.listTools();\n }\n\n /**\n * Resets the entire testing state (polyfill extension).\n * Clears both tool call history and all mock responses.\n */\n reset(): void {\n this.clearToolCalls();\n this.clearAllMockToolResponses();\n console.log('[Model Context Testing] Testing state reset');\n }\n}\n\n/**\n * ModelContext implementation that bridges to the Model Context Protocol SDK.\n * Implements the W3C Web Model Context API proposal with two-bucket tool management:\n * - Bucket A (provideContextTools): Tools registered via provideContext()\n * - Bucket B (dynamicTools): Tools registered via registerTool()\n *\n * This separation ensures that component-scoped dynamic tools persist across\n * app-level provideContext() calls.\n *\n * @class WebModelContext\n * @implements {InternalModelContext}\n */\nclass WebModelContext implements InternalModelContext {\n private bridge: MCPBridge;\n private eventTarget: EventTarget;\n\n // Tool storage (Bucket A = provideContext, Bucket B = dynamic)\n private provideContextTools: Map<string, ValidatedToolDescriptor>;\n private dynamicTools: Map<string, ValidatedToolDescriptor>;\n\n // Resource storage (Bucket A = provideContext, Bucket B = dynamic)\n private provideContextResources: Map<string, ValidatedResourceDescriptor>;\n private dynamicResources: Map<string, ValidatedResourceDescriptor>;\n\n // Prompt storage (Bucket A = provideContext, Bucket B = dynamic)\n private provideContextPrompts: Map<string, ValidatedPromptDescriptor>;\n private dynamicPrompts: Map<string, ValidatedPromptDescriptor>;\n\n // Registration tracking for duplicate detection\n private toolRegistrationTimestamps: Map<string, number>;\n private resourceRegistrationTimestamps: Map<string, number>;\n private promptRegistrationTimestamps: Map<string, number>;\n\n // Unregister functions for dynamic registrations\n private toolUnregisterFunctions: Map<string, () => void>;\n private resourceUnregisterFunctions: Map<string, () => void>;\n private promptUnregisterFunctions: Map<string, () => void>;\n\n /**\n * Tracks which list change notifications are pending.\n * Uses microtask-based batching to coalesce rapid registrations\n * (e.g., React mount phase) into a single notification per list type.\n */\n private pendingNotifications = new Set<ListChangeType>();\n\n private testingAPI?: WebModelContextTesting;\n\n /**\n * Creates a new WebModelContext instance.\n *\n * @param {MCPBridge} bridge - The MCP bridge to use for communication\n */\n constructor(bridge: MCPBridge) {\n this.bridge = bridge;\n this.eventTarget = new EventTarget();\n\n // Initialize tool storage\n this.provideContextTools = new Map();\n this.dynamicTools = new Map();\n this.toolRegistrationTimestamps = new Map();\n this.toolUnregisterFunctions = new Map();\n\n // Initialize resource storage\n this.provideContextResources = new Map();\n this.dynamicResources = new Map();\n this.resourceRegistrationTimestamps = new Map();\n this.resourceUnregisterFunctions = new Map();\n\n // Initialize prompt storage\n this.provideContextPrompts = new Map();\n this.dynamicPrompts = new Map();\n this.promptRegistrationTimestamps = new Map();\n this.promptUnregisterFunctions = new Map();\n }\n\n /**\n * Sets the testing API instance.\n * Called during initialization to enable testing features.\n *\n * @param {WebModelContextTesting} testingAPI - The testing API instance\n * @internal\n */\n setTestingAPI(testingAPI: WebModelContextTesting): void {\n this.testingAPI = testingAPI;\n }\n\n /**\n * Adds an event listener for tool call events.\n *\n * @param {'toolcall'} type - Event type (only 'toolcall' is supported)\n * @param {(event: ToolCallEvent) => void | Promise<void>} listener - Event handler function\n * @param {boolean | AddEventListenerOptions} [options] - Event listener options\n */\n addEventListener(\n type: 'toolcall',\n listener: (event: ToolCallEvent) => void | Promise<void>,\n options?: boolean | AddEventListenerOptions\n ): void {\n this.eventTarget.addEventListener(type, listener as EventListener, options);\n }\n\n /**\n * Removes an event listener for tool call events.\n *\n * @param {'toolcall'} type - Event type (only 'toolcall' is supported)\n * @param {(event: ToolCallEvent) => void | Promise<void>} listener - Event handler function\n * @param {boolean | EventListenerOptions} [options] - Event listener options\n */\n removeEventListener(\n type: 'toolcall',\n listener: (event: ToolCallEvent) => void | Promise<void>,\n options?: boolean | EventListenerOptions\n ): void {\n this.eventTarget.removeEventListener(type, listener as EventListener, options);\n }\n\n /**\n * Dispatches a tool call event to all registered listeners.\n *\n * @param {Event} event - The event to dispatch\n * @returns {boolean} False if event was cancelled, true otherwise\n */\n dispatchEvent(event: Event): boolean {\n return this.eventTarget.dispatchEvent(event);\n }\n\n /**\n * Provides context (tools, resources, prompts) to AI models by registering base items (Bucket A).\n * Clears and replaces all previously registered base items while preserving\n * dynamic items registered via register* methods.\n *\n * @param {ModelContextInput} context - Context containing tools, resources, and prompts to register\n * @throws {Error} If a name/uri collides with existing dynamic items\n */\n provideContext(context: ModelContextInput): void {\n const toolCount = context.tools?.length ?? 0;\n const resourceCount = context.resources?.length ?? 0;\n const promptCount = context.prompts?.length ?? 0;\n console.log(\n `[Web Model Context] provideContext: ${toolCount} tools, ${resourceCount} resources, ${promptCount} prompts`\n );\n\n // Clear base items (Bucket A)\n this.provideContextTools.clear();\n this.provideContextResources.clear();\n this.provideContextPrompts.clear();\n\n // Register tools\n for (const tool of context.tools ?? []) {\n if (this.dynamicTools.has(tool.name)) {\n throw new Error(\n `[Web Model Context] Tool name collision: \"${tool.name}\" is already registered via registerTool(). ` +\n 'Please use a different name or unregister the dynamic tool first.'\n );\n }\n\n const { jsonSchema: inputJson, zodValidator: inputZod } = normalizeSchema(tool.inputSchema);\n const normalizedOutput = tool.outputSchema ? normalizeSchema(tool.outputSchema) : null;\n\n const validatedTool: ValidatedToolDescriptor = {\n name: tool.name,\n description: tool.description,\n inputSchema: inputJson,\n ...(normalizedOutput && { outputSchema: normalizedOutput.jsonSchema }),\n ...(tool.annotations && { annotations: tool.annotations }),\n execute: tool.execute,\n inputValidator: inputZod,\n ...(normalizedOutput && { outputValidator: normalizedOutput.zodValidator }),\n };\n\n this.provideContextTools.set(tool.name, validatedTool);\n }\n\n // Register resources\n for (const resource of context.resources ?? []) {\n if (this.dynamicResources.has(resource.uri)) {\n throw new Error(\n `[Web Model Context] Resource URI collision: \"${resource.uri}\" is already registered via registerResource(). ` +\n 'Please use a different URI or unregister the dynamic resource first.'\n );\n }\n\n const validatedResource = this.validateResource(resource);\n this.provideContextResources.set(resource.uri, validatedResource);\n }\n\n // Register prompts\n for (const prompt of context.prompts ?? []) {\n if (this.dynamicPrompts.has(prompt.name)) {\n throw new Error(\n `[Web Model Context] Prompt name collision: \"${prompt.name}\" is already registered via registerPrompt(). ` +\n 'Please use a different name or unregister the dynamic prompt first.'\n );\n }\n\n const validatedPrompt = this.validatePrompt(prompt);\n this.provideContextPrompts.set(prompt.name, validatedPrompt);\n }\n\n // Update bridge and schedule notifications (batched via microtask)\n this.updateBridgeTools();\n this.updateBridgeResources();\n this.updateBridgePrompts();\n\n this.scheduleListChanged('tools');\n this.scheduleListChanged('resources');\n this.scheduleListChanged('prompts');\n }\n\n /**\n * Validates and normalizes a resource descriptor.\n * @private\n */\n private validateResource(resource: ResourceDescriptor): ValidatedResourceDescriptor {\n // Extract template parameters from URI (e.g., \"file://{path}\" -> [\"path\"])\n const templateParamRegex = /\\{([^}]+)\\}/g;\n const templateParams: string[] = [];\n for (const match of resource.uri.matchAll(templateParamRegex)) {\n const paramName = match[1];\n if (paramName) {\n templateParams.push(paramName);\n }\n }\n\n return {\n uri: resource.uri,\n name: resource.name,\n description: resource.description,\n mimeType: resource.mimeType,\n read: resource.read,\n isTemplate: templateParams.length > 0,\n templateParams,\n };\n }\n\n /**\n * Validates and normalizes a prompt descriptor.\n * @private\n */\n private validatePrompt<TArgsSchema extends ZodSchemaObject>(\n prompt: PromptDescriptor<TArgsSchema>\n ): ValidatedPromptDescriptor {\n let argsSchema: InputSchema | undefined;\n let argsValidator: z.ZodType | undefined;\n\n if (prompt.argsSchema) {\n const normalized = normalizeSchema(prompt.argsSchema);\n argsSchema = normalized.jsonSchema;\n argsValidator = normalized.zodValidator;\n }\n\n return {\n name: prompt.name,\n description: prompt.description,\n argsSchema,\n get: prompt.get as (args: Record<string, unknown>) => Promise<{ messages: PromptMessage[] }>,\n argsValidator,\n };\n }\n\n /**\n * Registers a single tool dynamically (Bucket B).\n * Dynamic tools persist across provideContext() calls and can be independently managed.\n *\n * @param {ToolDescriptor} tool - The tool descriptor to register\n * @returns {{unregister: () => void}} Object with unregister function\n * @throws {Error} If tool name collides with existing tools\n */\n registerTool<\n TInputSchema extends ZodSchemaObject = Record<string, never>,\n TOutputSchema extends ZodSchemaObject = Record<string, never>,\n >(tool: ToolDescriptor<TInputSchema, TOutputSchema>): { unregister: () => void } {\n console.log(`[Web Model Context] Registering tool dynamically: ${tool.name}`);\n\n const now = Date.now();\n const lastRegistration = this.toolRegistrationTimestamps.get(tool.name);\n\n if (lastRegistration && now - lastRegistration < RAPID_DUPLICATE_WINDOW_MS) {\n console.warn(\n `[Web Model Context] Tool \"${tool.name}\" registered multiple times within ${RAPID_DUPLICATE_WINDOW_MS}ms. ` +\n 'This is likely due to React Strict Mode double-mounting. Ignoring duplicate registration.'\n );\n\n const existingUnregister = this.toolUnregisterFunctions.get(tool.name);\n if (existingUnregister) {\n return { unregister: existingUnregister };\n }\n }\n\n if (this.provideContextTools.has(tool.name)) {\n throw new Error(\n `[Web Model Context] Tool name collision: \"${tool.name}\" is already registered via provideContext(). ` +\n 'Please use a different name or update your provideContext() call.'\n );\n }\n\n if (this.dynamicTools.has(tool.name)) {\n throw new Error(\n `[Web Model Context] Tool name collision: \"${tool.name}\" is already registered via registerTool(). ` +\n 'Please unregister it first or use a different name.'\n );\n }\n\n const { jsonSchema: inputJson, zodValidator: inputZod } = normalizeSchema(tool.inputSchema);\n\n const normalizedOutput = tool.outputSchema ? normalizeSchema(tool.outputSchema) : null;\n\n const validatedTool: ValidatedToolDescriptor = {\n name: tool.name,\n description: tool.description,\n inputSchema: inputJson,\n ...(normalizedOutput && { outputSchema: normalizedOutput.jsonSchema }),\n ...(tool.annotations && { annotations: tool.annotations }),\n execute: tool.execute as (args: Record<string, unknown>) => Promise<ToolResponse>,\n inputValidator: inputZod,\n ...(normalizedOutput && { outputValidator: normalizedOutput.zodValidator }),\n };\n\n this.dynamicTools.set(tool.name, validatedTool);\n this.toolRegistrationTimestamps.set(tool.name, now);\n this.updateBridgeTools();\n this.scheduleListChanged('tools');\n\n const unregisterFn = () => {\n console.log(`[Web Model Context] Unregistering tool: ${tool.name}`);\n\n if (this.provideContextTools.has(tool.name)) {\n throw new Error(\n `[Web Model Context] Cannot unregister tool \"${tool.name}\": ` +\n 'This tool was registered via provideContext(). Use provideContext() to update the base tool set.'\n );\n }\n\n if (!this.dynamicTools.has(tool.name)) {\n console.warn(\n `[Web Model Context] Tool \"${tool.name}\" is not registered, ignoring unregister call`\n );\n return;\n }\n\n this.dynamicTools.delete(tool.name);\n this.toolRegistrationTimestamps.delete(tool.name);\n this.toolUnregisterFunctions.delete(tool.name);\n this.updateBridgeTools();\n this.scheduleListChanged('tools');\n };\n\n this.toolUnregisterFunctions.set(tool.name, unregisterFn);\n\n return { unregister: unregisterFn };\n }\n\n // ==================== RESOURCE METHODS ====================\n\n /**\n * Registers a single resource dynamically (Bucket B).\n * Dynamic resources persist across provideContext() calls and can be independently managed.\n *\n * @param {ResourceDescriptor} resource - The resource descriptor to register\n * @returns {{unregister: () => void}} Object with unregister function\n * @throws {Error} If resource URI collides with existing resources\n */\n registerResource(resource: ResourceDescriptor): { unregister: () => void } {\n console.log(`[Web Model Context] Registering resource dynamically: ${resource.uri}`);\n\n const now = Date.now();\n const lastRegistration = this.resourceRegistrationTimestamps.get(resource.uri);\n\n if (lastRegistration && now - lastRegistration < RAPID_DUPLICATE_WINDOW_MS) {\n console.warn(\n `[Web Model Context] Resource \"${resource.uri}\" registered multiple times within ${RAPID_DUPLICATE_WINDOW_MS}ms. ` +\n 'This is likely due to React Strict Mode double-mounting. Ignoring duplicate registration.'\n );\n\n const existingUnregister = this.resourceUnregisterFunctions.get(resource.uri);\n if (existingUnregister) {\n return { unregister: existingUnregister };\n }\n }\n\n if (this.provideContextResources.has(resource.uri)) {\n throw new Error(\n `[Web Model Context] Resource URI collision: \"${resource.uri}\" is already registered via provideContext(). ` +\n 'Please use a different URI or update your provideContext() call.'\n );\n }\n\n if (this.dynamicResources.has(resource.uri)) {\n throw new Error(\n `[Web Model Context] Resource URI collision: \"${resource.uri}\" is already registered via registerResource(). ` +\n 'Please unregister it first or use a different URI.'\n );\n }\n\n const validatedResource = this.validateResource(resource);\n this.dynamicResources.set(resource.uri, validatedResource);\n this.resourceRegistrationTimestamps.set(resource.uri, now);\n this.updateBridgeResources();\n this.scheduleListChanged('resources');\n\n const unregisterFn = () => {\n console.log(`[Web Model Context] Unregistering resource: ${resource.uri}`);\n\n if (this.provideContextResources.has(resource.uri)) {\n throw new Error(\n `[Web Model Context] Cannot unregister resource \"${resource.uri}\": ` +\n 'This resource was registered via provideContext(). Use provideContext() to update the base resource set.'\n );\n }\n\n if (!this.dynamicResources.has(resource.uri)) {\n console.warn(\n `[Web Model Context] Resource \"${resource.uri}\" is not registered, ignoring unregister call`\n );\n return;\n }\n\n this.dynamicResources.delete(resource.uri);\n this.resourceRegistrationTimestamps.delete(resource.uri);\n this.resourceUnregisterFunctions.delete(resource.uri);\n this.updateBridgeResources();\n this.scheduleListChanged('resources');\n };\n\n this.resourceUnregisterFunctions.set(resource.uri, unregisterFn);\n\n return { unregister: unregisterFn };\n }\n\n /**\n * Unregisters a resource by URI.\n * Can unregister resources from either Bucket A (provideContext) or Bucket B (registerResource).\n *\n * @param {string} uri - URI of the resource to unregister\n */\n unregisterResource(uri: string): void {\n console.log(`[Web Model Context] Unregistering resource: ${uri}`);\n\n const inProvideContext = this.provideContextResources.has(uri);\n const inDynamic = this.dynamicResources.has(uri);\n\n if (!inProvideContext && !inDynamic) {\n console.warn(\n `[Web Model Context] Resource \"${uri}\" is not registered, ignoring unregister call`\n );\n return;\n }\n\n if (inProvideContext) {\n this.provideContextResources.delete(uri);\n }\n\n if (inDynamic) {\n this.dynamicResources.delete(uri);\n this.resourceRegistrationTimestamps.delete(uri);\n this.resourceUnregisterFunctions.delete(uri);\n }\n\n this.updateBridgeResources();\n this.scheduleListChanged('resources');\n }\n\n /**\n * Lists all registered resources in MCP format.\n * Returns static resources from both buckets (not templates).\n *\n * @returns {Resource[]} Array of resource descriptors\n */\n listResources(): Resource[] {\n return Array.from(this.bridge.resources.values())\n .filter((r) => !r.isTemplate)\n .map((resource) => ({\n uri: resource.uri,\n name: resource.name,\n description: resource.description,\n mimeType: resource.mimeType,\n }));\n }\n\n /**\n * Lists all registered resource templates.\n * Returns only resources with URI templates (dynamic resources).\n *\n * @returns {Array<{uriTemplate: string, name: string, description?: string, mimeType?: string}>}\n */\n listResourceTemplates(): Array<{\n uriTemplate: string;\n name: string;\n description?: string;\n mimeType?: string;\n }> {\n return Array.from(this.bridge.resources.values())\n .filter((r) => r.isTemplate)\n .map((resource) => ({\n uriTemplate: resource.uri,\n name: resource.name,\n ...(resource.description !== undefined && { description: resource.description }),\n ...(resource.mimeType !== undefined && { mimeType: resource.mimeType }),\n }));\n }\n\n // ==================== PROMPT METHODS ====================\n\n /**\n * Registers a single prompt dynamically (Bucket B).\n * Dynamic prompts persist across provideContext() calls and can be independently managed.\n *\n * @param {PromptDescriptor} prompt - The prompt descriptor to register\n * @returns {{unregister: () => void}} Object with unregister function\n * @throws {Error} If prompt name collides with existing prompts\n */\n registerPrompt<TArgsSchema extends ZodSchemaObject = Record<string, never>>(\n prompt: PromptDescriptor<TArgsSchema>\n ): { unregister: () => void } {\n console.log(`[Web Model Context] Registering prompt dynamically: ${prompt.name}`);\n\n const now = Date.now();\n const lastRegistration = this.promptRegistrationTimestamps.get(prompt.name);\n\n if (lastRegistration && now - lastRegistration < RAPID_DUPLICATE_WINDOW_MS) {\n console.warn(\n `[Web Model Context] Prompt \"${prompt.name}\" registered multiple times within ${RAPID_DUPLICATE_WINDOW_MS}ms. ` +\n 'This is likely due to React Strict Mode double-mounting. Ignoring duplicate registration.'\n );\n\n const existingUnregister = this.promptUnregisterFunctions.get(prompt.name);\n if (existingUnregister) {\n return { unregister: existingUnregister };\n }\n }\n\n if (this.provideContextPrompts.has(prompt.name)) {\n throw new Error(\n `[Web Model Context] Prompt name collision: \"${prompt.name}\" is already registered via provideContext(). ` +\n 'Please use a different name or update your provideContext() call.'\n );\n }\n\n if (this.dynamicPrompts.has(prompt.name)) {\n throw new Error(\n `[Web Model Context] Prompt name collision: \"${prompt.name}\" is already registered via registerPrompt(). ` +\n 'Please unregister it first or use a different name.'\n );\n }\n\n const validatedPrompt = this.validatePrompt(prompt);\n this.dynamicPrompts.set(prompt.name, validatedPrompt);\n this.promptRegistrationTimestamps.set(prompt.name, now);\n this.updateBridgePrompts();\n this.scheduleListChanged('prompts');\n\n const unregisterFn = () => {\n console.log(`[Web Model Context] Unregistering prompt: ${prompt.name}`);\n\n if (this.provideContextPrompts.has(prompt.name)) {\n throw new Error(\n `[Web Model Context] Cannot unregister prompt \"${prompt.name}\": ` +\n 'This prompt was registered via provideContext(). Use provideContext() to update the base prompt set.'\n );\n }\n\n if (!this.dynamicPrompts.has(prompt.name)) {\n console.warn(\n `[Web Model Context] Prompt \"${prompt.name}\" is not registered, ignoring unregister call`\n );\n return;\n }\n\n this.dynamicPrompts.delete(prompt.name);\n this.promptRegistrationTimestamps.delete(prompt.name);\n this.promptUnregisterFunctions.delete(prompt.name);\n this.updateBridgePrompts();\n this.scheduleListChanged('prompts');\n };\n\n this.promptUnregisterFunctions.set(prompt.name, unregisterFn);\n\n return { unregister: unregisterFn };\n }\n\n /**\n * Unregisters a prompt by name.\n * Can unregister prompts from either Bucket A (provideContext) or Bucket B (registerPrompt).\n *\n * @param {string} name - Name of the prompt to unregister\n */\n unregisterPrompt(name: string): void {\n console.log(`[Web Model Context] Unregistering prompt: ${name}`);\n\n const inProvideContext = this.provideContextPrompts.has(name);\n const inDynamic = this.dynamicPrompts.has(name);\n\n if (!inProvideContext && !inDynamic) {\n console.warn(\n `[Web Model Context] Prompt \"${name}\" is not registered, ignoring unregister call`\n );\n return;\n }\n\n if (inProvideContext) {\n this.provideContextPrompts.delete(name);\n }\n\n if (inDynamic) {\n this.dynamicPrompts.delete(name);\n this.promptRegistrationTimestamps.delete(name);\n this.promptUnregisterFunctions.delete(name);\n }\n\n this.updateBridgePrompts();\n this.scheduleListChanged('prompts');\n }\n\n /**\n * Lists all registered prompts in MCP format.\n * Returns prompts from both buckets.\n *\n * @returns {Prompt[]} Array of prompt descriptors\n */\n listPrompts(): Prompt[] {\n return Array.from(this.bridge.prompts.values()).map((prompt) => ({\n name: prompt.name,\n description: prompt.description,\n arguments: prompt.argsSchema?.properties\n ? Object.entries(prompt.argsSchema.properties).map(([name, schema]) => ({\n name,\n description: (schema as { description?: string }).description,\n required: prompt.argsSchema?.required?.includes(name) ?? false,\n }))\n : undefined,\n }));\n }\n\n /**\n * Unregisters a tool by name (Chromium native API).\n * Can unregister tools from either Bucket A (provideContext) or Bucket B (registerTool).\n *\n * @param {string} name - Name of the tool to unregister\n */\n unregisterTool(name: string): void {\n console.log(`[Web Model Context] Unregistering tool: ${name}`);\n\n const inProvideContext = this.provideContextTools.has(name);\n const inDynamic = this.dynamicTools.has(name);\n\n if (!inProvideContext && !inDynamic) {\n console.warn(\n `[Web Model Context] Tool \"${name}\" is not registered, ignoring unregister call`\n );\n return;\n }\n\n if (inProvideContext) {\n this.provideContextTools.delete(name);\n }\n\n if (inDynamic) {\n this.dynamicTools.delete(name);\n this.toolRegistrationTimestamps.delete(name);\n this.toolUnregisterFunctions.delete(name);\n }\n\n this.updateBridgeTools();\n this.scheduleListChanged('tools');\n }\n\n /**\n * Clears all registered context from both buckets (Chromium native API).\n * Removes all tools, resources, and prompts registered via provideContext() and register* methods.\n */\n clearContext(): void {\n console.log('[Web Model Context] Clearing all context (tools, resources, prompts)');\n\n // Clear tools\n this.provideContextTools.clear();\n this.dynamicTools.clear();\n this.toolRegistrationTimestamps.clear();\n this.toolUnregisterFunctions.clear();\n\n // Clear resources\n this.provideContextResources.clear();\n this.dynamicResources.clear();\n this.resourceRegistrationTimestamps.clear();\n this.resourceUnregisterFunctions.clear();\n\n // Clear prompts\n this.provideContextPrompts.clear();\n this.dynamicPrompts.clear();\n this.promptRegistrationTimestamps.clear();\n this.promptUnregisterFunctions.clear();\n\n // Update bridge\n this.updateBridgeTools();\n this.updateBridgeResources();\n this.updateBridgePrompts();\n\n // Schedule notifications (batched via microtask)\n this.scheduleListChanged('tools');\n this.scheduleListChanged('resources');\n this.scheduleListChanged('prompts');\n }\n\n /**\n * Updates the bridge tools map with merged tools from both buckets.\n * The final tool list is the union of Bucket A (provideContext) and Bucket B (dynamic).\n *\n * @private\n */\n private updateBridgeTools(): void {\n this.bridge.tools.clear();\n\n for (const [name, tool] of this.provideContextTools) {\n this.bridge.tools.set(name, tool);\n }\n\n for (const [name, tool] of this.dynamicTools) {\n this.bridge.tools.set(name, tool);\n }\n\n console.log(\n `[Web Model Context] Updated bridge with ${this.provideContextTools.size} base tools + ${this.dynamicTools.size} dynamic tools = ${this.bridge.tools.size} total`\n );\n }\n\n /**\n * Notifies all servers and testing callbacks that the tools list has changed.\n * Sends MCP notifications to connected servers and invokes registered testing callbacks.\n *\n * @private\n */\n private notifyToolsListChanged(): void {\n if (this.bridge.tabServer.notification) {\n this.bridge.tabServer.notification({\n method: 'notifications/tools/list_changed',\n params: {},\n });\n }\n\n if (this.bridge.iframeServer?.notification) {\n this.bridge.iframeServer.notification({\n method: 'notifications/tools/list_changed',\n params: {},\n });\n }\n\n if (this.testingAPI && 'notifyToolsChanged' in this.testingAPI) {\n (this.testingAPI as WebModelContextTesting).notifyToolsChanged();\n }\n }\n\n /**\n * Updates the bridge resources map with merged resources from both buckets.\n *\n * @private\n */\n private updateBridgeResources(): void {\n this.bridge.resources.clear();\n\n for (const [uri, resource] of this.provideContextResources) {\n this.bridge.resources.set(uri, resource);\n }\n\n for (const [uri, resource] of this.dynamicResources) {\n this.bridge.resources.set(uri, resource);\n }\n\n console.log(\n `[Web Model Context] Updated bridge with ${this.provideContextResources.size} base resources + ${this.dynamicResources.size} dynamic resources = ${this.bridge.resources.size} total`\n );\n }\n\n /**\n * Notifies all servers that the resources list has changed.\n *\n * @private\n */\n private notifyResourcesListChanged(): void {\n if (this.bridge.tabServer.notification) {\n this.bridge.tabServer.notification({\n method: 'notifications/resources/list_changed',\n params: {},\n });\n }\n\n if (this.bridge.iframeServer?.notification) {\n this.bridge.iframeServer.notification({\n method: 'notifications/resources/list_changed',\n params: {},\n });\n }\n }\n\n /**\n * Updates the bridge prompts map with merged prompts from both buckets.\n *\n * @private\n */\n private updateBridgePrompts(): void {\n this.bridge.prompts.clear();\n\n for (const [name, prompt] of this.provideContextPrompts) {\n this.bridge.prompts.set(name, prompt);\n }\n\n for (const [name, prompt] of this.dynamicPrompts) {\n this.bridge.prompts.set(name, prompt);\n }\n\n console.log(\n `[Web Model Context] Updated bridge with ${this.provideContextPrompts.size} base prompts + ${this.dynamicPrompts.size} dynamic prompts = ${this.bridge.prompts.size} total`\n );\n }\n\n /**\n * Notifies all servers that the prompts list has changed.\n *\n * @private\n */\n private notifyPromptsListChanged(): void {\n if (this.bridge.tabServer.notification) {\n this.bridge.tabServer.notification({\n method: 'notifications/prompts/list_changed',\n params: {},\n });\n }\n\n if (this.bridge.iframeServer?.notification) {\n this.bridge.iframeServer.notification({\n method: 'notifications/prompts/list_changed',\n params: {},\n });\n }\n }\n\n /**\n * Schedules a list changed notification using microtask batching.\n * Multiple calls for the same list type within the same task are coalesced\n * into a single notification. This dramatically reduces notification spam\n * during React mount/unmount cycles.\n *\n * @param listType - The type of list that changed ('tools' | 'resources' | 'prompts')\n * @private\n */\n private scheduleListChanged(listType: ListChangeType): void {\n if (this.pendingNotifications.has(listType)) return;\n\n this.pendingNotifications.add(listType);\n queueMicrotask(() => {\n this.pendingNotifications.delete(listType);\n\n // Dispatch to the appropriate notification method\n // Exhaustive switch ensures compile-time safety when adding new list types\n switch (listType) {\n case 'tools':\n this.notifyToolsListChanged();\n break;\n case 'resources':\n this.notifyResourcesListChanged();\n break;\n case 'prompts':\n this.notifyPromptsListChanged();\n break;\n default: {\n // Exhaustiveness check: TypeScript will error if a case is missing\n const _exhaustive: never = listType;\n console.error(`[Web Model Context] Unknown list type: ${_exhaustive}`);\n }\n }\n });\n }\n\n /**\n * Reads a resource by URI (internal use only by MCP bridge).\n * Handles both static resources and URI templates.\n *\n * @param {string} uri - The URI of the resource to read\n * @returns {Promise<{contents: ResourceContents[]}>} The resource contents\n * @throws {Error} If resource is not found\n * @internal\n */\n async readResource(uri: string): Promise<{ contents: ResourceContents[] }> {\n console.log(`[Web Model Context] Reading resource: ${uri}`);\n\n // First, try to find an exact match (static resource)\n const staticResource = this.bridge.resources.get(uri);\n if (staticResource && !staticResource.isTemplate) {\n try {\n const parsedUri = new URL(uri);\n return await staticResource.read(parsedUri);\n } catch (error) {\n console.error(`[Web Model Context] Error reading resource ${uri}:`, error);\n throw error;\n }\n }\n\n // Try to match against URI templates\n for (const resource of this.bridge.resources.values()) {\n if (!resource.isTemplate) continue;\n\n const params = this.matchUriTemplate(resource.uri, uri);\n if (params) {\n try {\n const parsedUri = new URL(uri);\n return await resource.read(parsedUri, params);\n } catch (error) {\n console.error(`[Web Model Context] Error reading resource ${uri}:`, error);\n throw error;\n }\n }\n }\n\n throw new Error(`Resource not found: ${uri}`);\n }\n\n /**\n * Matches a URI against a URI template and extracts parameters.\n *\n * @param {string} template - The URI template (e.g., \"file://{path}\")\n * @param {string} uri - The actual URI to match\n * @returns {Record<string, string> | null} Extracted parameters or null if no match\n * @private\n */\n private matchUriTemplate(template: string, uri: string): Record<string, string> | null {\n // Convert template to regex pattern\n // e.g., \"file://{path}\" -> \"^file://(.+)$\" with capture group for \"path\"\n const paramNames: string[] = [];\n let regexPattern = template.replace(/[.*+?^${}()|[\\]\\\\]/g, (char) => {\n // Don't escape { and } - we'll handle them specially\n if (char === '{' || char === '}') return char;\n return `\\\\${char}`;\n });\n\n // Replace {param} with capture groups\n regexPattern = regexPattern.replace(/\\{([^}]+)\\}/g, (_, paramName) => {\n paramNames.push(paramName);\n return '(.+)';\n });\n\n const regex = new RegExp(`^${regexPattern}$`);\n const match = uri.match(regex);\n\n if (!match) return null;\n\n const params: Record<string, string> = {};\n for (let i = 0; i < paramNames.length; i++) {\n const paramName = paramNames[i];\n const paramValue = match[i + 1];\n if (paramName !== undefined && paramValue !== undefined) {\n params[paramName] = paramValue;\n }\n }\n\n return params;\n }\n\n /**\n * Gets a prompt with arguments (internal use only by MCP bridge).\n *\n * @param {string} name - Name of the prompt\n * @param {Record<string, unknown>} args - Arguments to pass to the prompt\n * @returns {Promise<{messages: PromptMessage[]}>} The prompt messages\n * @throws {Error} If prompt is not found\n * @internal\n */\n async getPrompt(\n name: string,\n args?: Record<string, unknown>\n ): Promise<{ messages: PromptMessage[] }> {\n console.log(`[Web Model Context] Getting prompt: ${name}`);\n\n const prompt = this.bridge.prompts.get(name);\n if (!prompt) {\n throw new Error(`Prompt not found: ${name}`);\n }\n\n // Validate arguments if schema is defined\n if (prompt.argsValidator && args) {\n const validation = validateWithZod(args, prompt.argsValidator);\n if (!validation.success) {\n console.error(\n `[Web Model Context] Argument validation failed for prompt ${name}:`,\n validation.error\n );\n throw new Error(`Argument validation error for prompt \"${name}\":\\n${validation.error}`);\n }\n }\n\n try {\n return await prompt.get(args ?? {});\n } catch (error) {\n console.error(`[Web Model Context] Error getting prompt ${name}:`, error);\n throw error;\n }\n }\n\n /**\n * Executes a tool with validation and event dispatch.\n * Follows this sequence:\n * 1. Validates input arguments against schema\n * 2. Records tool call in testing API (if available)\n * 3. Checks for mock response (if testing)\n * 4. Dispatches 'toolcall' event to listeners\n * 5. Executes tool function if not prevented\n * 6. Validates output (permissive mode - warns only)\n *\n * @param {string} toolName - Name of the tool to execute\n * @param {Record<string, unknown>} args - Arguments to pass to the tool\n * @returns {Promise<ToolResponse>} The tool's response\n * @throws {Error} If tool is not found\n * @internal\n */\n async executeTool(toolName: string, args: Record<string, unknown>): Promise<ToolResponse> {\n const tool = this.bridge.tools.get(toolName);\n if (!tool) {\n throw new Error(`Tool not found: ${toolName}`);\n }\n\n console.log(`[Web Model Context] Validating input for tool: ${toolName}`);\n const validation = validateWithZod(args, tool.inputValidator);\n if (!validation.success) {\n console.error(\n `[Web Model Context] Input validation failed for ${toolName}:`,\n validation.error\n );\n return {\n content: [\n {\n type: 'text',\n text: `Input validation error for tool \"${toolName}\":\\n${validation.error}`,\n },\n ],\n isError: true,\n };\n }\n\n const validatedArgs = validation.data as Record<string, unknown>;\n\n if (this.testingAPI) {\n this.testingAPI.recordToolCall(toolName, validatedArgs);\n }\n\n if (this.testingAPI?.hasMockResponse(toolName)) {\n const mockResponse = this.testingAPI.getMockResponse(toolName);\n if (mockResponse) {\n console.log(`[Web Model Context] Returning mock response for tool: ${toolName}`);\n return mockResponse;\n }\n }\n\n const event = new WebToolCallEvent(toolName, validatedArgs);\n\n this.dispatchEvent(event);\n\n if (event.defaultPrevented && event.hasResponse()) {\n const response = event.getResponse();\n if (response) {\n console.log(`[Web Model Context] Tool ${toolName} handled by event listener`);\n return response;\n }\n }\n\n console.log(`[Web Model Context] Executing tool: ${toolName}`);\n try {\n const response = await tool.execute(validatedArgs);\n\n if (tool.outputValidator && response.structuredContent) {\n const outputValidation = validateWithZod(response.structuredContent, tool.outputValidator);\n if (!outputValidation.success) {\n console.warn(\n `[Web Model Context] Output validation failed for ${toolName}:`,\n outputValidation.error\n );\n }\n }\n\n return response;\n } catch (error) {\n console.error(`[Web Model Context] Error executing tool ${toolName}:`, error);\n return {\n content: [\n {\n type: 'text',\n text: `Error: ${error instanceof Error ? error.message : String(error)}`,\n },\n ],\n isError: true,\n };\n }\n }\n\n /**\n * Lists all registered tools in MCP format.\n * Returns tools from both buckets with full MCP specification including\n * annotations and output schemas.\n *\n * @returns {Array<{name: string, description: string, inputSchema: InputSchema, outputSchema?: InputSchema, annotations?: ToolAnnotations}>} Array of tool descriptors\n */\n listTools() {\n return Array.from(this.bridge.tools.values()).map((tool) => ({\n name: tool.name,\n description: tool.description,\n inputSchema: tool.inputSchema,\n ...(tool.outputSchema && { outputSchema: tool.outputSchema }),\n ...(tool.annotations && { annotations: tool.annotations }),\n }));\n }\n\n // ==================== SAMPLING METHODS ====================\n\n /**\n * Request an LLM completion from the connected client.\n * This sends a sampling request to the connected MCP client.\n *\n * @param {SamplingRequestParams} params - Parameters for the sampling request\n * @returns {Promise<SamplingResult>} The LLM completion result\n */\n async createMessage(params: SamplingRequestParams): Promise<SamplingResult> {\n console.log('[Web Model Context] Requesting sampling from client');\n const server = this.bridge.tabServer;\n\n // Access the underlying Server instance to call createMessage\n const underlyingServer = (\n server as unknown as {\n server: { createMessage: (params: unknown) => Promise<SamplingResult> };\n }\n ).server;\n\n if (!underlyingServer?.createMessage) {\n throw new Error('Sampling is not supported: no connected client with sampling capability');\n }\n\n return underlyingServer.createMessage(params);\n }\n\n // ==================== ELICITATION METHODS ====================\n\n /**\n * Request user input from the connected client.\n * This sends an elicitation request to the connected MCP client.\n *\n * @param {ElicitationParams} params - Parameters for the elicitation request\n * @returns {Promise<ElicitationResult>} The user's response\n */\n async elicitInput(params: ElicitationParams): Promise<ElicitationResult> {\n console.log('[Web Model Context] Requesting elicitation from client');\n const server = this.bridge.tabServer;\n\n // Access the underlying Server instance to call elicitInput\n const underlyingServer = (\n server as unknown as {\n server: { elicitInput: (params: unknown) => Promise<ElicitationResult> };\n }\n ).server;\n\n if (!underlyingServer?.elicitInput) {\n throw new Error(\n 'Elicitation is not supported: no connected client with elicitation capability'\n );\n }\n\n return underlyingServer.elicitInput(params);\n }\n}\n\n/**\n * Initializes the MCP bridge with dual-server support.\n * Creates TabServer for same-window communication and optionally IframeChildServer\n * for parent-child iframe communication.\n *\n * @param {WebModelContextInitOptions} [options] - Configuration options\n * @returns {MCPBridge} The initialized MCP bridge\n */\nfunction initializeMCPBridge(options?: WebModelContextInitOptions): MCPBridge {\n console.log('[Web Model Context] Initializing MCP bridge');\n\n const hostname = window.location.hostname || 'localhost';\n const transportOptions = options?.transport;\n\n const setupServerHandlers = (server: McpServer, bridge: MCPBridge) => {\n // ==================== TOOL HANDLERS ====================\n server.setRequestHandler(ListToolsRequestSchema, async () => {\n console.log('[MCP Bridge] Handling list_tools request');\n return {\n tools: bridge.modelContext.listTools(),\n };\n });\n\n server.setRequestHandler(CallToolRequestSchema, async (request) => {\n console.log(`[MCP Bridge] Handling call_tool request: ${request.params.name}`);\n\n const toolName = request.params.name;\n const args = (request.params.arguments || {}) as Record<string, unknown>;\n\n try {\n const response = await bridge.modelContext.executeTool(toolName, args);\n return {\n content: response.content,\n isError: response.isError,\n };\n } catch (error) {\n console.error(`[MCP Bridge] Error calling tool ${toolName}:`, error);\n throw error;\n }\n });\n\n // ==================== RESOURCE HANDLERS ====================\n server.setRequestHandler(ListResourcesRequestSchema, async () => {\n console.log('[MCP Bridge] Handling list_resources request');\n return {\n resources: bridge.modelContext.listResources(),\n // Note: Resource templates are included in the resources list as the MCP SDK\n // doesn't export ListResourceTemplatesRequestSchema separately.\n // Clients can identify templates by checking for URI patterns containing {param}.\n };\n });\n\n server.setRequestHandler(ReadResourceRequestSchema, async (request) => {\n console.log(`[MCP Bridge] Handling read_resource request: ${request.params.uri}`);\n\n try {\n return await bridge.modelContext.readResource(request.params.uri);\n } catch (error) {\n console.error(`[MCP Bridge] Error reading resource ${request.params.uri}:`, error);\n throw error;\n }\n });\n\n // ==================== PROMPT HANDLERS ====================\n server.setRequestHandler(ListPromptsRequestSchema, async () => {\n console.log('[MCP Bridge] Handling list_prompts request');\n return {\n prompts: bridge.modelContext.listPrompts(),\n };\n });\n\n server.setRequestHandler(GetPromptRequestSchema, async (request) => {\n console.log(`[MCP Bridge] Handling get_prompt request: ${request.params.name}`);\n\n try {\n return await bridge.modelContext.getPrompt(\n request.params.name,\n request.params.arguments as Record<string, unknown> | undefined\n );\n } catch (error) {\n console.error(`[MCP Bridge] Error getting prompt ${request.params.name}:`, error);\n throw error;\n }\n });\n\n // Note: Sampling and elicitation are server-to-client requests.\n // The server calls createMessage() and elicitInput() methods on the Server instance.\n // These are NOT request handlers - the client handles these requests.\n };\n\n const customTransport: Transport | undefined = transportOptions?.create?.();\n\n if (customTransport) {\n console.log('[Web Model Context] Using custom transport');\n\n const server = new McpServer(\n {\n name: hostname,\n version: '1.0.0',\n },\n {\n capabilities: {\n tools: { listChanged: true },\n resources: { listChanged: true },\n prompts: { listChanged: true },\n },\n }\n );\n\n const bridge: MCPBridge = {\n tabServer: server,\n tools: new Map(),\n resources: new Map(),\n prompts: new Map(),\n modelContext: undefined as unknown as InternalModelContext,\n isInitialized: true,\n };\n\n const modelContext = new WebModelContext(bridge);\n bridge.modelContext = modelContext;\n\n setupServerHandlers(server, bridge);\n server.connect(customTransport);\n\n console.log('[Web Model Context] MCP server connected with custom transport');\n return bridge;\n }\n\n console.log('[Web Model Context] Using dual-server mode');\n\n const tabServerEnabled = transportOptions?.tabServer !== false;\n const tabServer = new McpServer(\n {\n name: `${hostname}-tab`,\n version: '1.0.0',\n },\n {\n capabilities: {\n tools: { listChanged: true },\n resources: { listChanged: true },\n prompts: { listChanged: true },\n },\n }\n );\n\n const bridge: MCPBridge = {\n tabServer,\n tools: new Map(),\n resources: new Map(),\n prompts: new Map(),\n modelContext: undefined as unknown as InternalModelContext,\n isInitialized: true,\n };\n\n const modelContext = new WebModelContext(bridge);\n bridge.modelContext = modelContext;\n\n setupServerHandlers(tabServer, bridge);\n\n if (tabServerEnabled) {\n const tabServerOptions: Partial<TabServerTransportOptions> =\n typeof transportOptions?.tabServer === 'object' ? transportOptions.tabServer : {};\n const { allowedOrigins, ...restTabServerOptions } = tabServerOptions;\n\n const tabTransport = new TabServerTransport({\n allowedOrigins: allowedOrigins ?? ['*'],\n ...(restTabServerOptions as Omit<TabServerTransportOptions, 'allowedOrigins'>),\n });\n\n tabServer.connect(tabTransport);\n console.log('[Web Model Context] Tab server connected');\n }\n\n const isInIframe = typeof window !== 'undefined' && window.parent !== window;\n const iframeServerConfig = transportOptions?.iframeServer;\n const iframeServerEnabled =\n iframeServerConfig !== false && (iframeServerConfig !== undefined || isInIframe);\n\n if (iframeServerEnabled) {\n console.log('[Web Model Context] Enabling iframe server');\n\n const iframeServer = new McpServer(\n {\n name: `${hostname}-iframe`,\n version: '1.0.0',\n },\n {\n capabilities: {\n tools: { listChanged: true },\n resources: { listChanged: true },\n prompts: { listChanged: true },\n },\n }\n );\n\n setupServerHandlers(iframeServer, bridge);\n\n const iframeServerOptions: Partial<IframeChildTransportOptions> =\n typeof iframeServerConfig === 'object' ? iframeServerConfig : {};\n const { allowedOrigins, ...restIframeServerOptions } = iframeServerOptions;\n\n const iframeTransport = new IframeChildTransport({\n allowedOrigins: allowedOrigins ?? ['*'],\n ...(restIframeServerOptions as Omit<IframeChildTransportOptions, 'allowedOrigins'>),\n });\n\n iframeServer.connect(iframeTransport);\n bridge.iframeServer = iframeServer;\n\n console.log('[Web Model Context] Iframe server connected');\n }\n\n return bridge;\n}\n\n/**\n * Initializes the Web Model Context API on window.navigator.\n * Creates and exposes navigator.modelContext and navigator.modelContextTesting.\n * Automatically detects and uses native Chromium implementation if available.\n *\n * @param {WebModelContextInitOptions} [options] - Configuration options\n * @throws {Error} If initialization fails\n * @example\n * ```typescript\n * import { initializeWebModelContext } from '@mcp-b/global';\n *\n * initializeWebModelContext({\n * transport: {\n * tabServer: {\n * allowedOrigins: ['https://example.com']\n * }\n * }\n * });\n * ```\n */\nexport function initializeWebModelContext(options?: WebModelContextInitOptions): void {\n if (typeof window === 'undefined') {\n console.warn('[Web Model Context] Not in browser environment, skipping initialization');\n return;\n }\n\n const effectiveOptions = options ?? window.__webModelContextOptions;\n const native = detectNativeAPI();\n\n if (native.hasNativeContext && native.hasNativeTesting) {\n const nativeContext = window.navigator.modelContext;\n const nativeTesting = window.navigator.modelContextTesting;\n\n if (!nativeContext || !nativeTesting) {\n console.error('[Web Model Context] Native API detection mismatch');\n return;\n }\n\n console.log('✅ [Web Model Context] Native Chromium API detected');\n console.log(' Using native implementation with MCP bridge synchronization');\n console.log(' Native API will automatically collect tools from embedded iframes');\n\n try {\n const bridge = initializeMCPBridge(effectiveOptions);\n\n const adapter = new NativeModelContextAdapter(bridge, nativeContext, nativeTesting);\n\n bridge.modelContext = adapter;\n bridge.modelContextTesting = nativeTesting;\n\n Object.defineProperty(window, '__mcpBridge', {\n value: bridge,\n writable: false,\n configurable: true,\n });\n\n console.log('✅ [Web Model Context] MCP bridge synced with native API');\n console.log(' MCP clients will receive automatic tool updates from native registry');\n } catch (error) {\n console.error('[Web Model Context] Failed to initialize native adapter:', error);\n throw error;\n }\n\n return;\n }\n\n if (native.hasNativeContext && !native.hasNativeTesting) {\n console.warn('[Web Model Context] Partial native API detected');\n console.warn(' navigator.modelContext exists but navigator.modelContextTesting is missing');\n console.warn(' Cannot sync with native API. Please enable experimental features:');\n console.warn(' - Navigate to chrome://flags');\n console.warn(' - Enable \"Experimental Web Platform Features\"');\n console.warn(' - Or launch with: --enable-experimental-web-platform-features');\n console.warn(' Skipping initialization to avoid conflicts');\n return;\n }\n\n if (window.navigator.modelContext) {\n console.warn(\n '[Web Model Context] window.navigator.modelContext already exists, skipping initialization'\n );\n return;\n }\n\n console.log('[Web Model Context] Native API not detected, installing polyfill');\n\n try {\n const bridge = initializeMCPBridge(effectiveOptions);\n\n Object.defineProperty(window.navigator, 'modelContext', {\n value: bridge.modelContext,\n writable: false,\n configurable: false,\n });\n\n Object.defineProperty(window, '__mcpBridge', {\n value: bridge,\n writable: false,\n configurable: true,\n });\n\n console.log('✅ [Web Model Context] window.navigator.modelContext initialized successfully');\n\n console.log('[Model Context Testing] Installing polyfill');\n console.log(' 💡 To use the native implementation in Chromium:');\n console.log(' - Navigate to chrome://flags');\n console.log(' - Enable \"Experimental Web Platform Features\"');\n console.log(' - Or launch with: --enable-experimental-web-platform-features');\n\n const testingAPI = new WebModelContextTesting(bridge);\n bridge.modelContextTesting = testingAPI;\n\n (bridge.modelContext as WebModelContext).setTestingAPI(testingAPI);\n\n Object.defineProperty(window.navigator, 'modelContextTesting', {\n value: testingAPI,\n writable: false,\n configurable: true,\n });\n\n console.log(\n '✅ [Model Context Testing] Polyfill installed at window.navigator.modelContextTesting'\n );\n } catch (error) {\n console.error('[Web Model Context] Failed to initialize:', error);\n throw error;\n }\n}\n\n/**\n * Cleans up the Web Model Context API.\n * Closes all MCP servers and removes API from window.navigator.\n * Useful for testing and hot module replacement.\n *\n * @example\n * ```typescript\n * import { cleanupWebModelContext } from '@mcp-b/global';\n *\n * cleanupWebModelContext();\n * ```\n */\nexport function cleanupWebModelContext(): void {\n if (typeof window === 'undefined') return;\n\n if (window.__mcpBridge) {\n try {\n window.__mcpBridge.tabServer.close();\n\n if (window.__mcpBridge.iframeServer) {\n window.__mcpBridge.iframeServer.close();\n }\n } catch (error) {\n console.warn('[Web Model Context] Error closing MCP servers:', error);\n }\n }\n\n delete (window.navigator as unknown as { modelContext?: unknown }).modelContext;\n delete (window.navigator as unknown as { modelContextTesting?: unknown }).modelContextTesting;\n delete (window as unknown as { __mcpBridge?: unknown }).__mcpBridge;\n\n console.log('[Web Model Context] Cleaned up');\n}\n","import { initializeWebModelContext } from './global.js';\nimport type { TransportConfiguration, WebModelContextInitOptions } from './types.js';\n\ntype TabServerConfig = NonNullable<TransportConfiguration['tabServer']>;\n\nfunction mergeTransportOptions(\n base: TransportConfiguration,\n override: TransportConfiguration\n): TransportConfiguration {\n if (!base) {\n return override;\n }\n if (!override) {\n return base;\n }\n\n return {\n ...base,\n ...override,\n tabServer: {\n ...(base.tabServer ?? {}),\n ...(override.tabServer ?? {}),\n },\n };\n}\n\nfunction mergeInitOptions(\n base?: WebModelContextInitOptions,\n override?: WebModelContextInitOptions\n): WebModelContextInitOptions | undefined {\n if (!base) {\n return override;\n }\n if (!override) {\n return base;\n }\n\n return {\n ...base,\n ...override,\n transport: mergeTransportOptions(base.transport ?? {}, override.transport ?? {}),\n };\n}\n\nfunction parseScriptTagOptions(\n script: HTMLScriptElement | null\n): WebModelContextInitOptions | undefined {\n if (!script || !script.dataset) {\n return undefined;\n }\n\n const { dataset } = script;\n\n if (dataset.webmcpOptions) {\n try {\n return JSON.parse(dataset.webmcpOptions) as WebModelContextInitOptions;\n } catch (error) {\n console.error('[Web Model Context] Invalid JSON in data-webmcp-options:', error);\n return undefined;\n }\n }\n\n const options: WebModelContextInitOptions = {};\n let hasOptions = false;\n\n if (dataset.webmcpAutoInitialize !== undefined) {\n options.autoInitialize = dataset.webmcpAutoInitialize !== 'false';\n hasOptions = true;\n }\n\n const tabServerOptions: TabServerConfig = {};\n let hasTabServerOptions = false;\n\n if (dataset.webmcpAllowedOrigins) {\n const origins = dataset.webmcpAllowedOrigins\n .split(',')\n .map((origin) => origin.trim())\n .filter((origin) => origin.length > 0);\n\n if (origins.length > 0) {\n tabServerOptions.allowedOrigins = origins;\n hasOptions = true;\n hasTabServerOptions = true;\n }\n }\n\n if (dataset.webmcpChannelId) {\n tabServerOptions.channelId = dataset.webmcpChannelId;\n hasOptions = true;\n hasTabServerOptions = true;\n }\n\n if (hasTabServerOptions) {\n options.transport = {\n ...(options.transport ?? {}),\n tabServer: {\n ...(options.transport?.tabServer ?? {}),\n ...tabServerOptions,\n },\n };\n }\n\n return hasOptions ? options : undefined;\n}\n\nif (typeof window !== 'undefined' && typeof document !== 'undefined') {\n const globalOptions = window.__webModelContextOptions;\n const scriptElement = document.currentScript as HTMLScriptElement | null;\n const scriptOptions = parseScriptTagOptions(scriptElement);\n const mergedOptions =\n mergeInitOptions(globalOptions, scriptOptions) ?? globalOptions ?? scriptOptions;\n\n if (mergedOptions) {\n window.__webModelContextOptions = mergedOptions;\n }\n\n const shouldAutoInitialize = mergedOptions?.autoInitialize !== false;\n\n try {\n if (shouldAutoInitialize) {\n initializeWebModelContext(mergedOptions);\n }\n } catch (error) {\n console.error('[Web Model Context] Auto-initialization failed:', error);\n }\n}\n\nexport { cleanupWebModelContext, initializeWebModelContext } from './global.js';\nexport type * from './types.js';\nexport { zodToJsonSchema } from './validation.js';\n"],"mappings":"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"}
|