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

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,79 +1,200 @@
1
1
  import { IframeChildTransport, TabServerTransport } from "@mcp-b/transports";
2
2
  import { CallToolRequestSchema, GetPromptRequestSchema, ListPromptsRequestSchema, ListResourcesRequestSchema, ListToolsRequestSchema, ReadResourceRequestSchema, Server } from "@mcp-b/webmcp-ts-sdk";
3
- import { jsonSchemaToZod } from "@composio/json-schema-to-zod";
3
+ import { jsonSchemaToZod } from "@n8n/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/validation.ts
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 (err) {
49
+ if (typeof console !== "undefined" && console.warn) {
50
+ const message = err instanceof Error ? err.message : String(err);
51
+ console.warn(`[WebMCP] localStorage access failed, debug logging disabled: ${message}`);
52
+ }
53
+ return false;
54
+ }
55
+ }
8
56
  /**
9
- * Detect if a schema is a Zod schema object (Record<string, ZodType>)
10
- * or a JSON Schema object
57
+ * No-op function for disabled log levels
11
58
  */
59
+ const noop = () => {};
60
+ /**
61
+ * Create a namespaced logger
62
+ *
63
+ * Uses .bind() to prepend namespace prefixes to console methods without manual
64
+ * string concatenation. Debug enablement is determined at logger creation time
65
+ * for performance - changes to localStorage after creation won't affect existing
66
+ * loggers. Refresh the page to apply new WEBMCP_DEBUG settings.
67
+ *
68
+ * @param namespace - Namespace for the logger (e.g., 'WebModelContext', 'NativeAdapter')
69
+ * @returns Logger instance with debug, info, warn, error methods
70
+ *
71
+ * @example
72
+ * ```typescript
73
+ * const logger = createLogger('WebModelContext');
74
+ * logger.debug('Tool registered:', toolName); // Only shown if WEBMCP_DEBUG includes 'WebModelContext'
75
+ * logger.error('Execution failed:', error); // Always enabled
76
+ * ```
77
+ */
78
+ function createLogger(namespace) {
79
+ const prefix = `[${namespace}]`;
80
+ const isDebug = isDebugEnabled(namespace);
81
+ const boundWarn = console.warn.bind(console, prefix);
82
+ const boundError = console.error.bind(console, prefix);
83
+ const boundLog = console.log.bind(console, prefix);
84
+ return {
85
+ warn: boundWarn,
86
+ error: boundError,
87
+ debug: isDebug ? boundLog : noop,
88
+ info: isDebug ? boundLog : noop
89
+ };
90
+ }
91
+
92
+ //#endregion
93
+ //#region src/validation.ts
94
+ const logger$2 = createLogger("WebModelContext");
95
+ const nativeToJsonSchema = z.toJSONSchema;
96
+ const hasNativeToJSONSchema = typeof nativeToJsonSchema === "function";
97
+ const isRecord = (value) => typeof value === "object" && value !== null;
98
+ const isZod4Schema = (schema) => isRecord(schema) && "_zod" in schema;
99
+ const isZod3Schema = (schema) => isRecord(schema) && "_def" in schema && !("_zod" in schema);
100
+ const stripSchemaMeta = (schema) => {
101
+ const { $schema: _,...rest } = schema;
102
+ return rest;
103
+ };
104
+ const isOptionalSchema = (schema) => {
105
+ const typeName = schema._def?.typeName;
106
+ return typeName === "ZodOptional" || typeName === "ZodDefault";
107
+ };
12
108
  function isZodSchema(schema) {
13
- if (typeof schema !== "object" || schema === null) return false;
109
+ if (!isRecord(schema)) return false;
14
110
  if ("type" in schema && typeof schema.type === "string") return false;
15
111
  const values = Object.values(schema);
16
112
  if (values.length === 0) return false;
17
- return values.some((val) => val instanceof z.ZodType);
113
+ return values.some((value) => isZod4Schema(value) || isZod3Schema(value));
114
+ }
115
+ const hasZod4Schemas = (schema) => Object.values(schema).some((value) => isZod4Schema(value));
116
+ const tryNativeZodToJsonSchema = (schema) => {
117
+ if (!hasZod4Schemas(schema) || !hasNativeToJSONSchema) return null;
118
+ try {
119
+ return stripSchemaMeta(nativeToJsonSchema(z.object(schema), { target: "draft-7" }));
120
+ } catch (error) {
121
+ logger$2.warn("z.toJSONSchema failed, falling back to zod-to-json-schema:", error);
122
+ return null;
123
+ }
124
+ };
125
+ const fallbackZodToJsonSchema = (schema) => {
126
+ const properties = {};
127
+ const required = [];
128
+ for (const [key, zodSchema] of Object.entries(schema)) {
129
+ properties[key] = stripSchemaMeta(zodToJsonSchema$1(zodSchema, {
130
+ strictUnions: true,
131
+ $refStrategy: "none"
132
+ }));
133
+ if (!isOptionalSchema(zodSchema)) required.push(key);
134
+ }
135
+ const result = {
136
+ type: "object",
137
+ properties
138
+ };
139
+ if (required.length > 0) result.required = required;
140
+ return result;
141
+ };
142
+ function zodToJsonSchema(schema) {
143
+ const nativeSchema = tryNativeZodToJsonSchema(schema);
144
+ if (nativeSchema) return nativeSchema;
145
+ try {
146
+ return fallbackZodToJsonSchema(schema);
147
+ } catch (error) {
148
+ logger$2.warn("zodToJsonSchema failed:", error);
149
+ return {
150
+ type: "object",
151
+ properties: {}
152
+ };
153
+ }
18
154
  }
19
- /**
20
- * Convert JSON Schema to Zod validator
21
- * Uses @composio/json-schema-to-zod for conversion
22
- */
23
155
  function jsonSchemaToZod$1(jsonSchema) {
24
156
  try {
25
157
  return jsonSchemaToZod(jsonSchema);
26
158
  } catch (error) {
27
- console.warn("[Web Model Context] Failed to convert JSON Schema to Zod:", error);
159
+ logger$2.warn("jsonSchemaToZod failed:", error);
28
160
  return z.object({}).passthrough();
29
161
  }
30
162
  }
