@agent-surface/webmcp 0.25.0 → 0.26.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -25,7 +25,7 @@ adapter.start({ registry, consumer: { id: "browser-agent", kind: "webmcp" } });
25
25
 
26
26
  If `navigator.modelContext` is absent, `start()` resolves and does nothing (feature-detect, never polyfill). Capability errors ride in tool content with `code`/`retry`/`details` preserved, never as protocol-level errors. `stop()` withdraws every tool the adapter exposed and can run repeatedly.
27
27
 
28
- Confirmations are two-phase by default. To confirm in page within one tool call, pass host UI; it runs through WebMCP's `client.requestUserInteraction` and the registry still decides:
28
+ Confirmations complete within one tool call. By default the call waits for your host's confirmation UI to resolve the pending record, then retries with the evidence; denial or expiry returns `CONFIRMATION_INVALID`, and `stop()` aborts the wait. To prompt through WebMCP's `client.requestUserInteraction` instead, pass host UI; the registry still decides:
29
29
 
30
30
  ```ts
31
31
  createWebMcpAdapter({
@@ -33,6 +33,8 @@ createWebMcpAdapter({
33
33
  });
34
34
  ```
35
35
 
36
+ WebMCP does not revoke the agent's DOM access, and the confirmation UI lives in the same page, so the server stays the real gate.
37
+
36
38
  Only the imperative API is used. The declarative API (DOM forms as tools) is a non-goal: capabilities must be compiler-authorized, not derived from rendered DOM.
37
39
 
38
40
  ## Targeted WebMCP revision
