@mcp-b/global 0.0.0-beta-20260109203913 → 0.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -4,7 +4,90 @@ import { jsonSchemaToZod } from "@composio/json-schema-to-zod";
4
4
  import { z } from "zod";
5
5
  import { zodToJsonSchema as zodToJsonSchema$1 } from "zod-to-json-schema";
6
6
 
7
+ //#region src/logger.ts
8
+ /**
9
+ * @license
10
+ * Copyright 2025 Google LLC
11
+ * SPDX-License-Identifier: Apache-2.0
12
+ */
13
+ /**
14
+ * Lightweight logging system for @mcp-b/global
15
+ *
16
+ * Design Decision: This implements a custom logger instead of using the 'debug'
17
+ * package to reduce bundle size and eliminate external dependencies in the
18
+ * browser build. The API is intentionally simpler, focusing on the specific
19
+ * needs of browser-based MCP implementations.
20
+ *
21
+ * Configuration via localStorage:
22
+ * - localStorage.setItem('WEBMCP_DEBUG', '*') - enable all debug logging
23
+ * - localStorage.setItem('WEBMCP_DEBUG', 'WebModelContext') - enable specific namespace
24
+ * - localStorage.setItem('WEBMCP_DEBUG', 'WebModelContext,NativeAdapter') - multiple namespaces
25
+ * - localStorage.setItem('WEBMCP_DEBUG', 'WebModelContext:') - enable namespace and sub-namespaces
26
+ * - localStorage.removeItem('WEBMCP_DEBUG') - disable debug logging (default)
27
+ *
28
+ * Environment Support:
29
+ * - Automatically detects localStorage availability
30
+ * - Gracefully degrades to "disabled" state when localStorage is inaccessible
31
+ * - Never throws errors from configuration checks (safe for private browsing mode)
32
+ */
33
+ /** localStorage key for debug configuration */
34
+ const DEBUG_CONFIG_KEY = "WEBMCP_DEBUG";
35
+ /**
36
+ * Check if debug logging is enabled for a namespace
37
+ *
38
+ * Supports namespace hierarchy via colons. Setting 'WebModelContext' will match
39
+ * both 'WebModelContext' and 'WebModelContext:init', but NOT 'WebModelContextTesting'.
40
+ */
41
+ function isDebugEnabled(namespace) {
42
+ if (typeof window === "undefined" || !window.localStorage) return false;
43
+ try {
44
+ const debugConfig = localStorage.getItem(DEBUG_CONFIG_KEY);
45
+ if (!debugConfig) return false;
46
+ if (debugConfig === "*") return true;
47
+ return debugConfig.split(",").map((p) => p.trim()).some((pattern) => namespace === pattern || namespace.startsWith(`${pattern}:`));
48
+ } catch {
49
+ return false;
50
+ }
51
+ }
52
+ /**
53
+ * No-op function for disabled log levels
54
+ */
55
+ const noop = () => {};
56
+ /**
57
+ * Create a namespaced logger
58
+ *
59
+ * Uses .bind() to prepend namespace prefixes to console methods without manual
60
+ * string concatenation. Debug enablement is determined at logger creation time
61
+ * for performance - changes to localStorage after creation won't affect existing
62
+ * loggers. Refresh the page to apply new WEBMCP_DEBUG settings.
63
+ *
64
+ * @param namespace - Namespace for the logger (e.g., 'WebModelContext', 'NativeAdapter')
65
+ * @returns Logger instance with debug, info, warn, error methods
66
+ *
67
+ * @example
68
+ * ```typescript
69
+ * const logger = createLogger('WebModelContext');
70
+ * logger.debug('Tool registered:', toolName); // Only shown if WEBMCP_DEBUG includes 'WebModelContext'
71
+ * logger.error('Execution failed:', error); // Always enabled
72
+ * ```
73
+ */
74
+ function createLogger(namespace) {
75
+ const prefix = `[${namespace}]`;
76
+ const isDebug = isDebugEnabled(namespace);
77
+ const boundWarn = console.warn.bind(console, prefix);
78
+ const boundError = console.error.bind(console, prefix);
79
+ const boundLog = console.log.bind(console, prefix);
80
+ return {
81
+ warn: boundWarn,
82
+ error: boundError,
83
+ debug: isDebug ? boundLog : noop,
84
+ info: isDebug ? boundLog : noop
85
+ };
86
+ }
87
+
88
+ //#endregion
7
89
  //#region src/validation.ts
90
+ const logger$2 = createLogger("WebModelContext");
8
91
  /**
9
92
  * Detect if a schema is a Zod schema object (Record<string, ZodType>)
10
93
  * or a JSON Schema object
@@ -24,7 +107,7 @@ function jsonSchemaToZod$1(jsonSchema) {
24
107
  try {
25
108
  return jsonSchemaToZod(jsonSchema);
26
109
  } catch (error) {
27
- console.warn("[Web Model Context] Failed to convert JSON Schema to Zod:", error);
110
+ logger$2.warn("Failed to convert JSON Schema to Zod:", error);
28
111
  return z.object({}).passthrough();
29
112
  }
30
113
  }
@@ -74,6 +157,10 @@ function validateWithZod(data, validator) {
74
157
 
75
158
  //#endregion
76
159
  //#region src/global.ts
160
+ const logger$1 = createLogger("WebModelContext");
161
+ const nativeLogger = createLogger("NativeAdapter");
162
+ const bridgeLogger = createLogger("MCPBridge");
163
+ const testingLogger = createLogger("ModelContextTesting");
77
164
  /**
78
165
  * Marker property name used to identify polyfill implementations.
79
166
  * This constant ensures single source of truth for the marker used in
@@ -142,7 +229,6 @@ var NativeModelContextAdapter = class {
142
229
  this.nativeContext = nativeContext;
143
230
  this.nativeTesting = nativeTesting;
144
231
  this.nativeTesting.registerToolsChangedCallback(() => {
145
- console.log("[Native Adapter] Tool change detected from native API");
146
232
  this.syncToolsFromNative();
147
233
  });
148
234
  this.syncToolsFromNative();
@@ -159,7 +245,6 @@ var NativeModelContextAdapter = class {
159
245
  this.syncInProgress = true;
160
246
  try {
161
247
  const nativeTools = this.nativeTesting.listTools();
162
- console.log(`[Native Adapter] Syncing ${nativeTools.length} tools from native API`);
163
248
  this.bridge.tools.clear();
164
249
  for (const toolInfo of nativeTools) try {
165
250
  const inputSchema = JSON.parse(toolInfo.inputSchema);
@@ -175,7 +260,7 @@ var NativeModelContextAdapter = class {
175
260
  };
176
261
  this.bridge.tools.set(toolInfo.name, validatedTool);
177
262
  } catch (error) {
178
- console.error(`[Native Adapter] Failed to sync tool "${toolInfo.name}":`, error);
263
+ nativeLogger.error(`Failed to sync tool "${toolInfo.name}":`, error);
179
264
  }
180
265
  this.notifyMCPServers();
181
266
  } finally {
@@ -235,7 +320,6 @@ var NativeModelContextAdapter = class {
235
320
  * @param {ModelContextInput} context - Context containing tools to register
236
321
  */