31
- /**
32
- * Convert Zod schema object to JSON Schema
33
- * Uses zod-to-json-schema package for comprehensive conversion
34
- *
35
- * @param schema - Record of Zod type definitions (e.g., { name: z.string(), age: z.number() })
36
- * @returns JSON Schema object compatible with MCP InputSchema
37
- */
38
- function zodToJsonSchema(schema) {
39
- const { $schema: _,...rest } = zodToJsonSchema$1(z.object(schema), {
40
- $refStrategy: "none",
41
- target: "jsonSchema7"
42
- });
43
- return rest;
44
- }
45
- /**
46
- * Normalize a schema to both JSON Schema and Zod formats
47
- * Detects which format is provided and converts to the other
48
- */
163
+ const buildZodValidator = (schema, jsonSchema) => {
164
+ if (hasZod4Schemas(schema) && hasNativeToJSONSchema) return z.object(schema);
165
+ return jsonSchemaToZod$1(jsonSchema);
166
+ };
49
167
  function normalizeSchema(schema) {
50
- if (isZodSchema(schema)) return {
51
- jsonSchema: zodToJsonSchema(schema),
52
- zodValidator: z.object(schema)
53
- };
54
- const jsonSchema = schema;
168
+ if (isZodSchema(schema)) {
169
+ const jsonSchema = zodToJsonSchema(schema);
170
+ return {
171
+ jsonSchema,
172
+ zodValidator: buildZodValidator(schema, jsonSchema)
173
+ };
174
+ }
55
175
  return {
56
- jsonSchema,
57
- zodValidator: jsonSchemaToZod$1(jsonSchema)
176
+ jsonSchema: schema,
177
+ zodValidator: jsonSchemaToZod$1(schema)
58
178
  };
59
179
  }