package/dist/index.d.ts CHANGED
@@ -58,8 +58,8 @@ interface CreateWebMcpAdapterOptions {
58
58
  * the WebMCP client supports `requestUserInteraction`, this host UI runs
59
59
  * inside it; the answer resolves the registry's pending confirmation and the
60
60
  * call is retried once, so the agent sees one final result. The registry
61
- * stays the confirmation authority. Absent (or no client support) ⇒
62
- * unchanged two-phase behavior.
61
+ * stays the confirmation authority. Absent (or no client support, or the UI
62
+ * throws) ⇒ the call waits for the host's own confirmation UI instead.
63
63
  */
64
64
  confirm?: (request: PendingConfirmation, client: WebMcpClient) => Promise<boolean> | boolean;
65
65
  /** Test seam: defaults to (navigator as any).modelContext. */
@@ -71,8 +71,14 @@ interface CreateWebMcpAdapterOptions {
71
71
  * reconciled on every surface-changed (incremental registerTool/unregisterTool
72
72
  * when the browser supports it, full provideContext otherwise); unavailable
73
73
  * capabilities are not registered (WebMCP has no disabled state today —
74
- * accepted limitation); confirmations stay two-phase unless `confirm` is set;
75
- * absent modelContext ⇒ start() does nothing; stop() withdraws every tool.
74
+ * accepted limitation); absent modelContext ⇒ start() does nothing; stop()
75
+ * withdraws every tool and aborts confirmation waits.
76
+ *
77
+ * Confirmations complete within one call: through `confirm` when it applies,
78
+ * otherwise by waiting (bounded by the confirmation TTL) for the host to
79
+ * resolve the pending record. Plain two-phase cannot work on this transport:
80
+ * the tool schema has no slot for a confirmationId, so a retry never carries
81
+ * evidence and each one opens a new confirmation.
76
82
  */
77
83
  declare function createWebMcpAdapter(options?: CreateWebMcpAdapterOptions): AgentSurfaceAdapter;
78
84
 
package/dist/index.js CHANGED
@@ -21,7 +21,17 @@ function createWebMcpAdapter(options) {
21
21
  exposed: /* @__PURE__ */ new Map(),
22
22
  unsubscribe: () => {
23
23
  },
24
- active: true
24
+ active: true,
25
+ waits: /* @__PURE__ */ new Set()
26
+ };
27
+ const waitForConfirmation = async (confirmationId) => {
28
+ const controller = new AbortController();
29
+ state.waits.add(controller);
30
+ try {
31
+ await host.registry.confirmations.waitFor(confirmationId, { signal: controller.signal });
32
+ } finally {
33
+ state.waits.delete(controller);
34
+ }
25
35
  };
26
36
  const invoke = (target, invocationId, input, confirmationId) => host.registry.invoke(
27
37
  {
@@ -45,6 +55,7 @@ function createWebMcpAdapter(options) {
45
55
  const invocationId = randomInvocationId();
46
56
  let result = await invoke(target, invocationId, input);
47
57
  const confirmationId = result.status === "error" && result.error.code === "CONFIRMATION_REQUIRED" ? result.error.details?.confirmationId : void 0;
58
+ let resolvedInPage = false;
48
59
  if (options?.confirm && typeof confirmationId === "string" && typeof client?.requestUserInteraction === "function" && state.active) {
49
60
  const pending = host.registry.confirmations.pending().find((record) => record.confirmationId === confirmationId);
50
61
  if (pending) {
@@ -61,9 +72,14 @@ function createWebMcpAdapter(options) {
61
72
  approved ? { approved: true } : { approved: false, reason: "Declined in page" }
62
73
  );
63
74
  result = await invoke(target, invocationId, input, confirmationId);
75
+ resolvedInPage = true;
64
76
  }
65
77
  }
66
78
  }
79
+ if (!resolvedInPage && typeof confirmationId === "string" && state.active) {
80
+ await waitForConfirmation(confirmationId);
81
+ if (state.active) result = await invoke(target, invocationId, input, confirmationId);
82
+ }
67
83
  if (result.status === "ok") {
68
84
  return {
69
85
  content: [{ type: "text", text: JSON.stringify(result.output ?? null) }]
@@ -181,6 +197,8 @@ function createWebMcpAdapter(options) {
181
197
  if (!state) return;
182
198
  state.active = false;
183
199
  state.unsubscribe();
200
+ for (const controller of state.waits) controller.abort();
201
+ state.waits.clear();
184
202
  const { modelContext } = state;
185
203
  if (state.incremental) {
186
204
  for (const name of state.exposed.keys()) {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/core-facade.ts","../src/index.ts"],"sourcesContent":["export { encodeWireName, encodeWireNameForInstance } from \"@agent-surface/core\";\nexport type {\n AgentCapabilityDescriptorUnion,\n AgentConsumer,\n AgentSurfaceRegistry,\n JsonSchema,\n JsonValue,\n PendingConfirmation,\n SnapshotContext,\n} from \"@agent-surface/core\";\n\nexport function randomInvocationId(): string {\n return `inv_${Math.random().toString(36).slice(2, 14)}`;\n}\n","import {\n encodeWireName,\n randomInvocationId,\n type AgentCapabilityDescriptorUnion,\n type AgentConsumer,\n type AgentSurfaceRegistry,\n type JsonSchema,\n type JsonValue,\n type PendingConfirmation,\n type SnapshotContext,\n} from \"./core-facade.js\";\n\n/* ───────────────────────── adapter contract (docs/09) ───────────────────────── */\n\nexport interface AdapterHost {\n registry: AgentSurfaceRegistry;\n consumer: AgentConsumer; // identity this adapter acts as\n /** Adapter-scoped snapshot defaults (scope, budget). */\n snapshotContext?: Omit<SnapshotContext, \"consumer\">;\n}\n\nexport interface AgentSurfaceAdapter {\n readonly name: string;\n start(host: AdapterHost): void | Promise<void>;\n stop(): void | Promise<void>;\n}\n\n/* ───────────── assumed navigator.modelContext shape (Experimental) ─────────────\n * The WebMCP surface area is unstable (OQ-2); this module encodes the current\n * assumption and absorbs drift so nothing WebMCP-shaped leaks into core.\n * Targeted revision: see \"Targeted WebMCP revision\" in docs/09.\n */\n\nexport interface WebMcpToolAnnotations {\n /** The tool does not change state; a browser agent may skip its approval prompt. */\n readOnlyHint?: boolean;\n}\n\n/** The per-call client WebMCP passes to `execute`. */\nexport interface WebMcpClient {\n /** Pauses the tool call to run in-page UI; resolves with the callback's value. */\n requestUserInteraction?<T>(callback: () => Promise<T>): Promise<T>;\n}\n\nexport interface WebMcpToolInit {\n name: string;\n description: string;\n inputSchema: JsonSchema;\n annotations?: WebMcpToolAnnotations;\n execute(input: JsonValue, client?: WebMcpClient): Promise<WebMcpToolResult>;\n}\n\nexport interface WebMcpToolResult {\n content: Array<{ type: \"text\"; text: string }>;\n isError?: boolean;\n}\n\nexport interface WebMcpModelContext {\n /** Replaces the whole tool set. Fallback when the incremental API is absent. */\n provideContext(context: { tools: WebMcpToolInit[] }): void;\n /** Removes every tool provided through provideContext. */\n clearContext?(): void;\n registerTool?(tool: WebMcpToolInit): unknown;\n unregisterTool?(name: string): void;\n}\n\nexport interface CreateWebMcpAdapterOptions {\n snapshotContext?: Omit<SnapshotContext, \"consumer\">;\n /**\n * Curate presentation before exposing. Execution always remains registry-routed.\n * Return null to skip; undefined to keep defaults.\n */\n exposeCapability?: (\n descriptor: AgentCapabilityDescriptorUnion,\n ) => { description?: string } | null | undefined;\n /**\n * Opt-in in-page confirmation. When a call returns CONFIRMATION_REQUIRED and\n * the WebMCP client supports `requestUserInteraction`, this host UI runs\n * inside it; the answer resolves the registry's pending confirmation and the\n * call is retried once, so the agent sees one final result. The registry\n * stays the confirmation authority. Absent (or no client support) ⇒\n * unchanged two-phase behavior.\n */\n confirm?: (request: PendingConfirmation, client: WebMcpClient) => Promise<boolean> | boolean;\n /** Test seam: defaults to (navigator as any).modelContext. */\n modelContext?: WebMcpModelContext;\n}\n\ninterface ToolTarget {\n capabilityId: string;\n registrationId: string;\n /** Updated in place when the tool survives a surface change unchanged. */\n surfaceVersion: string;\n}\n\ninterface ExposedTool {\n tool: WebMcpToolInit;\n target: ToolTarget;\n /** Everything the browser agent sees, plus the registration it routes to. */\n signature: string;\n}\n\ninterface DesiredTool {\n name: string;\n capabilityId: string;\n registrationId: string;\n inputSchema: JsonSchema;\n description: string;\n readOnly: boolean;\n}\n\nconst READ_ONLY_EFFECTS: ReadonlySet<string> = new Set([\"read\", \"server-query\"]);\n\n/**\n * Maps the registry onto `navigator.modelContext`, treating WebMCP strictly\n * as transport/discovery: one wire-named tool per AVAILABLE capability,\n * reconciled on every surface-changed (incremental registerTool/unregisterTool\n * when the browser supports it, full provideContext otherwise); unavailable\n * capabilities are not registered (WebMCP has no disabled state today —\n * accepted limitation); confirmations stay two-phase unless `confirm` is set;\n * absent modelContext ⇒ start() does nothing; stop() withdraws every tool.\n */\nexport function createWebMcpAdapter(options?: CreateWebMcpAdapterOptions): AgentSurfaceAdapter {\n let session:\n | {\n modelContext: WebMcpModelContext;\n incremental: boolean;\n exposed: Map<string, ExposedTool>;\n unsubscribe: () => void;\n active: boolean;\n }\n | undefined;\n\n return {\n name: \"webmcp\",\n\n start(host: AdapterHost): void {\n if (session) return;\n const modelContext =\n options?.modelContext ??\n (globalThis as { navigator?: { modelContext?: WebMcpModelContext } }).navigator\n ?.modelContext;\n if (!modelContext) return; // feature-detect, never polyfill\n\n const incremental =\n typeof modelContext.registerTool === \"function\" &&\n typeof modelContext.unregisterTool === \"function\";\n const state = {\n modelContext,\n incremental,\n exposed: new Map<string, ExposedTool>(),\n unsubscribe: () => {},\n active: true,\n };\n\n const invoke = (target: ToolTarget, invocationId: string, input: JsonValue, confirmationId?: string) =>\n host.registry.invoke(\n {\n invocationId,\n capabilityId: target.capabilityId,\n registrationId: target.registrationId,\n surfaceVersion: target.surfaceVersion,\n // Forwarded as given (like the core toolset): dropping `{}` made\n // zero-argument actions fail INVALID_INPUT. Observations ignore input.\n ...(input !== undefined ? { input } : {}),\n ...(confirmationId !== undefined ? { confirmationId } : {}),\n },\n { consumer: host.consumer },\n );\n\n const toTool = (desired: DesiredTool, target: ToolTarget): WebMcpToolInit => ({\n name: desired.name,\n description: desired.description,\n inputSchema: desired.inputSchema,\n ...(desired.readOnly ? { annotations: { readOnlyHint: true } } : {}),\n execute: async (input: JsonValue, client?: WebMcpClient): Promise<WebMcpToolResult> => {\n const invocationId = randomInvocationId();\n let result = await invoke(target, invocationId, input);\n\n const confirmationId =\n result.status === \"error\" && result.error.code === \"CONFIRMATION_REQUIRED\"\n ? result.error.details?.confirmationId\n : undefined;\n if (\n options?.confirm &&\n typeof confirmationId === \"string\" &&\n typeof client?.requestUserInteraction === \"function\" &&\n state.active\n ) {\n const pending = host.registry.confirmations\n .pending()\n .find((record) => record.confirmationId === confirmationId);\n if (pending) {\n const confirm = options.confirm;\n let approved: boolean | undefined;\n try {\n approved =\n (await client.requestUserInteraction(async () => confirm(pending, client))) ===\n true;\n } catch {\n approved = undefined; // UI failed: leave it pending, fall back to two-phase\n }\n // A stop() mid-prompt returns the pending result as-is (docs/09 §9).\n if (approved !== undefined && state.active) {\n host.registry.confirmations.resolve(\n confirmationId,\n approved ? { approved: true } : { approved: false, reason: \"Declined in page\" },\n );\n // Same invocationId + confirmationId (docs/03 D14): the registry\n // decides the outcome, the adapter only relayed the answer.\n result = await invoke(target, invocationId, input, confirmationId);\n }\n }\n }\n\n // Capability errors ride in tool CONTENT, never protocol errors\n // (docs/07 adapter mapping): code/retry/details preserved.\n if (result.status === \"ok\") {\n return {\n content: [{ type: \"text\", text: JSON.stringify(result.output ?? null) }],\n };\n }\n return {\n content: [{ type: \"text\", text: JSON.stringify(result.error) }],\n isError: true,\n };\n },\n });\n\n const desiredTools = (): { surfaceVersion: string; tools: DesiredTool[] } => {\n const snapshot = host.registry.snapshot({\n consumer: host.consumer,\n ...(options?.snapshotContext ?? host.snapshotContext ?? {}),\n includeUnavailable: false,\n });\n const tools: DesiredTool[] = [];\n const add = (\n descriptor: AgentCapabilityDescriptorUnion,\n capabilityId: string,\n registrationId: string,\n inputSchema: JsonSchema,\n defaultDescription: string,\n readOnly: boolean,\n ): void => {\n if (!descriptor.available) return;\n const curated = options?.exposeCapability?.(descriptor);\n if (options?.exposeCapability && curated === null) return;\n tools.push({\n name: encodeWireName(capabilityId),\n capabilityId,\n registrationId,\n inputSchema,\n description: curated?.description ?? defaultDescription,\n // Derived from the declared kind/effect only; curation cannot widen it.\n readOnly,\n });\n };\n\n for (const component of snapshot.components) {\n for (const obs of component.observations) {\n add(\n obs,\n obs.capabilityId,\n component.registrationId,\n { type: \"object\", properties: {}, additionalProperties: false },\n `[view · read] ${obs.description}`,\n true,\n );\n }\n for (const act of component.actions) {\n add(\n act,\n act.capabilityId,\n component.registrationId,\n act.inputSchema,\n `[view · ${act.effect}] ${act.description}`,\n READ_ONLY_EFFECTS.has(act.effect),\n );\n }\n }\n for (const proc of snapshot.procedures) {\n add(\n proc,\n proc.procedureId,\n proc.registrationId,\n proc.inputSchema,\n `[domain · ${proc.effect}${proc.confirmation === \"required\" ? \" · requires confirmation\" : \"\"}] ${proc.description}`,\n READ_ONLY_EFFECTS.has(proc.effect),\n );\n }\n return { surfaceVersion: snapshot.surfaceVersion, tools };\n };\n\n const reconcile = (): void => {\n if (!state.active) return;\n const { surfaceVersion, tools } = desiredTools();\n const next = new Map<string, ExposedTool>();\n const toRegister: WebMcpToolInit[] = [];\n\n for (const desired of tools) {\n const signature = JSON.stringify([\n desired.description,\n desired.inputSchema,\n desired.registrationId,\n desired.capabilityId,\n desired.readOnly,\n ]);\n const current = state.exposed.get(desired.name);\n if (current && current.signature === signature) {\n // Unchanged tool: keep the registration, refresh the version it\n // echoes so execute carries the latest projected surfaceVersion.\n current.target.surfaceVersion = surfaceVersion;\n next.set(desired.name, current);\n continue;\n }\n const target: ToolTarget = {\n capabilityId: desired.capabilityId,\n registrationId: desired.registrationId,\n surfaceVersion,\n };\n const tool = toTool(desired, target);\n next.set(desired.name, { tool, target, signature });\n toRegister.push(tool);\n }\n\n if (state.incremental) {\n for (const [name, current] of state.exposed) {\n const replacement = next.get(name);\n if (replacement !== current) modelContext.unregisterTool!(name);\n }\n for (const tool of toRegister) modelContext.registerTool!(tool);\n } else {\n modelContext.provideContext({ tools: [...next.values()].map((entry) => entry.tool) });\n }\n state.exposed = next;\n };\n\n session = state;\n reconcile();\n state.unsubscribe = host.registry.subscribe((event) => {\n if (event.type === \"surface-changed\") reconcile();\n });\n },\n\n stop(): void {\n const state = session;\n session = undefined;\n if (!state) return; // idempotent\n state.active = false;\n state.unsubscribe();\n const { modelContext } = state;\n if (state.incremental) {\n // Withdraw only our tools; other page code may own the rest.\n for (const name of state.exposed.keys()) {\n try {\n modelContext.unregisterTool!(name);\n } catch {\n // Already gone on the browser side; nothing left to release.\n }\n }\n } else if (typeof modelContext.clearContext === \"function\") {\n modelContext.clearContext();\n } else {\n modelContext.provideContext({ tools: [] });\n }\n state.exposed.clear();\n },\n };\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/core-facade.ts","../src/index.ts"],"sourcesContent":["export { encodeWireName, encodeWireNameForInstance } from \"@agent-surface/core\";\nexport type {\n AgentCapabilityDescriptorUnion,\n AgentConsumer,\n AgentSurfaceRegistry,\n JsonSchema,\n JsonValue,\n PendingConfirmation,\n SnapshotContext,\n} from \"@agent-surface/core\";\n\nexport function randomInvocationId(): string {\n return `inv_${Math.random().toString(36).slice(2, 14)}`;\n}\n","import {\n encodeWireName,\n randomInvocationId,\n type AgentCapabilityDescriptorUnion,\n type AgentConsumer,\n type AgentSurfaceRegistry,\n type JsonSchema,\n type JsonValue,\n type PendingConfirmation,\n type SnapshotContext,\n} from \"./core-facade.js\";\n\n/* ───────────────────────── adapter contract (docs/09) ───────────────────────── */\n\nexport interface AdapterHost {\n registry: AgentSurfaceRegistry;\n consumer: AgentConsumer; // identity this adapter acts as\n /** Adapter-scoped snapshot defaults (scope, budget). */\n snapshotContext?: Omit<SnapshotContext, \"consumer\">;\n}\n\nexport interface AgentSurfaceAdapter {\n readonly name: string;\n start(host: AdapterHost): void | Promise<void>;\n stop(): void | Promise<void>;\n}\n\n/* ───────────── assumed navigator.modelContext shape (Experimental) ─────────────\n * The WebMCP surface area is unstable (OQ-2); this module encodes the current\n * assumption and absorbs drift so nothing WebMCP-shaped leaks into core.\n * Targeted revision: see \"Targeted WebMCP revision\" in docs/09.\n */\n\nexport interface WebMcpToolAnnotations {\n /** The tool does not change state; a browser agent may skip its approval prompt. */\n readOnlyHint?: boolean;\n}\n\n/** The per-call client WebMCP passes to `execute`. */\nexport interface WebMcpClient {\n /** Pauses the tool call to run in-page UI; resolves with the callback's value. */\n requestUserInteraction?<T>(callback: () => Promise<T>): Promise<T>;\n}\n\nexport interface WebMcpToolInit {\n name: string;\n description: string;\n inputSchema: JsonSchema;\n annotations?: WebMcpToolAnnotations;\n execute(input: JsonValue, client?: WebMcpClient): Promise<WebMcpToolResult>;\n}\n\nexport interface WebMcpToolResult {\n content: Array<{ type: \"text\"; text: string }>;\n isError?: boolean;\n}\n\nexport interface WebMcpModelContext {\n /** Replaces the whole tool set. Fallback when the incremental API is absent. */\n provideContext(context: { tools: WebMcpToolInit[] }): void;\n /** Removes every tool provided through provideContext. */\n clearContext?(): void;\n registerTool?(tool: WebMcpToolInit): unknown;\n unregisterTool?(name: string): void;\n}\n\nexport interface CreateWebMcpAdapterOptions {\n snapshotContext?: Omit<SnapshotContext, \"consumer\">;\n /**\n * Curate presentation before exposing. Execution always remains registry-routed.\n * Return null to skip; undefined to keep defaults.\n */\n exposeCapability?: (\n descriptor: AgentCapabilityDescriptorUnion,\n ) => { description?: string } | null | undefined;\n /**\n * Opt-in in-page confirmation. When a call returns CONFIRMATION_REQUIRED and\n * the WebMCP client supports `requestUserInteraction`, this host UI runs\n * inside it; the answer resolves the registry's pending confirmation and the\n * call is retried once, so the agent sees one final result. The registry\n * stays the confirmation authority. Absent (or no client support, or the UI\n * throws) ⇒ the call waits for the host's own confirmation UI instead.\n */\n confirm?: (request: PendingConfirmation, client: WebMcpClient) => Promise<boolean> | boolean;\n /** Test seam: defaults to (navigator as any).modelContext. */\n modelContext?: WebMcpModelContext;\n}\n\ninterface ToolTarget {\n capabilityId: string;\n registrationId: string;\n /** Updated in place when the tool survives a surface change unchanged. */\n surfaceVersion: string;\n}\n\ninterface ExposedTool {\n tool: WebMcpToolInit;\n target: ToolTarget;\n /** Everything the browser agent sees, plus the registration it routes to. */\n signature: string;\n}\n\ninterface DesiredTool {\n name: string;\n capabilityId: string;\n registrationId: string;\n inputSchema: JsonSchema;\n description: string;\n readOnly: boolean;\n}\n\nconst READ_ONLY_EFFECTS: ReadonlySet<string> = new Set([\"read\", \"server-query\"]);\n\n/**\n * Maps the registry onto `navigator.modelContext`, treating WebMCP strictly\n * as transport/discovery: one wire-named tool per AVAILABLE capability,\n * reconciled on every surface-changed (incremental registerTool/unregisterTool\n * when the browser supports it, full provideContext otherwise); unavailable\n * capabilities are not registered (WebMCP has no disabled state today —\n * accepted limitation); absent modelContext ⇒ start() does nothing; stop()\n * withdraws every tool and aborts confirmation waits.\n *\n * Confirmations complete within one call: through `confirm` when it applies,\n * otherwise by waiting (bounded by the confirmation TTL) for the host to\n * resolve the pending record. Plain two-phase cannot work on this transport:\n * the tool schema has no slot for a confirmationId, so a retry never carries\n * evidence and each one opens a new confirmation.\n */\nexport function createWebMcpAdapter(options?: CreateWebMcpAdapterOptions): AgentSurfaceAdapter {\n let session:\n | {\n modelContext: WebMcpModelContext;\n incremental: boolean;\n exposed: Map<string, ExposedTool>;\n unsubscribe: () => void;\n active: boolean;\n waits: Set<AbortController>;\n }\n | undefined;\n\n return {\n name: \"webmcp\",\n\n start(host: AdapterHost): void {\n if (session) return;\n const modelContext =\n options?.modelContext ??\n (globalThis as { navigator?: { modelContext?: WebMcpModelContext } }).navigator\n ?.modelContext;\n if (!modelContext) return; // feature-detect, never polyfill\n\n const incremental =\n typeof modelContext.registerTool === \"function\" &&\n typeof modelContext.unregisterTool === \"function\";\n const state = {\n modelContext,\n incremental,\n exposed: new Map<string, ExposedTool>(),\n unsubscribe: () => {},\n active: true,\n waits: new Set<AbortController>(),\n };\n\n /** Wait for the host to resolve a pending confirmation; aborted by stop(). */\n const waitForConfirmation = async (confirmationId: string): Promise<void> => {\n const controller = new AbortController();\n state.waits.add(controller);\n try {\n await host.registry.confirmations.waitFor(confirmationId, { signal: controller.signal });\n } finally {\n state.waits.delete(controller);\n }\n };\n\n const invoke = (target: ToolTarget, invocationId: string, input: JsonValue, confirmationId?: string) =>\n host.registry.invoke(\n {\n invocationId,\n capabilityId: target.capabilityId,\n registrationId: target.registrationId,\n surfaceVersion: target.surfaceVersion,\n // Forwarded as given (like the core toolset): dropping `{}` made\n // zero-argument actions fail INVALID_INPUT. Observations ignore input.\n ...(input !== undefined ? { input } : {}),\n ...(confirmationId !== undefined ? { confirmationId } : {}),\n },\n { consumer: host.consumer },\n );\n\n const toTool = (desired: DesiredTool, target: ToolTarget): WebMcpToolInit => ({\n name: desired.name,\n description: desired.description,\n inputSchema: desired.inputSchema,\n ...(desired.readOnly ? { annotations: { readOnlyHint: true } } : {}),\n execute: async (input: JsonValue, client?: WebMcpClient): Promise<WebMcpToolResult> => {\n const invocationId = randomInvocationId();\n let result = await invoke(target, invocationId, input);\n\n const confirmationId =\n result.status === \"error\" && result.error.code === \"CONFIRMATION_REQUIRED\"\n ? result.error.details?.confirmationId\n : undefined;\n let resolvedInPage = false;\n if (\n options?.confirm &&\n typeof confirmationId === \"string\" &&\n typeof client?.requestUserInteraction === \"function\" &&\n state.active\n ) {\n const pending = host.registry.confirmations\n .pending()\n .find((record) => record.confirmationId === confirmationId);\n if (pending) {\n const confirm = options.confirm;\n let approved: boolean | undefined;\n try {\n approved =\n (await client.requestUserInteraction(async () => confirm(pending, client))) ===\n true;\n } catch {\n approved = undefined; // UI failed: leave it pending, fall back to waiting\n }\n // A stop() mid-prompt returns the pending result as-is (docs/09 §9).\n if (approved !== undefined && state.active) {\n host.registry.confirmations.resolve(\n confirmationId,\n approved ? { approved: true } : { approved: false, reason: \"Declined in page\" },\n );\n // Same invocationId + confirmationId (docs/03 D14): the registry\n // decides the outcome, the adapter only relayed the answer.\n result = await invoke(target, invocationId, input, confirmationId);\n resolvedInPage = true;\n }\n }\n }\n\n // Fallback: wait for the host's own confirmation UI, then retry once.\n // Denial and expiry come back as CONFIRMATION_INVALID, never retried.\n // A stop() before or during the wait returns the pending result as-is.\n if (!resolvedInPage && typeof confirmationId === \"string\" && state.active) {\n await waitForConfirmation(confirmationId);\n if (state.active) result = await invoke(target, invocationId, input, confirmationId);\n }\n\n // Capability errors ride in tool CONTENT, never protocol errors\n // (docs/07 adapter mapping): code/retry/details preserved.\n if (result.status === \"ok\") {\n return {\n content: [{ type: \"text\", text: JSON.stringify(result.output ?? null) }],\n };\n }\n return {\n content: [{ type: \"text\", text: JSON.stringify(result.error) }],\n isError: true,\n };\n },\n });\n\n const desiredTools = (): { surfaceVersion: string; tools: DesiredTool[] } => {\n const snapshot = host.registry.snapshot({\n consumer: host.consumer,\n ...(options?.snapshotContext ?? host.snapshotContext ?? {}),\n includeUnavailable: false,\n });\n const tools: DesiredTool[] = [];\n const add = (\n descriptor: AgentCapabilityDescriptorUnion,\n capabilityId: string,\n registrationId: string,\n inputSchema: JsonSchema,\n defaultDescription: string,\n readOnly: boolean,\n ): void => {\n if (!descriptor.available) return;\n const curated = options?.exposeCapability?.(descriptor);\n if (options?.exposeCapability && curated === null) return;\n tools.push({\n name: encodeWireName(capabilityId),\n capabilityId,\n registrationId,\n inputSchema,\n description: curated?.description ?? defaultDescription,\n // Derived from the declared kind/effect only; curation cannot widen it.\n readOnly,\n });\n };\n\n for (const component of snapshot.components) {\n for (const obs of component.observations) {\n add(\n obs,\n obs.capabilityId,\n component.registrationId,\n { type: \"object\", properties: {}, additionalProperties: false },\n `[view · read] ${obs.description}`,\n true,\n );\n }\n for (const act of component.actions) {\n add(\n act,\n act.capabilityId,\n component.registrationId,\n act.inputSchema,\n `[view · ${act.effect}] ${act.description}`,\n READ_ONLY_EFFECTS.has(act.effect),\n );\n }\n }\n for (const proc of snapshot.procedures) {\n add(\n proc,\n proc.procedureId,\n proc.registrationId,\n proc.inputSchema,\n `[domain · ${proc.effect}${proc.confirmation === \"required\" ? \" · requires confirmation\" : \"\"}] ${proc.description}`,\n READ_ONLY_EFFECTS.has(proc.effect),\n );\n }\n return { surfaceVersion: snapshot.surfaceVersion, tools };\n };\n\n const reconcile = (): void => {\n if (!state.active) return;\n const { surfaceVersion, tools } = desiredTools();\n const next = new Map<string, ExposedTool>();\n const toRegister: WebMcpToolInit[] = [];\n\n for (const desired of tools) {\n const signature = JSON.stringify([\n desired.description,\n desired.inputSchema,\n desired.registrationId,\n desired.capabilityId,\n desired.readOnly,\n ]);\n const current = state.exposed.get(desired.name);\n if (current && current.signature === signature) {\n // Unchanged tool: keep the registration, refresh the version it\n // echoes so execute carries the latest projected surfaceVersion.\n current.target.surfaceVersion = surfaceVersion;\n next.set(desired.name, current);\n continue;\n }\n const target: ToolTarget = {\n capabilityId: desired.capabilityId,\n registrationId: desired.registrationId,\n surfaceVersion,\n };\n const tool = toTool(desired, target);\n next.set(desired.name, { tool, target, signature });\n toRegister.push(tool);\n }\n\n if (state.incremental) {\n for (const [name, current] of state.exposed) {\n const replacement = next.get(name);\n if (replacement !== current) modelContext.unregisterTool!(name);\n }\n for (const tool of toRegister) modelContext.registerTool!(tool);\n } else {\n modelContext.provideContext({ tools: [...next.values()].map((entry) => entry.tool) });\n }\n state.exposed = next;\n };\n\n session = state;\n reconcile();\n state.unsubscribe = host.registry.subscribe((event) => {\n if (event.type === \"surface-changed\") reconcile();\n });\n },\n\n stop(): void {\n const state = session;\n session = undefined;\n if (!state) return; // idempotent\n state.active = false;\n state.unsubscribe();\n for (const controller of state.waits) controller.abort();\n state.waits.clear();\n const { modelContext } = state;\n if (state.incremental) {\n // Withdraw only our tools; other page code may own the rest.\n for (const name of state.exposed.keys()) {\n try {\n modelContext.unregisterTool!(name);\n } catch {\n // Already gone on the browser side; nothing left to release.\n }\n }\n } else if (typeof modelContext.clearContext === \"function\") {\n modelContext.clearContext();\n } else {\n modelContext.provideContext({ tools: [] });\n }\n state.exposed.clear();\n },\n };\n}\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-surface/webmcp",
3
- "version": "0.25.0",
3
+ "version": "0.26.0",
4
4
  "description": "[Experimental] WebMCP (navigator.modelContext) transport adapter for agent-surface",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -18,11 +18,11 @@
18
18
  "LICENSE"
19
19
  ],
20
20
  "dependencies": {
21
- "@agent-surface/core": "^0.25.0"
21
+ "@agent-surface/core": "^0.26.0"
22
22
  },
23
23
  "devDependencies": {
24
24
  "zod": "^4.1.5",
25
- "@agent-surface/testing": "0.25.0"
25
+ "@agent-surface/testing": "0.26.0"
26
26
  },
27
27
  "author": "Paolo Barbato",
28
28
  "engines": {