237
322
  provideContext(context) {
238
- console.log("[Native Adapter] Delegating provideContext to native API");
239
323
  this.nativeContext.provideContext(context);
240
324
  }
241
325
  /**
@@ -247,7 +331,6 @@ var NativeModelContextAdapter = class {
247
331
  * @returns {{unregister: () => void}} Object with unregister function
248
332
  */
249
333
  registerTool(tool) {
250
- console.log(`[Native Adapter] Delegating registerTool("${tool.name}") to native API`);
251
334
  return this.nativeContext.registerTool(tool);
252
335
  }
253
336
  /**
@@ -257,7 +340,6 @@ var NativeModelContextAdapter = class {
257
340
  * @param {string} name - Name of the tool to unregister
258
341
  */
259
342
  unregisterTool(name) {
260
- console.log(`[Native Adapter] Delegating unregisterTool("${name}") to native API`);
261
343
  this.nativeContext.unregisterTool(name);
262
344
  }
263
345
  /**
@@ -265,7 +347,6 @@ var NativeModelContextAdapter = class {
265
347
  * Delegates to navigator.modelContext.clearContext().
266
348
  */
267
349
  clearContext() {
268
- console.log("[Native Adapter] Delegating clearContext to native API");
269
350
  this.nativeContext.clearContext();
270
351
  }
271
352
  /**
@@ -278,12 +359,11 @@ var NativeModelContextAdapter = class {
278
359
  * @internal
279
360
  */