60
- /**
61
- * Validate data with Zod schema and return formatted result
62
- */
63
180
  function validateWithZod(data, validator) {
64
181
  const result = validator.safeParse(data);
65
- if (!result.success) return {
66
- success: false,
67
- error: `Validation failed:\n${result.error.errors.map((err) => ` - ${err.path.join(".") || "root"}: ${err.message}`).join("\n")}`
68
- };
69
- return {
182
+ if (result.success) return {
70
183
  success: true,
71
184
  data: result.data
72
185
  };
186
+ return {
187
+ success: false,
188
+ error: `Validation failed:\n${result.error.issues.map((err) => ` - ${err.path.join(".") || "root"}: ${err.message}`).join("\n")}`
189
+ };
73
190
  }
74
191
 
75
192
  //#endregion
76
193
  //#region src/global.ts
194
+ const logger$1 = createLogger("WebModelContext");
195
+ const nativeLogger = createLogger("NativeAdapter");
196
+ const bridgeLogger = createLogger("MCPBridge");
197
+ const testingLogger = createLogger("ModelContextTesting");
77
198
  /**
78
199
  * Marker property name used to identify polyfill implementations.
79
200
  * This constant ensures single source of truth for the marker used in
@@ -92,6 +213,7 @@ const POLYFILL_MARKER_PROPERTY = "__isWebMCPPolyfill";
92
213
  * @returns Detection result with flags for native context and testing API availability
93
214
  */
94
215
  function detectNativeAPI() {
216
+ /* c8 ignore next 2 */
95
217
  if (typeof window === "undefined" || typeof navigator === "undefined") return {
96
218
  hasNativeContext: false,
97
219
  hasNativeTesting: false
@@ -99,8 +221,8 @@ function detectNativeAPI() {
99
221
  const modelContext = navigator.modelContext;
100
222
  const modelContextTesting = navigator.modelContextTesting;
101
223
  if (!modelContext || !modelContextTesting) return {
102
- hasNativeContext: false,
103
- hasNativeTesting: false
224
+ hasNativeContext: Boolean(modelContext),
225
+ hasNativeTesting: Boolean(modelContextTesting)
104
226
  };
105
227
  if (POLYFILL_MARKER_PROPERTY in modelContextTesting && modelContextTesting[POLYFILL_MARKER_PROPERTY] === true) return {
106
228
  hasNativeContext: false,
@@ -142,7 +264,6 @@ var NativeModelContextAdapter = class {
142
264
  this.nativeContext = nativeContext;
143
265
  this.nativeTesting = nativeTesting;
144
266
  this.nativeTesting.registerToolsChangedCallback(() => {
145
- console.log("[Native Adapter] Tool change detected from native API");
146
267
  this.syncToolsFromNative();
147
268
  });
148
269
  this.syncToolsFromNative();
@@ -159,7 +280,6 @@ var NativeModelContextAdapter = class {
159
280
  this.syncInProgress = true;
160
281
  try {
161
282
  const nativeTools = this.nativeTesting.listTools();
162
- console.log(`[Native Adapter] Syncing ${nativeTools.length} tools from native API`);
163
283
  this.bridge.tools.clear();
164
284
  for (const toolInfo of nativeTools) try {
165
285
  const inputSchema = JSON.parse(toolInfo.inputSchema);
@@ -175,7 +295,7 @@ var NativeModelContextAdapter = class {
175
295
  };
176
296
  this.bridge.tools.set(toolInfo.name, validatedTool);
177
297
  } catch (error) {
178
- console.error(`[Native Adapter] Failed to sync tool "${toolInfo.name}":`, error);
298
+ nativeLogger.error(`Failed to sync tool "${toolInfo.name}":`, error);
179
299
  }
180
300
  this.notifyMCPServers();
181
301
  } finally {
@@ -235,7 +355,6 @@ var NativeModelContextAdapter = class {
235
355
  * @param {ModelContextInput} context - Context containing tools to register
236
356
  */
237
357
  provideContext(context) {
238
- console.log("[Native Adapter] Delegating provideContext to native API");
239
358
  this.nativeContext.provideContext(context);
240
359
  }
241
360
  /**
@@ -247,7 +366,6 @@ var NativeModelContextAdapter = class {
247
366
  * @returns {{unregister: () => void}} Object with unregister function
248
367
  */
249
368
  registerTool(tool) {
250
- console.log(`[Native Adapter] Delegating registerTool("${tool.name}") to native API`);
251
369
  return this.nativeContext.registerTool(tool);
252
370
  }
253
371
  /**
@@ -257,7 +375,6 @@ var NativeModelContextAdapter = class {
257
375
  * @param {string} name - Name of the tool to unregister
258
376
  */
259
377
  unregisterTool(name) {
260
- console.log(`[Native Adapter] Delegating unregisterTool("${name}") to native API`);
261
378
  this.nativeContext.unregisterTool(name);
262
379
  }
263
380
  /**
@@ -265,7 +382,6 @@ var NativeModelContextAdapter = class {
265
382
  * Delegates to navigator.modelContext.clearContext().
266
383
  */
267
384
  clearContext() {
268
- console.log("[Native Adapter] Delegating clearContext to native API");
269
385
  this.nativeContext.clearContext();
270
386
  }
271
387
  /**
@@ -278,12 +394,11 @@ var NativeModelContextAdapter = class {
278
394
  * @internal
279
395
  */
280
396
  async executeTool(toolName, args) {
281
- console.log(`[Native Adapter] Executing tool "${toolName}" via native API`);
282
397
  try {
283
398
  const result = await this.nativeTesting.executeTool(toolName, JSON.stringify(args));
284
399
  return this.convertToToolResponse(result);
285
400
  } catch (error) {
286
- console.error(`[Native Adapter] Error executing tool "${toolName}":`, error);
401
+ nativeLogger.error(`Error executing tool "${toolName}":`, error);
287
402
  return {
288
403
  content: [{
289
404
  type: "text",
@@ -314,7 +429,7 @@ var NativeModelContextAdapter = class {
314
429
  * This is a polyfill-only feature.
315
430
  */
316
431
  registerResource(_resource) {
317
- console.warn("[Native Adapter] registerResource is not supported by native API");
432
+ nativeLogger.warn("registerResource is not supported by native API");
318
433
  return { unregister: () => {} };
319
434
  }
320
435
  /**
@@ -322,7 +437,7 @@ var NativeModelContextAdapter = class {
322
437
  * Note: Native Chromium API does not yet support resources.
323
438
  */
324
439
  unregisterResource(_uri) {
325
- console.warn("[Native Adapter] unregisterResource is not supported by native API");
440
+ nativeLogger.warn("unregisterResource is not supported by native API");
326
441
  }
327
442
  /**
328
443
  * Lists all registered resources.
@@ -352,7 +467,7 @@ var NativeModelContextAdapter = class {
352
467
  * This is a polyfill-only feature.
353
468
  */
354
469
  registerPrompt(_prompt) {
355
- console.warn("[Native Adapter] registerPrompt is not supported by native API");
470
+ nativeLogger.warn("registerPrompt is not supported by native API");
356
471
  return { unregister: () => {} };
357
472
  }
358
473
  /**
@@ -360,7 +475,7 @@ var NativeModelContextAdapter = class {
360
475
  * Note: Native Chromium API does not yet support prompts.
361
476
  */
362
477
  unregisterPrompt(_name) {
363
- console.warn("[Native Adapter] unregisterPrompt is not supported by native API");
478
+ nativeLogger.warn("unregisterPrompt is not supported by native API");
364
479
  }
365
480
  /**
366
481
  * Lists all registered prompts.
@@ -415,7 +530,6 @@ var NativeModelContextAdapter = class {
415
530
  * This is handled by the polyfill.
416
531
  */
417
532
  async createMessage(params) {
418
- console.log("[Native Adapter] Requesting sampling from client");
419
533
  const underlyingServer = this.bridge.tabServer.server;
420
534
  if (!underlyingServer?.createMessage) throw new Error("Sampling is not supported: no connected client with sampling capability");
421
535
  return underlyingServer.createMessage(params);
@@ -426,7 +540,6 @@ var NativeModelContextAdapter = class {
426
540
  * This is handled by the polyfill.
427
541
  */
428
542
  async elicitInput(params) {
429
- console.log("[Native Adapter] Requesting elicitation from client");
430
543
  const underlyingServer = this.bridge.tabServer.server;
431
544
  if (!underlyingServer?.elicitInput) throw new Error("Elicitation is not supported: no connected client with elicitation capability");
432
545
  return underlyingServer.elicitInput(params);
@@ -565,7 +678,7 @@ var WebModelContextTesting = class {
565
678
  for (const callback of this.toolsChangedCallbacks) try {
566
679
  callback();
567
680
  } catch (error) {
568
- console.error("[Model Context Testing] Error in tools changed callback:", error);
681
+ testingLogger.error("Error in tools changed callback:", error);
569
682
  }
570
683
  }
571
684
  /**
@@ -579,7 +692,6 @@ var WebModelContextTesting = class {
579
692
  * @throws {Error} If the tool does not exist
580
693
  */
581
694
  async executeTool(toolName, inputArgsJson) {
582
- console.log(`[Model Context Testing] Executing tool: ${toolName}`);
583
695
  let args;
584
696
  try {
585
697
  args = JSON.parse(inputArgsJson);
@@ -616,7 +728,6 @@ var WebModelContextTesting = class {
616
728
  */
617
729
  registerToolsChangedCallback(callback) {
618
730
  this.toolsChangedCallbacks.add(callback);
619
- console.log("[Model Context Testing] Tools changed callback registered");
620
731
  }
621
732
  /**
622
733
  * Gets all tool calls that have been recorded (polyfill extension).
@@ -631,7 +742,6 @@ var WebModelContextTesting = class {
631
742
  */
632
743
  clearToolCalls() {
633
744
  this.toolCallHistory = [];
634
- console.log("[Model Context Testing] Tool call history cleared");
635
745
  }
636
746
  /**
637
747
  * Sets a mock response for a specific tool (polyfill extension).
@@ -642,7 +752,6 @@ var WebModelContextTesting = class {
642
752
  */
643
753
  setMockToolResponse(toolName, response) {
644
754
  this.mockResponses.set(toolName, response);
645
- console.log(`[Model Context Testing] Mock response set for tool: ${toolName}`);
646
755
  }
647
756
  /**
648
757
  * Clears the mock response for a specific tool (polyfill extension).
@@ -651,14 +760,12 @@ var WebModelContextTesting = class {
651
760
  */
652
761
  clearMockToolResponse(toolName) {
653
762
  this.mockResponses.delete(toolName);
654
- console.log(`[Model Context Testing] Mock response cleared for tool: ${toolName}`);
655
763
  }
656
764
  /**
657
765
  * Clears all mock tool responses (polyfill extension).
658
766
  */
659
767
  clearAllMockToolResponses() {
660
768
  this.mockResponses.clear();
661
- console.log("[Model Context Testing] All mock responses cleared");
662
769
  }
663
770
  /**
664
771
  * Gets the current tools registered in the system (polyfill extension).
@@ -675,7 +782,6 @@ var WebModelContextTesting = class {
675
782
  reset() {
676
783
  this.clearToolCalls();
677
784
  this.clearAllMockToolResponses();
678
- console.log("[Model Context Testing] Testing state reset");
679
785
  }
680
786
  };
681
787
  /**
@@ -781,14 +887,13 @@ var WebModelContext = class {
781
887
  * @throws {Error} If a name/uri collides with existing dynamic items
782
888
  */
783
889
  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
890
  this.provideContextTools.clear();
789
891
  this.provideContextResources.clear();
790
892
  this.provideContextPrompts.clear();
791
893
  for (const tool of context.tools ?? []) {
894
+ 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.`);
895
+ 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.`);
896
+ 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
897
  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
898
  const { jsonSchema: inputJson, zodValidator: inputZod } = normalizeSchema(tool.inputSchema);
794
899
  const normalizedOutput = tool.outputSchema ? normalizeSchema(tool.outputSchema) : null;
@@ -826,11 +931,11 @@ var WebModelContext = class {
826
931
  * @private
827
932
  */
828
933
  validateResource(resource) {
829
- const templateParamRegex = /\{([^}]+)\}/g;
934
+ const templateParamRegex = /\{([^}]{1,100})\}/g;
830
935
  const templateParams = [];
831
936
  for (const match of resource.uri.matchAll(templateParamRegex)) {
832
937
  const paramName = match[1];
833
- if (paramName) templateParams.push(paramName);
938
+ templateParams.push(paramName);
834
939
  }
835
940
  return {
836
941
  uri: resource.uri,
@@ -871,11 +976,13 @@ var WebModelContext = class {
871
976
  * @throws {Error} If tool name collides with existing tools
872
977
  */
873
978
  registerTool(tool) {
874
- console.log(`[Web Model Context] Registering tool dynamically: ${tool.name}`);
979
+ 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.`);
980
+ 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.`);
981
+ 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
982
  const now = Date.now();
876
983
  const lastRegistration = this.toolRegistrationTimestamps.get(tool.name);
877
984
  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.`);
985
+ 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
986
  const existingUnregister = this.toolUnregisterFunctions.get(tool.name);
880
987
  if (existingUnregister) return { unregister: existingUnregister };
881
988
  }
@@ -898,10 +1005,9 @@ var WebModelContext = class {
898
1005
  this.updateBridgeTools();
899
1006
  this.scheduleListChanged("tools");
900
1007
  const unregisterFn = () => {
901
- console.log(`[Web Model Context] Unregistering tool: ${tool.name}`);
902
1008
  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
1009
  if (!this.dynamicTools.has(tool.name)) {
904
- console.warn(`[Web Model Context] Tool "${tool.name}" is not registered, ignoring unregister call`);
1010
+ logger$1.warn(`Tool "${tool.name}" is not registered, ignoring unregister call`);
905
1011
  return;
906
1012
  }
907
1013
  this.dynamicTools.delete(tool.name);
@@ -922,11 +1028,10 @@ var WebModelContext = class {
922
1028
  * @throws {Error} If resource URI collides with existing resources
923
1029
  */
924
1030
  registerResource(resource) {
925
- console.log(`[Web Model Context] Registering resource dynamically: ${resource.uri}`);
926
1031
  const now = Date.now();
927
1032
  const lastRegistration = this.resourceRegistrationTimestamps.get(resource.uri);
928
1033
  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.`);
1034
+ 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
1035
  const existingUnregister = this.resourceUnregisterFunctions.get(resource.uri);
931
1036
  if (existingUnregister) return { unregister: existingUnregister };
932
1037
  }
@@ -938,10 +1043,9 @@ var WebModelContext = class {
938
1043
  this.updateBridgeResources();
939
1044
  this.scheduleListChanged("resources");
940
1045
  const unregisterFn = () => {
941
- console.log(`[Web Model Context] Unregistering resource: ${resource.uri}`);
942
1046
  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
1047
  if (!this.dynamicResources.has(resource.uri)) {
944
- console.warn(`[Web Model Context] Resource "${resource.uri}" is not registered, ignoring unregister call`);
1048
+ logger$1.warn(`Resource "${resource.uri}" is not registered, ignoring unregister call`);
945
1049
  return;
946
1050
  }
947
1051
  this.dynamicResources.delete(resource.uri);
@@ -960,11 +1064,10 @@ var WebModelContext = class {
960
1064
  * @param {string} uri - URI of the resource to unregister
961
1065
  */
962
1066
  unregisterResource(uri) {
963
- console.log(`[Web Model Context] Unregistering resource: ${uri}`);
964
1067
  const inProvideContext = this.provideContextResources.has(uri);
965
1068
  const inDynamic = this.dynamicResources.has(uri);
966
1069
  if (!inProvideContext && !inDynamic) {
967
- console.warn(`[Web Model Context] Resource "${uri}" is not registered, ignoring unregister call`);
1070
+ logger$1.warn(`Resource "${uri}" is not registered, ignoring unregister call`);
968
1071
  return;
969
1072
  }
970
1073
  if (inProvideContext) this.provideContextResources.delete(uri);
@@ -1013,11 +1116,10 @@ var WebModelContext = class {
1013
1116
  * @throws {Error} If prompt name collides with existing prompts
1014
1117
  */
1015
1118
  registerPrompt(prompt) {
1016
- console.log(`[Web Model Context] Registering prompt dynamically: ${prompt.name}`);
1017
1119
  const now = Date.now();
1018
1120
  const lastRegistration = this.promptRegistrationTimestamps.get(prompt.name);
1019
1121
  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.`);
1122
+ 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
1123
  const existingUnregister = this.promptUnregisterFunctions.get(prompt.name);
1022
1124
  if (existingUnregister) return { unregister: existingUnregister };
1023
1125
  }
@@ -1029,10 +1131,9 @@ var WebModelContext = class {
1029
1131
  this.updateBridgePrompts();
1030
1132
  this.scheduleListChanged("prompts");
1031
1133
  const unregisterFn = () => {
1032
- console.log(`[Web Model Context] Unregistering prompt: ${prompt.name}`);
1033
1134
  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
1135
  if (!this.dynamicPrompts.has(prompt.name)) {
1035
- console.warn(`[Web Model Context] Prompt "${prompt.name}" is not registered, ignoring unregister call`);
1136
+ logger$1.warn(`Prompt "${prompt.name}" is not registered, ignoring unregister call`);
1036
1137
  return;
1037
1138
  }
1038
1139
  this.dynamicPrompts.delete(prompt.name);
@@ -1051,11 +1152,10 @@ var WebModelContext = class {
1051
1152
  * @param {string} name - Name of the prompt to unregister
1052
1153
  */
1053
1154
  unregisterPrompt(name) {
1054
- console.log(`[Web Model Context] Unregistering prompt: ${name}`);
1055
1155
  const inProvideContext = this.provideContextPrompts.has(name);
1056
1156
  const inDynamic = this.dynamicPrompts.has(name);
1057
1157
  if (!inProvideContext && !inDynamic) {
1058
- console.warn(`[Web Model Context] Prompt "${name}" is not registered, ignoring unregister call`);
1158
+ logger$1.warn(`Prompt "${name}" is not registered, ignoring unregister call`);
1059
1159
  return;
1060
1160
  }
1061
1161
  if (inProvideContext) this.provideContextPrompts.delete(name);
@@ -1091,11 +1191,10 @@ var WebModelContext = class {
1091
1191
  * @param {string} name - Name of the tool to unregister
1092
1192
  */
1093
1193
  unregisterTool(name) {
1094
- console.log(`[Web Model Context] Unregistering tool: ${name}`);
1095
1194
  const inProvideContext = this.provideContextTools.has(name);
1096
1195
  const inDynamic = this.dynamicTools.has(name);
1097
1196
  if (!inProvideContext && !inDynamic) {
1098
- console.warn(`[Web Model Context] Tool "${name}" is not registered, ignoring unregister call`);
1197
+ logger$1.warn(`Tool "${name}" is not registered, ignoring unregister call`);
1099
1198
  return;
1100
1199
  }
1101
1200
  if (inProvideContext) this.provideContextTools.delete(name);
@@ -1112,7 +1211,6 @@ var WebModelContext = class {
1112
1211
  * Removes all tools, resources, and prompts registered via provideContext() and register* methods.
1113
1212
  */
1114
1213
  clearContext() {
1115
- console.log("[Web Model Context] Clearing all context (tools, resources, prompts)");
1116
1214
  this.provideContextTools.clear();
1117
1215
  this.dynamicTools.clear();
1118
1216
  this.toolRegistrationTimestamps.clear();
@@ -1142,7 +1240,6 @@ var WebModelContext = class {
1142
1240
  this.bridge.tools.clear();
1143
1241
  for (const [name, tool] of this.provideContextTools) this.bridge.tools.set(name, tool);
1144
1242
  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
1243
  }
1147
1244
  /**
1148
1245
  * Notifies all servers and testing callbacks that the tools list has changed.
@@ -1170,7 +1267,6 @@ var WebModelContext = class {
1170
1267
  this.bridge.resources.clear();
1171
1268
  for (const [uri, resource] of this.provideContextResources) this.bridge.resources.set(uri, resource);
1172
1269
  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
1270
  }
1175
1271
  /**
1176
1272
  * Notifies all servers that the resources list has changed.
@@ -1196,7 +1292,6 @@ var WebModelContext = class {
1196
1292
  this.bridge.prompts.clear();
1197
1293
  for (const [name, prompt] of this.provideContextPrompts) this.bridge.prompts.set(name, prompt);
1198
1294
  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
1295
  }
1201
1296
  /**
1202
1297
  * Notifies all servers that the prompts list has changed.
@@ -1239,7 +1334,7 @@ var WebModelContext = class {
1239
1334
  break;
1240
1335
  default: {
1241
1336
  const _exhaustive = listType;
1242
- console.error(`[Web Model Context] Unknown list type: ${_exhaustive}`);
1337
+ logger$1.error(`Unknown list type: ${_exhaustive}`);
1243
1338
  }
1244
1339
  }
1245
1340
  });
@@ -1254,23 +1349,34 @@ var WebModelContext = class {
1254
1349
  * @internal
1255
1350
  */
1256
1351
  async readResource(uri) {
1257
- console.log(`[Web Model Context] Reading resource: ${uri}`);
1258
1352
  const staticResource = this.bridge.resources.get(uri);
1259
1353
  if (staticResource && !staticResource.isTemplate) try {
1260
- const parsedUri = new URL(uri);
1354
+ let parsedUri;
1355
+ try {
1356
+ parsedUri = new URL(uri);
1357
+ } catch {
1358
+ parsedUri = new URL(`custom-scheme:///${encodeURIComponent(uri)}`);
1359
+ parsedUri.originalUri = uri;
1360
+ }
1261
1361
  return await staticResource.read(parsedUri);
1262
1362
  } catch (error) {
1263
- console.error(`[Web Model Context] Error reading resource ${uri}:`, error);
1363
+ logger$1.error(`Error reading resource ${uri}:`, error);
1264
1364
  throw error;
1265
1365
  }
1266
1366
  for (const resource of this.bridge.resources.values()) {
1267
1367
  if (!resource.isTemplate) continue;
1268
1368
  const params = this.matchUriTemplate(resource.uri, uri);
1269
1369
  if (params) try {
1270
- const parsedUri = new URL(uri);
1370
+ let parsedUri;
1371
+ try {
1372
+ parsedUri = new URL(uri);
1373
+ } catch {
1374
+ parsedUri = new URL(`custom-scheme:///${encodeURIComponent(uri)}`);
1375
+ parsedUri.originalUri = uri;
1376
+ }
1271
1377
  return await resource.read(parsedUri, params);
1272
1378
  } catch (error) {
1273
- console.error(`[Web Model Context] Error reading resource ${uri}:`, error);
1379
+ logger$1.error(`Error reading resource ${uri}:`, error);
1274
1380
  throw error;
1275
1381
  }
1276
1382
  }
@@ -1300,8 +1406,7 @@ var WebModelContext = class {
1300
1406
  const params = {};
1301
1407
  for (let i = 0; i < paramNames.length; i++) {
1302
1408
  const paramName = paramNames[i];
1303
- const paramValue = match[i + 1];
1304
- if (paramName !== void 0 && paramValue !== void 0) params[paramName] = paramValue;
1409
+ params[paramName] = match[i + 1];
1305
1410
  }
1306
1411
  return params;
1307
1412
  }
@@ -1315,20 +1420,19 @@ var WebModelContext = class {
1315
1420
  * @internal
1316
1421
  */
1317
1422
  async getPrompt(name, args) {
1318
- console.log(`[Web Model Context] Getting prompt: ${name}`);
1319
1423
  const prompt = this.bridge.prompts.get(name);
1320
1424
  if (!prompt) throw new Error(`Prompt not found: ${name}`);
1321
1425
  if (prompt.argsValidator && args) {
1322
1426
  const validation = validateWithZod(args, prompt.argsValidator);
1323
1427
  if (!validation.success) {
1324
- console.error(`[Web Model Context] Argument validation failed for prompt ${name}:`, validation.error);
1428
+ logger$1.error(`Argument validation failed for prompt ${name}:`, validation.error);
1325
1429
  throw new Error(`Argument validation error for prompt "${name}":\n${validation.error}`);
1326
1430
  }
1327
1431
  }
1328
1432
  try {
1329
1433
  return await prompt.get(args ?? {});
1330
1434
  } catch (error) {
1331
- console.error(`[Web Model Context] Error getting prompt ${name}:`, error);
1435
+ logger$1.error(`Error getting prompt ${name}:`, error);
1332
1436
  throw error;
1333
1437
  }
1334
1438
  }
@@ -1351,10 +1455,9 @@ var WebModelContext = class {
1351
1455
  async executeTool(toolName, args) {
1352
1456
  const tool = this.bridge.tools.get(toolName);
1353
1457
  if (!tool) throw new Error(`Tool not found: ${toolName}`);
1354
- console.log(`[Web Model Context] Validating input for tool: ${toolName}`);
1355
1458
  const validation = validateWithZod(args, tool.inputValidator);
1356
1459
  if (!validation.success) {
1357
- console.error(`[Web Model Context] Input validation failed for ${toolName}:`, validation.error);
1460
+ logger$1.error(`Input validation failed for ${toolName}:`, validation.error);
1358
1461
  return {
1359
1462
  content: [{
1360
1463
  type: "text",
@@ -1367,31 +1470,24 @@ var WebModelContext = class {
1367
1470
  if (this.testingAPI) this.testingAPI.recordToolCall(toolName, validatedArgs);
1368
1471
  if (this.testingAPI?.hasMockResponse(toolName)) {
1369
1472
  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
- }
1473
+ if (mockResponse) return mockResponse;
1374
1474
  }
1375
1475
  const event = new WebToolCallEvent(toolName, validatedArgs);
1376
1476
  this.dispatchEvent(event);
1377
1477
  if (event.defaultPrevented && event.hasResponse()) {
1378
1478
  const response = event.getResponse();
1379
- if (response) {
1380
- console.log(`[Web Model Context] Tool ${toolName} handled by event listener`);
1381
- return response;
1382
- }
1479
+ if (response) return response;
1383
1480
  }
1384
- console.log(`[Web Model Context] Executing tool: ${toolName}`);
1385
1481
  try {
1386
1482
  const response = await tool.execute(validatedArgs);
1387
1483
  if (tool.outputValidator && response.structuredContent) {
1388
1484
  const outputValidation = validateWithZod(response.structuredContent, tool.outputValidator);
1389
- if (!outputValidation.success) console.warn(`[Web Model Context] Output validation failed for ${toolName}:`, outputValidation.error);
1485
+ if (!outputValidation.success) logger$1.warn(`Output validation failed for ${toolName}:`, outputValidation.error);
1390
1486
  }
1391
- if (response.metadata && "willNavigate" in response.metadata) console.info(`[Web Model Context] Tool "${toolName}" will trigger navigation`, response.metadata);
1487
+ if (response.metadata && typeof response.metadata === "object" && "willNavigate" in response.metadata) logger$1.info(`Tool "${toolName}" will trigger navigation`, response.metadata);
1392
1488
  return response;
1393
1489
  } catch (error) {
1394
- console.error(`[Web Model Context] Error executing tool ${toolName}:`, error);
1490
+ logger$1.error(`Error executing tool ${toolName}:`, error);
1395
1491
  return {
1396
1492
  content: [{
1397
1493
  type: "text",
@@ -1425,7 +1521,6 @@ var WebModelContext = class {
1425
1521
  * @returns {Promise<SamplingResult>} The LLM completion result
1426
1522
  */
1427
1523
  async createMessage(params) {
1428
- console.log("[Web Model Context] Requesting sampling from client");
1429
1524
  const underlyingServer = this.bridge.tabServer.server;
1430
1525
  if (!underlyingServer?.createMessage) throw new Error("Sampling is not supported: no connected client with sampling capability");
1431
1526
  return underlyingServer.createMessage(params);
@@ -1438,7 +1533,6 @@ var WebModelContext = class {
1438
1533
  * @returns {Promise<ElicitationResult>} The user's response
1439
1534
  */
1440
1535
  async elicitInput(params) {
1441
- console.log("[Web Model Context] Requesting elicitation from client");
1442
1536
  const underlyingServer = this.bridge.tabServer.server;
1443
1537
  if (!underlyingServer?.elicitInput) throw new Error("Elicitation is not supported: no connected client with elicitation capability");
1444
1538
  return underlyingServer.elicitInput(params);
@@ -1453,16 +1547,13 @@ var WebModelContext = class {
1453
1547
  * @returns {MCPBridge} The initialized MCP bridge
1454
1548
  */
1455
1549
  function initializeMCPBridge(options) {
1456
- console.log("[Web Model Context] Initializing MCP bridge");
1457
1550
  const hostname = window.location.hostname || "localhost";
1458
1551
  const transportOptions = options?.transport;
1459
1552
  const setupServerHandlers = (server, bridge$1) => {
1460
1553
  server.setRequestHandler(ListToolsRequestSchema, async () => {
1461
- console.log("[MCP Bridge] Handling list_tools request");
1462
1554
  return { tools: bridge$1.modelContext.listTools() };
1463
1555
  });
1464
1556
  server.setRequestHandler(CallToolRequestSchema, async (request) => {
1465
- console.log(`[MCP Bridge] Handling call_tool request: ${request.params.name}`);
1466
1557
  const toolName = request.params.name;
1467
1558
  const args = request.params.arguments || {};
1468
1559
  try {
@@ -1473,40 +1564,35 @@ function initializeMCPBridge(options) {
1473
1564
  ...response.structuredContent && { structuredContent: response.structuredContent }
1474
1565
  };
1475
1566
  } catch (error) {
1476
- console.error(`[MCP Bridge] Error calling tool ${toolName}:`, error);
1567
+ bridgeLogger.error(`Error calling tool ${toolName}:`, error);
1477
1568
  throw error;
1478
1569
  }
1479
1570
  });
1480
1571
  server.setRequestHandler(ListResourcesRequestSchema, async () => {
1481
- console.log("[MCP Bridge] Handling list_resources request");
1482
1572
  return { resources: bridge$1.modelContext.listResources() };
1483
1573
  });
1484
1574
  server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
1485
- console.log(`[MCP Bridge] Handling read_resource request: ${request.params.uri}`);
1486
1575
  try {
1487
1576
  return await bridge$1.modelContext.readResource(request.params.uri);
1488
1577
  } catch (error) {
1489
- console.error(`[MCP Bridge] Error reading resource ${request.params.uri}:`, error);
1578
+ bridgeLogger.error(`Error reading resource ${request.params.uri}:`, error);
1490
1579
  throw error;
1491
1580
  }
1492
1581
  });
1493
1582
  server.setRequestHandler(ListPromptsRequestSchema, async () => {
1494
- console.log("[MCP Bridge] Handling list_prompts request");
1495
1583
  return { prompts: bridge$1.modelContext.listPrompts() };
1496
1584
  });
1497
1585
  server.setRequestHandler(GetPromptRequestSchema, async (request) => {
1498
- console.log(`[MCP Bridge] Handling get_prompt request: ${request.params.name}`);
1499
1586
  try {
1500
1587
  return await bridge$1.modelContext.getPrompt(request.params.name, request.params.arguments);
1501
1588
  } catch (error) {
1502
- console.error(`[MCP Bridge] Error getting prompt ${request.params.name}:`, error);
1589
+ bridgeLogger.error(`Error getting prompt ${request.params.name}:`, error);
1503
1590
  throw error;
1504
1591
  }
1505
1592
  });
1506
1593
  };
1507
1594
  const customTransport = transportOptions?.create?.();
1508
1595
  if (customTransport) {
1509
- console.log("[Web Model Context] Using custom transport");
1510
1596
  const server = new Server({
1511
1597
  name: hostname,
1512
1598
  version: "1.0.0"
@@ -1526,10 +1612,8 @@ function initializeMCPBridge(options) {
1526
1612
  bridge$1.modelContext = new WebModelContext(bridge$1);
1527
1613
  setupServerHandlers(server, bridge$1);
1528
1614
  server.connect(customTransport);
1529
- console.log("[Web Model Context] MCP server connected with custom transport");
1530
1615
  return bridge$1;
1531
1616
  }
1532
- console.log("[Web Model Context] Using dual-server mode");
1533
1617
  const tabServerEnabled = transportOptions?.tabServer !== false;
1534
1618
  const tabServer = new Server({
1535
1619
  name: `${hostname}-tab`,
@@ -1556,12 +1640,10 @@ function initializeMCPBridge(options) {
1556
1640
  ...restTabServerOptions
1557
1641
  });
1558
1642
  tabServer.connect(tabTransport);
1559
- console.log("[Web Model Context] Tab server connected");
1560
1643
  }
1561
1644
  const isInIframe = typeof window !== "undefined" && window.parent !== window;
1562
1645
  const iframeServerConfig = transportOptions?.iframeServer;
1563
1646
  if (iframeServerConfig !== false && (iframeServerConfig !== void 0 || isInIframe)) {
1564
- console.log("[Web Model Context] Enabling iframe server");
1565
1647
  const iframeServer = new Server({
1566
1648
  name: `${hostname}-iframe`,
1567
1649
  version: "1.0.0"
@@ -1578,7 +1660,6 @@ function initializeMCPBridge(options) {
1578
1660
  });
1579
1661
  iframeServer.connect(iframeTransport);
1580
1662
  bridge.iframeServer = iframeServer;
1581
- console.log("[Web Model Context] Iframe server connected");
1582
1663
  }
1583
1664
  return bridge;
1584
1665
  }
@@ -1603,8 +1684,9 @@ function initializeMCPBridge(options) {
1603
1684
  * ```
1604
1685
  */
1605
1686
  function initializeWebModelContext(options) {
1687
+ /* c8 ignore next 4 */
1606
1688
  if (typeof window === "undefined") {
1607
- console.warn("[Web Model Context] Not in browser environment, skipping initialization");
1689
+ logger$1.warn("Not in browser environment, skipping initialization");
1608
1690
  return;
1609
1691
  }
1610
1692
  const effectiveOptions = options ?? window.__webModelContextOptions;
@@ -1613,12 +1695,12 @@ function initializeWebModelContext(options) {
1613
1695
  const nativeContext = window.navigator.modelContext;
1614
1696
  const nativeTesting = window.navigator.modelContextTesting;
1615
1697
  if (!nativeContext || !nativeTesting) {
1616
- console.error("[Web Model Context] Native API detection mismatch");
1698
+ logger$1.error("Native API detection mismatch");
1617
1699
  return;
1618
1700
  }
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");
1701
+ logger$1.info("✅ Native Chromium API detected");
1702
+ logger$1.info(" Using native implementation with MCP bridge synchronization");
1703
+ logger$1.info(" Native API will automatically collect tools from embedded iframes");
1622
1704
  try {
1623
1705
  const bridge = initializeMCPBridge(effectiveOptions);
1624
1706
  bridge.modelContext = new NativeModelContextAdapter(bridge, nativeContext, nativeTesting);
@@ -1628,29 +1710,29 @@ function initializeWebModelContext(options) {
1628
1710
  writable: false,
1629
1711
  configurable: true
1630
1712
  });
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");
1713
+ logger$1.info("✅ MCP bridge synced with native API");
1714
+ logger$1.info(" MCP clients will receive automatic tool updates from native registry");
1633
1715
  } catch (error) {
1634
- console.error("[Web Model Context] Failed to initialize native adapter:", error);
1716
+ logger$1.error("Failed to initialize native adapter:", error);
1635
1717
  throw error;
1636
1718
  }
1637
1719
  return;
1638
1720
  }
1639
1721
  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");
1722
+ logger$1.warn("Partial native API detected");
1723
+ logger$1.warn(" navigator.modelContext exists but navigator.modelContextTesting is missing");
1724
+ logger$1.warn(" Cannot sync with native API. Please enable experimental features:");
1725
+ logger$1.warn(" - Navigate to chrome://flags");
1726
+ logger$1.warn(" - Enable \"Experimental Web Platform Features\"");
1727
+ logger$1.warn(" - Or launch with: --enable-experimental-web-platform-features");
1728
+ logger$1.warn(" Skipping initialization to avoid conflicts");
1647
1729
  return;
1648
1730
  }
1649
1731
  if (window.navigator.modelContext) {
1650
- console.warn("[Web Model Context] window.navigator.modelContext already exists, skipping initialization");
1732
+ logger$1.warn("window.navigator.modelContext already exists, skipping initialization");
1651
1733
  return;
1652
1734
  }
1653
- console.log("[Web Model Context] Native API not detected, installing polyfill");
1735
+ logger$1.info("Native API not detected, installing polyfill");
1654
1736
  try {
1655
1737
  const bridge = initializeMCPBridge(effectiveOptions);
1656
1738
  Object.defineProperty(window.navigator, "modelContext", {
@@ -1663,12 +1745,12 @@ function initializeWebModelContext(options) {
1663
1745
  writable: false,
1664
1746
  configurable: true
1665
1747
  });
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");
1748
+ logger$1.info("✅ window.navigator.modelContext initialized successfully");
1749
+ testingLogger.info("Installing polyfill");
1750
+ testingLogger.info(" 💡 To use the native implementation in Chromium:");
1751
+ testingLogger.info(" - Navigate to chrome://flags");
1752
+ testingLogger.info(" - Enable \"Experimental Web Platform Features\"");
1753
+ testingLogger.info(" - Or launch with: --enable-experimental-web-platform-features");
1672
1754
  const testingAPI = new WebModelContextTesting(bridge);
1673
1755
  bridge.modelContextTesting = testingAPI;
1674
1756
  bridge.modelContext.setTestingAPI(testingAPI);
@@ -1677,9 +1759,9 @@ function initializeWebModelContext(options) {
1677
1759
  writable: false,
1678
1760
  configurable: true
1679
1761
  });
1680
- console.log("✅ [Model Context Testing] Polyfill installed at window.navigator.modelContextTesting");
1762
+ testingLogger.info("✅ Polyfill installed at window.navigator.modelContextTesting");
1681
1763
  } catch (error) {
1682
- console.error("[Web Model Context] Failed to initialize:", error);
1764
+ logger$1.error("Failed to initialize:", error);
1683
1765
  throw error;
1684
1766
  }
1685
1767
  }
@@ -1696,21 +1778,23 @@ function initializeWebModelContext(options) {
1696
1778
  * ```
1697
1779
  */
1698
1780
  function cleanupWebModelContext() {
1781
+ /* c8 ignore next */
1699
1782
  if (typeof window === "undefined") return;
1700
1783
  if (window.__mcpBridge) try {
1701
1784
  window.__mcpBridge.tabServer.close();
1702
1785
  if (window.__mcpBridge.iframeServer) window.__mcpBridge.iframeServer.close();
1703
1786
  } catch (error) {
1704
- console.warn("[Web Model Context] Error closing MCP servers:", error);
1787
+ logger$1.warn("Error closing MCP servers:", error);
1705
1788
  }
1706
1789
  delete window.navigator.modelContext;
1707
1790
  delete window.navigator.modelContextTesting;
1708
1791
  delete window.__mcpBridge;
1709
- console.log("[Web Model Context] Cleaned up");
1792
+ logger$1.info("Cleaned up");
1710
1793
  }
1711
1794
 
1712
1795
  //#endregion
1713
1796
  //#region src/index.ts
1797
+ const logger = createLogger("WebModelContext");
1714
1798
  function mergeTransportOptions(base, override) {
1715
1799
  if (!base) return override;
1716
1800
  if (!override) return base;
@@ -1738,7 +1822,7 @@ function parseScriptTagOptions(script) {
1738
1822
  if (dataset.webmcpOptions) try {
1739
1823
  return JSON.parse(dataset.webmcpOptions);
1740
1824
  } catch (error) {
1741
- console.error("[Web Model Context] Invalid JSON in data-webmcp-options:", error);
1825
+ logger.error("Invalid JSON in data-webmcp-options:", error);
1742
1826
  return;
1743
1827
  }
1744
1828
  const options = {};
@@ -1781,10 +1865,10 @@ if (typeof window !== "undefined" && typeof document !== "undefined") {
1781
1865
  try {
1782
1866
  if (shouldAutoInitialize) initializeWebModelContext(mergedOptions);
1783
1867
  } catch (error) {
1784
- console.error("[Web Model Context] Auto-initialization failed:", error);
1868
+ logger.error("Auto-initialization failed:", error);
1785
1869
  }
1786
1870
  }
1787
1871
 
1788
1872
  //#endregion
1789
- export { cleanupWebModelContext, initializeWebModelContext, zodToJsonSchema };
1873
+ export { cleanupWebModelContext, createLogger, initializeWebModelContext, zodToJsonSchema };
1790
1874
  //# sourceMappingURL=index.js.map