@mcp-b/webmcp-ts-sdk 5.0.1 → 5.0.3
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 +1 -0
- package/dist/index.js +41 -7
- package/dist/index.js.map +1 -1
- package/package.json +7 -5
package/dist/index.d.ts
CHANGED
|
@@ -21,6 +21,7 @@ declare class BrowserMcpServer extends EventTarget implements ModelContextWithEx
|
|
|
21
21
|
private readonly ownerDocument;
|
|
22
22
|
private readonly tools;
|
|
23
23
|
private peerOrigin;
|
|
24
|
+
private stopObservingPeerOrigin;
|
|
24
25
|
private readonly registrations;
|
|
25
26
|
private readonly nativeToolAbortControllers;
|
|
26
27
|
private readonly nativeBackfilledTools;
|
package/dist/index.js
CHANGED
|
@@ -57,6 +57,7 @@ var BrowserMcpServer = class extends EventTarget {
|
|
|
57
57
|
ownerDocument;
|
|
58
58
|
tools = /* @__PURE__ */ new Map();
|
|
59
59
|
peerOrigin;
|
|
60
|
+
stopObservingPeerOrigin;
|
|
60
61
|
registrations = /* @__PURE__ */ new Set();
|
|
61
62
|
nativeToolAbortControllers = /* @__PURE__ */ new Map();
|
|
62
63
|
nativeBackfilledTools = /* @__PURE__ */ new Map();
|
|
@@ -184,7 +185,11 @@ var BrowserMcpServer = class extends EventTarget {
|
|
|
184
185
|
};
|
|
185
186
|
}
|
|
186
187
|
registerTool = async (toolValue, optionsValue = {}) => {
|
|
187
|
-
const
|
|
188
|
+
const { signal, exposedTo } = optionsValue ?? {};
|
|
189
|
+
const options = {
|
|
190
|
+
...signal ? { signal } : {},
|
|
191
|
+
...exposedTo ? { exposedTo: [...exposedTo] } : {}
|
|
192
|
+
};
|
|
188
193
|
validateWebMcpAccess(this.ownerDocument);
|
|
189
194
|
if (this.closed) throw createInvalidStateError("BrowserMcpServer is closed");
|
|
190
195
|
if (!isPlainObject(toolValue)) throw new TypeError("registerTool(tool) requires a tool object");
|
|
@@ -210,7 +215,10 @@ var BrowserMcpServer = class extends EventTarget {
|
|
|
210
215
|
await this.registerNativeToolMirror(tool, normalized, options, execute, controller);
|
|
211
216
|
if (this.closed) throw createInvalidStateError("BrowserMcpServer is closed");
|
|
212
217
|
options.signal?.throwIfAborted();
|
|
213
|
-
registered = this.registerToolInMcp(tool, normalized, execute, options.exposedTo)
|
|
218
|
+
registered = this.registerToolInMcp(tool, normalized, execute, options.exposedTo?.map((origin) => {
|
|
219
|
+
const parsedOrigin = new URL(origin).origin;
|
|
220
|
+
return parsedOrigin === "null" ? origin : parsedOrigin;
|
|
221
|
+
}));
|
|
214
222
|
this.tools.set(tool.name, registered);
|
|
215
223
|
this.applyToolExposure();
|
|
216
224
|
if (options.signal?.aborted) {
|
|
@@ -419,7 +427,7 @@ var BrowserMcpServer = class extends EventTarget {
|
|
|
419
427
|
applyToolExposure() {
|
|
420
428
|
for (const { exposedTo, mcpHandle } of this.tools.values()) {
|
|
421
429
|
if (!exposedTo?.length || !mcpHandle) continue;
|
|
422
|
-
const visible = this.peerOrigin !== void 0 && exposedTo.includes(this.peerOrigin);
|
|
430
|
+
const visible = this.peerOrigin !== void 0 && this.peerOrigin !== "null" && exposedTo.includes(this.peerOrigin);
|
|
423
431
|
if (visible === mcpHandle.enabled) continue;
|
|
424
432
|
if (visible) mcpHandle.enable();
|
|
425
433
|
else mcpHandle.disable();
|
|
@@ -432,25 +440,51 @@ var BrowserMcpServer = class extends EventTarget {
|
|
|
432
440
|
* leave every restricted tool disabled.
|
|
433
441
|
*/
|
|
434
442
|
observePeerOrigin(transport) {
|
|
443
|
+
this.stopObservingPeerOrigin?.();
|
|
444
|
+
this.stopObservingPeerOrigin = void 0;
|
|
445
|
+
this.peerOrigin = void 0;
|
|
446
|
+
this.applyToolExposure();
|
|
435
447
|
if (!("clientOrigin" in transport)) return;
|
|
436
448
|
const peered = transport;
|
|
437
449
|
this.peerOrigin = peered.clientOrigin;
|
|
438
450
|
this.applyToolExposure();
|
|
439
451
|
const previous = peered.onclientorigin;
|
|
440
|
-
|
|
452
|
+
let observing = true;
|
|
453
|
+
const onclientorigin = (origin) => {
|
|
441
454
|
previous?.(origin);
|
|
455
|
+
if (!observing) return;
|
|
442
456
|
this.peerOrigin = origin;
|
|
443
457
|
this.applyToolExposure();
|
|
444
458
|
};
|
|
459
|
+
peered.onclientorigin = onclientorigin;
|
|
460
|
+
this.stopObservingPeerOrigin = () => {
|
|
461
|
+
observing = false;
|
|
462
|
+
if (peered.onclientorigin === onclientorigin) peered.onclientorigin = previous;
|
|
463
|
+
};
|
|
445
464
|
}
|
|
446
|
-
connect(transport) {
|
|
447
|
-
if (this.closed)
|
|
465
|
+
async connect(transport) {
|
|
466
|
+
if (this.closed) throw createInvalidStateError("BrowserMcpServer is closed");
|
|
467
|
+
if (this.mcpServer.server.transport) throw createInvalidStateError("BrowserMcpServer is already connected");
|
|
448
468
|
this.observePeerOrigin(transport);
|
|
449
|
-
|
|
469
|
+
const stopObserving = this.stopObservingPeerOrigin;
|
|
470
|
+
try {
|
|
471
|
+
await this.mcpServer.connect(transport);
|
|
472
|
+
} catch (error) {
|
|
473
|
+
if (this.stopObservingPeerOrigin === stopObserving) {
|
|
474
|
+
stopObserving?.();
|
|
475
|
+
this.stopObservingPeerOrigin = void 0;
|
|
476
|
+
this.peerOrigin = void 0;
|
|
477
|
+
this.applyToolExposure();
|
|
478
|
+
}
|
|
479
|
+
if (this.mcpServer.server.transport === transport) await this.mcpServer.close();
|
|
480
|
+
throw error;
|
|
481
|
+
}
|
|
450
482
|
}
|
|
451
483
|
close() {
|
|
452
484
|
if (this.closePromise) return this.closePromise;
|
|
453
485
|
this.closed = true;
|
|
486
|
+
this.stopObservingPeerOrigin?.();
|
|
487
|
+
this.stopObservingPeerOrigin = void 0;
|
|
454
488
|
this.closePromise = (async () => {
|
|
455
489
|
if (this.native && this.nativeToolChangeListener) {
|
|
456
490
|
this.native.removeEventListener("toolchange", this.nativeToolChangeListener);
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../src/browser-server.ts"],"sourcesContent":["import {\n coerceWebMcpToolDescriptor,\n createInvalidStateError,\n createToolInvocationFailedError,\n createUnknownError,\n isPlainObject,\n normalizeToolResponse,\n normalizeInputSchema,\n parseChromeToolInput,\n serializeChromeToolResult,\n toWebMcpAnnotations,\n validateExecutableOrigin,\n validatePotentiallyTrustworthyOrigins,\n validateWebMcpAccess,\n validateWebMcpToolDescriptor,\n withAbortSignal,\n} from '@mcp-b/webmcp-polyfill/schema';\nimport type { NormalizedInputSchema } from '@mcp-b/webmcp-polyfill/schema';\nimport type {\n ChromeModelContextExecuteToolOptions,\n ChromeModelContextExtensions,\n InputSchema,\n ModelContext,\n ModelContextGetToolOptions,\n ModelContextRegisterToolOptions,\n ModelContextTool,\n ModelContextWithExtensions,\n RegistrationHandle,\n RegisteredTool,\n ToolAnnotations,\n ToolDescriptor,\n ToolListItem,\n WebMcpToolInput,\n} from '@mcp-b/webmcp-types';\nimport {\n fromJsonSchema,\n isInputRequiredResult,\n McpServer,\n mergeCapabilities,\n ResourceTemplate,\n type GetPromptResult,\n type Implementation,\n type ReadResourceResult,\n type RegisteredPrompt as McpRegisteredPrompt,\n type RegisteredResource as McpRegisteredResource,\n type RegisteredResourceTemplate as McpRegisteredResourceTemplate,\n type RegisteredTool as McpRegisteredTool,\n type ServerOptions,\n type StandardSchemaWithJSON,\n type ToolAnnotations as McpToolAnnotations,\n type Transport,\n type Variables,\n} from '@modelcontextprotocol/server';\n\nconst DEFAULT_INPUT_SCHEMA = normalizeInputSchema(undefined).inputSchema;\nconst SERVER_MARKER_PROPERTY = '__isBrowserMcpServer' as const;\n\nexport function isBrowserMcpServer(context: unknown): context is BrowserMcpServer {\n return (\n typeof context === 'object' &&\n context !== null &&\n SERVER_MARKER_PROPERTY in context &&\n context[SERVER_MARKER_PROPERTY] === true\n );\n}\n\ninterface RegisteredWebMcpTool {\n item: ToolListItem;\n registeredInputSchema?: string;\n execute: (args: WebMcpToolInput, signal?: AbortSignal) => Promise<unknown>;\n mcpHandle: McpRegisteredTool | undefined;\n exposedTo?: readonly string[];\n abortSignal?: AbortSignal;\n abortListener?: () => void;\n}\n\ntype McpRegistration = McpRegisteredPrompt | McpRegisteredResource | McpRegisteredResourceTemplate;\n\nexport interface BrowserMcpServerOptions extends ServerOptions {\n native?: ModelContext;\n}\n\ntype NativeStandardToolsApi = ModelContext & {\n executeTool: NonNullable<ChromeModelContextExtensions['executeTool']>;\n};\ntype NativeRegisterToolFn = (\n tool: ModelContextTool<WebMcpToolInput>,\n options?: ModelContextRegisterToolOptions\n) => Promise<void>;\n\ninterface NativeBackfilledTool {\n source: RegisteredTool;\n item: ToolListItem;\n fingerprint: string;\n}\n\nfunction parseNativeToolResult(serialized: string | null): unknown {\n if (serialized === null) {\n return {\n content: [{ type: 'text', text: 'Tool execution interrupted by navigation' }],\n isError: true,\n };\n }\n\n let result: unknown;\n try {\n result = JSON.parse(serialized);\n } catch {\n return normalizeToolResponse(serialized);\n }\n return isInputRequiredResult(result) ? result : normalizeToolResponse(result);\n}\n\nfunction toMcpInputSchema(\n normalized: NormalizedInputSchema\n): StandardSchemaWithJSON<Record<string, unknown>> {\n // normalizeInputSchema() attaches a non-enumerable `~standard` when the caller supplied a\n // Standard Schema validator, so reuse it instead of recompiling the JSON Schema projection.\n const standardSchema = Object.getOwnPropertyDescriptor(normalized.inputSchema, '~standard');\n return standardSchema && !standardSchema.enumerable\n ? (normalized.inputSchema as unknown as StandardSchemaWithJSON<Record<string, unknown>>)\n : fromJsonSchema<Record<string, unknown>>(\n normalized.inputSchema as Parameters<typeof fromJsonSchema>[0]\n );\n}\n\nfunction toMcpAnnotations(\n annotations: ToolAnnotations | undefined\n): McpToolAnnotations | undefined {\n if (!annotations) return undefined;\n const { untrustedContentHint: _untrustedContentHint, ...mcpAnnotations } = annotations;\n return mcpAnnotations;\n}\n\nfunction toNativeTool(\n tool: ToolDescriptor<WebMcpToolInput>,\n inputSchema: InputSchema | undefined,\n execute: ModelContextTool<WebMcpToolInput>['execute']\n): ModelContextTool<WebMcpToolInput> {\n const annotations = tool.annotations ? toWebMcpAnnotations(tool.annotations) : undefined;\n return {\n name: tool.name,\n ...(tool.title !== undefined ? { title: tool.title } : {}),\n description: tool.description,\n ...(inputSchema !== undefined ? { inputSchema } : {}),\n ...(annotations ? { annotations } : {}),\n execute,\n };\n}\n\n/**\n * Thin WebMCP-to-MCP v2 adapter.\n *\n * The official v2 `McpServer` owns MCP registration, validation, and transport\n * behavior. This class only adds the document-facing WebMCP contract and native\n * Chrome mirroring.\n */\nexport class BrowserMcpServer extends EventTarget implements ModelContextWithExtensions {\n readonly [SERVER_MARKER_PROPERTY] = true as const;\n readonly mcpServer: McpServer;\n\n private readonly native: ModelContext | undefined;\n private readonly ownerDocument: Document | null;\n private readonly tools = new Map<string, RegisteredWebMcpTool>();\n private peerOrigin: string | undefined;\n private readonly registrations = new Set<McpRegistration>();\n private readonly nativeToolAbortControllers = new Map<string, AbortController>();\n private readonly nativeBackfilledTools = new Map<string, NativeBackfilledTool>();\n private readonly pendingTools = new Map<string, AbortController>();\n private readonly removingNativeTools = new Set<string>();\n private nativeSyncQueue: Promise<void> = Promise.resolve();\n private nativeToolChangeQueue: Promise<void> = Promise.resolve();\n private nativeToolChangeListener: EventListener | undefined;\n private closed = false;\n private closePromise: Promise<void> | undefined;\n private ontoolchangeHandler: ((this: ModelContext, event: Event) => unknown) | null = null;\n private readonly ontoolchangeListener: EventListener = (event) => {\n this.ontoolchangeHandler?.call(this, event);\n };\n\n constructor(serverInfo: Implementation, options: BrowserMcpServerOptions = {}) {\n super();\n const { native, ...serverOptions } = options;\n this.mcpServer = new McpServer(serverInfo, {\n ...serverOptions,\n capabilities: mergeCapabilities(serverOptions.capabilities ?? {}, {\n tools: { listChanged: true },\n resources: { listChanged: true },\n prompts: { listChanged: true },\n }),\n });\n this.native = native;\n this.ownerDocument = globalThis.document ?? null;\n if (\n native &&\n typeof native.addEventListener === 'function' &&\n typeof native.removeEventListener === 'function'\n ) {\n this.nativeToolChangeListener = () => {\n if (this.closed) return;\n this.nativeToolChangeQueue = this.nativeToolChangeQueue.then(async () => {\n try {\n await this.syncNativeTools();\n } catch (error) {\n console.warn('[BrowserMcpServer] Native WebMCP tool reconciliation failed:', error);\n }\n await this.notifyProducerToolsChanged();\n });\n };\n native.addEventListener('toolchange', this.nativeToolChangeListener);\n }\n }\n\n get ontoolchange(): ((this: ModelContext, event: Event) => unknown) | null {\n return this.ontoolchangeHandler;\n }\n\n set ontoolchange(handler: ((this: ModelContext, event: Event) => unknown) | null) {\n const listener = typeof handler === 'function' ? handler : null;\n if (listener === null) {\n this.ontoolchangeHandler = null;\n super.removeEventListener('toolchange', this.ontoolchangeListener);\n return;\n }\n\n if (this.ontoolchangeHandler === null) {\n super.addEventListener('toolchange', this.ontoolchangeListener);\n }\n this.ontoolchangeHandler = listener;\n }\n\n private async notifyProducerToolsChanged(): Promise<void> {\n if (this.closed) return;\n // Preserve task ordering because WebMCP does not expose its platform task source.\n await new Promise((resolve) => setTimeout(resolve, 0));\n if (!this.closed) this.dispatchEvent(new Event('toolchange'));\n }\n\n private getNativeStandardToolsApi(): NativeStandardToolsApi | undefined {\n const candidate: (ModelContext & Partial<ChromeModelContextExtensions>) | undefined =\n this.native;\n return candidate && typeof candidate.executeTool === 'function'\n ? (candidate as NativeStandardToolsApi)\n : undefined;\n }\n\n private async registerNativeToolMirror(\n tool: ToolDescriptor<WebMcpToolInput>,\n normalized: NormalizedInputSchema,\n options: ModelContextRegisterToolOptions,\n execute: RegisteredWebMcpTool['execute'],\n controller: AbortController\n ): Promise<void> {\n if (!this.native) return;\n\n // The overload set keys on a statically known inputSchema; mirrored tools carry a dynamic one.\n const nativeRegister = this.native.registerTool as unknown as NativeRegisterToolFn;\n const signal = options.signal\n ? AbortSignal.any([options.signal, controller.signal])\n : controller.signal;\n\n const nativeInputSchema =\n normalized.registeredInputSchema === undefined\n ? undefined\n : (JSON.parse(normalized.registeredInputSchema) as InputSchema);\n this.nativeToolAbortControllers.set(tool.name, controller);\n try {\n await nativeRegister.call(\n this.native,\n toNativeTool(tool, nativeInputSchema, (input) => execute(input)),\n { ...options, signal }\n );\n } catch (error) {\n controller.abort();\n if (this.nativeToolAbortControllers.get(tool.name) === controller) {\n this.nativeToolAbortControllers.delete(tool.name);\n }\n throw error;\n }\n if (this.nativeToolAbortControllers.get(tool.name) === controller) {\n this.removingNativeTools.delete(tool.name);\n }\n }\n\n private abortNativeToolMirror(\n name: string,\n controller = this.nativeToolAbortControllers.get(name)\n ): void {\n if (!controller || this.nativeToolAbortControllers.get(name) !== controller) return;\n this.removingNativeTools.add(name);\n controller.abort();\n this.nativeToolAbortControllers.delete(name);\n }\n\n private validateToolDescriptor(tool: ToolDescriptor<WebMcpToolInput>): NormalizedInputSchema {\n validateWebMcpToolDescriptor(tool);\n if (this.tools.has(tool.name) || this.pendingTools.has(tool.name)) {\n throw createInvalidStateError(`Tool already registered: ${tool.name}`);\n }\n return normalizeInputSchema(tool.inputSchema);\n }\n\n private registerToolInMcp(\n tool: ToolDescriptor<WebMcpToolInput>,\n normalized: NormalizedInputSchema,\n executeTool: RegisteredWebMcpTool['execute'],\n exposedTo: readonly string[] | undefined\n ): RegisteredWebMcpTool {\n const outputSchema =\n tool.outputSchema === undefined ? undefined : structuredClone(tool.outputSchema);\n const mcpOutputSchema =\n outputSchema === undefined\n ? undefined\n : fromJsonSchema(outputSchema as Parameters<typeof fromJsonSchema>[0]);\n const mcpAnnotations = toMcpAnnotations(tool.annotations);\n const mcpCompatibleInput =\n normalized.inputSchema.type === undefined || normalized.inputSchema.type === 'object';\n const mcpHandle = mcpCompatibleInput\n ? this.mcpServer.registerTool(\n tool.name,\n {\n ...(tool.title !== undefined ? { title: tool.title } : {}),\n description: tool.description,\n inputSchema: toMcpInputSchema(normalized),\n ...(mcpOutputSchema ? { outputSchema: mcpOutputSchema } : {}),\n ...(mcpAnnotations ? { annotations: mcpAnnotations } : {}),\n },\n async (args, context) => {\n const result = await executeTool(args, context.mcpReq.signal);\n if (isInputRequiredResult(result)) {\n throw new Error(\n `WebMCP tool \"${tool.name}\" returned input_required. Multi-round tool flows require BrowserMcpServer.mcpServer.registerTool().`\n );\n }\n return normalizeToolResponse(result);\n }\n )\n : undefined;\n // A restricted tool is never observable on the wire before its audience is\n // checked: the handle is disabled here, in the same synchronous step that created\n // it, and only applyToolExposure re-enables it.\n if (exposedTo?.length) mcpHandle?.disable();\n\n if (!mcpCompatibleInput) {\n console.warn(\n `[BrowserMcpServer] Tool \"${tool.name}\" remains available through WebMCP but cannot be exposed over MCP because MCP input schemas require an object root.`\n );\n }\n\n const item: ToolListItem = {\n name: tool.name,\n ...(tool.title !== undefined ? { title: tool.title } : {}),\n description: tool.description,\n inputSchema: normalized.inputSchema,\n ...(outputSchema === undefined ? {} : { outputSchema }),\n ...(tool.annotations ? { annotations: tool.annotations } : {}),\n };\n return {\n item,\n ...(normalized.registeredInputSchema !== undefined\n ? { registeredInputSchema: normalized.registeredInputSchema }\n : {}),\n execute: executeTool,\n mcpHandle,\n ...(exposedTo?.length ? { exposedTo } : {}),\n };\n }\n\n readonly registerTool: ModelContextWithExtensions['registerTool'] = async (\n toolValue: unknown,\n optionsValue: ModelContextRegisterToolOptions | null = {}\n ): Promise<void> => {\n const options = optionsValue ?? {};\n validateWebMcpAccess(this.ownerDocument);\n if (this.closed) throw createInvalidStateError('BrowserMcpServer is closed');\n if (!isPlainObject(toolValue)) {\n throw new TypeError('registerTool(tool) requires a tool object');\n }\n const tool = coerceWebMcpToolDescriptor(toolValue);\n const normalized = this.validateToolDescriptor(tool);\n options.signal?.throwIfAborted();\n validatePotentiallyTrustworthyOrigins(options.exposedTo);\n options.signal?.throwIfAborted();\n const execute: RegisteredWebMcpTool['execute'] = async (args, signal) => {\n signal?.throwIfAborted();\n return withAbortSignal(\n Promise.resolve().then(() => Reflect.apply(tool.execute, undefined, [args])),\n signal\n );\n };\n const controller = new AbortController();\n let registered: RegisteredWebMcpTool | undefined;\n const abort = () => {\n if (this.pendingTools.get(tool.name) === controller) {\n this.pendingTools.delete(tool.name);\n }\n if (registered && this.tools.get(tool.name) === registered) {\n this.removeTool(tool.name);\n } else {\n this.abortNativeToolMirror(tool.name, controller);\n }\n };\n options.signal?.addEventListener('abort', abort, { once: true });\n this.pendingTools.set(tool.name, controller);\n try {\n await this.registerNativeToolMirror(tool, normalized, options, execute, controller);\n if (this.closed) throw createInvalidStateError('BrowserMcpServer is closed');\n options.signal?.throwIfAborted();\n registered = this.registerToolInMcp(tool, normalized, execute, options.exposedTo);\n this.tools.set(tool.name, registered);\n this.applyToolExposure();\n if (options.signal?.aborted) {\n abort();\n options.signal.throwIfAborted();\n }\n } catch (error) {\n this.abortNativeToolMirror(tool.name, controller);\n options.signal?.removeEventListener('abort', abort);\n options.signal?.throwIfAborted();\n throw error;\n } finally {\n if (this.pendingTools.get(tool.name) === controller) {\n this.pendingTools.delete(tool.name);\n }\n }\n if (options.signal) {\n registered.abortSignal = options.signal;\n registered.abortListener = abort;\n }\n if (this.tools.get(tool.name) === registered) {\n if (this.native) await this.nativeToolChangeQueue;\n else await this.notifyProducerToolsChanged();\n }\n if (this.closed) throw createInvalidStateError('BrowserMcpServer is closed');\n options.signal?.throwIfAborted();\n };\n\n private removeTool(name: string, options?: { skipNative?: boolean; notify?: boolean }): void {\n const registered = this.tools.get(name);\n if (registered) {\n if (registered.abortSignal && registered.abortListener) {\n registered.abortSignal.removeEventListener('abort', registered.abortListener);\n }\n this.tools.delete(name);\n this.nativeBackfilledTools.delete(name);\n registered.mcpHandle?.remove();\n if ((options?.notify ?? true) && !this.native) {\n void this.notifyProducerToolsChanged();\n }\n }\n if (!options?.skipNative) this.abortNativeToolMirror(name);\n }\n\n syncNativeTools(): Promise<void> {\n const sync = this.nativeSyncQueue.then(async () => {\n if (this.closed) return;\n const native = this.getNativeStandardToolsApi();\n if (native) await this.backfillNativeStandardTools(native);\n });\n this.nativeSyncQueue = sync.then(\n () => undefined,\n () => undefined\n );\n return sync;\n }\n\n private async backfillNativeStandardTools(native: NativeStandardToolsApi): Promise<void> {\n const tools = await native.getTools();\n if (this.closed) return;\n const nextTools = new Map<string, NativeBackfilledTool>();\n const nativeNames = new Set(tools.map(({ name }) => name));\n for (const name of this.removingNativeTools) {\n if (!nativeNames.has(name)) this.removingNativeTools.delete(name);\n }\n for (const tool of tools) {\n // ponytail: MCP tool names are global, so keep the first valid visible tool.\n // Add origin-qualified aliases if MCP gains scoped tool identity.\n if (\n nextTools.has(tool.name) ||\n this.pendingTools.has(tool.name) ||\n this.removingNativeTools.has(tool.name)\n ) {\n continue;\n }\n let inputSchema: InputSchema | undefined = DEFAULT_INPUT_SCHEMA;\n if (tool.inputSchema !== undefined) {\n try {\n // An object since webmcp#241; a serialized string from older Chrome. The\n // round-trip detaches the object from the page's graph and rejects non-JSON.\n const serialized =\n typeof tool.inputSchema === 'string'\n ? tool.inputSchema\n : JSON.stringify(tool.inputSchema);\n const parsed: unknown = JSON.parse(serialized);\n inputSchema = isPlainObject(parsed) ? (parsed as InputSchema) : undefined;\n } catch {\n inputSchema = undefined;\n }\n }\n if (!inputSchema) {\n console.warn(\n `[BrowserMcpServer] Native tool \"${tool.name}\" was not exposed over MCP because its input schema is malformed.`\n );\n continue;\n }\n const item: ToolListItem = {\n name: tool.name,\n ...(tool.title !== undefined ? { title: tool.title } : {}),\n description: tool.description,\n inputSchema,\n ...(tool.annotations ? { annotations: tool.annotations } : {}),\n };\n nextTools.set(tool.name, {\n source: tool,\n item,\n fingerprint: JSON.stringify(item),\n });\n }\n\n for (const [name, current] of this.nativeBackfilledTools) {\n const next = nextTools.get(name);\n if (!next || next.fingerprint !== current.fingerprint) {\n this.removeTool(name, { skipNative: true, notify: false });\n continue;\n }\n this.nativeBackfilledTools.set(name, next);\n }\n\n for (const [name, next] of nextTools) {\n if (this.tools.has(name)) continue;\n const execute = async (args: WebMcpToolInput, signal?: AbortSignal) => {\n const currentTool = this.nativeBackfilledTools.get(name)?.source;\n if (!currentTool) throw new Error(`Native tool not found: ${name}`);\n const input = JSON.stringify(args);\n return parseNativeToolResult(\n signal\n ? await native.executeTool.call(this.native, currentTool, input, { signal })\n : await native.executeTool.call(this.native, currentTool, input)\n );\n };\n const tool: ToolDescriptor<WebMcpToolInput> = {\n name,\n ...(next.item.title !== undefined ? { title: next.item.title } : {}),\n description: next.item.description,\n inputSchema: next.item.inputSchema,\n ...(next.item.annotations ? { annotations: next.item.annotations } : {}),\n execute: (args) => execute(args),\n };\n try {\n const normalized = this.validateToolDescriptor(tool);\n // Native getTools() does not report the allowlist a tool registered with, so a\n // backfilled mirror carries none and stays as widely exposed as it is today.\n this.tools.set(tool.name, this.registerToolInMcp(tool, normalized, execute, undefined));\n this.nativeBackfilledTools.set(name, next);\n } catch (error) {\n console.warn(\n `[BrowserMcpServer] Native tool \"${name}\" was not exposed over MCP because its schema could not be compiled:`,\n error\n );\n }\n }\n }\n\n registerResource(descriptor: ResourceDescriptor): RegistrationHandle {\n if (this.closed) throw createInvalidStateError('BrowserMcpServer is closed');\n const registeredDescriptor = { ...descriptor };\n const config = {\n ...(registeredDescriptor.description !== undefined\n ? { description: registeredDescriptor.description }\n : {}),\n ...(registeredDescriptor.mimeType !== undefined\n ? { mimeType: registeredDescriptor.mimeType }\n : {}),\n };\n const template = registeredDescriptor.uri.includes('{')\n ? new ResourceTemplate(registeredDescriptor.uri, { list: undefined })\n : undefined;\n const mcpHandle = template\n ? this.mcpServer.registerResource(\n registeredDescriptor.name,\n template,\n config,\n async (uri, variables) => registeredDescriptor.read(uri, variables)\n )\n : this.mcpServer.registerResource(\n registeredDescriptor.name,\n registeredDescriptor.uri,\n config,\n async (uri) => registeredDescriptor.read(uri)\n );\n this.registrations.add(mcpHandle);\n return {\n unregister: () => {\n if (this.registrations.delete(mcpHandle)) mcpHandle.remove();\n },\n };\n }\n\n registerPrompt(descriptor: PromptDescriptor): RegistrationHandle {\n if (this.closed) throw createInvalidStateError('BrowserMcpServer is closed');\n const registeredDescriptor = {\n ...descriptor,\n ...(descriptor.argsSchema === undefined\n ? {}\n : { argsSchema: structuredClone(descriptor.argsSchema) }),\n };\n const argsSchema =\n registeredDescriptor.argsSchema === undefined\n ? undefined\n : fromJsonSchema<Record<string, string>>(\n registeredDescriptor.argsSchema as Parameters<typeof fromJsonSchema>[0]\n );\n const mcpHandle = this.mcpServer.registerPrompt(\n registeredDescriptor.name,\n {\n ...(registeredDescriptor.description !== undefined\n ? { description: registeredDescriptor.description }\n : {}),\n ...(argsSchema ? { argsSchema } : {}),\n },\n async (args) => registeredDescriptor.get(args ?? {})\n );\n this.registrations.add(mcpHandle);\n return {\n unregister: () => {\n if (this.registrations.delete(mcpHandle)) mcpHandle.remove();\n },\n };\n }\n\n listTools(): ToolListItem[] {\n return structuredClone([...this.tools.values()].map(({ item }) => item));\n }\n\n async getTools(options?: ModelContextGetToolOptions): Promise<RegisteredTool[]> {\n validateWebMcpAccess(this.ownerDocument);\n if (this.closed) throw createInvalidStateError('BrowserMcpServer is closed');\n if (this.native) {\n return this.native.getTools(options);\n }\n validatePotentiallyTrustworthyOrigins(options?.fromOrigins);\n if (options?.fromOrigins?.length) {\n throw new DOMException(\n 'Cross-document tool discovery requires native WebMCP',\n 'NotSupportedError'\n );\n }\n\n const origin = globalThis.location?.origin ?? '';\n const currentWindow = globalThis.window;\n\n const tools = [...this.tools.values()]\n .map(({ item, registeredInputSchema }) => {\n // A fresh object per call, aligned with the polyfill's post-webmcp#241\n // shape. A custom toJSON can serialize to non-object JSON; omit those\n // rather than emit a value consumers would mistake for a pre-154\n // serialized string.\n const parsed: unknown =\n registeredInputSchema === undefined ? undefined : JSON.parse(registeredInputSchema);\n return {\n name: item.name,\n title: item.title ?? '',\n description: item.description,\n ...(isPlainObject(parsed) ? { inputSchema: parsed } : {}),\n origin,\n window: currentWindow,\n ...(item.annotations ? { annotations: toWebMcpAnnotations(item.annotations) } : {}),\n };\n })\n .sort((a, b) => (a.name < b.name ? -1 : a.name > b.name ? 1 : 0));\n await new Promise((resolve) => setTimeout(resolve, 0));\n return tools;\n }\n\n async executeTool(\n tool: RegisteredTool,\n inputArgsJson: string,\n options?: ChromeModelContextExecuteToolOptions\n ): Promise<string | null> {\n validateWebMcpAccess(this.ownerDocument);\n if (this.closed) throw createInvalidStateError('BrowserMcpServer is closed');\n const native = this.getNativeStandardToolsApi();\n if (native) {\n return native.executeTool.call(this.native, tool, inputArgsJson, options);\n }\n\n if (tool === null || typeof tool !== 'object') {\n throw new TypeError('RegisteredTool must be an object');\n }\n for (const required of ['name', 'description', 'window', 'origin'] as const) {\n if (!(required in tool)) {\n throw new TypeError(`RegisteredTool.${required} is required`);\n }\n }\n validateExecutableOrigin(tool.origin);\n const origin = globalThis.location?.origin ?? '';\n const currentWindow = globalThis.window;\n if (tool.origin !== origin || tool.window !== currentWindow) {\n throw createUnknownError(`Native tool not found: ${tool.name}`);\n }\n options?.signal?.throwIfAborted();\n const registered = this.tools.get(tool.name);\n if (!registered) throw createUnknownError(`Tool not found: ${tool.name}`);\n const args = parseChromeToolInput(inputArgsJson);\n try {\n const result = await withAbortSignal(\n registered.execute(args, options?.signal),\n registered.abortSignal,\n () => createUnknownError('Tool unregistered')\n );\n return serializeChromeToolResult(result);\n } catch (error) {\n if (options?.signal?.aborted && error === options.signal.reason) throw error;\n if (registered.abortSignal?.aborted) throw error;\n throw createToolInvocationFailedError(error);\n }\n }\n\n /**\n * Re-evaluate which registered tools may appear on the wire.\n *\n * `exposedTo` narrows a tool to named embedder origins. The peer origin is only known\n * once a transport that reports one has heard from its peer, so a restricted tool stays\n * disabled until then — and stays disabled forever on transports that cannot name a peer\n * at all. Failing closed keeps a tool that asked for a narrow audience from reaching a\n * wider one; unrestricted tools are untouched and behave exactly as before.\n */\n private applyToolExposure(): void {\n for (const { exposedTo, mcpHandle } of this.tools.values()) {\n if (!exposedTo?.length || !mcpHandle) continue;\n const visible = this.peerOrigin !== undefined && exposedTo.includes(this.peerOrigin);\n if (visible === mcpHandle.enabled) continue;\n if (visible) mcpHandle.enable();\n else mcpHandle.disable();\n }\n }\n\n /**\n * Follow the peer origin of transports that report one, so `exposedTo` can be scoped to\n * the embedder actually connected. Duck-typed rather than imported: the SDK must not take\n * a build dependency on `@mcp-b/transports`, and transports that never name a peer simply\n * leave every restricted tool disabled.\n */\n private observePeerOrigin(transport: Transport): void {\n if (!('clientOrigin' in transport)) return;\n const peered = transport as Transport & {\n clientOrigin?: string;\n onclientorigin?: (origin: string) => void;\n };\n this.peerOrigin = peered.clientOrigin;\n this.applyToolExposure();\n const previous = peered.onclientorigin;\n peered.onclientorigin = (origin) => {\n previous?.(origin);\n this.peerOrigin = origin;\n this.applyToolExposure();\n };\n }\n\n connect(transport: Transport): Promise<void> {\n if (this.closed) return Promise.reject(createInvalidStateError('BrowserMcpServer is closed'));\n this.observePeerOrigin(transport);\n return this.mcpServer.connect(transport);\n }\n\n close(): Promise<void> {\n if (this.closePromise) return this.closePromise;\n this.closed = true;\n this.closePromise = (async () => {\n if (this.native && this.nativeToolChangeListener) {\n this.native.removeEventListener('toolchange', this.nativeToolChangeListener);\n this.nativeToolChangeListener = undefined;\n }\n for (const name of this.nativeToolAbortControllers.keys()) {\n this.abortNativeToolMirror(name);\n }\n for (const name of this.tools.keys()) {\n this.removeTool(name, { notify: false });\n }\n for (const handle of this.registrations) handle.remove();\n this.registrations.clear();\n this.nativeBackfilledTools.clear();\n this.removingNativeTools.clear();\n await this.mcpServer.close();\n })();\n return this.closePromise;\n }\n}\n\nexport interface ResourceDescriptor {\n uri: string;\n name: string;\n description?: string;\n mimeType?: string;\n read: (uri: URL, params?: Variables) => Promise<ReadResourceResult>;\n}\n\nexport interface PromptDescriptor {\n name: string;\n description?: string;\n argsSchema?: InputSchema;\n get: (args: Record<string, string>) => Promise<GetPromptResult>;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/browser-server.ts"],"sourcesContent":["import {\n coerceWebMcpToolDescriptor,\n createInvalidStateError,\n createToolInvocationFailedError,\n createUnknownError,\n isPlainObject,\n normalizeToolResponse,\n normalizeInputSchema,\n parseChromeToolInput,\n serializeChromeToolResult,\n toWebMcpAnnotations,\n validateExecutableOrigin,\n validatePotentiallyTrustworthyOrigins,\n validateWebMcpAccess,\n validateWebMcpToolDescriptor,\n withAbortSignal,\n} from '@mcp-b/webmcp-polyfill/schema';\nimport type { NormalizedInputSchema } from '@mcp-b/webmcp-polyfill/schema';\nimport type {\n ChromeModelContextExecuteToolOptions,\n ChromeModelContextExtensions,\n InputSchema,\n ModelContext,\n ModelContextGetToolOptions,\n ModelContextRegisterToolOptions,\n ModelContextTool,\n ModelContextWithExtensions,\n RegistrationHandle,\n RegisteredTool,\n ToolAnnotations,\n ToolDescriptor,\n ToolListItem,\n WebMcpToolInput,\n} from '@mcp-b/webmcp-types';\nimport {\n fromJsonSchema,\n isInputRequiredResult,\n McpServer,\n mergeCapabilities,\n ResourceTemplate,\n type GetPromptResult,\n type Implementation,\n type ReadResourceResult,\n type RegisteredPrompt as McpRegisteredPrompt,\n type RegisteredResource as McpRegisteredResource,\n type RegisteredResourceTemplate as McpRegisteredResourceTemplate,\n type RegisteredTool as McpRegisteredTool,\n type ServerOptions,\n type StandardSchemaWithJSON,\n type ToolAnnotations as McpToolAnnotations,\n type Transport,\n type Variables,\n} from '@modelcontextprotocol/server';\n\nconst DEFAULT_INPUT_SCHEMA = normalizeInputSchema(undefined).inputSchema;\nconst SERVER_MARKER_PROPERTY = '__isBrowserMcpServer' as const;\n\nexport function isBrowserMcpServer(context: unknown): context is BrowserMcpServer {\n return (\n typeof context === 'object' &&\n context !== null &&\n SERVER_MARKER_PROPERTY in context &&\n context[SERVER_MARKER_PROPERTY] === true\n );\n}\n\ninterface RegisteredWebMcpTool {\n item: ToolListItem;\n registeredInputSchema?: string;\n execute: (args: WebMcpToolInput, signal?: AbortSignal) => Promise<unknown>;\n mcpHandle: McpRegisteredTool | undefined;\n exposedTo?: readonly string[];\n abortSignal?: AbortSignal;\n abortListener?: () => void;\n}\n\ntype McpRegistration = McpRegisteredPrompt | McpRegisteredResource | McpRegisteredResourceTemplate;\n\nexport interface BrowserMcpServerOptions extends ServerOptions {\n native?: ModelContext;\n}\n\ntype NativeStandardToolsApi = ModelContext & {\n executeTool: NonNullable<ChromeModelContextExtensions['executeTool']>;\n};\ntype NativeRegisterToolFn = (\n tool: ModelContextTool<WebMcpToolInput>,\n options?: ModelContextRegisterToolOptions\n) => Promise<void>;\n\ninterface NativeBackfilledTool {\n source: RegisteredTool;\n item: ToolListItem;\n fingerprint: string;\n}\n\nfunction parseNativeToolResult(serialized: string | null): unknown {\n if (serialized === null) {\n return {\n content: [{ type: 'text', text: 'Tool execution interrupted by navigation' }],\n isError: true,\n };\n }\n\n let result: unknown;\n try {\n result = JSON.parse(serialized);\n } catch {\n return normalizeToolResponse(serialized);\n }\n return isInputRequiredResult(result) ? result : normalizeToolResponse(result);\n}\n\nfunction toMcpInputSchema(\n normalized: NormalizedInputSchema\n): StandardSchemaWithJSON<Record<string, unknown>> {\n // normalizeInputSchema() attaches a non-enumerable `~standard` when the caller supplied a\n // Standard Schema validator, so reuse it instead of recompiling the JSON Schema projection.\n const standardSchema = Object.getOwnPropertyDescriptor(normalized.inputSchema, '~standard');\n return standardSchema && !standardSchema.enumerable\n ? (normalized.inputSchema as unknown as StandardSchemaWithJSON<Record<string, unknown>>)\n : fromJsonSchema<Record<string, unknown>>(\n normalized.inputSchema as Parameters<typeof fromJsonSchema>[0]\n );\n}\n\nfunction toMcpAnnotations(\n annotations: ToolAnnotations | undefined\n): McpToolAnnotations | undefined {\n if (!annotations) return undefined;\n const { untrustedContentHint: _untrustedContentHint, ...mcpAnnotations } = annotations;\n return mcpAnnotations;\n}\n\nfunction toNativeTool(\n tool: ToolDescriptor<WebMcpToolInput>,\n inputSchema: InputSchema | undefined,\n execute: ModelContextTool<WebMcpToolInput>['execute']\n): ModelContextTool<WebMcpToolInput> {\n const annotations = tool.annotations ? toWebMcpAnnotations(tool.annotations) : undefined;\n return {\n name: tool.name,\n ...(tool.title !== undefined ? { title: tool.title } : {}),\n description: tool.description,\n ...(inputSchema !== undefined ? { inputSchema } : {}),\n ...(annotations ? { annotations } : {}),\n execute,\n };\n}\n\n/**\n * Thin WebMCP-to-MCP v2 adapter.\n *\n * The official v2 `McpServer` owns MCP registration, validation, and transport\n * behavior. This class only adds the document-facing WebMCP contract and native\n * Chrome mirroring.\n */\nexport class BrowserMcpServer extends EventTarget implements ModelContextWithExtensions {\n readonly [SERVER_MARKER_PROPERTY] = true as const;\n readonly mcpServer: McpServer;\n\n private readonly native: ModelContext | undefined;\n private readonly ownerDocument: Document | null;\n private readonly tools = new Map<string, RegisteredWebMcpTool>();\n private peerOrigin: string | undefined;\n private stopObservingPeerOrigin: (() => void) | undefined;\n private readonly registrations = new Set<McpRegistration>();\n private readonly nativeToolAbortControllers = new Map<string, AbortController>();\n private readonly nativeBackfilledTools = new Map<string, NativeBackfilledTool>();\n private readonly pendingTools = new Map<string, AbortController>();\n private readonly removingNativeTools = new Set<string>();\n private nativeSyncQueue: Promise<void> = Promise.resolve();\n private nativeToolChangeQueue: Promise<void> = Promise.resolve();\n private nativeToolChangeListener: EventListener | undefined;\n private closed = false;\n private closePromise: Promise<void> | undefined;\n private ontoolchangeHandler: ((this: ModelContext, event: Event) => unknown) | null = null;\n private readonly ontoolchangeListener: EventListener = (event) => {\n this.ontoolchangeHandler?.call(this, event);\n };\n\n constructor(serverInfo: Implementation, options: BrowserMcpServerOptions = {}) {\n super();\n const { native, ...serverOptions } = options;\n this.mcpServer = new McpServer(serverInfo, {\n ...serverOptions,\n capabilities: mergeCapabilities(serverOptions.capabilities ?? {}, {\n tools: { listChanged: true },\n resources: { listChanged: true },\n prompts: { listChanged: true },\n }),\n });\n this.native = native;\n this.ownerDocument = globalThis.document ?? null;\n if (\n native &&\n typeof native.addEventListener === 'function' &&\n typeof native.removeEventListener === 'function'\n ) {\n this.nativeToolChangeListener = () => {\n if (this.closed) return;\n this.nativeToolChangeQueue = this.nativeToolChangeQueue.then(async () => {\n try {\n await this.syncNativeTools();\n } catch (error) {\n console.warn('[BrowserMcpServer] Native WebMCP tool reconciliation failed:', error);\n }\n await this.notifyProducerToolsChanged();\n });\n };\n native.addEventListener('toolchange', this.nativeToolChangeListener);\n }\n }\n\n get ontoolchange(): ((this: ModelContext, event: Event) => unknown) | null {\n return this.ontoolchangeHandler;\n }\n\n set ontoolchange(handler: ((this: ModelContext, event: Event) => unknown) | null) {\n const listener = typeof handler === 'function' ? handler : null;\n if (listener === null) {\n this.ontoolchangeHandler = null;\n super.removeEventListener('toolchange', this.ontoolchangeListener);\n return;\n }\n\n if (this.ontoolchangeHandler === null) {\n super.addEventListener('toolchange', this.ontoolchangeListener);\n }\n this.ontoolchangeHandler = listener;\n }\n\n private async notifyProducerToolsChanged(): Promise<void> {\n if (this.closed) return;\n // Preserve task ordering because WebMCP does not expose its platform task source.\n await new Promise((resolve) => setTimeout(resolve, 0));\n if (!this.closed) this.dispatchEvent(new Event('toolchange'));\n }\n\n private getNativeStandardToolsApi(): NativeStandardToolsApi | undefined {\n const candidate: (ModelContext & Partial<ChromeModelContextExtensions>) | undefined =\n this.native;\n return candidate && typeof candidate.executeTool === 'function'\n ? (candidate as NativeStandardToolsApi)\n : undefined;\n }\n\n private async registerNativeToolMirror(\n tool: ToolDescriptor<WebMcpToolInput>,\n normalized: NormalizedInputSchema,\n options: ModelContextRegisterToolOptions,\n execute: RegisteredWebMcpTool['execute'],\n controller: AbortController\n ): Promise<void> {\n if (!this.native) return;\n\n // The overload set keys on a statically known inputSchema; mirrored tools carry a dynamic one.\n const nativeRegister = this.native.registerTool as unknown as NativeRegisterToolFn;\n const signal = options.signal\n ? AbortSignal.any([options.signal, controller.signal])\n : controller.signal;\n\n const nativeInputSchema =\n normalized.registeredInputSchema === undefined\n ? undefined\n : (JSON.parse(normalized.registeredInputSchema) as InputSchema);\n this.nativeToolAbortControllers.set(tool.name, controller);\n try {\n await nativeRegister.call(\n this.native,\n toNativeTool(tool, nativeInputSchema, (input) => execute(input)),\n { ...options, signal }\n );\n } catch (error) {\n controller.abort();\n if (this.nativeToolAbortControllers.get(tool.name) === controller) {\n this.nativeToolAbortControllers.delete(tool.name);\n }\n throw error;\n }\n if (this.nativeToolAbortControllers.get(tool.name) === controller) {\n this.removingNativeTools.delete(tool.name);\n }\n }\n\n private abortNativeToolMirror(\n name: string,\n controller = this.nativeToolAbortControllers.get(name)\n ): void {\n if (!controller || this.nativeToolAbortControllers.get(name) !== controller) return;\n this.removingNativeTools.add(name);\n controller.abort();\n this.nativeToolAbortControllers.delete(name);\n }\n\n private validateToolDescriptor(tool: ToolDescriptor<WebMcpToolInput>): NormalizedInputSchema {\n validateWebMcpToolDescriptor(tool);\n if (this.tools.has(tool.name) || this.pendingTools.has(tool.name)) {\n throw createInvalidStateError(`Tool already registered: ${tool.name}`);\n }\n return normalizeInputSchema(tool.inputSchema);\n }\n\n private registerToolInMcp(\n tool: ToolDescriptor<WebMcpToolInput>,\n normalized: NormalizedInputSchema,\n executeTool: RegisteredWebMcpTool['execute'],\n exposedTo: readonly string[] | undefined\n ): RegisteredWebMcpTool {\n const outputSchema =\n tool.outputSchema === undefined ? undefined : structuredClone(tool.outputSchema);\n const mcpOutputSchema =\n outputSchema === undefined\n ? undefined\n : fromJsonSchema(outputSchema as Parameters<typeof fromJsonSchema>[0]);\n const mcpAnnotations = toMcpAnnotations(tool.annotations);\n const mcpCompatibleInput =\n normalized.inputSchema.type === undefined || normalized.inputSchema.type === 'object';\n const mcpHandle = mcpCompatibleInput\n ? this.mcpServer.registerTool(\n tool.name,\n {\n ...(tool.title !== undefined ? { title: tool.title } : {}),\n description: tool.description,\n inputSchema: toMcpInputSchema(normalized),\n ...(mcpOutputSchema ? { outputSchema: mcpOutputSchema } : {}),\n ...(mcpAnnotations ? { annotations: mcpAnnotations } : {}),\n },\n async (args, context) => {\n const result = await executeTool(args, context.mcpReq.signal);\n if (isInputRequiredResult(result)) {\n throw new Error(\n `WebMCP tool \"${tool.name}\" returned input_required. Multi-round tool flows require BrowserMcpServer.mcpServer.registerTool().`\n );\n }\n return normalizeToolResponse(result);\n }\n )\n : undefined;\n // A restricted tool is never observable on the wire before its audience is\n // checked: the handle is disabled here, in the same synchronous step that created\n // it, and only applyToolExposure re-enables it.\n if (exposedTo?.length) mcpHandle?.disable();\n\n if (!mcpCompatibleInput) {\n console.warn(\n `[BrowserMcpServer] Tool \"${tool.name}\" remains available through WebMCP but cannot be exposed over MCP because MCP input schemas require an object root.`\n );\n }\n\n const item: ToolListItem = {\n name: tool.name,\n ...(tool.title !== undefined ? { title: tool.title } : {}),\n description: tool.description,\n inputSchema: normalized.inputSchema,\n ...(outputSchema === undefined ? {} : { outputSchema }),\n ...(tool.annotations ? { annotations: tool.annotations } : {}),\n };\n return {\n item,\n ...(normalized.registeredInputSchema !== undefined\n ? { registeredInputSchema: normalized.registeredInputSchema }\n : {}),\n execute: executeTool,\n mcpHandle,\n ...(exposedTo?.length ? { exposedTo } : {}),\n };\n }\n\n readonly registerTool: ModelContextWithExtensions['registerTool'] = async (\n toolValue: unknown,\n optionsValue: ModelContextRegisterToolOptions | null = {}\n ): Promise<void> => {\n const { signal, exposedTo } = optionsValue ?? {};\n const options = {\n ...(signal ? { signal } : {}),\n ...(exposedTo ? { exposedTo: [...exposedTo] } : {}),\n };\n validateWebMcpAccess(this.ownerDocument);\n if (this.closed) throw createInvalidStateError('BrowserMcpServer is closed');\n if (!isPlainObject(toolValue)) {\n throw new TypeError('registerTool(tool) requires a tool object');\n }\n const tool = coerceWebMcpToolDescriptor(toolValue);\n const normalized = this.validateToolDescriptor(tool);\n options.signal?.throwIfAborted();\n validatePotentiallyTrustworthyOrigins(options.exposedTo);\n options.signal?.throwIfAborted();\n const execute: RegisteredWebMcpTool['execute'] = async (args, signal) => {\n signal?.throwIfAborted();\n return withAbortSignal(\n Promise.resolve().then(() => Reflect.apply(tool.execute, undefined, [args])),\n signal\n );\n };\n const controller = new AbortController();\n let registered: RegisteredWebMcpTool | undefined;\n const abort = () => {\n if (this.pendingTools.get(tool.name) === controller) {\n this.pendingTools.delete(tool.name);\n }\n if (registered && this.tools.get(tool.name) === registered) {\n this.removeTool(tool.name);\n } else {\n this.abortNativeToolMirror(tool.name, controller);\n }\n };\n options.signal?.addEventListener('abort', abort, { once: true });\n this.pendingTools.set(tool.name, controller);\n try {\n await this.registerNativeToolMirror(tool, normalized, options, execute, controller);\n if (this.closed) throw createInvalidStateError('BrowserMcpServer is closed');\n options.signal?.throwIfAborted();\n registered = this.registerToolInMcp(\n tool,\n normalized,\n execute,\n options.exposedTo?.map((origin) => {\n const parsedOrigin = new URL(origin).origin;\n // Keep exact extension identifiers when this browser cannot parse their origin.\n return parsedOrigin === 'null' ? origin : parsedOrigin;\n })\n );\n this.tools.set(tool.name, registered);\n this.applyToolExposure();\n if (options.signal?.aborted) {\n abort();\n options.signal.throwIfAborted();\n }\n } catch (error) {\n this.abortNativeToolMirror(tool.name, controller);\n options.signal?.removeEventListener('abort', abort);\n options.signal?.throwIfAborted();\n throw error;\n } finally {\n if (this.pendingTools.get(tool.name) === controller) {\n this.pendingTools.delete(tool.name);\n }\n }\n if (options.signal) {\n registered.abortSignal = options.signal;\n registered.abortListener = abort;\n }\n if (this.tools.get(tool.name) === registered) {\n if (this.native) await this.nativeToolChangeQueue;\n else await this.notifyProducerToolsChanged();\n }\n if (this.closed) throw createInvalidStateError('BrowserMcpServer is closed');\n options.signal?.throwIfAborted();\n };\n\n private removeTool(name: string, options?: { skipNative?: boolean; notify?: boolean }): void {\n const registered = this.tools.get(name);\n if (registered) {\n if (registered.abortSignal && registered.abortListener) {\n registered.abortSignal.removeEventListener('abort', registered.abortListener);\n }\n this.tools.delete(name);\n this.nativeBackfilledTools.delete(name);\n registered.mcpHandle?.remove();\n if ((options?.notify ?? true) && !this.native) {\n void this.notifyProducerToolsChanged();\n }\n }\n if (!options?.skipNative) this.abortNativeToolMirror(name);\n }\n\n syncNativeTools(): Promise<void> {\n const sync = this.nativeSyncQueue.then(async () => {\n if (this.closed) return;\n const native = this.getNativeStandardToolsApi();\n if (native) await this.backfillNativeStandardTools(native);\n });\n this.nativeSyncQueue = sync.then(\n () => undefined,\n () => undefined\n );\n return sync;\n }\n\n private async backfillNativeStandardTools(native: NativeStandardToolsApi): Promise<void> {\n const tools = await native.getTools();\n if (this.closed) return;\n const nextTools = new Map<string, NativeBackfilledTool>();\n const nativeNames = new Set(tools.map(({ name }) => name));\n for (const name of this.removingNativeTools) {\n if (!nativeNames.has(name)) this.removingNativeTools.delete(name);\n }\n for (const tool of tools) {\n // ponytail: MCP tool names are global, so keep the first valid visible tool.\n // Add origin-qualified aliases if MCP gains scoped tool identity.\n if (\n nextTools.has(tool.name) ||\n this.pendingTools.has(tool.name) ||\n this.removingNativeTools.has(tool.name)\n ) {\n continue;\n }\n let inputSchema: InputSchema | undefined = DEFAULT_INPUT_SCHEMA;\n if (tool.inputSchema !== undefined) {\n try {\n // An object since webmcp#241; a serialized string from older Chrome. The\n // round-trip detaches the object from the page's graph and rejects non-JSON.\n const serialized =\n typeof tool.inputSchema === 'string'\n ? tool.inputSchema\n : JSON.stringify(tool.inputSchema);\n const parsed: unknown = JSON.parse(serialized);\n inputSchema = isPlainObject(parsed) ? (parsed as InputSchema) : undefined;\n } catch {\n inputSchema = undefined;\n }\n }\n if (!inputSchema) {\n console.warn(\n `[BrowserMcpServer] Native tool \"${tool.name}\" was not exposed over MCP because its input schema is malformed.`\n );\n continue;\n }\n const item: ToolListItem = {\n name: tool.name,\n ...(tool.title !== undefined ? { title: tool.title } : {}),\n description: tool.description,\n inputSchema,\n ...(tool.annotations ? { annotations: tool.annotations } : {}),\n };\n nextTools.set(tool.name, {\n source: tool,\n item,\n fingerprint: JSON.stringify(item),\n });\n }\n\n for (const [name, current] of this.nativeBackfilledTools) {\n const next = nextTools.get(name);\n if (!next || next.fingerprint !== current.fingerprint) {\n this.removeTool(name, { skipNative: true, notify: false });\n continue;\n }\n this.nativeBackfilledTools.set(name, next);\n }\n\n for (const [name, next] of nextTools) {\n if (this.tools.has(name)) continue;\n const execute = async (args: WebMcpToolInput, signal?: AbortSignal) => {\n const currentTool = this.nativeBackfilledTools.get(name)?.source;\n if (!currentTool) throw new Error(`Native tool not found: ${name}`);\n const input = JSON.stringify(args);\n return parseNativeToolResult(\n signal\n ? await native.executeTool.call(this.native, currentTool, input, { signal })\n : await native.executeTool.call(this.native, currentTool, input)\n );\n };\n const tool: ToolDescriptor<WebMcpToolInput> = {\n name,\n ...(next.item.title !== undefined ? { title: next.item.title } : {}),\n description: next.item.description,\n inputSchema: next.item.inputSchema,\n ...(next.item.annotations ? { annotations: next.item.annotations } : {}),\n execute: (args) => execute(args),\n };\n try {\n const normalized = this.validateToolDescriptor(tool);\n // Native getTools() does not report the allowlist a tool registered with, so a\n // backfilled mirror carries none and stays as widely exposed as it is today.\n this.tools.set(tool.name, this.registerToolInMcp(tool, normalized, execute, undefined));\n this.nativeBackfilledTools.set(name, next);\n } catch (error) {\n console.warn(\n `[BrowserMcpServer] Native tool \"${name}\" was not exposed over MCP because its schema could not be compiled:`,\n error\n );\n }\n }\n }\n\n registerResource(descriptor: ResourceDescriptor): RegistrationHandle {\n if (this.closed) throw createInvalidStateError('BrowserMcpServer is closed');\n const registeredDescriptor = { ...descriptor };\n const config = {\n ...(registeredDescriptor.description !== undefined\n ? { description: registeredDescriptor.description }\n : {}),\n ...(registeredDescriptor.mimeType !== undefined\n ? { mimeType: registeredDescriptor.mimeType }\n : {}),\n };\n const template = registeredDescriptor.uri.includes('{')\n ? new ResourceTemplate(registeredDescriptor.uri, { list: undefined })\n : undefined;\n const mcpHandle = template\n ? this.mcpServer.registerResource(\n registeredDescriptor.name,\n template,\n config,\n async (uri, variables) => registeredDescriptor.read(uri, variables)\n )\n : this.mcpServer.registerResource(\n registeredDescriptor.name,\n registeredDescriptor.uri,\n config,\n async (uri) => registeredDescriptor.read(uri)\n );\n this.registrations.add(mcpHandle);\n return {\n unregister: () => {\n if (this.registrations.delete(mcpHandle)) mcpHandle.remove();\n },\n };\n }\n\n registerPrompt(descriptor: PromptDescriptor): RegistrationHandle {\n if (this.closed) throw createInvalidStateError('BrowserMcpServer is closed');\n const registeredDescriptor = {\n ...descriptor,\n ...(descriptor.argsSchema === undefined\n ? {}\n : { argsSchema: structuredClone(descriptor.argsSchema) }),\n };\n const argsSchema =\n registeredDescriptor.argsSchema === undefined\n ? undefined\n : fromJsonSchema<Record<string, string>>(\n registeredDescriptor.argsSchema as Parameters<typeof fromJsonSchema>[0]\n );\n const mcpHandle = this.mcpServer.registerPrompt(\n registeredDescriptor.name,\n {\n ...(registeredDescriptor.description !== undefined\n ? { description: registeredDescriptor.description }\n : {}),\n ...(argsSchema ? { argsSchema } : {}),\n },\n async (args) => registeredDescriptor.get(args ?? {})\n );\n this.registrations.add(mcpHandle);\n return {\n unregister: () => {\n if (this.registrations.delete(mcpHandle)) mcpHandle.remove();\n },\n };\n }\n\n listTools(): ToolListItem[] {\n return structuredClone([...this.tools.values()].map(({ item }) => item));\n }\n\n async getTools(options?: ModelContextGetToolOptions): Promise<RegisteredTool[]> {\n validateWebMcpAccess(this.ownerDocument);\n if (this.closed) throw createInvalidStateError('BrowserMcpServer is closed');\n if (this.native) {\n return this.native.getTools(options);\n }\n validatePotentiallyTrustworthyOrigins(options?.fromOrigins);\n if (options?.fromOrigins?.length) {\n throw new DOMException(\n 'Cross-document tool discovery requires native WebMCP',\n 'NotSupportedError'\n );\n }\n\n const origin = globalThis.location?.origin ?? '';\n const currentWindow = globalThis.window;\n\n const tools = [...this.tools.values()]\n .map(({ item, registeredInputSchema }) => {\n // A fresh object per call, aligned with the polyfill's post-webmcp#241\n // shape. A custom toJSON can serialize to non-object JSON; omit those\n // rather than emit a value consumers would mistake for a pre-154\n // serialized string.\n const parsed: unknown =\n registeredInputSchema === undefined ? undefined : JSON.parse(registeredInputSchema);\n return {\n name: item.name,\n title: item.title ?? '',\n description: item.description,\n ...(isPlainObject(parsed) ? { inputSchema: parsed } : {}),\n origin,\n window: currentWindow,\n ...(item.annotations ? { annotations: toWebMcpAnnotations(item.annotations) } : {}),\n };\n })\n .sort((a, b) => (a.name < b.name ? -1 : a.name > b.name ? 1 : 0));\n await new Promise((resolve) => setTimeout(resolve, 0));\n return tools;\n }\n\n async executeTool(\n tool: RegisteredTool,\n inputArgsJson: string,\n options?: ChromeModelContextExecuteToolOptions\n ): Promise<string | null> {\n validateWebMcpAccess(this.ownerDocument);\n if (this.closed) throw createInvalidStateError('BrowserMcpServer is closed');\n const native = this.getNativeStandardToolsApi();\n if (native) {\n return native.executeTool.call(this.native, tool, inputArgsJson, options);\n }\n\n if (tool === null || typeof tool !== 'object') {\n throw new TypeError('RegisteredTool must be an object');\n }\n for (const required of ['name', 'description', 'window', 'origin'] as const) {\n if (!(required in tool)) {\n throw new TypeError(`RegisteredTool.${required} is required`);\n }\n }\n validateExecutableOrigin(tool.origin);\n const origin = globalThis.location?.origin ?? '';\n const currentWindow = globalThis.window;\n if (tool.origin !== origin || tool.window !== currentWindow) {\n throw createUnknownError(`Native tool not found: ${tool.name}`);\n }\n options?.signal?.throwIfAborted();\n const registered = this.tools.get(tool.name);\n if (!registered) throw createUnknownError(`Tool not found: ${tool.name}`);\n const args = parseChromeToolInput(inputArgsJson);\n try {\n const result = await withAbortSignal(\n registered.execute(args, options?.signal),\n registered.abortSignal,\n () => createUnknownError('Tool unregistered')\n );\n return serializeChromeToolResult(result);\n } catch (error) {\n if (options?.signal?.aborted && error === options.signal.reason) throw error;\n if (registered.abortSignal?.aborted) throw error;\n throw createToolInvocationFailedError(error);\n }\n }\n\n /**\n * Re-evaluate which registered tools may appear on the wire.\n *\n * `exposedTo` narrows a tool to named embedder origins. The peer origin is only known\n * once a transport that reports one has heard from its peer, so a restricted tool stays\n * disabled until then — and stays disabled forever on transports that cannot name a peer\n * at all. Failing closed keeps a tool that asked for a narrow audience from reaching a\n * wider one; unrestricted tools are untouched and behave exactly as before.\n */\n private applyToolExposure(): void {\n for (const { exposedTo, mcpHandle } of this.tools.values()) {\n if (!exposedTo?.length || !mcpHandle) continue;\n // Opaque origins serialize identically and cannot identify an allowed peer.\n const visible =\n this.peerOrigin !== undefined &&\n this.peerOrigin !== 'null' &&\n exposedTo.includes(this.peerOrigin);\n if (visible === mcpHandle.enabled) continue;\n if (visible) mcpHandle.enable();\n else mcpHandle.disable();\n }\n }\n\n /**\n * Follow the peer origin of transports that report one, so `exposedTo` can be scoped to\n * the embedder actually connected. Duck-typed rather than imported: the SDK must not take\n * a build dependency on `@mcp-b/transports`, and transports that never name a peer simply\n * leave every restricted tool disabled.\n */\n private observePeerOrigin(transport: Transport): void {\n this.stopObservingPeerOrigin?.();\n this.stopObservingPeerOrigin = undefined;\n this.peerOrigin = undefined;\n this.applyToolExposure();\n if (!('clientOrigin' in transport)) return;\n const peered = transport as Transport & {\n clientOrigin?: string;\n onclientorigin?: ((origin: string) => void) | undefined;\n };\n this.peerOrigin = peered.clientOrigin;\n this.applyToolExposure();\n const previous = peered.onclientorigin;\n let observing = true;\n const onclientorigin = (origin: string) => {\n previous?.(origin);\n if (!observing) return;\n this.peerOrigin = origin;\n this.applyToolExposure();\n };\n peered.onclientorigin = onclientorigin;\n this.stopObservingPeerOrigin = () => {\n observing = false;\n if (peered.onclientorigin === onclientorigin) peered.onclientorigin = previous;\n };\n }\n\n async connect(transport: Transport): Promise<void> {\n if (this.closed) throw createInvalidStateError('BrowserMcpServer is closed');\n if (this.mcpServer.server.transport) {\n throw createInvalidStateError('BrowserMcpServer is already connected');\n }\n this.observePeerOrigin(transport);\n const stopObserving = this.stopObservingPeerOrigin;\n try {\n await this.mcpServer.connect(transport);\n } catch (error) {\n if (this.stopObservingPeerOrigin === stopObserving) {\n stopObserving?.();\n this.stopObservingPeerOrigin = undefined;\n this.peerOrigin = undefined;\n this.applyToolExposure();\n }\n if (this.mcpServer.server.transport === transport) await this.mcpServer.close();\n throw error;\n }\n }\n\n close(): Promise<void> {\n if (this.closePromise) return this.closePromise;\n this.closed = true;\n this.stopObservingPeerOrigin?.();\n this.stopObservingPeerOrigin = undefined;\n this.closePromise = (async () => {\n if (this.native && this.nativeToolChangeListener) {\n this.native.removeEventListener('toolchange', this.nativeToolChangeListener);\n this.nativeToolChangeListener = undefined;\n }\n for (const name of this.nativeToolAbortControllers.keys()) {\n this.abortNativeToolMirror(name);\n }\n for (const name of this.tools.keys()) {\n this.removeTool(name, { notify: false });\n }\n for (const handle of this.registrations) handle.remove();\n this.registrations.clear();\n this.nativeBackfilledTools.clear();\n this.removingNativeTools.clear();\n await this.mcpServer.close();\n })();\n return this.closePromise;\n }\n}\n\nexport interface ResourceDescriptor {\n uri: string;\n name: string;\n description?: string;\n mimeType?: string;\n read: (uri: URL, params?: Variables) => Promise<ReadResourceResult>;\n}\n\nexport interface PromptDescriptor {\n name: string;\n description?: string;\n argsSchema?: InputSchema;\n get: (args: Record<string, string>) => Promise<GetPromptResult>;\n}\n"],"mappings":";;;;AAsDA,MAAM,uBAAuB,qBAAqB,OAAU,CAAC;AAC7D,MAAM,yBAAyB;AAE/B,SAAgB,mBAAmB,SAA+C;CAChF,OACE,OAAO,YAAY,YACnB,YAAY,QACZ,0BAA0B,WAC1B,QAAQ,4BAA4B;;AAkCxC,SAAS,sBAAsB,YAAoC;CACjE,IAAI,eAAe,MACjB,OAAO;EACL,SAAS,CAAC;GAAE,MAAM;GAAQ,MAAM;GAA4C,CAAC;EAC7E,SAAS;EACV;CAGH,IAAI;CACJ,IAAI;EACF,SAAS,KAAK,MAAM,WAAW;SACzB;EACN,OAAO,sBAAsB,WAAW;;CAE1C,OAAO,sBAAsB,OAAO,GAAG,SAAS,sBAAsB,OAAO;;AAG/E,SAAS,iBACP,YACiD;CAGjD,MAAM,iBAAiB,OAAO,yBAAyB,WAAW,aAAa,YAAY;CAC3F,OAAO,kBAAkB,CAAC,eAAe,aACpC,WAAW,cACZ,eACE,WAAW,YACZ;;AAGP,SAAS,iBACP,aACgC;CAChC,IAAI,CAAC,aAAa,OAAO;CACzB,MAAM,EAAE,sBAAsB,uBAAuB,GAAG,mBAAmB;CAC3E,OAAO;;AAGT,SAAS,aACP,MACA,aACA,SACmC;CACnC,MAAM,cAAc,KAAK,cAAc,oBAAoB,KAAK,YAAY,GAAG;CAC/E,OAAO;EACL,MAAM,KAAK;EACX,GAAI,KAAK,UAAU,SAAY,EAAE,OAAO,KAAK,OAAO,GAAG,EAAE;EACzD,aAAa,KAAK;EAClB,GAAI,gBAAgB,SAAY,EAAE,aAAa,GAAG,EAAE;EACpD,GAAI,cAAc,EAAE,aAAa,GAAG,EAAE;EACtC;EACD;;;;;;;;;AAUH,IAAa,mBAAb,cAAsC,YAAkD;CACtF,CAAU,0BAA0B;CACpC,AAAS;CAET,AAAiB;CACjB,AAAiB;CACjB,AAAiB,wBAAQ,IAAI,KAAmC;CAChE,AAAQ;CACR,AAAQ;CACR,AAAiB,gCAAgB,IAAI,KAAsB;CAC3D,AAAiB,6CAA6B,IAAI,KAA8B;CAChF,AAAiB,wCAAwB,IAAI,KAAmC;CAChF,AAAiB,+BAAe,IAAI,KAA8B;CAClE,AAAiB,sCAAsB,IAAI,KAAa;CACxD,AAAQ,kBAAiC,QAAQ,SAAS;CAC1D,AAAQ,wBAAuC,QAAQ,SAAS;CAChE,AAAQ;CACR,AAAQ,SAAS;CACjB,AAAQ;CACR,AAAQ,sBAA8E;CACtF,AAAiB,wBAAuC,UAAU;EAChE,KAAK,qBAAqB,KAAK,MAAM,MAAM;;CAG7C,YAAY,YAA4B,UAAmC,EAAE,EAAE;EAC7E,OAAO;EACP,MAAM,EAAE,QAAQ,GAAG,kBAAkB;EACrC,KAAK,YAAY,IAAI,UAAU,YAAY;GACzC,GAAG;GACH,cAAc,kBAAkB,cAAc,gBAAgB,EAAE,EAAE;IAChE,OAAO,EAAE,aAAa,MAAM;IAC5B,WAAW,EAAE,aAAa,MAAM;IAChC,SAAS,EAAE,aAAa,MAAM;IAC/B,CAAC;GACH,CAAC;EACF,KAAK,SAAS;EACd,KAAK,gBAAgB,WAAW,YAAY;EAC5C,IACE,UACA,OAAO,OAAO,qBAAqB,cACnC,OAAO,OAAO,wBAAwB,YACtC;GACA,KAAK,iCAAiC;IACpC,IAAI,KAAK,QAAQ;IACjB,KAAK,wBAAwB,KAAK,sBAAsB,KAAK,YAAY;KACvE,IAAI;MACF,MAAM,KAAK,iBAAiB;cACrB,OAAO;MACd,QAAQ,KAAK,gEAAgE,MAAM;;KAErF,MAAM,KAAK,4BAA4B;MACvC;;GAEJ,OAAO,iBAAiB,cAAc,KAAK,yBAAyB;;;CAIxE,IAAI,eAAuE;EACzE,OAAO,KAAK;;CAGd,IAAI,aAAa,SAAiE;EAChF,MAAM,WAAW,OAAO,YAAY,aAAa,UAAU;EAC3D,IAAI,aAAa,MAAM;GACrB,KAAK,sBAAsB;GAC3B,MAAM,oBAAoB,cAAc,KAAK,qBAAqB;GAClE;;EAGF,IAAI,KAAK,wBAAwB,MAC/B,MAAM,iBAAiB,cAAc,KAAK,qBAAqB;EAEjE,KAAK,sBAAsB;;CAG7B,MAAc,6BAA4C;EACxD,IAAI,KAAK,QAAQ;EAEjB,MAAM,IAAI,SAAS,YAAY,WAAW,SAAS,EAAE,CAAC;EACtD,IAAI,CAAC,KAAK,QAAQ,KAAK,cAAc,IAAI,MAAM,aAAa,CAAC;;CAG/D,AAAQ,4BAAgE;EACtE,MAAM,YACJ,KAAK;EACP,OAAO,aAAa,OAAO,UAAU,gBAAgB,aAChD,YACD;;CAGN,MAAc,yBACZ,MACA,YACA,SACA,SACA,YACe;EACf,IAAI,CAAC,KAAK,QAAQ;EAGlB,MAAM,iBAAiB,KAAK,OAAO;EACnC,MAAM,SAAS,QAAQ,SACnB,YAAY,IAAI,CAAC,QAAQ,QAAQ,WAAW,OAAO,CAAC,GACpD,WAAW;EAEf,MAAM,oBACJ,WAAW,0BAA0B,SACjC,SACC,KAAK,MAAM,WAAW,sBAAsB;EACnD,KAAK,2BAA2B,IAAI,KAAK,MAAM,WAAW;EAC1D,IAAI;GACF,MAAM,eAAe,KACnB,KAAK,QACL,aAAa,MAAM,oBAAoB,UAAU,QAAQ,MAAM,CAAC,EAChE;IAAE,GAAG;IAAS;IAAQ,CACvB;WACM,OAAO;GACd,WAAW,OAAO;GAClB,IAAI,KAAK,2BAA2B,IAAI,KAAK,KAAK,KAAK,YACrD,KAAK,2BAA2B,OAAO,KAAK,KAAK;GAEnD,MAAM;;EAER,IAAI,KAAK,2BAA2B,IAAI,KAAK,KAAK,KAAK,YACrD,KAAK,oBAAoB,OAAO,KAAK,KAAK;;CAI9C,AAAQ,sBACN,MACA,aAAa,KAAK,2BAA2B,IAAI,KAAK,EAChD;EACN,IAAI,CAAC,cAAc,KAAK,2BAA2B,IAAI,KAAK,KAAK,YAAY;EAC7E,KAAK,oBAAoB,IAAI,KAAK;EAClC,WAAW,OAAO;EAClB,KAAK,2BAA2B,OAAO,KAAK;;CAG9C,AAAQ,uBAAuB,MAA8D;EAC3F,6BAA6B,KAAK;EAClC,IAAI,KAAK,MAAM,IAAI,KAAK,KAAK,IAAI,KAAK,aAAa,IAAI,KAAK,KAAK,EAC/D,MAAM,wBAAwB,4BAA4B,KAAK,OAAO;EAExE,OAAO,qBAAqB,KAAK,YAAY;;CAG/C,AAAQ,kBACN,MACA,YACA,aACA,WACsB;EACtB,MAAM,eACJ,KAAK,iBAAiB,SAAY,SAAY,gBAAgB,KAAK,aAAa;EAClF,MAAM,kBACJ,iBAAiB,SACb,SACA,eAAe,aAAqD;EAC1E,MAAM,iBAAiB,iBAAiB,KAAK,YAAY;EACzD,MAAM,qBACJ,WAAW,YAAY,SAAS,UAAa,WAAW,YAAY,SAAS;EAC/E,MAAM,YAAY,qBACd,KAAK,UAAU,aACb,KAAK,MACL;GACE,GAAI,KAAK,UAAU,SAAY,EAAE,OAAO,KAAK,OAAO,GAAG,EAAE;GACzD,aAAa,KAAK;GAClB,aAAa,iBAAiB,WAAW;GACzC,GAAI,kBAAkB,EAAE,cAAc,iBAAiB,GAAG,EAAE;GAC5D,GAAI,iBAAiB,EAAE,aAAa,gBAAgB,GAAG,EAAE;GAC1D,EACD,OAAO,MAAM,YAAY;GACvB,MAAM,SAAS,MAAM,YAAY,MAAM,QAAQ,OAAO,OAAO;GAC7D,IAAI,sBAAsB,OAAO,EAC/B,MAAM,IAAI,MACR,gBAAgB,KAAK,KAAK,sGAC3B;GAEH,OAAO,sBAAsB,OAAO;IAEvC,GACD;EAIJ,IAAI,WAAW,QAAQ,WAAW,SAAS;EAE3C,IAAI,CAAC,oBACH,QAAQ,KACN,4BAA4B,KAAK,KAAK,qHACvC;EAWH,OAAO;GACL;IARA,MAAM,KAAK;IACX,GAAI,KAAK,UAAU,SAAY,EAAE,OAAO,KAAK,OAAO,GAAG,EAAE;IACzD,aAAa,KAAK;IAClB,aAAa,WAAW;IACxB,GAAI,iBAAiB,SAAY,EAAE,GAAG,EAAE,cAAc;IACtD,GAAI,KAAK,cAAc,EAAE,aAAa,KAAK,aAAa,GAAG,EAAE;IAGzD;GACJ,GAAI,WAAW,0BAA0B,SACrC,EAAE,uBAAuB,WAAW,uBAAuB,GAC3D,EAAE;GACN,SAAS;GACT;GACA,GAAI,WAAW,SAAS,EAAE,WAAW,GAAG,EAAE;GAC3C;;CAGH,AAAS,eAA2D,OAClE,WACA,eAAuD,EAAE,KACvC;EAClB,MAAM,EAAE,QAAQ,cAAc,gBAAgB,EAAE;EAChD,MAAM,UAAU;GACd,GAAI,SAAS,EAAE,QAAQ,GAAG,EAAE;GAC5B,GAAI,YAAY,EAAE,WAAW,CAAC,GAAG,UAAU,EAAE,GAAG,EAAE;GACnD;EACD,qBAAqB,KAAK,cAAc;EACxC,IAAI,KAAK,QAAQ,MAAM,wBAAwB,6BAA6B;EAC5E,IAAI,CAAC,cAAc,UAAU,EAC3B,MAAM,IAAI,UAAU,4CAA4C;EAElE,MAAM,OAAO,2BAA2B,UAAU;EAClD,MAAM,aAAa,KAAK,uBAAuB,KAAK;EACpD,QAAQ,QAAQ,gBAAgB;EAChC,sCAAsC,QAAQ,UAAU;EACxD,QAAQ,QAAQ,gBAAgB;EAChC,MAAM,UAA2C,OAAO,MAAM,WAAW;GACvE,QAAQ,gBAAgB;GACxB,OAAO,gBACL,QAAQ,SAAS,CAAC,WAAW,QAAQ,MAAM,KAAK,SAAS,QAAW,CAAC,KAAK,CAAC,CAAC,EAC5E,OACD;;EAEH,MAAM,aAAa,IAAI,iBAAiB;EACxC,IAAI;EACJ,MAAM,cAAc;GAClB,IAAI,KAAK,aAAa,IAAI,KAAK,KAAK,KAAK,YACvC,KAAK,aAAa,OAAO,KAAK,KAAK;GAErC,IAAI,cAAc,KAAK,MAAM,IAAI,KAAK,KAAK,KAAK,YAC9C,KAAK,WAAW,KAAK,KAAK;QAE1B,KAAK,sBAAsB,KAAK,MAAM,WAAW;;EAGrD,QAAQ,QAAQ,iBAAiB,SAAS,OAAO,EAAE,MAAM,MAAM,CAAC;EAChE,KAAK,aAAa,IAAI,KAAK,MAAM,WAAW;EAC5C,IAAI;GACF,MAAM,KAAK,yBAAyB,MAAM,YAAY,SAAS,SAAS,WAAW;GACnF,IAAI,KAAK,QAAQ,MAAM,wBAAwB,6BAA6B;GAC5E,QAAQ,QAAQ,gBAAgB;GAChC,aAAa,KAAK,kBAChB,MACA,YACA,SACA,QAAQ,WAAW,KAAK,WAAW;IACjC,MAAM,eAAe,IAAI,IAAI,OAAO,CAAC;IAErC,OAAO,iBAAiB,SAAS,SAAS;KAC1C,CACH;GACD,KAAK,MAAM,IAAI,KAAK,MAAM,WAAW;GACrC,KAAK,mBAAmB;GACxB,IAAI,QAAQ,QAAQ,SAAS;IAC3B,OAAO;IACP,QAAQ,OAAO,gBAAgB;;WAE1B,OAAO;GACd,KAAK,sBAAsB,KAAK,MAAM,WAAW;GACjD,QAAQ,QAAQ,oBAAoB,SAAS,MAAM;GACnD,QAAQ,QAAQ,gBAAgB;GAChC,MAAM;YACE;GACR,IAAI,KAAK,aAAa,IAAI,KAAK,KAAK,KAAK,YACvC,KAAK,aAAa,OAAO,KAAK,KAAK;;EAGvC,IAAI,QAAQ,QAAQ;GAClB,WAAW,cAAc,QAAQ;GACjC,WAAW,gBAAgB;;EAE7B,IAAI,KAAK,MAAM,IAAI,KAAK,KAAK,KAAK,YAChC,IAAI,KAAK,QAAQ,MAAM,KAAK;OACvB,MAAM,KAAK,4BAA4B;EAE9C,IAAI,KAAK,QAAQ,MAAM,wBAAwB,6BAA6B;EAC5E,QAAQ,QAAQ,gBAAgB;;CAGlC,AAAQ,WAAW,MAAc,SAA4D;EAC3F,MAAM,aAAa,KAAK,MAAM,IAAI,KAAK;EACvC,IAAI,YAAY;GACd,IAAI,WAAW,eAAe,WAAW,eACvC,WAAW,YAAY,oBAAoB,SAAS,WAAW,cAAc;GAE/E,KAAK,MAAM,OAAO,KAAK;GACvB,KAAK,sBAAsB,OAAO,KAAK;GACvC,WAAW,WAAW,QAAQ;GAC9B,KAAK,SAAS,UAAU,SAAS,CAAC,KAAK,QACrC,AAAK,KAAK,4BAA4B;;EAG1C,IAAI,CAAC,SAAS,YAAY,KAAK,sBAAsB,KAAK;;CAG5D,kBAAiC;EAC/B,MAAM,OAAO,KAAK,gBAAgB,KAAK,YAAY;GACjD,IAAI,KAAK,QAAQ;GACjB,MAAM,SAAS,KAAK,2BAA2B;GAC/C,IAAI,QAAQ,MAAM,KAAK,4BAA4B,OAAO;IAC1D;EACF,KAAK,kBAAkB,KAAK,WACpB,cACA,OACP;EACD,OAAO;;CAGT,MAAc,4BAA4B,QAA+C;EACvF,MAAM,QAAQ,MAAM,OAAO,UAAU;EACrC,IAAI,KAAK,QAAQ;EACjB,MAAM,4BAAY,IAAI,KAAmC;EACzD,MAAM,cAAc,IAAI,IAAI,MAAM,KAAK,EAAE,WAAW,KAAK,CAAC;EAC1D,KAAK,MAAM,QAAQ,KAAK,qBACtB,IAAI,CAAC,YAAY,IAAI,KAAK,EAAE,KAAK,oBAAoB,OAAO,KAAK;EAEnE,KAAK,MAAM,QAAQ,OAAO;GAGxB,IACE,UAAU,IAAI,KAAK,KAAK,IACxB,KAAK,aAAa,IAAI,KAAK,KAAK,IAChC,KAAK,oBAAoB,IAAI,KAAK,KAAK,EAEvC;GAEF,IAAI,cAAuC;GAC3C,IAAI,KAAK,gBAAgB,QACvB,IAAI;IAGF,MAAM,aACJ,OAAO,KAAK,gBAAgB,WACxB,KAAK,cACL,KAAK,UAAU,KAAK,YAAY;IACtC,MAAM,SAAkB,KAAK,MAAM,WAAW;IAC9C,cAAc,cAAc,OAAO,GAAI,SAAyB;WAC1D;IACN,cAAc;;GAGlB,IAAI,CAAC,aAAa;IAChB,QAAQ,KACN,mCAAmC,KAAK,KAAK,mEAC9C;IACD;;GAEF,MAAM,OAAqB;IACzB,MAAM,KAAK;IACX,GAAI,KAAK,UAAU,SAAY,EAAE,OAAO,KAAK,OAAO,GAAG,EAAE;IACzD,aAAa,KAAK;IAClB;IACA,GAAI,KAAK,cAAc,EAAE,aAAa,KAAK,aAAa,GAAG,EAAE;IAC9D;GACD,UAAU,IAAI,KAAK,MAAM;IACvB,QAAQ;IACR;IACA,aAAa,KAAK,UAAU,KAAK;IAClC,CAAC;;EAGJ,KAAK,MAAM,CAAC,MAAM,YAAY,KAAK,uBAAuB;GACxD,MAAM,OAAO,UAAU,IAAI,KAAK;GAChC,IAAI,CAAC,QAAQ,KAAK,gBAAgB,QAAQ,aAAa;IACrD,KAAK,WAAW,MAAM;KAAE,YAAY;KAAM,QAAQ;KAAO,CAAC;IAC1D;;GAEF,KAAK,sBAAsB,IAAI,MAAM,KAAK;;EAG5C,KAAK,MAAM,CAAC,MAAM,SAAS,WAAW;GACpC,IAAI,KAAK,MAAM,IAAI,KAAK,EAAE;GAC1B,MAAM,UAAU,OAAO,MAAuB,WAAyB;IACrE,MAAM,cAAc,KAAK,sBAAsB,IAAI,KAAK,EAAE;IAC1D,IAAI,CAAC,aAAa,MAAM,IAAI,MAAM,0BAA0B,OAAO;IACnE,MAAM,QAAQ,KAAK,UAAU,KAAK;IAClC,OAAO,sBACL,SACI,MAAM,OAAO,YAAY,KAAK,KAAK,QAAQ,aAAa,OAAO,EAAE,QAAQ,CAAC,GAC1E,MAAM,OAAO,YAAY,KAAK,KAAK,QAAQ,aAAa,MAAM,CACnE;;GAEH,MAAM,OAAwC;IAC5C;IACA,GAAI,KAAK,KAAK,UAAU,SAAY,EAAE,OAAO,KAAK,KAAK,OAAO,GAAG,EAAE;IACnE,aAAa,KAAK,KAAK;IACvB,aAAa,KAAK,KAAK;IACvB,GAAI,KAAK,KAAK,cAAc,EAAE,aAAa,KAAK,KAAK,aAAa,GAAG,EAAE;IACvE,UAAU,SAAS,QAAQ,KAAK;IACjC;GACD,IAAI;IACF,MAAM,aAAa,KAAK,uBAAuB,KAAK;IAGpD,KAAK,MAAM,IAAI,KAAK,MAAM,KAAK,kBAAkB,MAAM,YAAY,SAAS,OAAU,CAAC;IACvF,KAAK,sBAAsB,IAAI,MAAM,KAAK;YACnC,OAAO;IACd,QAAQ,KACN,mCAAmC,KAAK,uEACxC,MACD;;;;CAKP,iBAAiB,YAAoD;EACnE,IAAI,KAAK,QAAQ,MAAM,wBAAwB,6BAA6B;EAC5E,MAAM,uBAAuB,EAAE,GAAG,YAAY;EAC9C,MAAM,SAAS;GACb,GAAI,qBAAqB,gBAAgB,SACrC,EAAE,aAAa,qBAAqB,aAAa,GACjD,EAAE;GACN,GAAI,qBAAqB,aAAa,SAClC,EAAE,UAAU,qBAAqB,UAAU,GAC3C,EAAE;GACP;EACD,MAAM,WAAW,qBAAqB,IAAI,SAAS,IAAI,GACnD,IAAI,iBAAiB,qBAAqB,KAAK,EAAE,MAAM,QAAW,CAAC,GACnE;EACJ,MAAM,YAAY,WACd,KAAK,UAAU,iBACb,qBAAqB,MACrB,UACA,QACA,OAAO,KAAK,cAAc,qBAAqB,KAAK,KAAK,UAAU,CACpE,GACD,KAAK,UAAU,iBACb,qBAAqB,MACrB,qBAAqB,KACrB,QACA,OAAO,QAAQ,qBAAqB,KAAK,IAAI,CAC9C;EACL,KAAK,cAAc,IAAI,UAAU;EACjC,OAAO,EACL,kBAAkB;GAChB,IAAI,KAAK,cAAc,OAAO,UAAU,EAAE,UAAU,QAAQ;KAE/D;;CAGH,eAAe,YAAkD;EAC/D,IAAI,KAAK,QAAQ,MAAM,wBAAwB,6BAA6B;EAC5E,MAAM,uBAAuB;GAC3B,GAAG;GACH,GAAI,WAAW,eAAe,SAC1B,EAAE,GACF,EAAE,YAAY,gBAAgB,WAAW,WAAW,EAAE;GAC3D;EACD,MAAM,aACJ,qBAAqB,eAAe,SAChC,SACA,eACE,qBAAqB,WACtB;EACP,MAAM,YAAY,KAAK,UAAU,eAC/B,qBAAqB,MACrB;GACE,GAAI,qBAAqB,gBAAgB,SACrC,EAAE,aAAa,qBAAqB,aAAa,GACjD,EAAE;GACN,GAAI,aAAa,EAAE,YAAY,GAAG,EAAE;GACrC,EACD,OAAO,SAAS,qBAAqB,IAAI,QAAQ,EAAE,CAAC,CACrD;EACD,KAAK,cAAc,IAAI,UAAU;EACjC,OAAO,EACL,kBAAkB;GAChB,IAAI,KAAK,cAAc,OAAO,UAAU,EAAE,UAAU,QAAQ;KAE/D;;CAGH,YAA4B;EAC1B,OAAO,gBAAgB,CAAC,GAAG,KAAK,MAAM,QAAQ,CAAC,CAAC,KAAK,EAAE,WAAW,KAAK,CAAC;;CAG1E,MAAM,SAAS,SAAiE;EAC9E,qBAAqB,KAAK,cAAc;EACxC,IAAI,KAAK,QAAQ,MAAM,wBAAwB,6BAA6B;EAC5E,IAAI,KAAK,QACP,OAAO,KAAK,OAAO,SAAS,QAAQ;EAEtC,sCAAsC,SAAS,YAAY;EAC3D,IAAI,SAAS,aAAa,QACxB,MAAM,IAAI,aACR,wDACA,oBACD;EAGH,MAAM,SAAS,WAAW,UAAU,UAAU;EAC9C,MAAM,gBAAgB,WAAW;EAEjC,MAAM,QAAQ,CAAC,GAAG,KAAK,MAAM,QAAQ,CAAC,CACnC,KAAK,EAAE,MAAM,4BAA4B;GAKxC,MAAM,SACJ,0BAA0B,SAAY,SAAY,KAAK,MAAM,sBAAsB;GACrF,OAAO;IACL,MAAM,KAAK;IACX,OAAO,KAAK,SAAS;IACrB,aAAa,KAAK;IAClB,GAAI,cAAc,OAAO,GAAG,EAAE,aAAa,QAAQ,GAAG,EAAE;IACxD;IACA,QAAQ;IACR,GAAI,KAAK,cAAc,EAAE,aAAa,oBAAoB,KAAK,YAAY,EAAE,GAAG,EAAE;IACnF;IACD,CACD,MAAM,GAAG,MAAO,EAAE,OAAO,EAAE,OAAO,KAAK,EAAE,OAAO,EAAE,OAAO,IAAI,EAAG;EACnE,MAAM,IAAI,SAAS,YAAY,WAAW,SAAS,EAAE,CAAC;EACtD,OAAO;;CAGT,MAAM,YACJ,MACA,eACA,SACwB;EACxB,qBAAqB,KAAK,cAAc;EACxC,IAAI,KAAK,QAAQ,MAAM,wBAAwB,6BAA6B;EAC5E,MAAM,SAAS,KAAK,2BAA2B;EAC/C,IAAI,QACF,OAAO,OAAO,YAAY,KAAK,KAAK,QAAQ,MAAM,eAAe,QAAQ;EAG3E,IAAI,SAAS,QAAQ,OAAO,SAAS,UACnC,MAAM,IAAI,UAAU,mCAAmC;EAEzD,KAAK,MAAM,YAAY;GAAC;GAAQ;GAAe;GAAU;GAAS,EAChE,IAAI,EAAE,YAAY,OAChB,MAAM,IAAI,UAAU,kBAAkB,SAAS,cAAc;EAGjE,yBAAyB,KAAK,OAAO;EACrC,MAAM,SAAS,WAAW,UAAU,UAAU;EAC9C,MAAM,gBAAgB,WAAW;EACjC,IAAI,KAAK,WAAW,UAAU,KAAK,WAAW,eAC5C,MAAM,mBAAmB,0BAA0B,KAAK,OAAO;EAEjE,SAAS,QAAQ,gBAAgB;EACjC,MAAM,aAAa,KAAK,MAAM,IAAI,KAAK,KAAK;EAC5C,IAAI,CAAC,YAAY,MAAM,mBAAmB,mBAAmB,KAAK,OAAO;EACzE,MAAM,OAAO,qBAAqB,cAAc;EAChD,IAAI;GAMF,OAAO,0BAA0B,MALZ,gBACnB,WAAW,QAAQ,MAAM,SAAS,OAAO,EACzC,WAAW,mBACL,mBAAmB,oBAAoB,CAC9C,CACuC;WACjC,OAAO;GACd,IAAI,SAAS,QAAQ,WAAW,UAAU,QAAQ,OAAO,QAAQ,MAAM;GACvE,IAAI,WAAW,aAAa,SAAS,MAAM;GAC3C,MAAM,gCAAgC,MAAM;;;;;;;;;;;;CAahD,AAAQ,oBAA0B;EAChC,KAAK,MAAM,EAAE,WAAW,eAAe,KAAK,MAAM,QAAQ,EAAE;GAC1D,IAAI,CAAC,WAAW,UAAU,CAAC,WAAW;GAEtC,MAAM,UACJ,KAAK,eAAe,UACpB,KAAK,eAAe,UACpB,UAAU,SAAS,KAAK,WAAW;GACrC,IAAI,YAAY,UAAU,SAAS;GACnC,IAAI,SAAS,UAAU,QAAQ;QAC1B,UAAU,SAAS;;;;;;;;;CAU5B,AAAQ,kBAAkB,WAA4B;EACpD,KAAK,2BAA2B;EAChC,KAAK,0BAA0B;EAC/B,KAAK,aAAa;EAClB,KAAK,mBAAmB;EACxB,IAAI,EAAE,kBAAkB,YAAY;EACpC,MAAM,SAAS;EAIf,KAAK,aAAa,OAAO;EACzB,KAAK,mBAAmB;EACxB,MAAM,WAAW,OAAO;EACxB,IAAI,YAAY;EAChB,MAAM,kBAAkB,WAAmB;GACzC,WAAW,OAAO;GAClB,IAAI,CAAC,WAAW;GAChB,KAAK,aAAa;GAClB,KAAK,mBAAmB;;EAE1B,OAAO,iBAAiB;EACxB,KAAK,gCAAgC;GACnC,YAAY;GACZ,IAAI,OAAO,mBAAmB,gBAAgB,OAAO,iBAAiB;;;CAI1E,MAAM,QAAQ,WAAqC;EACjD,IAAI,KAAK,QAAQ,MAAM,wBAAwB,6BAA6B;EAC5E,IAAI,KAAK,UAAU,OAAO,WACxB,MAAM,wBAAwB,wCAAwC;EAExE,KAAK,kBAAkB,UAAU;EACjC,MAAM,gBAAgB,KAAK;EAC3B,IAAI;GACF,MAAM,KAAK,UAAU,QAAQ,UAAU;WAChC,OAAO;GACd,IAAI,KAAK,4BAA4B,eAAe;IAClD,iBAAiB;IACjB,KAAK,0BAA0B;IAC/B,KAAK,aAAa;IAClB,KAAK,mBAAmB;;GAE1B,IAAI,KAAK,UAAU,OAAO,cAAc,WAAW,MAAM,KAAK,UAAU,OAAO;GAC/E,MAAM;;;CAIV,QAAuB;EACrB,IAAI,KAAK,cAAc,OAAO,KAAK;EACnC,KAAK,SAAS;EACd,KAAK,2BAA2B;EAChC,KAAK,0BAA0B;EAC/B,KAAK,gBAAgB,YAAY;GAC/B,IAAI,KAAK,UAAU,KAAK,0BAA0B;IAChD,KAAK,OAAO,oBAAoB,cAAc,KAAK,yBAAyB;IAC5E,KAAK,2BAA2B;;GAElC,KAAK,MAAM,QAAQ,KAAK,2BAA2B,MAAM,EACvD,KAAK,sBAAsB,KAAK;GAElC,KAAK,MAAM,QAAQ,KAAK,MAAM,MAAM,EAClC,KAAK,WAAW,MAAM,EAAE,QAAQ,OAAO,CAAC;GAE1C,KAAK,MAAM,UAAU,KAAK,eAAe,OAAO,QAAQ;GACxD,KAAK,cAAc,OAAO;GAC1B,KAAK,sBAAsB,OAAO;GAClC,KAAK,oBAAoB,OAAO;GAChC,MAAM,KAAK,UAAU,OAAO;MAC1B;EACJ,OAAO,KAAK"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mcp-b/webmcp-ts-sdk",
|
|
3
|
-
"version": "5.0.
|
|
3
|
+
"version": "5.0.3",
|
|
4
4
|
"description": "Thin WebMCP-to-MCP v2 browser adapter with native Chrome tool mirroring",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"adapter",
|
|
@@ -59,15 +59,16 @@
|
|
|
59
59
|
},
|
|
60
60
|
"dependencies": {
|
|
61
61
|
"@modelcontextprotocol/server": "2.0.0",
|
|
62
|
-
"@mcp-b/webmcp-polyfill": "5.0.
|
|
63
|
-
"@mcp-b/webmcp-types": "5.0.
|
|
62
|
+
"@mcp-b/webmcp-polyfill": "5.0.3",
|
|
63
|
+
"@mcp-b/webmcp-types": "5.0.3"
|
|
64
64
|
},
|
|
65
65
|
"devDependencies": {
|
|
66
66
|
"@modelcontextprotocol/client": "2.0.0",
|
|
67
|
+
"@vitest/coverage-v8": "4.1.6",
|
|
67
68
|
"playwright": "^1.60.0",
|
|
68
69
|
"typescript": "^5.8.3",
|
|
69
|
-
"vite-plus": "
|
|
70
|
-
"vitest": "npm:@voidzero-dev/vite-plus-test@
|
|
70
|
+
"vite-plus": "0.1.22",
|
|
71
|
+
"vitest": "npm:@voidzero-dev/vite-plus-test@0.1.22"
|
|
71
72
|
},
|
|
72
73
|
"engines": {
|
|
73
74
|
"node": ">=20"
|
|
@@ -81,6 +82,7 @@
|
|
|
81
82
|
"publish:dry": "pnpm publish --access public --dry-run",
|
|
82
83
|
"publish:npm": "pnpm publish --access public",
|
|
83
84
|
"test": "vp test run",
|
|
85
|
+
"test:coverage": "vp test run --coverage",
|
|
84
86
|
"typecheck": "tsc --noEmit"
|
|
85
87
|
}
|
|
86
88
|
}
|