@mcp-b/global 1.0.14 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { TabServerTransport } from "@mcp-b/transports";
1
+ import { IframeChildTransport, TabServerTransport } from "@mcp-b/transports";
2
2
  import { CallToolRequestSchema, ListToolsRequestSchema, Server } from "@mcp-b/webmcp-ts-sdk";
3
3
  import { jsonSchemaToZod } from "@composio/json-schema-to-zod";
4
4
  import { z } from "zod";
@@ -200,10 +200,7 @@ var WebModelContext = class {
200
200
  this.provideContextTools.set(tool.name, validatedTool);
201
201
  }
202
202
  this.updateBridgeTools();
203
- if (this.bridge.server.notification) this.bridge.server.notification({
204
- method: "notifications/tools/list_changed",
205
- params: {}
206
- });
203
+ this.notifyToolsListChanged();
207
204
  }
208
205
  /**
209
206
  * Register a single tool dynamically (Bucket B)
@@ -236,10 +233,7 @@ var WebModelContext = class {
236
233
  this.dynamicTools.set(tool.name, validatedTool);
237
234
  this.registrationTimestamps.set(tool.name, now);
238
235
  this.updateBridgeTools();
239
- if (this.bridge.server.notification) this.bridge.server.notification({
240
- method: "notifications/tools/list_changed",
241
- params: {}
242
- });
236
+ this.notifyToolsListChanged();
243
237
  const unregisterFn = () => {
244
238
  console.log(`[Web Model Context] Unregistering tool: ${tool.name}`);
245
239
  if (this.provideContextTools.has(tool.name)) throw new Error(`[Web Model Context] Cannot unregister tool "${tool.name}": This tool was registered via provideContext(). Use provideContext() to update the base tool set.`);
@@ -251,10 +245,7 @@ var WebModelContext = class {
251
245
  this.registrationTimestamps.delete(tool.name);
252
246
  this.unregisterFunctions.delete(tool.name);
253
247
  this.updateBridgeTools();
254
- if (this.bridge.server.notification) this.bridge.server.notification({
255
- method: "notifications/tools/list_changed",
256
- params: {}
257
- });
248
+ this.notifyToolsListChanged();
258
249
  };
259
250
  this.unregisterFunctions.set(tool.name, unregisterFn);
260
251
  return { unregister: unregisterFn };
@@ -270,6 +261,19 @@ var WebModelContext = class {
270
261
  console.log(`[Web Model Context] Updated bridge with ${this.provideContextTools.size} base tools + ${this.dynamicTools.size} dynamic tools = ${this.bridge.tools.size} total`);
271
262
  }
272
263
  /**
264
+ * Notify all servers that the tools list has changed
265
+ */
266
+ notifyToolsListChanged() {
267
+ if (this.bridge.tabServer.notification) this.bridge.tabServer.notification({
268
+ method: "notifications/tools/list_changed",
269
+ params: {}
270
+ });
271
+ if (this.bridge.iframeServer?.notification) this.bridge.iframeServer.notification({
272
+ method: "notifications/tools/list_changed",
273
+ params: {}
274
+ });
275
+ }
276
+ /**
273
277
  * Execute a tool with hybrid approach:
274
278
  * 1. Validate input arguments
275
279
  * 2. Dispatch toolcall event first
@@ -335,59 +339,111 @@ var WebModelContext = class {
335
339
  }
336
340
  };
337
341
  /**
338
- * Initialize the MCP bridge
342
+ * Initialize the MCP bridge with dual-server support
343
+ * Creates both TabServer (same-window) and IframeChildServer (parent-child) by default
339
344
  */
