@mcp-b/global 1.1.2 → 1.1.3-beta.2
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.d.ts +590 -50
- package/dist/index.d.ts.map +1 -1
- package/dist/index.iife.js +5 -5
- package/dist/index.js +597 -65
- package/dist/index.js.map +1 -1
- package/package.json +4 -3
package/dist/index.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { IframeChildTransport, TabServerTransport } from "@mcp-b/transports";
|
|
2
|
-
import { CallToolRequestSchema, ListToolsRequestSchema, Server } from "@mcp-b/webmcp-ts-sdk";
|
|
2
|
+
import { CallToolRequestSchema, GetPromptRequestSchema, ListPromptsRequestSchema, ListResourcesRequestSchema, ListToolsRequestSchema, ReadResourceRequestSchema, Server } from "@mcp-b/webmcp-ts-sdk";
|
|
3
3
|
import { jsonSchemaToZod } from "@composio/json-schema-to-zod";
|
|
4
4
|
import { z } from "zod";
|
|
5
|
+
import { zodToJsonSchema as zodToJsonSchema$1 } from "zod-to-json-schema";
|
|
5
6
|
|
|
6
7
|
//#region src/validation.ts
|
|
7
8
|
/**
|
|
@@ -29,44 +30,17 @@ function jsonSchemaToZod$1(jsonSchema) {
|
|
|
29
30
|
}
|
|
30
31
|
/**
|
|
31
32
|
* Convert Zod schema object to JSON Schema
|
|
32
|
-
*
|
|
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
|
|
33
37
|
*/
|
|
34
38
|
function zodToJsonSchema(schema) {
|
|
35
|
-
const
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
let enumValues;
|
|
41
|
-
let items;
|
|
42
|
-
if (zodType instanceof z.ZodString) type = "string";
|
|
43
|
-
else if (zodType instanceof z.ZodNumber) type = "number";
|
|
44
|
-
else if (zodType instanceof z.ZodBoolean) type = "boolean";
|
|
45
|
-
else if (zodType instanceof z.ZodArray) {
|
|
46
|
-
type = "array";
|
|
47
|
-
const elementType = zodType.element;
|
|
48
|
-
if (elementType instanceof z.ZodString) items = { type: "string" };
|
|
49
|
-
else if (elementType instanceof z.ZodNumber) items = { type: "number" };
|
|
50
|
-
else if (elementType instanceof z.ZodBoolean) items = { type: "boolean" };
|
|
51
|
-
else items = { type: "string" };
|
|
52
|
-
} else if (zodType instanceof z.ZodObject) type = "object";
|
|
53
|
-
else if (zodType instanceof z.ZodEnum) {
|
|
54
|
-
type = "string";
|
|
55
|
-
const enumDef = zodType._def;
|
|
56
|
-
if (enumDef?.values) enumValues = enumDef.values;
|
|
57
|
-
}
|
|
58
|
-
const propertySchema = { type };
|
|
59
|
-
if (description) propertySchema.description = description;
|
|
60
|
-
if (enumValues) propertySchema.enum = enumValues;
|
|
61
|
-
if (items) propertySchema.items = items;
|
|
62
|
-
properties[key] = propertySchema;
|
|
63
|
-
if (!zodType.isOptional()) required.push(key);
|
|
64
|
-
}
|
|
65
|
-
return {
|
|
66
|
-
type: "object",
|
|
67
|
-
properties,
|
|
68
|
-
...required.length > 0 && { required }
|
|
69
|
-
};
|
|
39
|
+
const { $schema: _,...rest } = zodToJsonSchema$1(z.object(schema), {
|
|
40
|
+
$refStrategy: "none",
|
|
41
|
+
target: "jsonSchema7"
|
|
42
|
+
});
|
|
43
|
+
return rest;
|
|
70
44
|
}
|
|
71
45
|
/**
|
|
72
46
|
* Normalize a schema to both JSON Schema and Zod formats
|
|
@@ -326,6 +300,75 @@ var NativeModelContextAdapter = class {
|
|
|
326
300
|
}));
|
|
327
301
|
}
|
|
328
302
|
/**
|
|
303
|
+
* Registers a resource dynamically.
|
|
304
|
+
* Note: Native Chromium API does not yet support resources.
|
|
305
|
+
* This is a polyfill-only feature.
|
|
306
|
+
*/
|
|
307
|
+
registerResource(_resource) {
|
|
308
|
+
console.warn("[Native Adapter] registerResource is not supported by native API");
|
|
309
|
+
return { unregister: () => {} };
|
|
310
|
+
}
|
|
311
|
+
/**
|
|
312
|
+
* Unregisters a resource by URI.
|
|
313
|
+
* Note: Native Chromium API does not yet support resources.
|
|
314
|
+
*/
|
|
315
|
+
unregisterResource(_uri) {
|
|
316
|
+
console.warn("[Native Adapter] unregisterResource is not supported by native API");
|
|
317
|
+
}
|
|
318
|
+
/**
|
|
319
|
+
* Lists all registered resources.
|
|
320
|
+
* Note: Native Chromium API does not yet support resources.
|
|
321
|
+
*/
|
|
322
|
+
listResources() {
|
|
323
|
+
return [];
|
|
324
|
+
}
|
|
325
|
+
/**
|
|
326
|
+
* Lists all resource templates.
|
|
327
|
+
* Note: Native Chromium API does not yet support resources.
|
|
328
|
+
*/
|
|
329
|
+
listResourceTemplates() {
|
|
330
|
+
return [];
|
|
331
|
+
}
|
|
332
|
+
/**
|
|
333
|
+
* Reads a resource by URI.
|
|
334
|
+
* Note: Native Chromium API does not yet support resources.
|
|
335
|
+
* @internal
|
|
336
|
+
*/
|
|
337
|
+
async readResource(_uri) {
|
|
338
|
+
throw new Error("[Native Adapter] readResource is not supported by native API");
|
|
339
|
+
}
|
|
340
|
+
/**
|
|
341
|
+
* Registers a prompt dynamically.
|
|
342
|
+
* Note: Native Chromium API does not yet support prompts.
|
|
343
|
+
* This is a polyfill-only feature.
|
|
344
|
+
*/
|
|
345
|
+
registerPrompt(_prompt) {
|
|
346
|
+
console.warn("[Native Adapter] registerPrompt is not supported by native API");
|
|
347
|
+
return { unregister: () => {} };
|
|
348
|
+
}
|
|
349
|
+
/**
|
|
350
|
+
* Unregisters a prompt by name.
|
|
351
|
+
* Note: Native Chromium API does not yet support prompts.
|
|
352
|
+
*/
|
|
353
|
+
unregisterPrompt(_name) {
|
|
354
|
+
console.warn("[Native Adapter] unregisterPrompt is not supported by native API");
|
|
355
|
+
}
|
|
356
|
+
/**
|
|
357
|
+
* Lists all registered prompts.
|
|
358
|
+
* Note: Native Chromium API does not yet support prompts.
|
|
359
|
+
*/
|
|
360
|
+
listPrompts() {
|
|
361
|
+
return [];
|
|
362
|
+
}
|
|
363
|
+
/**
|
|
364
|
+
* Gets a prompt with arguments.
|
|
365
|
+
* Note: Native Chromium API does not yet support prompts.
|
|
366
|
+
* @internal
|
|
367
|
+
*/
|
|
368
|
+
async getPrompt(_name, _args) {
|
|
369
|
+
throw new Error("[Native Adapter] getPrompt is not supported by native API");
|
|
370
|
+
}
|
|
371
|
+
/**
|
|
329
372
|
* Adds an event listener for tool call events.
|
|
330
373
|
* Delegates to the native API's addEventListener.
|
|
331
374
|
*
|
|
@@ -357,6 +400,28 @@ var NativeModelContextAdapter = class {
|
|
|
357
400
|
dispatchEvent(event) {
|
|
358
401
|
return this.nativeContext.dispatchEvent(event);
|
|
359
402
|
}
|
|
403
|
+
/**
|
|
404
|
+
* Request an LLM completion from the connected client.
|
|
405
|
+
* Note: Native Chromium API does not yet support sampling.
|
|
406
|
+
* This is handled by the polyfill.
|
|
407
|
+
*/
|
|
408
|
+
async createMessage(params) {
|
|
409
|
+
console.log("[Native Adapter] Requesting sampling from client");
|
|
410
|
+
const underlyingServer = this.bridge.tabServer.server;
|
|
411
|
+
if (!underlyingServer?.createMessage) throw new Error("Sampling is not supported: no connected client with sampling capability");
|
|
412
|
+
return underlyingServer.createMessage(params);
|
|
413
|
+
}
|
|
414
|
+
/**
|
|
415
|
+
* Request user input from the connected client.
|
|
416
|
+
* Note: Native Chromium API does not yet support elicitation.
|
|
417
|
+
* This is handled by the polyfill.
|
|
418
|
+
*/
|
|
419
|
+
async elicitInput(params) {
|
|
420
|
+
console.log("[Native Adapter] Requesting elicitation from client");
|
|
421
|
+
const underlyingServer = this.bridge.tabServer.server;
|
|
422
|
+
if (!underlyingServer?.elicitInput) throw new Error("Elicitation is not supported: no connected client with elicitation capability");
|
|
423
|
+
return underlyingServer.elicitInput(params);
|
|
424
|
+
}
|
|
360
425
|
};
|
|
361
426
|
/**
|
|
362
427
|
* ToolCallEvent implementation for the Web Model Context API.
|
|
@@ -612,8 +677,16 @@ var WebModelContext = class {
|
|
|
612
677
|
eventTarget;
|
|
613
678
|
provideContextTools;
|
|
614
679
|
dynamicTools;
|
|
615
|
-
|
|
616
|
-
|
|
680
|
+
provideContextResources;
|
|
681
|
+
dynamicResources;
|
|
682
|
+
provideContextPrompts;
|
|
683
|
+
dynamicPrompts;
|
|
684
|
+
toolRegistrationTimestamps;
|
|
685
|
+
resourceRegistrationTimestamps;
|
|
686
|
+
promptRegistrationTimestamps;
|
|
687
|
+
toolUnregisterFunctions;
|
|
688
|
+
resourceUnregisterFunctions;
|
|
689
|
+
promptUnregisterFunctions;
|
|
617
690
|
testingAPI;
|
|
618
691
|
/**
|
|
619
692
|
* Creates a new WebModelContext instance.
|
|
@@ -625,8 +698,16 @@ var WebModelContext = class {
|
|
|
625
698
|
this.eventTarget = new EventTarget();
|
|
626
699
|
this.provideContextTools = /* @__PURE__ */ new Map();
|
|
627
700
|
this.dynamicTools = /* @__PURE__ */ new Map();
|
|
628
|
-
this.
|
|
629
|
-
this.
|
|
701
|
+
this.toolRegistrationTimestamps = /* @__PURE__ */ new Map();
|
|
702
|
+
this.toolUnregisterFunctions = /* @__PURE__ */ new Map();
|
|
703
|
+
this.provideContextResources = /* @__PURE__ */ new Map();
|
|
704
|
+
this.dynamicResources = /* @__PURE__ */ new Map();
|
|
705
|
+
this.resourceRegistrationTimestamps = /* @__PURE__ */ new Map();
|
|
706
|
+
this.resourceUnregisterFunctions = /* @__PURE__ */ new Map();
|
|
707
|
+
this.provideContextPrompts = /* @__PURE__ */ new Map();
|
|
708
|
+
this.dynamicPrompts = /* @__PURE__ */ new Map();
|
|
709
|
+
this.promptRegistrationTimestamps = /* @__PURE__ */ new Map();
|
|
710
|
+
this.promptUnregisterFunctions = /* @__PURE__ */ new Map();
|
|
630
711
|
}
|
|
631
712
|
/**
|
|
632
713
|
* Sets the testing API instance.
|
|
@@ -668,17 +749,22 @@ var WebModelContext = class {
|
|
|
668
749
|
return this.eventTarget.dispatchEvent(event);
|
|
669
750
|
}
|
|
670
751
|
/**
|
|
671
|
-
* Provides context (tools) to AI models by registering base
|
|
672
|
-
* Clears and replaces all previously registered base
|
|
673
|
-
* dynamic
|
|
752
|
+
* Provides context (tools, resources, prompts) to AI models by registering base items (Bucket A).
|
|
753
|
+
* Clears and replaces all previously registered base items while preserving
|
|
754
|
+
* dynamic items registered via register* methods.
|
|
674
755
|
*
|
|
675
|
-
* @param {ModelContextInput} context - Context containing tools to register
|
|
676
|
-
* @throws {Error} If a
|
|
756
|
+
* @param {ModelContextInput} context - Context containing tools, resources, and prompts to register
|
|
757
|
+
* @throws {Error} If a name/uri collides with existing dynamic items
|
|
677
758
|
*/
|
|
678
759
|
provideContext(context) {
|
|
679
|
-
|
|
760
|
+
const toolCount = context.tools?.length ?? 0;
|
|
761
|
+
const resourceCount = context.resources?.length ?? 0;
|
|
762
|
+
const promptCount = context.prompts?.length ?? 0;
|
|
763
|
+
console.log(`[Web Model Context] provideContext: ${toolCount} tools, ${resourceCount} resources, ${promptCount} prompts`);
|
|
680
764
|
this.provideContextTools.clear();
|
|
681
|
-
|
|
765
|
+
this.provideContextResources.clear();
|
|
766
|
+
this.provideContextPrompts.clear();
|
|
767
|
+
for (const tool of context.tools ?? []) {
|
|
682
768
|
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.`);
|
|
683
769
|
const { jsonSchema: inputJson, zodValidator: inputZod } = normalizeSchema(tool.inputSchema);
|
|
684
770
|
const normalizedOutput = tool.outputSchema ? normalizeSchema(tool.outputSchema) : null;
|
|
@@ -694,8 +780,63 @@ var WebModelContext = class {
|
|
|
694
780
|
};
|
|
695
781
|
this.provideContextTools.set(tool.name, validatedTool);
|
|
696
782
|
}
|
|
783
|
+
for (const resource of context.resources ?? []) {
|
|
784
|
+
if (this.dynamicResources.has(resource.uri)) throw new Error(`[Web Model Context] Resource URI collision: "${resource.uri}" is already registered via registerResource(). Please use a different URI or unregister the dynamic resource first.`);
|
|
785
|
+
const validatedResource = this.validateResource(resource);
|
|
786
|
+
this.provideContextResources.set(resource.uri, validatedResource);
|
|
787
|
+
}
|
|
788
|
+
for (const prompt of context.prompts ?? []) {
|
|
789
|
+
if (this.dynamicPrompts.has(prompt.name)) throw new Error(`[Web Model Context] Prompt name collision: "${prompt.name}" is already registered via registerPrompt(). Please use a different name or unregister the dynamic prompt first.`);
|
|
790
|
+
const validatedPrompt = this.validatePrompt(prompt);
|
|
791
|
+
this.provideContextPrompts.set(prompt.name, validatedPrompt);
|
|
792
|
+
}
|
|
697
793
|
this.updateBridgeTools();
|
|
794
|
+
this.updateBridgeResources();
|
|
795
|
+
this.updateBridgePrompts();
|
|
698
796
|
this.notifyToolsListChanged();
|
|
797
|
+
this.notifyResourcesListChanged();
|
|
798
|
+
this.notifyPromptsListChanged();
|
|
799
|
+
}
|
|
800
|
+
/**
|
|
801
|
+
* Validates and normalizes a resource descriptor.
|
|
802
|
+
* @private
|
|
803
|
+
*/
|
|
804
|
+
validateResource(resource) {
|
|
805
|
+
const templateParamRegex = /\{([^}]+)\}/g;
|
|
806
|
+
const templateParams = [];
|
|
807
|
+
for (const match of resource.uri.matchAll(templateParamRegex)) {
|
|
808
|
+
const paramName = match[1];
|
|
809
|
+
if (paramName) templateParams.push(paramName);
|
|
810
|
+
}
|
|
811
|
+
return {
|
|
812
|
+
uri: resource.uri,
|
|
813
|
+
name: resource.name,
|
|
814
|
+
description: resource.description,
|
|
815
|
+
mimeType: resource.mimeType,
|
|
816
|
+
read: resource.read,
|
|
817
|
+
isTemplate: templateParams.length > 0,
|
|
818
|
+
templateParams
|
|
819
|
+
};
|
|
820
|
+
}
|
|
821
|
+
/**
|
|
822
|
+
* Validates and normalizes a prompt descriptor.
|
|
823
|
+
* @private
|
|
824
|
+
*/
|
|
825
|
+
validatePrompt(prompt) {
|
|
826
|
+
let argsSchema;
|
|
827
|
+
let argsValidator;
|
|
828
|
+
if (prompt.argsSchema) {
|
|
829
|
+
const normalized = normalizeSchema(prompt.argsSchema);
|
|
830
|
+
argsSchema = normalized.jsonSchema;
|
|
831
|
+
argsValidator = normalized.zodValidator;
|
|
832
|
+
}
|
|
833
|
+
return {
|
|
834
|
+
name: prompt.name,
|
|
835
|
+
description: prompt.description,
|
|
836
|
+
argsSchema,
|
|
837
|
+
get: prompt.get,
|
|
838
|
+
argsValidator
|
|
839
|
+
};
|
|
699
840
|
}
|
|
700
841
|
/**
|
|
701
842
|
* Registers a single tool dynamically (Bucket B).
|
|
@@ -708,10 +849,10 @@ var WebModelContext = class {
|
|
|
708
849
|
registerTool(tool) {
|
|
709
850
|
console.log(`[Web Model Context] Registering tool dynamically: ${tool.name}`);
|
|
710
851
|
const now = Date.now();
|
|
711
|
-
const lastRegistration = this.
|
|
852
|
+
const lastRegistration = this.toolRegistrationTimestamps.get(tool.name);
|
|
712
853
|
if (lastRegistration && now - lastRegistration < RAPID_DUPLICATE_WINDOW_MS) {
|
|
713
854
|
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.`);
|
|
714
|
-
const existingUnregister = this.
|
|
855
|
+
const existingUnregister = this.toolUnregisterFunctions.get(tool.name);
|
|
715
856
|
if (existingUnregister) return { unregister: existingUnregister };
|
|
716
857
|
}
|
|
717
858
|
if (this.provideContextTools.has(tool.name)) throw new Error(`[Web Model Context] Tool name collision: "${tool.name}" is already registered via provideContext(). Please use a different name or update your provideContext() call.`);
|
|
@@ -729,7 +870,7 @@ var WebModelContext = class {
|
|
|
729
870
|
...normalizedOutput && { outputValidator: normalizedOutput.zodValidator }
|
|
730
871
|
};
|
|
731
872
|
this.dynamicTools.set(tool.name, validatedTool);
|
|
732
|
-
this.
|
|
873
|
+
this.toolRegistrationTimestamps.set(tool.name, now);
|
|
733
874
|
this.updateBridgeTools();
|
|
734
875
|
this.notifyToolsListChanged();
|
|
735
876
|
const unregisterFn = () => {
|
|
@@ -740,15 +881,186 @@ var WebModelContext = class {
|
|
|
740
881
|
return;
|
|
741
882
|
}
|
|
742
883
|
this.dynamicTools.delete(tool.name);
|
|
743
|
-
this.
|
|
744
|
-
this.
|
|
884
|
+
this.toolRegistrationTimestamps.delete(tool.name);
|
|
885
|
+
this.toolUnregisterFunctions.delete(tool.name);
|
|
745
886
|
this.updateBridgeTools();
|
|
746
887
|
this.notifyToolsListChanged();
|
|
747
888
|
};
|
|
748
|
-
this.
|
|
889
|
+
this.toolUnregisterFunctions.set(tool.name, unregisterFn);
|
|
749
890
|
return { unregister: unregisterFn };
|
|
750
891
|
}
|
|
751
892
|
/**
|
|
893
|
+
* Registers a single resource dynamically (Bucket B).
|
|
894
|
+
* Dynamic resources persist across provideContext() calls and can be independently managed.
|
|
895
|
+
*
|
|
896
|
+
* @param {ResourceDescriptor} resource - The resource descriptor to register
|
|
897
|
+
* @returns {{unregister: () => void}} Object with unregister function
|
|
898
|
+
* @throws {Error} If resource URI collides with existing resources
|
|
899
|
+
*/
|
|
900
|
+
registerResource(resource) {
|
|
901
|
+
console.log(`[Web Model Context] Registering resource dynamically: ${resource.uri}`);
|
|
902
|
+
const now = Date.now();
|
|
903
|
+
const lastRegistration = this.resourceRegistrationTimestamps.get(resource.uri);
|
|
904
|
+
if (lastRegistration && now - lastRegistration < RAPID_DUPLICATE_WINDOW_MS) {
|
|
905
|
+
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.`);
|
|
906
|
+
const existingUnregister = this.resourceUnregisterFunctions.get(resource.uri);
|
|
907
|
+
if (existingUnregister) return { unregister: existingUnregister };
|
|
908
|
+
}
|
|
909
|
+
if (this.provideContextResources.has(resource.uri)) throw new Error(`[Web Model Context] Resource URI collision: "${resource.uri}" is already registered via provideContext(). Please use a different URI or update your provideContext() call.`);
|
|
910
|
+
if (this.dynamicResources.has(resource.uri)) throw new Error(`[Web Model Context] Resource URI collision: "${resource.uri}" is already registered via registerResource(). Please unregister it first or use a different URI.`);
|
|
911
|
+
const validatedResource = this.validateResource(resource);
|
|
912
|
+
this.dynamicResources.set(resource.uri, validatedResource);
|
|
913
|
+
this.resourceRegistrationTimestamps.set(resource.uri, now);
|
|
914
|
+
this.updateBridgeResources();
|
|
915
|
+
this.notifyResourcesListChanged();
|
|
916
|
+
const unregisterFn = () => {
|
|
917
|
+
console.log(`[Web Model Context] Unregistering resource: ${resource.uri}`);
|
|
918
|
+
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.`);
|
|
919
|
+
if (!this.dynamicResources.has(resource.uri)) {
|
|
920
|
+
console.warn(`[Web Model Context] Resource "${resource.uri}" is not registered, ignoring unregister call`);
|
|
921
|
+
return;
|
|
922
|
+
}
|
|
923
|
+
this.dynamicResources.delete(resource.uri);
|
|
924
|
+
this.resourceRegistrationTimestamps.delete(resource.uri);
|
|
925
|
+
this.resourceUnregisterFunctions.delete(resource.uri);
|
|
926
|
+
this.updateBridgeResources();
|
|
927
|
+
this.notifyResourcesListChanged();
|
|
928
|
+
};
|
|
929
|
+
this.resourceUnregisterFunctions.set(resource.uri, unregisterFn);
|
|
930
|
+
return { unregister: unregisterFn };
|
|
931
|
+
}
|
|
932
|
+
/**
|
|
933
|
+
* Unregisters a resource by URI.
|
|
934
|
+
* Can unregister resources from either Bucket A (provideContext) or Bucket B (registerResource).
|
|
935
|
+
*
|
|
936
|
+
* @param {string} uri - URI of the resource to unregister
|
|
937
|
+
*/
|
|
938
|
+
unregisterResource(uri) {
|
|
939
|
+
console.log(`[Web Model Context] Unregistering resource: ${uri}`);
|
|
940
|
+
const inProvideContext = this.provideContextResources.has(uri);
|
|
941
|
+
const inDynamic = this.dynamicResources.has(uri);
|
|
942
|
+
if (!inProvideContext && !inDynamic) {
|
|
943
|
+
console.warn(`[Web Model Context] Resource "${uri}" is not registered, ignoring unregister call`);
|
|
944
|
+
return;
|
|
945
|
+
}
|
|
946
|
+
if (inProvideContext) this.provideContextResources.delete(uri);
|
|
947
|
+
if (inDynamic) {
|
|
948
|
+
this.dynamicResources.delete(uri);
|
|
949
|
+
this.resourceRegistrationTimestamps.delete(uri);
|
|
950
|
+
this.resourceUnregisterFunctions.delete(uri);
|
|
951
|
+
}
|
|
952
|
+
this.updateBridgeResources();
|
|
953
|
+
this.notifyResourcesListChanged();
|
|
954
|
+
}
|
|
955
|
+
/**
|
|
956
|
+
* Lists all registered resources in MCP format.
|
|
957
|
+
* Returns static resources from both buckets (not templates).
|
|
958
|
+
*
|
|
959
|
+
* @returns {Resource[]} Array of resource descriptors
|
|
960
|
+
*/
|
|
961
|
+
listResources() {
|
|
962
|
+
return Array.from(this.bridge.resources.values()).filter((r) => !r.isTemplate).map((resource) => ({
|
|
963
|
+
uri: resource.uri,
|
|
964
|
+
name: resource.name,
|
|
965
|
+
description: resource.description,
|
|
966
|
+
mimeType: resource.mimeType
|
|
967
|
+
}));
|
|
968
|
+
}
|
|
969
|
+
/**
|
|
970
|
+
* Lists all registered resource templates.
|
|
971
|
+
* Returns only resources with URI templates (dynamic resources).
|
|
972
|
+
*
|
|
973
|
+
* @returns {Array<{uriTemplate: string, name: string, description?: string, mimeType?: string}>}
|
|
974
|
+
*/
|
|
975
|
+
listResourceTemplates() {
|
|
976
|
+
return Array.from(this.bridge.resources.values()).filter((r) => r.isTemplate).map((resource) => ({
|
|
977
|
+
uriTemplate: resource.uri,
|
|
978
|
+
name: resource.name,
|
|
979
|
+
...resource.description !== void 0 && { description: resource.description },
|
|
980
|
+
...resource.mimeType !== void 0 && { mimeType: resource.mimeType }
|
|
981
|
+
}));
|
|
982
|
+
}
|
|
983
|
+
/**
|
|
984
|
+
* Registers a single prompt dynamically (Bucket B).
|
|
985
|
+
* Dynamic prompts persist across provideContext() calls and can be independently managed.
|
|
986
|
+
*
|
|
987
|
+
* @param {PromptDescriptor} prompt - The prompt descriptor to register
|
|
988
|
+
* @returns {{unregister: () => void}} Object with unregister function
|
|
989
|
+
* @throws {Error} If prompt name collides with existing prompts
|
|
990
|
+
*/
|
|
991
|
+
registerPrompt(prompt) {
|
|
992
|
+
console.log(`[Web Model Context] Registering prompt dynamically: ${prompt.name}`);
|
|
993
|
+
const now = Date.now();
|
|
994
|
+
const lastRegistration = this.promptRegistrationTimestamps.get(prompt.name);
|
|
995
|
+
if (lastRegistration && now - lastRegistration < RAPID_DUPLICATE_WINDOW_MS) {
|
|
996
|
+
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.`);
|
|
997
|
+
const existingUnregister = this.promptUnregisterFunctions.get(prompt.name);
|
|
998
|
+
if (existingUnregister) return { unregister: existingUnregister };
|
|
999
|
+
}
|
|
1000
|
+
if (this.provideContextPrompts.has(prompt.name)) throw new Error(`[Web Model Context] Prompt name collision: "${prompt.name}" is already registered via provideContext(). Please use a different name or update your provideContext() call.`);
|
|
1001
|
+
if (this.dynamicPrompts.has(prompt.name)) throw new Error(`[Web Model Context] Prompt name collision: "${prompt.name}" is already registered via registerPrompt(). Please unregister it first or use a different name.`);
|
|
1002
|
+
const validatedPrompt = this.validatePrompt(prompt);
|
|
1003
|
+
this.dynamicPrompts.set(prompt.name, validatedPrompt);
|
|
1004
|
+
this.promptRegistrationTimestamps.set(prompt.name, now);
|
|
1005
|
+
this.updateBridgePrompts();
|
|
1006
|
+
this.notifyPromptsListChanged();
|
|
1007
|
+
const unregisterFn = () => {
|
|
1008
|
+
console.log(`[Web Model Context] Unregistering prompt: ${prompt.name}`);
|
|
1009
|
+
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.`);
|
|
1010
|
+
if (!this.dynamicPrompts.has(prompt.name)) {
|
|
1011
|
+
console.warn(`[Web Model Context] Prompt "${prompt.name}" is not registered, ignoring unregister call`);
|
|
1012
|
+
return;
|
|
1013
|
+
}
|
|
1014
|
+
this.dynamicPrompts.delete(prompt.name);
|
|
1015
|
+
this.promptRegistrationTimestamps.delete(prompt.name);
|
|
1016
|
+
this.promptUnregisterFunctions.delete(prompt.name);
|
|
1017
|
+
this.updateBridgePrompts();
|
|
1018
|
+
this.notifyPromptsListChanged();
|
|
1019
|
+
};
|
|
1020
|
+
this.promptUnregisterFunctions.set(prompt.name, unregisterFn);
|
|
1021
|
+
return { unregister: unregisterFn };
|
|
1022
|
+
}
|
|
1023
|
+
/**
|
|
1024
|
+
* Unregisters a prompt by name.
|
|
1025
|
+
* Can unregister prompts from either Bucket A (provideContext) or Bucket B (registerPrompt).
|
|
1026
|
+
*
|
|
1027
|
+
* @param {string} name - Name of the prompt to unregister
|
|
1028
|
+
*/
|
|
1029
|
+
unregisterPrompt(name) {
|
|
1030
|
+
console.log(`[Web Model Context] Unregistering prompt: ${name}`);
|
|
1031
|
+
const inProvideContext = this.provideContextPrompts.has(name);
|
|
1032
|
+
const inDynamic = this.dynamicPrompts.has(name);
|
|
1033
|
+
if (!inProvideContext && !inDynamic) {
|
|
1034
|
+
console.warn(`[Web Model Context] Prompt "${name}" is not registered, ignoring unregister call`);
|
|
1035
|
+
return;
|
|
1036
|
+
}
|
|
1037
|
+
if (inProvideContext) this.provideContextPrompts.delete(name);
|
|
1038
|
+
if (inDynamic) {
|
|
1039
|
+
this.dynamicPrompts.delete(name);
|
|
1040
|
+
this.promptRegistrationTimestamps.delete(name);
|
|
1041
|
+
this.promptUnregisterFunctions.delete(name);
|
|
1042
|
+
}
|
|
1043
|
+
this.updateBridgePrompts();
|
|
1044
|
+
this.notifyPromptsListChanged();
|
|
1045
|
+
}
|
|
1046
|
+
/**
|
|
1047
|
+
* Lists all registered prompts in MCP format.
|
|
1048
|
+
* Returns prompts from both buckets.
|
|
1049
|
+
*
|
|
1050
|
+
* @returns {Prompt[]} Array of prompt descriptors
|
|
1051
|
+
*/
|
|
1052
|
+
listPrompts() {
|
|
1053
|
+
return Array.from(this.bridge.prompts.values()).map((prompt) => ({
|
|
1054
|
+
name: prompt.name,
|
|
1055
|
+
description: prompt.description,
|
|
1056
|
+
arguments: prompt.argsSchema?.properties ? Object.entries(prompt.argsSchema.properties).map(([name, schema]) => ({
|
|
1057
|
+
name,
|
|
1058
|
+
description: schema.description,
|
|
1059
|
+
required: prompt.argsSchema?.required?.includes(name) ?? false
|
|
1060
|
+
})) : void 0
|
|
1061
|
+
}));
|
|
1062
|
+
}
|
|
1063
|
+
/**
|
|
752
1064
|
* Unregisters a tool by name (Chromium native API).
|
|
753
1065
|
* Can unregister tools from either Bucket A (provideContext) or Bucket B (registerTool).
|
|
754
1066
|
*
|
|
@@ -765,24 +1077,36 @@ var WebModelContext = class {
|
|
|
765
1077
|
if (inProvideContext) this.provideContextTools.delete(name);
|
|
766
1078
|
if (inDynamic) {
|
|
767
1079
|
this.dynamicTools.delete(name);
|
|
768
|
-
this.
|
|
769
|
-
this.
|
|
1080
|
+
this.toolRegistrationTimestamps.delete(name);
|
|
1081
|
+
this.toolUnregisterFunctions.delete(name);
|
|
770
1082
|
}
|
|
771
1083
|
this.updateBridgeTools();
|
|
772
1084
|
this.notifyToolsListChanged();
|
|
773
1085
|
}
|
|
774
1086
|
/**
|
|
775
|
-
* Clears all registered
|
|
776
|
-
* Removes all tools registered via provideContext() and
|
|
1087
|
+
* Clears all registered context from both buckets (Chromium native API).
|
|
1088
|
+
* Removes all tools, resources, and prompts registered via provideContext() and register* methods.
|
|
777
1089
|
*/
|
|
778
1090
|
clearContext() {
|
|
779
|
-
console.log("[Web Model Context] Clearing all tools");
|
|
1091
|
+
console.log("[Web Model Context] Clearing all context (tools, resources, prompts)");
|
|
780
1092
|
this.provideContextTools.clear();
|
|
781
1093
|
this.dynamicTools.clear();
|
|
782
|
-
this.
|
|
783
|
-
this.
|
|
1094
|
+
this.toolRegistrationTimestamps.clear();
|
|
1095
|
+
this.toolUnregisterFunctions.clear();
|
|
1096
|
+
this.provideContextResources.clear();
|
|
1097
|
+
this.dynamicResources.clear();
|
|
1098
|
+
this.resourceRegistrationTimestamps.clear();
|
|
1099
|
+
this.resourceUnregisterFunctions.clear();
|
|
1100
|
+
this.provideContextPrompts.clear();
|
|
1101
|
+
this.dynamicPrompts.clear();
|
|
1102
|
+
this.promptRegistrationTimestamps.clear();
|
|
1103
|
+
this.promptUnregisterFunctions.clear();
|
|
784
1104
|
this.updateBridgeTools();
|
|
1105
|
+
this.updateBridgeResources();
|
|
1106
|
+
this.updateBridgePrompts();
|
|
785
1107
|
this.notifyToolsListChanged();
|
|
1108
|
+
this.notifyResourcesListChanged();
|
|
1109
|
+
this.notifyPromptsListChanged();
|
|
786
1110
|
}
|
|
787
1111
|
/**
|
|
788
1112
|
* Updates the bridge tools map with merged tools from both buckets.
|
|
@@ -814,6 +1138,146 @@ var WebModelContext = class {
|
|
|
814
1138
|
if (this.testingAPI && "notifyToolsChanged" in this.testingAPI) this.testingAPI.notifyToolsChanged();
|
|
815
1139
|
}
|
|
816
1140
|
/**
|
|
1141
|
+
* Updates the bridge resources map with merged resources from both buckets.
|
|
1142
|
+
*
|
|
1143
|
+
* @private
|
|
1144
|
+
*/
|
|
1145
|
+
updateBridgeResources() {
|
|
1146
|
+
this.bridge.resources.clear();
|
|
1147
|
+
for (const [uri, resource] of this.provideContextResources) this.bridge.resources.set(uri, resource);
|
|
1148
|
+
for (const [uri, resource] of this.dynamicResources) this.bridge.resources.set(uri, resource);
|
|
1149
|
+
console.log(`[Web Model Context] Updated bridge with ${this.provideContextResources.size} base resources + ${this.dynamicResources.size} dynamic resources = ${this.bridge.resources.size} total`);
|
|
1150
|
+
}
|
|
1151
|
+
/**
|
|
1152
|
+
* Notifies all servers that the resources list has changed.
|
|
1153
|
+
*
|
|
1154
|
+
* @private
|
|
1155
|
+
*/
|
|
1156
|
+
notifyResourcesListChanged() {
|
|
1157
|
+
if (this.bridge.tabServer.notification) this.bridge.tabServer.notification({
|
|
1158
|
+
method: "notifications/resources/list_changed",
|
|
1159
|
+
params: {}
|
|
1160
|
+
});
|
|
1161
|
+
if (this.bridge.iframeServer?.notification) this.bridge.iframeServer.notification({
|
|
1162
|
+
method: "notifications/resources/list_changed",
|
|
1163
|
+
params: {}
|
|
1164
|
+
});
|
|
1165
|
+
}
|
|
1166
|
+
/**
|
|
1167
|
+
* Updates the bridge prompts map with merged prompts from both buckets.
|
|
1168
|
+
*
|
|
1169
|
+
* @private
|
|
1170
|
+
*/
|
|
1171
|
+
updateBridgePrompts() {
|
|
1172
|
+
this.bridge.prompts.clear();
|
|
1173
|
+
for (const [name, prompt] of this.provideContextPrompts) this.bridge.prompts.set(name, prompt);
|
|
1174
|
+
for (const [name, prompt] of this.dynamicPrompts) this.bridge.prompts.set(name, prompt);
|
|
1175
|
+
console.log(`[Web Model Context] Updated bridge with ${this.provideContextPrompts.size} base prompts + ${this.dynamicPrompts.size} dynamic prompts = ${this.bridge.prompts.size} total`);
|
|
1176
|
+
}
|
|
1177
|
+
/**
|
|
1178
|
+
* Notifies all servers that the prompts list has changed.
|
|
1179
|
+
*
|
|
1180
|
+
* @private
|
|
1181
|
+
*/
|
|
1182
|
+
notifyPromptsListChanged() {
|
|
1183
|
+
if (this.bridge.tabServer.notification) this.bridge.tabServer.notification({
|
|
1184
|
+
method: "notifications/prompts/list_changed",
|
|
1185
|
+
params: {}
|
|
1186
|
+
});
|
|
1187
|
+
if (this.bridge.iframeServer?.notification) this.bridge.iframeServer.notification({
|
|
1188
|
+
method: "notifications/prompts/list_changed",
|
|
1189
|
+
params: {}
|
|
1190
|
+
});
|
|
1191
|
+
}
|
|
1192
|
+
/**
|
|
1193
|
+
* Reads a resource by URI (internal use only by MCP bridge).
|
|
1194
|
+
* Handles both static resources and URI templates.
|
|
1195
|
+
*
|
|
1196
|
+
* @param {string} uri - The URI of the resource to read
|
|
1197
|
+
* @returns {Promise<{contents: ResourceContents[]}>} The resource contents
|
|
1198
|
+
* @throws {Error} If resource is not found
|
|
1199
|
+
* @internal
|
|
1200
|
+
*/
|
|
1201
|
+
async readResource(uri) {
|
|
1202
|
+
console.log(`[Web Model Context] Reading resource: ${uri}`);
|
|
1203
|
+
const staticResource = this.bridge.resources.get(uri);
|
|
1204
|
+
if (staticResource && !staticResource.isTemplate) try {
|
|
1205
|
+
const parsedUri = new URL(uri);
|
|
1206
|
+
return await staticResource.read(parsedUri);
|
|
1207
|
+
} catch (error) {
|
|
1208
|
+
console.error(`[Web Model Context] Error reading resource ${uri}:`, error);
|
|
1209
|
+
throw error;
|
|
1210
|
+
}
|
|
1211
|
+
for (const resource of this.bridge.resources.values()) {
|
|
1212
|
+
if (!resource.isTemplate) continue;
|
|
1213
|
+
const params = this.matchUriTemplate(resource.uri, uri);
|
|
1214
|
+
if (params) try {
|
|
1215
|
+
const parsedUri = new URL(uri);
|
|
1216
|
+
return await resource.read(parsedUri, params);
|
|
1217
|
+
} catch (error) {
|
|
1218
|
+
console.error(`[Web Model Context] Error reading resource ${uri}:`, error);
|
|
1219
|
+
throw error;
|
|
1220
|
+
}
|
|
1221
|
+
}
|
|
1222
|
+
throw new Error(`Resource not found: ${uri}`);
|
|
1223
|
+
}
|
|
1224
|
+
/**
|
|
1225
|
+
* Matches a URI against a URI template and extracts parameters.
|
|
1226
|
+
*
|
|
1227
|
+
* @param {string} template - The URI template (e.g., "file://{path}")
|
|
1228
|
+
* @param {string} uri - The actual URI to match
|
|
1229
|
+
* @returns {Record<string, string> | null} Extracted parameters or null if no match
|
|
1230
|
+
* @private
|
|
1231
|
+
*/
|
|
1232
|
+
matchUriTemplate(template, uri) {
|
|
1233
|
+
const paramNames = [];
|
|
1234
|
+
let regexPattern = template.replace(/[.*+?^${}()|[\]\\]/g, (char) => {
|
|
1235
|
+
if (char === "{" || char === "}") return char;
|
|
1236
|
+
return `\\${char}`;
|
|
1237
|
+
});
|
|
1238
|
+
regexPattern = regexPattern.replace(/\{([^}]+)\}/g, (_, paramName) => {
|
|
1239
|
+
paramNames.push(paramName);
|
|
1240
|
+
return "(.+)";
|
|
1241
|
+
});
|
|
1242
|
+
const regex = /* @__PURE__ */ new RegExp(`^${regexPattern}$`);
|
|
1243
|
+
const match = uri.match(regex);
|
|
1244
|
+
if (!match) return null;
|
|
1245
|
+
const params = {};
|
|
1246
|
+
for (let i = 0; i < paramNames.length; i++) {
|
|
1247
|
+
const paramName = paramNames[i];
|
|
1248
|
+
const paramValue = match[i + 1];
|
|
1249
|
+
if (paramName !== void 0 && paramValue !== void 0) params[paramName] = paramValue;
|
|
1250
|
+
}
|
|
1251
|
+
return params;
|
|
1252
|
+
}
|
|
1253
|
+
/**
|
|
1254
|
+
* Gets a prompt with arguments (internal use only by MCP bridge).
|
|
1255
|
+
*
|
|
1256
|
+
* @param {string} name - Name of the prompt
|
|
1257
|
+
* @param {Record<string, unknown>} args - Arguments to pass to the prompt
|
|
1258
|
+
* @returns {Promise<{messages: PromptMessage[]}>} The prompt messages
|
|
1259
|
+
* @throws {Error} If prompt is not found
|
|
1260
|
+
* @internal
|
|
1261
|
+
*/
|
|
1262
|
+
async getPrompt(name, args) {
|
|
1263
|
+
console.log(`[Web Model Context] Getting prompt: ${name}`);
|
|
1264
|
+
const prompt = this.bridge.prompts.get(name);
|
|
1265
|
+
if (!prompt) throw new Error(`Prompt not found: ${name}`);
|
|
1266
|
+
if (prompt.argsValidator && args) {
|
|
1267
|
+
const validation = validateWithZod(args, prompt.argsValidator);
|
|
1268
|
+
if (!validation.success) {
|
|
1269
|
+
console.error(`[Web Model Context] Argument validation failed for prompt ${name}:`, validation.error);
|
|
1270
|
+
throw new Error(`Argument validation error for prompt "${name}":\n${validation.error}`);
|
|
1271
|
+
}
|
|
1272
|
+
}
|
|
1273
|
+
try {
|
|
1274
|
+
return await prompt.get(args ?? {});
|
|
1275
|
+
} catch (error) {
|
|
1276
|
+
console.error(`[Web Model Context] Error getting prompt ${name}:`, error);
|
|
1277
|
+
throw error;
|
|
1278
|
+
}
|
|
1279
|
+
}
|
|
1280
|
+
/**
|
|
817
1281
|
* Executes a tool with validation and event dispatch.
|
|
818
1282
|
* Follows this sequence:
|
|
819
1283
|
* 1. Validates input arguments against schema
|
|
@@ -897,6 +1361,32 @@ var WebModelContext = class {
|
|
|
897
1361
|
...tool.annotations && { annotations: tool.annotations }
|
|
898
1362
|
}));
|
|
899
1363
|
}
|
|
1364
|
+
/**
|
|
1365
|
+
* Request an LLM completion from the connected client.
|
|
1366
|
+
* This sends a sampling request to the connected MCP client.
|
|
1367
|
+
*
|
|
1368
|
+
* @param {SamplingRequestParams} params - Parameters for the sampling request
|
|
1369
|
+
* @returns {Promise<SamplingResult>} The LLM completion result
|
|
1370
|
+
*/
|
|
1371
|
+
async createMessage(params) {
|
|
1372
|
+
console.log("[Web Model Context] Requesting sampling from client");
|
|
1373
|
+
const underlyingServer = this.bridge.tabServer.server;
|
|
1374
|
+
if (!underlyingServer?.createMessage) throw new Error("Sampling is not supported: no connected client with sampling capability");
|
|
1375
|
+
return underlyingServer.createMessage(params);
|
|
1376
|
+
}
|
|
1377
|
+
/**
|
|
1378
|
+
* Request user input from the connected client.
|
|
1379
|
+
* This sends an elicitation request to the connected MCP client.
|
|
1380
|
+
*
|
|
1381
|
+
* @param {ElicitationParams} params - Parameters for the elicitation request
|
|
1382
|
+
* @returns {Promise<ElicitationResult>} The user's response
|
|
1383
|
+
*/
|
|
1384
|
+
async elicitInput(params) {
|
|
1385
|
+
console.log("[Web Model Context] Requesting elicitation from client");
|
|
1386
|
+
const underlyingServer = this.bridge.tabServer.server;
|
|
1387
|
+
if (!underlyingServer?.elicitInput) throw new Error("Elicitation is not supported: no connected client with elicitation capability");
|
|
1388
|
+
return underlyingServer.elicitInput(params);
|
|
1389
|
+
}
|
|
900
1390
|
};
|
|
901
1391
|
/**
|
|
902
1392
|
* Initializes the MCP bridge with dual-server support.
|
|
@@ -930,6 +1420,32 @@ function initializeMCPBridge(options) {
|
|
|
930
1420
|
throw error;
|
|
931
1421
|
}
|
|
932
1422
|
});
|
|
1423
|
+
server.setRequestHandler(ListResourcesRequestSchema, async () => {
|
|
1424
|
+
console.log("[MCP Bridge] Handling list_resources request");
|
|
1425
|
+
return { resources: bridge$1.modelContext.listResources() };
|
|
1426
|
+
});
|
|
1427
|
+
server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
|
|
1428
|
+
console.log(`[MCP Bridge] Handling read_resource request: ${request.params.uri}`);
|
|
1429
|
+
try {
|
|
1430
|
+
return await bridge$1.modelContext.readResource(request.params.uri);
|
|
1431
|
+
} catch (error) {
|
|
1432
|
+
console.error(`[MCP Bridge] Error reading resource ${request.params.uri}:`, error);
|
|
1433
|
+
throw error;
|
|
1434
|
+
}
|
|
1435
|
+
});
|
|
1436
|
+
server.setRequestHandler(ListPromptsRequestSchema, async () => {
|
|
1437
|
+
console.log("[MCP Bridge] Handling list_prompts request");
|
|
1438
|
+
return { prompts: bridge$1.modelContext.listPrompts() };
|
|
1439
|
+
});
|
|
1440
|
+
server.setRequestHandler(GetPromptRequestSchema, async (request) => {
|
|
1441
|
+
console.log(`[MCP Bridge] Handling get_prompt request: ${request.params.name}`);
|
|
1442
|
+
try {
|
|
1443
|
+
return await bridge$1.modelContext.getPrompt(request.params.name, request.params.arguments);
|
|
1444
|
+
} catch (error) {
|
|
1445
|
+
console.error(`[MCP Bridge] Error getting prompt ${request.params.name}:`, error);
|
|
1446
|
+
throw error;
|
|
1447
|
+
}
|
|
1448
|
+
});
|
|
933
1449
|
};
|
|
934
1450
|
const customTransport = transportOptions?.create?.();
|
|
935
1451
|
if (customTransport) {
|
|
@@ -937,10 +1453,16 @@ function initializeMCPBridge(options) {
|
|
|
937
1453
|
const server = new Server({
|
|
938
1454
|
name: hostname,
|
|
939
1455
|
version: "1.0.0"
|
|
940
|
-
}, { capabilities: {
|
|
1456
|
+
}, { capabilities: {
|
|
1457
|
+
tools: { listChanged: true },
|
|
1458
|
+
resources: { listChanged: true },
|
|
1459
|
+
prompts: { listChanged: true }
|
|
1460
|
+
} });
|
|
941
1461
|
const bridge$1 = {
|
|
942
1462
|
tabServer: server,
|
|
943
1463
|
tools: /* @__PURE__ */ new Map(),
|
|
1464
|
+
resources: /* @__PURE__ */ new Map(),
|
|
1465
|
+
prompts: /* @__PURE__ */ new Map(),
|
|
944
1466
|
modelContext: void 0,
|
|
945
1467
|
isInitialized: true
|
|
946
1468
|
};
|
|
@@ -955,10 +1477,16 @@ function initializeMCPBridge(options) {
|
|
|
955
1477
|
const tabServer = new Server({
|
|
956
1478
|
name: `${hostname}-tab`,
|
|
957
1479
|
version: "1.0.0"
|
|
958
|
-
}, { capabilities: {
|
|
1480
|
+
}, { capabilities: {
|
|
1481
|
+
tools: { listChanged: true },
|
|
1482
|
+
resources: { listChanged: true },
|
|
1483
|
+
prompts: { listChanged: true }
|
|
1484
|
+
} });
|
|
959
1485
|
const bridge = {
|
|
960
1486
|
tabServer,
|
|
961
1487
|
tools: /* @__PURE__ */ new Map(),
|
|
1488
|
+
resources: /* @__PURE__ */ new Map(),
|
|
1489
|
+
prompts: /* @__PURE__ */ new Map(),
|
|
962
1490
|
modelContext: void 0,
|
|
963
1491
|
isInitialized: true
|
|
964
1492
|
};
|
|
@@ -980,7 +1508,11 @@ function initializeMCPBridge(options) {
|
|
|
980
1508
|
const iframeServer = new Server({
|
|
981
1509
|
name: `${hostname}-iframe`,
|
|
982
1510
|
version: "1.0.0"
|
|
983
|
-
}, { capabilities: {
|
|
1511
|
+
}, { capabilities: {
|
|
1512
|
+
tools: { listChanged: true },
|
|
1513
|
+
resources: { listChanged: true },
|
|
1514
|
+
prompts: { listChanged: true }
|
|
1515
|
+
} });
|
|
984
1516
|
setupServerHandlers(iframeServer, bridge);
|
|
985
1517
|
const { allowedOrigins,...restIframeServerOptions } = typeof iframeServerConfig === "object" ? iframeServerConfig : {};
|
|
986
1518
|
const iframeTransport = new IframeChildTransport({
|
|
@@ -1197,5 +1729,5 @@ if (typeof window !== "undefined" && typeof document !== "undefined") {
|
|
|
1197
1729
|
}
|
|
1198
1730
|
|
|
1199
1731
|
//#endregion
|
|
1200
|
-
export { cleanupWebModelContext, initializeWebModelContext };
|
|
1732
|
+
export { cleanupWebModelContext, initializeWebModelContext, zodToJsonSchema };
|
|
1201
1733
|
//# sourceMappingURL=index.js.map
|