@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/README.md +37 -0
- package/dist/index.d.ts +43 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.iife.js +4 -30
- package/dist/index.js +155 -119
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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)
|
|
1439
|
+
if (!outputValidation.success) logger$1.warn(`Output validation failed for ${toolName}:`, outputValidation.error);
|
|
1390
1440
|
}
|
|
1391
|
-
if (response.metadata && "willNavigate" in 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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1651
|
+
logger$1.error("Native API detection mismatch");
|
|
1617
1652
|
return;
|
|
1618
1653
|
}
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
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
|
-
|
|
1632
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
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
|
-
|
|
1685
|
+
logger$1.warn("window.navigator.modelContext already exists, skipping initialization");
|
|
1651
1686
|
return;
|
|
1652
1687
|
}
|
|
1653
|
-
|
|
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
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
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
|
-
|
|
1715
|
+
testingLogger.info("✅ Polyfill installed at window.navigator.modelContextTesting");
|
|
1681
1716
|
} catch (error) {
|
|
1682
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|