340
- function initializeMCPBridge() {
345
+ function initializeMCPBridge(options) {
341
346
  console.log("[Web Model Context] Initializing MCP bridge");
342
- const server = new Server({
343
- name: window.location.hostname || "localhost",
347
+ const hostname = window.location.hostname || "localhost";
348
+ const transportOptions = options?.transport;
349
+ const setupServerHandlers = (server, bridge$1) => {
350
+ server.setRequestHandler(ListToolsRequestSchema, async () => {
351
+ console.log("[MCP Bridge] Handling list_tools request");
352
+ return { tools: bridge$1.modelContext.listTools() };
353
+ });
354
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
355
+ console.log(`[MCP Bridge] Handling call_tool request: ${request.params.name}`);
356
+ const toolName = request.params.name;
357
+ const args = request.params.arguments || {};
358
+ try {
359
+ const response = await bridge$1.modelContext.executeTool(toolName, args);
360
+ return {
361
+ content: response.content,
362
+ isError: response.isError
363
+ };
364
+ } catch (error) {
365
+ console.error(`[MCP Bridge] Error calling tool ${toolName}:`, error);
366
+ throw error;
367
+ }
368
+ });
369
+ };
370
+ const customTransport = transportOptions?.create?.();
371
+ if (customTransport) {
372
+ console.log("[Web Model Context] Using custom transport");
373
+ const server = new Server({
374
+ name: hostname,
375
+ version: "1.0.0"
376
+ }, { capabilities: { tools: { listChanged: true } } });
377
+ const bridge$1 = {
378
+ tabServer: server,
379
+ tools: /* @__PURE__ */ new Map(),
380
+ modelContext: void 0,
381
+ isInitialized: true
382
+ };
383
+ bridge$1.modelContext = new WebModelContext(bridge$1);
384
+ setupServerHandlers(server, bridge$1);
385
+ server.connect(customTransport);
386
+ console.log("[Web Model Context] MCP server connected with custom transport");
387
+ return bridge$1;
388
+ }
389
+ console.log("[Web Model Context] Using dual-server mode");
390
+ const tabServerEnabled = transportOptions?.tabServer !== false;
391
+ const tabServer = new Server({
392
+ name: `${hostname}-tab`,
344
393
  version: "1.0.0"
345
394
  }, { capabilities: { tools: { listChanged: true } } });
346
395
  const bridge = {
347
- server,
396
+ tabServer,
348
397
  tools: /* @__PURE__ */ new Map(),
349
398
  modelContext: void 0,
350
399
  isInitialized: true
351
400
  };
352
401
  bridge.modelContext = new WebModelContext(bridge);
353
- server.setRequestHandler(ListToolsRequestSchema, async () => {
354
- console.log("[MCP Bridge] Handling list_tools request");
355
- return { tools: bridge.modelContext.listTools() };
356
- });
357
- server.setRequestHandler(CallToolRequestSchema, async (request) => {
358
- console.log(`[MCP Bridge] Handling call_tool request: ${request.params.name}`);
359
- const toolName = request.params.name;
360
- const args = request.params.arguments || {};
361
- try {
362
- const response = await bridge.modelContext.executeTool(toolName, args);
363
- return {
364
- content: response.content,
365
- isError: response.isError
366
- };
367
- } catch (error) {
368
- console.error(`[MCP Bridge] Error calling tool ${toolName}:`, error);
369
- throw error;
370
- }
371
- });
372
- const transport = new TabServerTransport({ allowedOrigins: ["*"] });
373
- server.connect(transport);
374
- console.log("[Web Model Context] MCP server connected");
402
+ setupServerHandlers(tabServer, bridge);
403
+ if (tabServerEnabled) {
404
+ const { allowedOrigins,...restTabServerOptions } = typeof transportOptions?.tabServer === "object" ? transportOptions.tabServer : {};
405
+ const tabTransport = new TabServerTransport({
406
+ allowedOrigins: allowedOrigins ?? ["*"],
407
+ ...restTabServerOptions
408
+ });
409
+ tabServer.connect(tabTransport);
410
+ console.log("[Web Model Context] Tab server connected");
411
+ }
412
+ const isInIframe = typeof window !== "undefined" && window.parent !== window;
413
+ const iframeServerConfig = transportOptions?.iframeServer;
414
+ if (iframeServerConfig !== false && (iframeServerConfig !== void 0 || isInIframe)) {
415
+ console.log("[Web Model Context] Enabling iframe server");
416
+ const iframeServer = new Server({
417
+ name: `${hostname}-iframe`,
418
+ version: "1.0.0"
419
+ }, { capabilities: { tools: { listChanged: true } } });
420
+ setupServerHandlers(iframeServer, bridge);
421
+ const { allowedOrigins,...restIframeServerOptions } = typeof iframeServerConfig === "object" ? iframeServerConfig : {};
422
+ const iframeTransport = new IframeChildTransport({
423
+ allowedOrigins: allowedOrigins ?? ["*"],
424
+ ...restIframeServerOptions
425
+ });
426
+ iframeServer.connect(iframeTransport);
427
+ bridge.iframeServer = iframeServer;
428
+ console.log("[Web Model Context] Iframe server connected");
429
+ }
375
430
  return bridge;
376
431
  }
377
432
  /**
378
433
  * Initialize the Web Model Context API (window.navigator.modelContext)
379
434
  */
380
- function initializeWebModelContext() {
435
+ function initializeWebModelContext(options) {
381
436
  if (typeof window === "undefined") {
382
437
  console.warn("[Web Model Context] Not in browser environment, skipping initialization");
383
438
  return;
384
439
  }
440
+ const effectiveOptions = options ?? window.__webModelContextOptions;
385
441
  if (window.navigator.modelContext) {
386
442
  console.warn("[Web Model Context] window.navigator.modelContext already exists, skipping initialization");
387
443
  return;
388
444
  }
389
445
  try {
390
- const bridge = initializeMCPBridge();
446
+ const bridge = initializeMCPBridge(effectiveOptions);
391
447
  Object.defineProperty(window.navigator, "modelContext", {
392
448
  value: bridge.modelContext,
393
449
  writable: false,
@@ -410,9 +466,10 @@ function initializeWebModelContext() {
410
466
  function cleanupWebModelContext() {
411
467
  if (typeof window === "undefined") return;
412
468
  if (window.__mcpBridge) try {
413
- window.__mcpBridge.server.close();
469
+ window.__mcpBridge.tabServer.close();
470
+ if (window.__mcpBridge.iframeServer) window.__mcpBridge.iframeServer.close();
414
471
  } catch (error) {
415
- console.warn("[Web Model Context] Error closing MCP server:", error);
472
+ console.warn("[Web Model Context] Error closing MCP servers:", error);
416
473
  }
417
474
  delete window.navigator.modelContext;
418
475
  delete window.__mcpBridge;
@@ -421,10 +478,78 @@ function cleanupWebModelContext() {
421
478
 
422
479
  //#endregion
423
480
  //#region src/index.ts
424
- if (typeof window !== "undefined" && typeof document !== "undefined") try {
425
- initializeWebModelContext();
426
- } catch (error) {
427
- console.error("[Web Model Context] Auto-initialization failed:", error);
481
+ function mergeTransportOptions(base, override) {
482
+ if (!base) return override;
483
+ if (!override) return base;
484
+ return {
485
+ ...base,
486
+ ...override,
487
+ tabServer: {
488
+ ...base.tabServer ?? {},
489
+ ...override.tabServer ?? {}
490
+ }
491
+ };
492
+ }
493
+ function mergeInitOptions(base, override) {
494
+ if (!base) return override;
495
+ if (!override) return base;
496
+ return {
497
+ ...base,
498
+ ...override,
499
+ transport: mergeTransportOptions(base.transport ?? {}, override.transport ?? {})
500
+ };
501
+ }
502
+ function parseScriptTagOptions(script) {
503
+ if (!script || !script.dataset) return;
504
+ const { dataset } = script;
505
+ if (dataset.webmcpOptions) try {
506
+ return JSON.parse(dataset.webmcpOptions);
507
+ } catch (error) {
508
+ console.error("[Web Model Context] Invalid JSON in data-webmcp-options:", error);
509
+ return;
510
+ }
511
+ const options = {};
512
+ let hasOptions = false;
513
+ if (dataset.webmcpAutoInitialize !== void 0) {
514
+ options.autoInitialize = dataset.webmcpAutoInitialize !== "false";
515
+ hasOptions = true;
516
+ }
517
+ const tabServerOptions = {};
518
+ let hasTabServerOptions = false;
519
+ if (dataset.webmcpAllowedOrigins) {
520
+ const origins = dataset.webmcpAllowedOrigins.split(",").map((origin) => origin.trim()).filter((origin) => origin.length > 0);
521
+ if (origins.length > 0) {
522
+ tabServerOptions.allowedOrigins = origins;
523
+ hasOptions = true;
524
+ hasTabServerOptions = true;
525
+ }
526
+ }
527
+ if (dataset.webmcpChannelId) {
528
+ tabServerOptions.channelId = dataset.webmcpChannelId;
529
+ hasOptions = true;
530
+ hasTabServerOptions = true;
531
+ }
532
+ if (hasTabServerOptions) options.transport = {
533
+ ...options.transport ?? {},
534
+ tabServer: {
535
+ ...options.transport?.tabServer ?? {},
536
+ ...tabServerOptions
537
+ }
538
+ };
539
+ return hasOptions ? options : void 0;
540
+ }
541
+ if (typeof window !== "undefined" && typeof document !== "undefined") {
542
+ const globalOptions = window.__webModelContextOptions;
543
+ const scriptElement = document.currentScript;
544
+ const scriptOptions = parseScriptTagOptions(scriptElement);
545
+ const mergedOptions = mergeInitOptions(globalOptions, scriptOptions) ?? globalOptions ?? scriptOptions;
546
+ if (mergedOptions) window.__webModelContextOptions = mergedOptions;
547
+ const shouldAutoInitialize = mergedOptions?.autoInitialize !== false;
548
+ try {
549
+ if (shouldAutoInitialize) initializeWebModelContext(mergedOptions);
550
+ } catch (error) {
551
+ console.error("[Web Model Context] Auto-initialization failed:", error);
552
+ }
428
553
  }
429
554
 
430
555
  //#endregion
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","McpServer","bridge: MCPBridge"],"sources":["../src/validation.ts","../src/global.ts","../src/index.ts"],"sourcesContent":["// validation.ts - JSON Schema <-> Zod conversion and validation utilities\n\nimport { 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 // JSON Schema always has a 'type' property at the root\n if ('type' in schema && typeof (schema as { type: unknown }).type === 'string') {\n return false; // This is JSON Schema\n }\n\n // Check if any property value is a Zod type instance\n const values = Object.values(schema);\n if (values.length === 0) {\n return false; // Empty object, treat as JSON Schema\n }\n\n // If any value is a ZodType, it's a Zod schema\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 // convertJsonSchemaToZod returns a Zod schema from JSON Schema\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 // Fallback: accept anything with passthrough\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 // Extract description if available\n const description = (zodType as { description?: string }).description || undefined;\n\n // Infer JSON Schema type from Zod type\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 // Try to get array item type\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 // Extract enum values\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 // Check if field is required (not optional)\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 // Input is Zod schema object → convert to JSON Schema and wrap in z.object()\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 // Input is JSON Schema → convert to Zod\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 // Format Zod errors into readable message\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","// global.ts - Web Model Context API Implementation\n// Bridges the Web Model Context API (window.navigator.modelContext) to MCP SDK\n\nimport { TabServerTransport } from '@mcp-b/transports';\nimport {\n CallToolRequestSchema,\n ListToolsRequestSchema,\n Server as McpServer,\n} from '@mcp-b/webmcp-ts-sdk';\nimport type {\n InternalModelContext,\n MCPBridge,\n ModelContextInput,\n ToolCallEvent,\n ToolDescriptor,\n ToolResponse,\n ValidatedToolDescriptor,\n} from './types.js';\nimport { normalizeSchema, validateWithZod } from './validation.js';\n\n/**\n * Custom ToolCallEvent implementation\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 constructor(toolName: string, args: Record<string, unknown>) {\n super('toolcall', { cancelable: true });\n this.name = toolName;\n this.arguments = args;\n }\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 getResponse(): ToolResponse | null {\n return this._response;\n }\n\n hasResponse(): boolean {\n return this._responded;\n }\n}\n\n/**\n * Time window (in ms) to detect rapid duplicate registrations\n * Registrations within this window are likely due to React Strict Mode\n */\nconst RAPID_DUPLICATE_WINDOW_MS = 50;\n\n/**\n * ModelContext implementation that bridges to MCP SDK\n * Implements the W3C Web Model Context API proposal with two-bucket tool management\n *\n * Two-Bucket System:\n * - Bucket A (provideContextTools): Tools registered via provideContext() - base/app-level tools\n * - Bucket B (dynamicTools): Tools registered via registerTool() - component-scoped tools\n *\n * Benefits:\n * - provideContext() only clears Bucket A, leaving Bucket B intact\n * - Components can manage their own tool lifecycle independently\n * - Final tool list = Bucket A + Bucket B (merged, with collision detection)\n */\nclass WebModelContext implements InternalModelContext {\n private bridge: MCPBridge;\n private eventTarget: EventTarget;\n\n // Bucket A: Tools from provideContext() - cleared when provideContext is called again\n private provideContextTools: Map<string, ValidatedToolDescriptor>;\n\n // Bucket B: Tools from registerTool() - persist across provideContext calls\n private dynamicTools: Map<string, ValidatedToolDescriptor>;\n\n // Track registration timestamps for rapid duplicate detection (React Strict Mode)\n private registrationTimestamps: Map<string, number>;\n\n // Store unregister functions for returning on rapid duplicates\n private unregisterFunctions: Map<string, () => void>;\n\n constructor(bridge: MCPBridge) {\n this.bridge = bridge;\n this.eventTarget = new EventTarget();\n this.provideContextTools = new Map();\n this.dynamicTools = new Map();\n this.registrationTimestamps = new Map();\n this.unregisterFunctions = new Map();\n }\n\n /**\n * Add event listener (compatible with ModelContext interface)\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 * Remove event listener\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 * Dispatch event\n */\n dispatchEvent(event: Event): boolean {\n return this.eventTarget.dispatchEvent(event);\n }\n\n /**\n * Provide context (tools) to AI models\n * Clears and replaces Bucket A (provideContext tools), leaving Bucket B (dynamic tools) intact\n */\n provideContext(context: ModelContextInput): void {\n console.log(`[Web Model Context] Registering ${context.tools.length} tools via provideContext`);\n\n // Clear only Bucket A (provideContext tools)\n this.provideContextTools.clear();\n\n // Process each tool: normalize schemas and create validated descriptors\n for (const tool of context.tools) {\n // Check for name collisions with Bucket B (dynamic 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 // Normalize input schema (convert to both JSON Schema and Zod)\n const { jsonSchema: inputJson, zodValidator: inputZod } = normalizeSchema(tool.inputSchema);\n\n // Normalize output schema if provided\n const normalizedOutput = tool.outputSchema ? normalizeSchema(tool.outputSchema) : null;\n\n // Create validated tool descriptor\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 // Add to Bucket A\n this.provideContextTools.set(tool.name, validatedTool);\n }\n\n // Update the merged tool list in bridge\n this.updateBridgeTools();\n\n // Notify that tools list changed\n if (this.bridge.server.notification) {\n this.bridge.server.notification({\n method: 'notifications/tools/list_changed',\n params: {},\n });\n }\n }\n\n /**\n * Register a single tool dynamically (Bucket B)\n * Returns an object with an unregister function to remove the tool\n * Tools registered via this method persist across provideContext() calls\n */\n registerTool(tool: ToolDescriptor<any, any>): { unregister: () => void } {\n console.log(`[Web Model Context] Registering tool dynamically: ${tool.name}`);\n\n // Check for rapid duplicate registration (React Strict Mode detection)\n const now = Date.now();\n const lastRegistration = this.registrationTimestamps.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 // Return the existing unregister function\n const existingUnregister = this.unregisterFunctions.get(tool.name);\n if (existingUnregister) {\n return { unregister: existingUnregister };\n }\n }\n\n // Check for name collision with Bucket A (provideContext tools)\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 // Check for name collision within Bucket B (genuine duplicate, not rapid)\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 // Normalize input schema (convert to both JSON Schema and Zod)\n const { jsonSchema: inputJson, zodValidator: inputZod } = normalizeSchema(tool.inputSchema);\n\n // Normalize output schema if provided\n const normalizedOutput = tool.outputSchema ? normalizeSchema(tool.outputSchema) : null;\n\n // Create validated tool descriptor\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 // Add to Bucket B (dynamic tools)\n this.dynamicTools.set(tool.name, validatedTool);\n\n // Store registration timestamp for rapid duplicate detection\n this.registrationTimestamps.set(tool.name, now);\n\n // Update the merged tool list in bridge\n this.updateBridgeTools();\n\n // Notify that tools list changed\n if (this.bridge.server.notification) {\n this.bridge.server.notification({\n method: 'notifications/tools/list_changed',\n params: {},\n });\n }\n\n // Create unregister function\n const unregisterFn = () => {\n console.log(`[Web Model Context] Unregistering tool: ${tool.name}`);\n\n // Check if this tool was registered via provideContext\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 // Remove from Bucket B\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\n // Clean up tracking data\n this.registrationTimestamps.delete(tool.name);\n this.unregisterFunctions.delete(tool.name);\n\n // Update the merged tool list in bridge\n this.updateBridgeTools();\n\n // Notify that tools list changed\n if (this.bridge.server.notification) {\n this.bridge.server.notification({\n method: 'notifications/tools/list_changed',\n params: {},\n });\n }\n };\n\n // Store unregister function for rapid duplicate detection\n this.unregisterFunctions.set(tool.name, unregisterFn);\n\n // Return unregister function\n return { unregister: unregisterFn };\n }\n\n /**\n * Update the bridge tools map with merged tools from both buckets\n * Final tool list = Bucket A (provideContext) + Bucket B (dynamic)\n */\n private updateBridgeTools(): void {\n // Clear the bridge tools map\n this.bridge.tools.clear();\n\n // Add tools from Bucket A (provideContext tools)\n for (const [name, tool] of this.provideContextTools) {\n this.bridge.tools.set(name, tool);\n }\n\n // Add tools from Bucket B (dynamic tools)\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 * Execute a tool with hybrid approach:\n * 1. Validate input arguments\n * 2. Dispatch toolcall event first\n * 3. If not prevented, call tool's execute function\n * 4. Validate output (permissive mode - warn only)\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 // 1. VALIDATE INPUT ARGUMENTS\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 // Use validated data for execution\n const validatedArgs = validation.data as Record<string, unknown>;\n\n // 2. Create toolcall event\n const event = new WebToolCallEvent(toolName, validatedArgs);\n\n // Dispatch event to listeners\n this.dispatchEvent(event);\n\n // If event was prevented and response provided, use that\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 // 3. Execute the tool's execute function\n console.log(`[Web Model Context] Executing tool: ${toolName}`);\n try {\n const response = await tool.execute(validatedArgs);\n\n // 4. VALIDATE OUTPUT (permissive mode - warn only, don't block)\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 // Continue anyway - permissive mode\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 * Get list of registered tools in MCP format\n * Includes full MCP spec: annotations, outputSchema, etc.\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\n/**\n * Initialize the MCP bridge\n */\nfunction initializeMCPBridge(): MCPBridge {\n console.log('[Web Model Context] Initializing MCP bridge');\n\n const hostname = window.location.hostname || 'localhost';\n\n // Create MCP server\n const server = new McpServer(\n {\n name: hostname,\n version: '1.0.0',\n },\n {\n capabilities: {\n tools: {\n listChanged: true,\n },\n },\n }\n );\n\n // Create bridge object (modelContext is assigned after instantiation)\n const bridge: MCPBridge = {\n server,\n tools: new Map(),\n modelContext: undefined as unknown as InternalModelContext,\n isInitialized: true,\n };\n\n // Create modelContext and attach to bridge\n const modelContext = new WebModelContext(bridge);\n bridge.modelContext = modelContext;\n\n // Set up MCP server 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 in MCP SDK format\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 // Connect transport\n const transport = new TabServerTransport({\n allowedOrigins: ['*'], // TODO: Make this configurable\n });\n\n server.connect(transport);\n\n console.log('[Web Model Context] MCP server connected');\n\n return bridge;\n}\n\n/**\n * Initialize the Web Model Context API (window.navigator.modelContext)\n */\nexport function initializeWebModelContext(): void {\n if (typeof window === 'undefined') {\n console.warn('[Web Model Context] Not in browser environment, skipping initialization');\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 try {\n // Initialize MCP bridge\n const bridge = initializeMCPBridge();\n\n // Expose shared modelContext instance\n Object.defineProperty(window.navigator, 'modelContext', {\n value: bridge.modelContext,\n writable: false,\n configurable: false,\n });\n\n // Expose bridge for debugging\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 } catch (error) {\n console.error('[Web Model Context] Failed to initialize:', error);\n throw error;\n }\n}\n\n/**\n * Cleanup function (for testing/development)\n */\nexport function cleanupWebModelContext(): void {\n if (typeof window === 'undefined') return;\n\n if (window.__mcpBridge) {\n try {\n window.__mcpBridge.server.close();\n } catch (error) {\n console.warn('[Web Model Context] Error closing MCP server:', error);\n }\n }\n\n delete (window.navigator as unknown as { modelContext?: unknown }).modelContext;\n delete (window as unknown as { __mcpBridge?: unknown }).__mcpBridge;\n\n console.log('[Web Model Context] Cleaned up');\n}\n","// index.ts - Entry point for Web Model Context API polyfill\n\nimport { initializeWebModelContext } from './global.js';\n\n// Auto-initialize immediately when script loads in browser environments\nif (typeof window !== 'undefined' && typeof document !== 'undefined') {\n try {\n initializeWebModelContext();\n } catch (error) {\n console.error('[Web Model Context] Auto-initialization failed:', error);\n }\n}\n\n// For manual initialization (when using as ES module)\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","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","bridge","customTransport: Transport | undefined","McpServer","bridge: MCPBridge","options: WebModelContextInitOptions","tabServerOptions: TabServerConfig"],"sources":["../src/validation.ts","../src/global.ts","../src/index.ts"],"sourcesContent":["// validation.ts - JSON Schema <-> Zod conversion and validation utilities\n\nimport { 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 // JSON Schema always has a 'type' property at the root\n if ('type' in schema && typeof (schema as { type: unknown }).type === 'string') {\n return false; // This is JSON Schema\n }\n\n // Check if any property value is a Zod type instance\n const values = Object.values(schema);\n if (values.length === 0) {\n return false; // Empty object, treat as JSON Schema\n }\n\n // If any value is a ZodType, it's a Zod schema\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 // convertJsonSchemaToZod returns a Zod schema from JSON Schema\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 // Fallback: accept anything with passthrough\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 // Extract description if available\n const description = (zodType as { description?: string }).description || undefined;\n\n // Infer JSON Schema type from Zod type\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 // Try to get array item type\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 // Extract enum values\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 // Check if field is required (not optional)\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 // Input is Zod schema object → convert to JSON Schema and wrap in z.object()\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 // Input is JSON Schema → convert to Zod\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 // Format Zod errors into readable message\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 { Transport } from '@mcp-b/webmcp-ts-sdk';\nimport {\n CallToolRequestSchema,\n ListToolsRequestSchema,\n Server as McpServer,\n} from '@mcp-b/webmcp-ts-sdk';\nimport type {\n InternalModelContext,\n MCPBridge,\n ModelContextInput,\n ToolCallEvent,\n ToolDescriptor,\n ToolResponse,\n ValidatedToolDescriptor,\n WebModelContextInitOptions,\n} from './types.js';\nimport { normalizeSchema, validateWithZod } from './validation.js';\n\ndeclare global {\n interface Window {\n __webModelContextOptions?: WebModelContextInitOptions;\n }\n}\n\n/**\n * Custom ToolCallEvent implementation\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 constructor(toolName: string, args: Record<string, unknown>) {\n super('toolcall', { cancelable: true });\n this.name = toolName;\n this.arguments = args;\n }\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 getResponse(): ToolResponse | null {\n return this._response;\n }\n\n hasResponse(): boolean {\n return this._responded;\n }\n}\n\n/**\n * Time window (in ms) to detect rapid duplicate registrations\n * Registrations within this window are likely due to React Strict Mode\n */\nconst RAPID_DUPLICATE_WINDOW_MS = 50;\n\n/**\n * ModelContext implementation that bridges to MCP SDK\n * Implements the W3C Web Model Context API proposal with two-bucket tool management\n *\n * Two-Bucket System:\n * - Bucket A (provideContextTools): Tools registered via provideContext() - base/app-level tools\n * - Bucket B (dynamicTools): Tools registered via registerTool() - component-scoped tools\n *\n * Benefits:\n * - provideContext() only clears Bucket A, leaving Bucket B intact\n * - Components can manage their own tool lifecycle independently\n * - Final tool list = Bucket A + Bucket B (merged, with collision detection)\n */\nclass WebModelContext implements InternalModelContext {\n private bridge: MCPBridge;\n private eventTarget: EventTarget;\n private provideContextTools: Map<string, ValidatedToolDescriptor>;\n private dynamicTools: Map<string, ValidatedToolDescriptor>;\n private registrationTimestamps: Map<string, number>;\n private unregisterFunctions: Map<string, () => void>;\n\n constructor(bridge: MCPBridge) {\n this.bridge = bridge;\n this.eventTarget = new EventTarget();\n this.provideContextTools = new Map();\n this.dynamicTools = new Map();\n this.registrationTimestamps = new Map();\n this.unregisterFunctions = new Map();\n }\n\n /**\n * Add event listener (compatible with ModelContext interface)\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 * Remove event listener\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 * Dispatch event\n */\n dispatchEvent(event: Event): boolean {\n return this.eventTarget.dispatchEvent(event);\n }\n\n /**\n * Provide context (tools) to AI models\n * Clears and replaces Bucket A (provideContext tools), leaving Bucket B (dynamic tools) intact\n */\n provideContext(context: ModelContextInput): void {\n console.log(`[Web Model Context] Registering ${context.tools.length} tools via provideContext`);\n\n this.provideContextTools.clear();\n\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\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 this.updateBridgeTools();\n\n this.notifyToolsListChanged();\n }\n\n /**\n * Register a single tool dynamically (Bucket B)\n * Returns an object with an unregister function to remove the tool\n * Tools registered via this method persist across provideContext() calls\n */\n registerTool(tool: ToolDescriptor<any, any>): { unregister: () => void } {\n console.log(`[Web Model Context] Registering tool dynamically: ${tool.name}`);\n\n const now = Date.now();\n const lastRegistration = this.registrationTimestamps.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.unregisterFunctions.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,\n inputValidator: inputZod,\n ...(normalizedOutput && { outputValidator: normalizedOutput.zodValidator }),\n };\n\n this.dynamicTools.set(tool.name, validatedTool);\n\n this.registrationTimestamps.set(tool.name, now);\n\n this.updateBridgeTools();\n\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\n this.registrationTimestamps.delete(tool.name);\n this.unregisterFunctions.delete(tool.name);\n\n this.updateBridgeTools();\n\n this.notifyToolsListChanged();\n };\n\n this.unregisterFunctions.set(tool.name, unregisterFn);\n\n return { unregister: unregisterFn };\n }\n\n /**\n * Update the bridge tools map with merged tools from both buckets\n * Final tool list = Bucket A (provideContext) + Bucket B (dynamic)\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 * Notify all servers that the tools list has changed\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\n /**\n * Execute a tool with hybrid approach:\n * 1. Validate input arguments\n * 2. Dispatch toolcall event first\n * 3. If not prevented, call tool's execute function\n * 4. Validate output (permissive mode - warn only)\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 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 * Get list of registered tools in MCP format\n * Includes full MCP spec: annotations, outputSchema, etc.\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\n/**\n * Initialize the MCP bridge with dual-server support\n * Creates both TabServer (same-window) and IframeChildServer (parent-child) by default\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 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 in MCP SDK format\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\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: {\n listChanged: true,\n },\n },\n }\n );\n\n const bridge: MCPBridge = {\n tabServer: server,\n tools: 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: {\n listChanged: true,\n },\n },\n }\n );\n\n // Create bridge object (modelContext is assigned after instantiation)\n const bridge: MCPBridge = {\n tabServer,\n tools: new Map(),\n modelContext: undefined as unknown as InternalModelContext,\n isInitialized: true,\n };\n\n // Create modelContext and attach to bridge\n const modelContext = new WebModelContext(bridge);\n bridge.modelContext = modelContext;\n\n // Set up handlers for tab server\n setupServerHandlers(tabServer, bridge);\n\n // Connect tab server transport\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: {\n listChanged: true,\n },\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 * Initialize the Web Model Context API (window.navigator.modelContext)\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\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 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 } catch (error) {\n console.error('[Web Model Context] Failed to initialize:', error);\n throw error;\n }\n}\n\n/**\n * Cleanup function (for testing/development)\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 as unknown as { __mcpBridge?: unknown }).__mcpBridge;\n\n console.log('[Web Model Context] Cleaned up');\n}\n","// index.ts - Entry point for Web Model Context API polyfill\n\nimport { 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\n// Auto-initialize immediately when script loads in browser environments\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\n// For manual initialization (when using as ES module)\nexport { cleanupWebModelContext, initializeWebModelContext } from './global.js';\nexport type * from './types.js';\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mcp-b/global",
3
- "version": "1.0.14",
3
+ "version": "1.1.0",
4
4
  "description": "W3C Web Model Context API polyfill - implements window.navigator.modelContext bridging to Model Context Protocol",
5
5
  "keywords": [
6
6
  "mcp",
@@ -47,12 +47,12 @@
47
47
  ],
48
48
  "dependencies": {
49
49
  "@composio/json-schema-to-zod": "^0.1.17",
50
- "zod": "^3.25.76",
51
- "@mcp-b/transports": "1.0.3",
50
+ "zod": "3.25.76",
51
+ "@mcp-b/transports": "1.1.0",
52
52
  "@mcp-b/webmcp-ts-sdk": "1.0.1"
53
53
  },
54
54
  "devDependencies": {
55
- "@types/node": "^22.15.21",
55
+ "@types/node": "22.17.2",
56
56
  "tsdown": "^0.15.10",
57
57
  "typescript": "^5.8.3"
58
58
  },