280
361
  async executeTool(toolName, args) {
281
- console.log(`[Native Adapter] Executing tool "${toolName}" via native API`);
282
362
  try {
283
363
  const result = await this.nativeTesting.executeTool(toolName, JSON.stringify(args));
284
364
  return this.convertToToolResponse(result);
285
365
  } catch (error) {
286
- console.error(`[Native Adapter] Error executing tool "${toolName}":`, error);
366
+ nativeLogger.error(`Error executing tool "${toolName}":`, error);
287
367
  return {
288
368
  content: [{
289
369
  type: "text",
@@ -314,7 +394,7 @@ var NativeModelContextAdapter = class {
314
394
  * This is a polyfill-only feature.
315
395
  */
316
396
  registerResource(_resource) {
317
- console.warn("[Native Adapter] registerResource is not supported by native API");
397
+ nativeLogger.warn("registerResource is not supported by native API");
318
398
  return { unregister: () => {} };
319
399
  }
320
400
  /**
@@ -322,7 +402,7 @@ var NativeModelContextAdapter = class {
322
402
  * Note: Native Chromium API does not yet support resources.
323
403
  */
324
404
  unregisterResource(_uri) {
325
- console.warn("[Native Adapter] unregisterResource is not supported by native API");
405
+ nativeLogger.warn("unregisterResource is not supported by native API");
326
406
  }
327
407
  /**
328
408
  * Lists all registered resources.
@@ -352,7 +432,7 @@ var NativeModelContextAdapter = class {
352
432
  * This is a polyfill-only feature.
353
433
  */
354
434
  registerPrompt(_prompt) {
355
- console.warn("[Native Adapter] registerPrompt is not supported by native API");
435
+ nativeLogger.warn("registerPrompt is not supported by native API");
356
436
  return { unregister: () => {} };
357
437
  }
358
438
  /**
@@ -360,7 +440,7 @@ var NativeModelContextAdapter = class {
360
440
  * Note: Native Chromium API does not yet support prompts.
361
441
  */
362
442
  unregisterPrompt(_name) {
363
- console.warn("[Native Adapter] unregisterPrompt is not supported by native API");
443
+ nativeLogger.warn("unregisterPrompt is not supported by native API");
364
444
  }
365
445
  /**
366
446
  * Lists all registered prompts.
@@ -415,7 +495,6 @@ var NativeModelContextAdapter = class {
415
495
  * This is handled by the polyfill.
416
496
  */
417
497
  async createMessage(params) {
418
- console.log("[Native Adapter] Requesting sampling from client");
419
498
  const underlyingServer = this.bridge.tabServer.server;
420
499
  if (!underlyingServer?.createMessage) throw new Error("Sampling is not supported: no connected client with sampling capability");
421
500
  return underlyingServer.createMessage(params);
@@ -426,7 +505,6 @@ var NativeModelContextAdapter = class {
426
505
  * This is handled by the polyfill.
427
506
  */
428
507
  async elicitInput(params) {
429
- console.log("[Native Adapter] Requesting elicitation from client");
430
508
  const underlyingServer = this.bridge.tabServer.server;
431
509
  if (!underlyingServer?.elicitInput) throw new Error("Elicitation is not supported: no connected client with elicitation capability");
432
510
  return underlyingServer.elicitInput(params);
@@ -565,7 +643,7 @@ var WebModelContextTesting = class {
565
643
  for (const callback of this.toolsChangedCallbacks) try {
566
644
  callback();
567
645
  } catch (error) {
568
- console.error("[Model Context Testing] Error in tools changed callback:", error);
646
+ testingLogger.error("Error in tools changed callback:", error);
569
647
  }
570
648
  }
571
649
  /**
@@ -579,7 +657,6 @@ var WebModelContextTesting = class {
579
657
  * @throws {Error} If the tool does not exist
580
658
  */
581
659
  async executeTool(toolName, inputArgsJson) {
582
- console.log(`[Model Context Testing] Executing tool: ${toolName}`);
583
660
  let args;
584
661
  try {
585
662
  args = JSON.parse(inputArgsJson);
@@ -616,7 +693,6 @@ var WebModelContextTesting = class {
616
693
  */
617
694
  registerToolsChangedCallback(callback) {
618
695
  this.toolsChangedCallbacks.add(callback);
619
- console.log("[Model Context Testing] Tools changed callback registered");
620
696
  }
621
697
  /**
622
698
  * Gets all tool calls that have been recorded (polyfill extension).
@@ -631,7 +707,6 @@ var WebModelContextTesting = class {
631
707
  */
632
708
  clearToolCalls() {
633
709
  this.toolCallHistory = [];
634
- console.log("[Model Context Testing] Tool call history cleared");
635
710
  }
636
711
  /**
637
712
  * Sets a mock response for a specific tool (polyfill extension).
@@ -642,7 +717,6 @@ var WebModelContextTesting = class {
642
717
  */
643
718
  setMockToolResponse(toolName, response) {
644
719
  this.mockResponses.set(toolName, response);
645
- console.log(`[Model Context Testing] Mock response set for tool: ${toolName}`);
646
720
  }
647
721
  /**
648
722
  * Clears the mock response for a specific tool (polyfill extension).
@@ -651,14 +725,12 @@ var WebModelContextTesting = class {
651
725
  */
652
726
  clearMockToolResponse(toolName) {
653
727
  this.mockResponses.delete(toolName);
654
- console.log(`[Model Context Testing] Mock response cleared for tool: ${toolName}`);
655
728
  }
656
729
  /**
657
730
  * Clears all mock tool responses (polyfill extension).
658
731
  */
659
732
  clearAllMockToolResponses() {
660
733
  this.mockResponses.clear();
661
- console.log("[Model Context Testing] All mock responses cleared");
662
734
  }
663
735
  /**
664
736
  * Gets the current tools registered in the system (polyfill extension).
@@ -675,7 +747,6 @@ var WebModelContextTesting = class {
675
747
  reset() {
676
748
  this.clearToolCalls();
677
749
  this.clearAllMockToolResponses();
678
- console.log("[Model Context Testing] Testing state reset");
679
750
  }
680
751
  };
681
752
  /**
@@ -781,14 +852,13 @@ var WebModelContext = class {
781
852
  * @throws {Error} If a name/uri collides with existing dynamic items
782
853
  */
783
854
  provideContext(context) {
784
- const toolCount = context.tools?.length ?? 0;
785
- const resourceCount = context.resources?.length ?? 0;
786
- const promptCount = context.prompts?.length ?? 0;
787
- console.log(`[Web Model Context] provideContext: ${toolCount} tools, ${resourceCount} resources, ${promptCount} prompts`);
788
855
  this.provideContextTools.clear();
789
856
  this.provideContextResources.clear();
790
857
  this.provideContextPrompts.clear();
791
858
  for (const tool of context.tools ?? []) {
859
+ if (tool.name.startsWith("_")) logger$1.warn(`⚠️ Warning: Tool name "${tool.name}" starts with underscore. This may cause compatibility issues with some MCP clients. Consider using a letter as the first character.`);
860
+ if (/^[0-9]/.test(tool.name)) logger$1.warn(`⚠️ Warning: Tool name "${tool.name}" starts with a number. This may cause compatibility issues. Consider using a letter as the first character.`);
861
+ if (tool.name.startsWith("-")) logger$1.warn(`⚠️ Warning: Tool name "${tool.name}" starts with hyphen. This may cause compatibility issues. Consider using a letter as the first character.`);
792
862
  if (this.dynamicTools.has(tool.name)) throw new Error(`[Web Model Context] Tool name collision: "${tool.name}" is already registered via registerTool(). Please use a different name or unregister the dynamic tool first.`);
793
863
  const { jsonSchema: inputJson, zodValidator: inputZod } = normalizeSchema(tool.inputSchema);
794
864
  const normalizedOutput = tool.outputSchema ? normalizeSchema(tool.outputSchema) : null;
@@ -871,11 +941,13 @@ var WebModelContext = class {
871
941
  * @throws {Error} If tool name collides with existing tools
872
942
  */
873
943
  registerTool(tool) {
874
- console.log(`[Web Model Context] Registering tool dynamically: ${tool.name}`);
944
+ if (tool.name.startsWith("_")) logger$1.warn(`⚠️ Warning: Tool name "${tool.name}" starts with underscore. This may cause compatibility issues with some MCP clients. Consider using a letter as the first character.`);
945
+ if (/^[0-9]/.test(tool.name)) logger$1.warn(`⚠️ Warning: Tool name "${tool.name}" starts with a number. This may cause compatibility issues. Consider using a letter as the first character.`);
946
+ if (tool.name.startsWith("-")) logger$1.warn(`⚠️ Warning: Tool name "${tool.name}" starts with hyphen. This may cause compatibility issues. Consider using a letter as the first character.`);
875
947
  const now = Date.now();
876
948
  const lastRegistration = this.toolRegistrationTimestamps.get(tool.name);
877
949
  if (lastRegistration && now - lastRegistration < RAPID_DUPLICATE_WINDOW_MS) {
878
- console.warn(`[Web Model Context] Tool "${tool.name}" registered multiple times within ${RAPID_DUPLICATE_WINDOW_MS}ms. This is likely due to React Strict Mode double-mounting. Ignoring duplicate registration.`);
950
+ logger$1.warn(`Tool "${tool.name}" registered multiple times within ${RAPID_DUPLICATE_WINDOW_MS}ms. This is likely due to React Strict Mode double-mounting. Ignoring duplicate registration.`);
879
951
  const existingUnregister = this.toolUnregisterFunctions.get(tool.name);
880
952
  if (existingUnregister) return { unregister: existingUnregister };
881
953
  }
@@ -898,10 +970,9 @@ var WebModelContext = class {
898
970
  this.updateBridgeTools();
899
971
  this.scheduleListChanged("tools");
900
972
  const unregisterFn = () => {
901
- console.log(`[Web Model Context] Unregistering tool: ${tool.name}`);
902
973
  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.`);
903
974
  if (!this.dynamicTools.has(tool.name)) {
904
- console.warn(`[Web Model Context] Tool "${tool.name}" is not registered, ignoring unregister call`);
975
+ logger$1.warn(`Tool "${tool.name}" is not registered, ignoring unregister call`);
905
976
  return;
906
977
  }
907
978
  this.dynamicTools.delete(tool.name);
@@ -922,11 +993,10 @@ var WebModelContext = class {
922
993
  * @throws {Error} If resource URI collides with existing resources
923
994
  */
924
995
  registerResource(resource) {
925
- console.log(`[Web Model Context] Registering resource dynamically: ${resource.uri}`);
926
996
  const now = Date.now();
927
997
  const lastRegistration = this.resourceRegistrationTimestamps.get(resource.uri);
928
998
  if (lastRegistration && now - lastRegistration < RAPID_DUPLICATE_WINDOW_MS) {
929
- console.warn(`[Web Model Context] Resource "${resource.uri}" registered multiple times within ${RAPID_DUPLICATE_WINDOW_MS}ms. This is likely due to React Strict Mode double-mounting. Ignoring duplicate registration.`);
999
+ logger$1.warn(`Resource "${resource.uri}" registered multiple times within ${RAPID_DUPLICATE_WINDOW_MS}ms. This is likely due to React Strict Mode double-mounting. Ignoring duplicate registration.`);
930
1000
  const existingUnregister = this.resourceUnregisterFunctions.get(resource.uri);
931
1001
  if (existingUnregister) return { unregister: existingUnregister };
932
1002
  }
@@ -938,10 +1008,9 @@ var WebModelContext = class {
938
1008
  this.updateBridgeResources();
939
1009
  this.scheduleListChanged("resources");
940
1010
  const unregisterFn = () => {
941
- console.log(`[Web Model Context] Unregistering resource: ${resource.uri}`);
942
1011
  if (this.provideContextResources.has(resource.uri)) throw new Error(`[Web Model Context] Cannot unregister resource "${resource.uri}": This resource was registered via provideContext(). Use provideContext() to update the base resource set.`);
943
1012
  if (!this.dynamicResources.has(resource.uri)) {
944
- console.warn(`[Web Model Context] Resource "${resource.uri}" is not registered, ignoring unregister call`);
1013
+ logger$1.warn(`Resource "${resource.uri}" is not registered, ignoring unregister call`);
945
1014
  return;
946
1015
  }
947
1016
  this.dynamicResources.delete(resource.uri);
@@ -960,11 +1029,10 @@ var WebModelContext = class {
960
1029
  * @param {string} uri - URI of the resource to unregister
961
1030
  */
962
1031
  unregisterResource(uri) {
963
- console.log(`[Web Model Context] Unregistering resource: ${uri}`);
964
1032
  const inProvideContext = this.provideContextResources.has(uri);
965
1033
  const inDynamic = this.dynamicResources.has(uri);
966
1034
  if (!inProvideContext && !inDynamic) {
967
- console.warn(`[Web Model Context] Resource "${uri}" is not registered, ignoring unregister call`);
1035
+ logger$1.warn(`Resource "${uri}" is not registered, ignoring unregister call`);
968
1036
  return;
969
1037
  }
970
1038
  if (inProvideContext) this.provideContextResources.delete(uri);
@@ -1013,11 +1081,10 @@ var WebModelContext = class {
1013
1081
  * @throws {Error} If prompt name collides with existing prompts
1014
1082
  */
1015
1083
  registerPrompt(prompt) {
1016
- console.log(`[Web Model Context] Registering prompt dynamically: ${prompt.name}`);
1017
1084
  const now = Date.now();
1018
1085
  const lastRegistration = this.promptRegistrationTimestamps.get(prompt.name);
1019
1086
  if (lastRegistration && now - lastRegistration < RAPID_DUPLICATE_WINDOW_MS) {
1020
- console.warn(`[Web Model Context] Prompt "${prompt.name}" registered multiple times within ${RAPID_DUPLICATE_WINDOW_MS}ms. This is likely due to React Strict Mode double-mounting. Ignoring duplicate registration.`);
1087
+ logger$1.warn(`Prompt "${prompt.name}" registered multiple times within ${RAPID_DUPLICATE_WINDOW_MS}ms. This is likely due to React Strict Mode double-mounting. Ignoring duplicate registration.`);
1021
1088
  const existingUnregister = this.promptUnregisterFunctions.get(prompt.name);
1022
1089
  if (existingUnregister) return { unregister: existingUnregister };
1023
1090
  }
@@ -1029,10 +1096,9 @@ var WebModelContext = class {
1029
1096
  this.updateBridgePrompts();
1030
1097
  this.scheduleListChanged("prompts");
1031
1098
  const unregisterFn = () => {
1032
- console.log(`[Web Model Context] Unregistering prompt: ${prompt.name}`);
1033
1099
  if (this.provideContextPrompts.has(prompt.name)) throw new Error(`[Web Model Context] Cannot unregister prompt "${prompt.name}": This prompt was registered via provideContext(). Use provideContext() to update the base prompt set.`);
1034
1100
  if (!this.dynamicPrompts.has(prompt.name)) {
1035
- console.warn(`[Web Model Context] Prompt "${prompt.name}" is not registered, ignoring unregister call`);
1101
+ logger$1.warn(`Prompt "${prompt.name}" is not registered, ignoring unregister call`);
1036
1102
  return;
1037
1103
  }
1038
1104
  this.dynamicPrompts.delete(prompt.name);
@@ -1051,11 +1117,10 @@ var WebModelContext = class {
1051
1117
  * @param {string} name - Name of the prompt to unregister
1052
1118
  */
1053
1119
  unregisterPrompt(name) {
1054
- console.log(`[Web Model Context] Unregistering prompt: ${name}`);
1055
1120
  const inProvideContext = this.provideContextPrompts.has(name);
1056
1121
  const inDynamic = this.dynamicPrompts.has(name);
1057
1122
  if (!inProvideContext && !inDynamic) {
1058
- console.warn(`[Web Model Context] Prompt "${name}" is not registered, ignoring unregister call`);
1123
+ logger$1.warn(`Prompt "${name}" is not registered, ignoring unregister call`);
1059
1124
  return;
1060
1125
  }
1061
1126
  if (inProvideContext) this.provideContextPrompts.delete(name);
@@ -1091,11 +1156,10 @@ var WebModelContext = class {
1091
1156
  * @param {string} name - Name of the tool to unregister
1092
1157
  */
1093
1158
  unregisterTool(name) {
1094
- console.log(`[Web Model Context] Unregistering tool: ${name}`);
1095
1159
  const inProvideContext = this.provideContextTools.has(name);
1096
1160
  const inDynamic = this.dynamicTools.has(name);
1097
1161
  if (!inProvideContext && !inDynamic) {
1098
- console.warn(`[Web Model Context] Tool "${name}" is not registered, ignoring unregister call`);
1162
+ logger$1.warn(`Tool "${name}" is not registered, ignoring unregister call`);
1099
1163
  return;
1100
1164
  }
1101
1165
  if (inProvideContext) this.provideContextTools.delete(name);
@@ -1112,7 +1176,6 @@ var WebModelContext = class {
1112
1176
  * Removes all tools, resources, and prompts registered via provideContext() and register* methods.
1113
1177
  */
1114
1178
  clearContext() {
1115
- console.log("[Web Model Context] Clearing all context (tools, resources, prompts)");
1116
1179
  this.provideContextTools.clear();
1117
1180
  this.dynamicTools.clear();
1118
1181
  this.toolRegistrationTimestamps.clear();
@@ -1142,7 +1205,6 @@ var WebModelContext = class {
1142
1205
  this.bridge.tools.clear();
1143
1206
  for (const [name, tool] of this.provideContextTools) this.bridge.tools.set(name, tool);
1144
1207
  for (const [name, tool] of this.dynamicTools) this.bridge.tools.set(name, tool);
1145
- console.log(`[Web Model Context] Updated bridge with ${this.provideContextTools.size} base tools + ${this.dynamicTools.size} dynamic tools = ${this.bridge.tools.size} total`);
1146
1208
  }
1147
1209
  /**
1148
1210
  * Notifies all servers and testing callbacks that the tools list has changed.
@@ -1170,7 +1232,6 @@ var WebModelContext = class {
1170
1232
  this.bridge.resources.clear();
1171
1233
  for (const [uri, resource] of this.provideContextResources) this.bridge.resources.set(uri, resource);
1172
1234
  for (const [uri, resource] of this.dynamicResources) this.bridge.resources.set(uri, resource);
1173
- console.log(`[Web Model Context] Updated bridge with ${this.provideContextResources.size} base resources + ${this.dynamicResources.size} dynamic resources = ${this.bridge.resources.size} total`);
1174
1235
  }
1175
1236
  /**
1176
1237
  * Notifies all servers that the resources list has changed.
@@ -1196,7 +1257,6 @@ var WebModelContext = class {
1196
1257
  this.bridge.prompts.clear();
1197
1258
  for (const [name, prompt] of this.provideContextPrompts) this.bridge.prompts.set(name, prompt);
1198
1259
  for (const [name, prompt] of this.dynamicPrompts) this.bridge.prompts.set(name, prompt);
1199
- console.log(`[Web Model Context] Updated bridge with ${this.provideContextPrompts.size} base prompts + ${this.dynamicPrompts.size} dynamic prompts = ${this.bridge.prompts.size} total`);
1200
1260
  }
1201
1261
  /**
1202
1262
  * Notifies all servers that the prompts list has changed.
@@ -1239,7 +1299,7 @@ var WebModelContext = class {
1239
1299
  break;
1240
1300
  default: {
1241
1301
  const _exhaustive = listType;
1242
- console.error(`[Web Model Context] Unknown list type: ${_exhaustive}`);
1302
+ logger$1.error(`Unknown list type: ${_exhaustive}`);
1243
1303
  }
1244
1304
  }
1245
1305
  });
@@ -1254,13 +1314,12 @@ var WebModelContext = class {
1254
1314
  * @internal
1255
1315
  */
1256
1316
  async readResource(uri) {
1257
- console.log(`[Web Model Context] Reading resource: ${uri}`);
1258
1317
  const staticResource = this.bridge.resources.get(uri);
1259
1318
  if (staticResource && !staticResource.isTemplate) try {
1260
1319
  const parsedUri = new URL(uri);
1261
1320
  return await staticResource.read(parsedUri);
1262
1321
  } catch (error) {
1263
- console.error(`[Web Model Context] Error reading resource ${uri}:`, error);
1322
+ logger$1.error(`Error reading resource ${uri}:`, error);
1264
1323
  throw error;
1265
1324
  }
1266
1325
  for (const resource of this.bridge.resources.values()) {
@@ -1270,7 +1329,7 @@ var WebModelContext = class {
1270
1329
  const parsedUri = new URL(uri);
1271
1330
  return await resource.read(parsedUri, params);
1272
1331
  } catch (error) {
1273
- console.error(`[Web Model Context] Error reading resource ${uri}:`, error);
1332
+ logger$1.error(`Error reading resource ${uri}:`, error);
1274
1333
  throw error;
1275
1334
  }
1276
1335
  }
@@ -1315,20 +1374,19 @@ var WebModelContext = class {
1315
1374
  * @internal
1316
1375
  */
1317
1376
  async getPrompt(name, args) {
1318
- console.log(`[Web Model Context] Getting prompt: ${name}`);
1319
1377
  const prompt = this.bridge.prompts.get(name);
1320
1378
  if (!prompt) throw new Error(`Prompt not found: ${name}`);
1321
1379
  if (prompt.argsValidator && args) {
1322
1380
  const validation = validateWithZod(args, prompt.argsValidator);
1323
1381
  if (!validation.success) {
1324
- console.error(`[Web Model Context] Argument validation failed for prompt ${name}:`, validation.error);
1382
+ logger$1.error(`Argument validation failed for prompt ${name}:`, validation.error);
1325
1383
  throw new Error(`Argument validation error for prompt "${name}":\n${validation.error}`);
1326
1384
  }
1327
1385
  }
1328
1386
  try {
1329
1387
  return await prompt.get(args ?? {});
1330
1388
  } catch (error) {
1331
- console.error(`[Web Model Context] Error getting prompt ${name}:`, error);
1389
+ logger$1.error(`Error getting prompt ${name}:`, error);
1332
1390
  throw error;
1333
1391
  }
1334
1392
  }
@@ -1351,10 +1409,9 @@ var WebModelContext = class {
1351
1409
  async executeTool(toolName, args) {
1352
1410
  const tool = this.bridge.tools.get(toolName);
1353
1411
  if (!tool) throw new Error(`Tool not found: ${toolName}`);
1354
- console.log(`[Web Model Context] Validating input for tool: ${toolName}`);
1355
1412
  const validation = validateWithZod(args, tool.inputValidator);
1356
1413
  if (!validation.success) {
1357
- console.error(`[Web Model Context] Input validation failed for ${toolName}:`, validation.error);
1414
+ logger$1.error(`Input validation failed for ${toolName}:`, validation.error);
1358
1415
  return {
1359
1416
  content: [{
1360
1417
  type: "text",
@@ -1367,31 +1424,24 @@ var WebModelContext = class {
1367
1424
  if (this.testingAPI) this.testingAPI.recordToolCall(toolName, validatedArgs);
1368
1425
  if (this.testingAPI?.hasMockResponse(toolName)) {
1369
1426
  const mockResponse = this.testingAPI.getMockResponse(toolName);
1370
- if (mockResponse) {
1371
- console.log(`[Web Model Context] Returning mock response for tool: ${toolName}`);
1372
- return mockResponse;
1373
- }
1427
+ if (mockResponse) return mockResponse;
1374
1428
  }
1375
1429
  const event = new WebToolCallEvent(toolName, validatedArgs);
1376
1430
  this.dispatchEvent(event);
1377
1431
  if (event.defaultPrevented && event.hasResponse()) {
1378
1432
  const response = event.getResponse();
1379
- if (response) {
1380
- console.log(`[Web Model Context] Tool ${toolName} handled by event listener`);
1381
- return response;
1382
- }
1433
+ if (response) return response;
1383
1434
  }
1384
- console.log(`[Web Model Context] Executing tool: ${toolName}`);
1385
1435
  try {
1386
1436
  const response = await tool.execute(validatedArgs);
1387
1437
  if (tool.outputValidator && response.structuredContent) {
1388
1438
  const outputValidation = validateWithZod(response.structuredContent, tool.outputValidator);
1389
- if (!outputValidation.success) console.warn(`[Web Model Context] Output validation failed for ${toolName}:`, outputValidation.error);
1439
+ if (!outputValidation.success) logger$1.warn(`Output validation failed for ${toolName}:`, outputValidation.error);
1390
1440
  }
1391
- if (response.metadata && "willNavigate" in response.metadata) console.info(`[Web Model Context] Tool "${toolName}" will trigger navigation`, response.metadata);
1441
+ if (response.metadata && typeof response.metadata === "object" && "willNavigate" in response.metadata) logger$1.info(`Tool "${toolName}" will trigger navigation`, response.metadata);
1392
1442
  return response;
1393
1443
  } catch (error) {
1394
- console.error(`[Web Model Context] Error executing tool ${toolName}:`, error);
1444
+ logger$1.error(`Error executing tool ${toolName}:`, error);
1395
1445
  return {
1396
1446
  content: [{
1397
1447
  type: "text",
@@ -1425,7 +1475,6 @@ var WebModelContext = class {
1425
1475
  * @returns {Promise<SamplingResult>} The LLM completion result
1426
1476
  */
1427
1477
  async createMessage(params) {
1428
- console.log("[Web Model Context] Requesting sampling from client");
1429
1478
  const underlyingServer = this.bridge.tabServer.server;
1430
1479
  if (!underlyingServer?.createMessage) throw new Error("Sampling is not supported: no connected client with sampling capability");
1431
1480
  return underlyingServer.createMessage(params);
@@ -1438,7 +1487,6 @@ var WebModelContext = class {
1438
1487
  * @returns {Promise<ElicitationResult>} The user's response
1439
1488
  */
1440
1489
  async elicitInput(params) {
1441
- console.log("[Web Model Context] Requesting elicitation from client");
1442
1490
  const underlyingServer = this.bridge.tabServer.server;
1443
1491
  if (!underlyingServer?.elicitInput) throw new Error("Elicitation is not supported: no connected client with elicitation capability");
1444
1492
  return underlyingServer.elicitInput(params);
@@ -1453,16 +1501,13 @@ var WebModelContext = class {
1453
1501
  * @returns {MCPBridge} The initialized MCP bridge
1454
1502
  */
1455
1503
  function initializeMCPBridge(options) {
1456
- console.log("[Web Model Context] Initializing MCP bridge");
1457
1504
  const hostname = window.location.hostname || "localhost";
1458
1505
  const transportOptions = options?.transport;
1459
1506
  const setupServerHandlers = (server, bridge$1) => {
1460
1507
  server.setRequestHandler(ListToolsRequestSchema, async () => {
1461
- console.log("[MCP Bridge] Handling list_tools request");
1462
1508
  return { tools: bridge$1.modelContext.listTools() };
1463
1509
  });
1464
1510
  server.setRequestHandler(CallToolRequestSchema, async (request) => {
1465
- console.log(`[MCP Bridge] Handling call_tool request: ${request.params.name}`);
1466
1511
  const toolName = request.params.name;
1467
1512
  const args = request.params.arguments || {};
1468
1513
  try {
@@ -1473,40 +1518,35 @@ function initializeMCPBridge(options) {
1473
1518
  ...response.structuredContent && { structuredContent: response.structuredContent }
1474
1519
  };
1475
1520
  } catch (error) {
1476
- console.error(`[MCP Bridge] Error calling tool ${toolName}:`, error);
1521
+ bridgeLogger.error(`Error calling tool ${toolName}:`, error);
1477
1522
  throw error;
1478
1523
  }
1479
1524
  });
1480
1525
  server.setRequestHandler(ListResourcesRequestSchema, async () => {
1481
- console.log("[MCP Bridge] Handling list_resources request");
1482
1526
  return { resources: bridge$1.modelContext.listResources() };
1483
1527
  });
1484
1528
  server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
1485
- console.log(`[MCP Bridge] Handling read_resource request: ${request.params.uri}`);
1486
1529
  try {
1487
1530
  return await bridge$1.modelContext.readResource(request.params.uri);
1488
1531
  } catch (error) {
1489
- console.error(`[MCP Bridge] Error reading resource ${request.params.uri}:`, error);
1532
+ bridgeLogger.error(`Error reading resource ${request.params.uri}:`, error);
1490
1533
  throw error;
1491
1534
  }
1492
1535
  });
1493
1536
  server.setRequestHandler(ListPromptsRequestSchema, async () => {
1494
- console.log("[MCP Bridge] Handling list_prompts request");
1495
1537
  return { prompts: bridge$1.modelContext.listPrompts() };
1496
1538
  });
1497
1539
  server.setRequestHandler(GetPromptRequestSchema, async (request) => {
1498
- console.log(`[MCP Bridge] Handling get_prompt request: ${request.params.name}`);
1499
1540
  try {
1500
1541
  return await bridge$1.modelContext.getPrompt(request.params.name, request.params.arguments);
1501
1542
  } catch (error) {
1502
- console.error(`[MCP Bridge] Error getting prompt ${request.params.name}:`, error);
1543
+ bridgeLogger.error(`Error getting prompt ${request.params.name}:`, error);
1503
1544
  throw error;
1504
1545
  }
1505
1546
  });
1506
1547
  };
1507
1548
  const customTransport = transportOptions?.create?.();
1508
1549
  if (customTransport) {
1509
- console.log("[Web Model Context] Using custom transport");
1510
1550
  const server = new Server({
1511
1551
  name: hostname,
1512
1552
  version: "1.0.0"
@@ -1526,10 +1566,8 @@ function initializeMCPBridge(options) {
1526
1566
  bridge$1.modelContext = new WebModelContext(bridge$1);
1527
1567
  setupServerHandlers(server, bridge$1);
1528
1568
  server.connect(customTransport);
1529
- console.log("[Web Model Context] MCP server connected with custom transport");
1530
1569
  return bridge$1;
1531
1570
  }
1532
- console.log("[Web Model Context] Using dual-server mode");
1533
1571
  const tabServerEnabled = transportOptions?.tabServer !== false;
1534
1572
  const tabServer = new Server({
1535
1573
  name: `${hostname}-tab`,
@@ -1556,12 +1594,10 @@ function initializeMCPBridge(options) {
1556
1594
  ...restTabServerOptions
1557
1595
  });
1558
1596
  tabServer.connect(tabTransport);
1559
- console.log("[Web Model Context] Tab server connected");
1560
1597
  }
1561
1598
  const isInIframe = typeof window !== "undefined" && window.parent !== window;
1562
1599
  const iframeServerConfig = transportOptions?.iframeServer;
1563
1600
  if (iframeServerConfig !== false && (iframeServerConfig !== void 0 || isInIframe)) {
1564
- console.log("[Web Model Context] Enabling iframe server");
1565
1601
  const iframeServer = new Server({
1566
1602
  name: `${hostname}-iframe`,
1567
1603
  version: "1.0.0"
@@ -1578,7 +1614,6 @@ function initializeMCPBridge(options) {
1578
1614
  });
1579
1615
  iframeServer.connect(iframeTransport);
1580
1616
  bridge.iframeServer = iframeServer;
1581
- console.log("[Web Model Context] Iframe server connected");
1582
1617
  }
1583
1618
  return bridge;
1584
1619
  }
@@ -1604,7 +1639,7 @@ function initializeMCPBridge(options) {
1604
1639
  */
1605
1640
  function initializeWebModelContext(options) {
1606
1641
  if (typeof window === "undefined") {
1607
- console.warn("[Web Model Context] Not in browser environment, skipping initialization");
1642
+ logger$1.warn("Not in browser environment, skipping initialization");
1608
1643
  return;
1609
1644
  }
1610
1645
  const effectiveOptions = options ?? window.__webModelContextOptions;
@@ -1613,12 +1648,12 @@ function initializeWebModelContext(options) {
1613
1648
  const nativeContext = window.navigator.modelContext;
1614
1649
  const nativeTesting = window.navigator.modelContextTesting;
1615
1650
  if (!nativeContext || !nativeTesting) {
1616
- console.error("[Web Model Context] Native API detection mismatch");
1651
+ logger$1.error("Native API detection mismatch");
1617
1652
  return;
1618
1653
  }
1619
- console.log("✅ [Web Model Context] Native Chromium API detected");
1620
- console.log(" Using native implementation with MCP bridge synchronization");
1621
- console.log(" Native API will automatically collect tools from embedded iframes");
1654
+ logger$1.info("✅ Native Chromium API detected");
1655
+ logger$1.info(" Using native implementation with MCP bridge synchronization");
1656
+ logger$1.info(" Native API will automatically collect tools from embedded iframes");
1622
1657
  try {
1623
1658
  const bridge = initializeMCPBridge(effectiveOptions);
1624
1659
  bridge.modelContext = new NativeModelContextAdapter(bridge, nativeContext, nativeTesting);
@@ -1628,29 +1663,29 @@ function initializeWebModelContext(options) {
1628
1663
  writable: false,
1629
1664
  configurable: true
1630
1665
  });
1631
- console.log("✅ [Web Model Context] MCP bridge synced with native API");
1632
- console.log(" MCP clients will receive automatic tool updates from native registry");
1666
+ logger$1.info("✅ MCP bridge synced with native API");
1667
+ logger$1.info(" MCP clients will receive automatic tool updates from native registry");
1633
1668
  } catch (error) {
1634
- console.error("[Web Model Context] Failed to initialize native adapter:", error);
1669
+ logger$1.error("Failed to initialize native adapter:", error);
1635
1670
  throw error;
1636
1671
  }
1637
1672
  return;
1638
1673
  }
1639
1674
  if (native.hasNativeContext && !native.hasNativeTesting) {
1640
- console.warn("[Web Model Context] Partial native API detected");
1641
- console.warn(" navigator.modelContext exists but navigator.modelContextTesting is missing");
1642
- console.warn(" Cannot sync with native API. Please enable experimental features:");
1643
- console.warn(" - Navigate to chrome://flags");
1644
- console.warn(" - Enable \"Experimental Web Platform Features\"");
1645
- console.warn(" - Or launch with: --enable-experimental-web-platform-features");
1646
- console.warn(" Skipping initialization to avoid conflicts");
1675
+ logger$1.warn("Partial native API detected");
1676
+ logger$1.warn(" navigator.modelContext exists but navigator.modelContextTesting is missing");
1677
+ logger$1.warn(" Cannot sync with native API. Please enable experimental features:");
1678
+ logger$1.warn(" - Navigate to chrome://flags");
1679
+ logger$1.warn(" - Enable \"Experimental Web Platform Features\"");
1680
+ logger$1.warn(" - Or launch with: --enable-experimental-web-platform-features");
1681
+ logger$1.warn(" Skipping initialization to avoid conflicts");
1647
1682
  return;
1648
1683
  }
1649
1684
  if (window.navigator.modelContext) {
1650
- console.warn("[Web Model Context] window.navigator.modelContext already exists, skipping initialization");
1685
+ logger$1.warn("window.navigator.modelContext already exists, skipping initialization");
1651
1686
  return;
1652
1687
  }
1653
- console.log("[Web Model Context] Native API not detected, installing polyfill");
1688
+ logger$1.info("Native API not detected, installing polyfill");
1654
1689
  try {
1655
1690
  const bridge = initializeMCPBridge(effectiveOptions);
1656
1691
  Object.defineProperty(window.navigator, "modelContext", {
@@ -1663,12 +1698,12 @@ function initializeWebModelContext(options) {
1663
1698
  writable: false,
1664
1699
  configurable: true
1665
1700
  });
1666
- console.log("✅ [Web Model Context] window.navigator.modelContext initialized successfully");
1667
- console.log("[Model Context Testing] Installing polyfill");
1668
- console.log(" 💡 To use the native implementation in Chromium:");
1669
- console.log(" - Navigate to chrome://flags");
1670
- console.log(" - Enable \"Experimental Web Platform Features\"");
1671
- console.log(" - Or launch with: --enable-experimental-web-platform-features");
1701
+ logger$1.info("✅ window.navigator.modelContext initialized successfully");
1702
+ testingLogger.info("Installing polyfill");
1703
+ testingLogger.info(" 💡 To use the native implementation in Chromium:");
1704
+ testingLogger.info(" - Navigate to chrome://flags");
1705
+ testingLogger.info(" - Enable \"Experimental Web Platform Features\"");
1706
+ testingLogger.info(" - Or launch with: --enable-experimental-web-platform-features");
1672
1707
  const testingAPI = new WebModelContextTesting(bridge);
1673
1708
  bridge.modelContextTesting = testingAPI;
1674
1709
  bridge.modelContext.setTestingAPI(testingAPI);
@@ -1677,9 +1712,9 @@ function initializeWebModelContext(options) {
1677
1712
  writable: false,
1678
1713
  configurable: true
1679
1714
  });
1680
- console.log("✅ [Model Context Testing] Polyfill installed at window.navigator.modelContextTesting");
1715
+ testingLogger.info("✅ Polyfill installed at window.navigator.modelContextTesting");
1681
1716
  } catch (error) {
1682
- console.error("[Web Model Context] Failed to initialize:", error);
1717
+ logger$1.error("Failed to initialize:", error);
1683
1718
  throw error;
1684
1719
  }
1685
1720
  }
@@ -1701,16 +1736,17 @@ function cleanupWebModelContext() {
1701
1736
  window.__mcpBridge.tabServer.close();
1702
1737
  if (window.__mcpBridge.iframeServer) window.__mcpBridge.iframeServer.close();
1703
1738
  } catch (error) {
1704
- console.warn("[Web Model Context] Error closing MCP servers:", error);
1739
+ logger$1.warn("Error closing MCP servers:", error);
1705
1740
  }
1706
1741
  delete window.navigator.modelContext;
1707
1742
  delete window.navigator.modelContextTesting;
1708
1743
  delete window.__mcpBridge;
1709
- console.log("[Web Model Context] Cleaned up");
1744
+ logger$1.info("Cleaned up");
1710
1745
  }
1711
1746
 
1712
1747
  //#endregion
1713
1748
  //#region src/index.ts
1749
+ const logger = createLogger("WebModelContext");
1714
1750
  function mergeTransportOptions(base, override) {
1715
1751
  if (!base) return override;
1716
1752
  if (!override) return base;
@@ -1738,7 +1774,7 @@ function parseScriptTagOptions(script) {
1738
1774
  if (dataset.webmcpOptions) try {
1739
1775
  return JSON.parse(dataset.webmcpOptions);
1740
1776
  } catch (error) {
1741
- console.error("[Web Model Context] Invalid JSON in data-webmcp-options:", error);
1777
+ logger.error("Invalid JSON in data-webmcp-options:", error);
1742
1778
  return;
1743
1779
  }
1744
1780
  const options = {};
@@ -1781,10 +1817,10 @@ if (typeof window !== "undefined" && typeof document !== "undefined") {
1781
1817
  try {
1782
1818
  if (shouldAutoInitialize) initializeWebModelContext(mergedOptions);
1783
1819
  } catch (error) {
1784
- console.error("[Web Model Context] Auto-initialization failed:", error);
1820
+ logger.error("Auto-initialization failed:", error);
1785
1821
  }
1786
1822
  }
1787
1823
 
1788
1824
  //#endregion
1789
- export { cleanupWebModelContext, initializeWebModelContext, zodToJsonSchema };
1825
+ export { cleanupWebModelContext, createLogger, initializeWebModelContext, zodToJsonSchema };
1790
1826
  //# sourceMappingURL=index.js.map