@agent-surface/webmcp 0.24.0 → 0.25.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 +26 -2
- package/dist/index.d.ts +32 -6
- package/dist/index.js +163 -67
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
> **Experimental.** The WebMCP (`navigator.modelContext`) surface area, permission model, and lifecycle are unstable; this adapter tracks them and absorbs the drift so nothing WebMCP-shaped leaks into `@agent-surface/core`. The application model stays in agent-surface — WebMCP is strictly transport/discovery.
|
|
4
4
|
|
|
5
|
-
WebMCP transport adapter for [agent-surface](https://github.com/Wiseair-srl/agent-surface): one wire-named tool per **available** capability,
|
|
5
|
+
WebMCP transport adapter for [agent-surface](https://github.com/Wiseair-srl/agent-surface): one wire-named tool per **available** capability, reconciled on every `surface-changed` (incremental `registerTool`/`unregisterTool` when the browser has them, a full `provideContext` otherwise). Unavailable capabilities are not registered (WebMCP has no disabled state today, so the availability reason is lost on this transport; accepted limitation). Observations and read-only effects carry `annotations.readOnlyHint`. The user agent is treated as the least-trusted consumer: scope the adapter and keep confirmations governed by the registry.
|
|
6
6
|
|
|
7
7
|
Docs: https://agent-surface.dev
|
|
8
8
|
|
|
@@ -23,7 +23,31 @@ const adapter = createWebMcpAdapter({
|
|
|
23
23
|
adapter.start({ registry, consumer: { id: "browser-agent", kind: "webmcp" } });
|
|
24
24
|
```
|
|
25
25
|
|
|
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
|
|
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
|
+
|
|
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:
|
|
29
|
+
|
|
30
|
+
```ts
|
|
31
|
+
createWebMcpAdapter({
|
|
32
|
+
confirm: (request) => showConfirmDialog(request.summary),
|
|
33
|
+
});
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
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
|
+
|
|
38
|
+
## Targeted WebMCP revision
|
|
39
|
+
|
|
40
|
+
The W3C Web Machine Learning CG draft ([webmachinelearning/webmcp](https://github.com/webmachinelearning/webmcp)) as exposed by the Chrome early preview (Chrome 146+, `chrome://flags/#enable-webmcp-testing`). Assumed surface:
|
|
41
|
+
|
|
42
|
+
| Member | Use |
|
|
43
|
+
|---|---|
|
|
44
|
+
| `modelContext.provideContext({ tools })` | required; fallback full-set replacement |
|
|
45
|
+
| `modelContext.clearContext()` | optional; `stop()` on the fallback path |
|
|
46
|
+
| `modelContext.registerTool(tool)` / `unregisterTool(name)` | optional, feature-detected together |
|
|
47
|
+
| tool `{ name, description, inputSchema, annotations?: { readOnlyHint? }, execute(input, client) }` | tool shape |
|
|
48
|
+
| `client.requestUserInteraction(callback)` | optional; in-page confirmation |
|
|
49
|
+
|
|
50
|
+
Keep this table in sync with [docs/09](https://github.com/Wiseair-srl/agent-surface/blob/main/docs/09-adapters.md#targeted-webmcp-revision).
|
|
27
51
|
|
|
28
52
|
Full specification: [docs/09](https://github.com/Wiseair-srl/agent-surface/blob/main/docs/09-adapters.md).
|
|
29
53
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AgentSurfaceRegistry, AgentConsumer, SnapshotContext, AgentCapabilityDescriptorUnion, JsonSchema, JsonValue } from '@agent-surface/core';
|
|
1
|
+
import { AgentSurfaceRegistry, AgentConsumer, SnapshotContext, AgentCapabilityDescriptorUnion, PendingConfirmation, JsonSchema, JsonValue } from '@agent-surface/core';
|
|
2
2
|
|
|
3
3
|
interface AdapterHost {
|
|
4
4
|
registry: AgentSurfaceRegistry;
|
|
@@ -11,11 +11,21 @@ interface AgentSurfaceAdapter {
|
|
|
11
11
|
start(host: AdapterHost): void | Promise<void>;
|
|
12
12
|
stop(): void | Promise<void>;
|
|
13
13
|
}
|
|
14
|
+
interface WebMcpToolAnnotations {
|
|
15
|
+
/** The tool does not change state; a browser agent may skip its approval prompt. */
|
|
16
|
+
readOnlyHint?: boolean;
|
|
17
|
+
}
|
|
18
|
+
/** The per-call client WebMCP passes to `execute`. */
|
|
19
|
+
interface WebMcpClient {
|
|
20
|
+
/** Pauses the tool call to run in-page UI; resolves with the callback's value. */
|
|
21
|
+
requestUserInteraction?<T>(callback: () => Promise<T>): Promise<T>;
|
|
22
|
+
}
|
|
14
23
|
interface WebMcpToolInit {
|
|
15
24
|
name: string;
|
|
16
25
|
description: string;
|
|
17
26
|
inputSchema: JsonSchema;
|
|
18
|
-
|
|
27
|
+
annotations?: WebMcpToolAnnotations;
|
|
28
|
+
execute(input: JsonValue, client?: WebMcpClient): Promise<WebMcpToolResult>;
|
|
19
29
|
}
|
|
20
30
|
interface WebMcpToolResult {
|
|
21
31
|
content: Array<{
|
|
@@ -25,9 +35,14 @@ interface WebMcpToolResult {
|
|
|
25
35
|
isError?: boolean;
|
|
26
36
|
}
|
|
27
37
|
interface WebMcpModelContext {
|
|
38
|
+
/** Replaces the whole tool set. Fallback when the incremental API is absent. */
|
|
28
39
|
provideContext(context: {
|
|
29
40
|
tools: WebMcpToolInit[];
|
|
30
41
|
}): void;
|
|
42
|
+
/** Removes every tool provided through provideContext. */
|
|
43
|
+
clearContext?(): void;
|
|
44
|
+
registerTool?(tool: WebMcpToolInit): unknown;
|
|
45
|
+
unregisterTool?(name: string): void;
|
|
31
46
|
}
|
|
32
47
|
interface CreateWebMcpAdapterOptions {
|
|
33
48
|
snapshotContext?: Omit<SnapshotContext, "consumer">;
|
|
@@ -38,16 +53,27 @@ interface CreateWebMcpAdapterOptions {
|
|
|
38
53
|
exposeCapability?: (descriptor: AgentCapabilityDescriptorUnion) => {
|
|
39
54
|
description?: string;
|
|
40
55
|
} | null | undefined;
|
|
56
|
+
/**
|
|
57
|
+
* Opt-in in-page confirmation. When a call returns CONFIRMATION_REQUIRED and
|
|
58
|
+
* the WebMCP client supports `requestUserInteraction`, this host UI runs
|
|
59
|
+
* inside it; the answer resolves the registry's pending confirmation and the
|
|
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.
|
|
63
|
+
*/
|
|
64
|
+
confirm?: (request: PendingConfirmation, client: WebMcpClient) => Promise<boolean> | boolean;
|
|
41
65
|
/** Test seam: defaults to (navigator as any).modelContext. */
|
|
42
66
|
modelContext?: WebMcpModelContext;
|
|
43
67
|
}
|
|
44
68
|
/**
|
|
45
69
|
* Maps the registry onto `navigator.modelContext`, treating WebMCP strictly
|
|
46
70
|
* as transport/discovery: one wire-named tool per AVAILABLE capability,
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
71
|
+
* reconciled on every surface-changed (incremental registerTool/unregisterTool
|
|
72
|
+
* when the browser supports it, full provideContext otherwise); unavailable
|
|
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.
|
|
50
76
|
*/
|
|
51
77
|
declare function createWebMcpAdapter(options?: CreateWebMcpAdapterOptions): AgentSurfaceAdapter;
|
|
52
78
|
|
|
53
|
-
export { type AdapterHost, type AgentSurfaceAdapter, type CreateWebMcpAdapterOptions, type WebMcpModelContext, type WebMcpToolInit, type WebMcpToolResult, createWebMcpAdapter };
|
|
79
|
+
export { type AdapterHost, type AgentSurfaceAdapter, type CreateWebMcpAdapterOptions, type WebMcpClient, type WebMcpModelContext, type WebMcpToolAnnotations, type WebMcpToolInit, type WebMcpToolResult, createWebMcpAdapter };
|
package/dist/index.js
CHANGED
|
@@ -5,100 +5,196 @@ function randomInvocationId() {
|
|
|
5
5
|
}
|
|
6
6
|
|
|
7
7
|
// src/index.ts
|
|
8
|
+
var READ_ONLY_EFFECTS = /* @__PURE__ */ new Set(["read", "server-query"]);
|
|
8
9
|
function createWebMcpAdapter(options) {
|
|
9
|
-
let
|
|
10
|
+
let session;
|
|
10
11
|
return {
|
|
11
12
|
name: "webmcp",
|
|
12
13
|
start(host) {
|
|
14
|
+
if (session) return;
|
|
13
15
|
const modelContext = options?.modelContext ?? globalThis.navigator?.modelContext;
|
|
14
16
|
if (!modelContext) return;
|
|
15
|
-
const
|
|
17
|
+
const incremental = typeof modelContext.registerTool === "function" && typeof modelContext.unregisterTool === "function";
|
|
18
|
+
const state = {
|
|
19
|
+
modelContext,
|
|
20
|
+
incremental,
|
|
21
|
+
exposed: /* @__PURE__ */ new Map(),
|
|
22
|
+
unsubscribe: () => {
|
|
23
|
+
},
|
|
24
|
+
active: true
|
|
25
|
+
};
|
|
26
|
+
const invoke = (target, invocationId, input, confirmationId) => host.registry.invoke(
|
|
27
|
+
{
|
|
28
|
+
invocationId,
|
|
29
|
+
capabilityId: target.capabilityId,
|
|
30
|
+
registrationId: target.registrationId,
|
|
31
|
+
surfaceVersion: target.surfaceVersion,
|
|
32
|
+
// Forwarded as given (like the core toolset): dropping `{}` made
|
|
33
|
+
// zero-argument actions fail INVALID_INPUT. Observations ignore input.
|
|
34
|
+
...input !== void 0 ? { input } : {},
|
|
35
|
+
...confirmationId !== void 0 ? { confirmationId } : {}
|
|
36
|
+
},
|
|
37
|
+
{ consumer: host.consumer }
|
|
38
|
+
);
|
|
39
|
+
const toTool = (desired, target) => ({
|
|
40
|
+
name: desired.name,
|
|
41
|
+
description: desired.description,
|
|
42
|
+
inputSchema: desired.inputSchema,
|
|
43
|
+
...desired.readOnly ? { annotations: { readOnlyHint: true } } : {},
|
|
44
|
+
execute: async (input, client) => {
|
|
45
|
+
const invocationId = randomInvocationId();
|
|
46
|
+
let result = await invoke(target, invocationId, input);
|
|
47
|
+
const confirmationId = result.status === "error" && result.error.code === "CONFIRMATION_REQUIRED" ? result.error.details?.confirmationId : void 0;
|
|
48
|
+
if (options?.confirm && typeof confirmationId === "string" && typeof client?.requestUserInteraction === "function" && state.active) {
|
|
49
|
+
const pending = host.registry.confirmations.pending().find((record) => record.confirmationId === confirmationId);
|
|
50
|
+
if (pending) {
|
|
51
|
+
const confirm = options.confirm;
|
|
52
|
+
let approved;
|
|
53
|
+
try {
|
|
54
|
+
approved = await client.requestUserInteraction(async () => confirm(pending, client)) === true;
|
|
55
|
+
} catch {
|
|
56
|
+
approved = void 0;
|
|
57
|
+
}
|
|
58
|
+
if (approved !== void 0 && state.active) {
|
|
59
|
+
host.registry.confirmations.resolve(
|
|
60
|
+
confirmationId,
|
|
61
|
+
approved ? { approved: true } : { approved: false, reason: "Declined in page" }
|
|
62
|
+
);
|
|
63
|
+
result = await invoke(target, invocationId, input, confirmationId);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
if (result.status === "ok") {
|
|
68
|
+
return {
|
|
69
|
+
content: [{ type: "text", text: JSON.stringify(result.output ?? null) }]
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
return {
|
|
73
|
+
content: [{ type: "text", text: JSON.stringify(result.error) }],
|
|
74
|
+
isError: true
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
const desiredTools = () => {
|
|
16
79
|
const snapshot = host.registry.snapshot({
|
|
17
80
|
consumer: host.consumer,
|
|
18
81
|
...options?.snapshotContext ?? host.snapshotContext ?? {},
|
|
19
82
|
includeUnavailable: false
|
|
20
83
|
});
|
|
21
84
|
const tools = [];
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
);
|
|
37
|
-
if (result.status === "ok") {
|
|
38
|
-
return {
|
|
39
|
-
content: [{ type: "text", text: JSON.stringify(result.output ?? null) }]
|
|
40
|
-
};
|
|
41
|
-
}
|
|
42
|
-
return {
|
|
43
|
-
content: [{ type: "text", text: JSON.stringify(result.error) }],
|
|
44
|
-
isError: true
|
|
45
|
-
};
|
|
46
|
-
}
|
|
47
|
-
});
|
|
85
|
+
const add = (descriptor, capabilityId, registrationId, inputSchema, defaultDescription, readOnly) => {
|
|
86
|
+
if (!descriptor.available) return;
|
|
87
|
+
const curated = options?.exposeCapability?.(descriptor);
|
|
88
|
+
if (options?.exposeCapability && curated === null) return;
|
|
89
|
+
tools.push({
|
|
90
|
+
name: encodeWireName(capabilityId),
|
|
91
|
+
capabilityId,
|
|
92
|
+
registrationId,
|
|
93
|
+
inputSchema,
|
|
94
|
+
description: curated?.description ?? defaultDescription,
|
|
95
|
+
// Derived from the declared kind/effect only; curation cannot widen it.
|
|
96
|
+
readOnly
|
|
97
|
+
});
|
|
98
|
+
};
|
|
48
99
|
for (const component of snapshot.components) {
|
|
49
100
|
for (const obs of component.observations) {
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
component.registrationId,
|
|
58
|
-
{ type: "object", properties: {}, additionalProperties: false },
|
|
59
|
-
curated?.description ?? `[view \xB7 read] ${obs.description}`
|
|
60
|
-
)
|
|
101
|
+
add(
|
|
102
|
+
obs,
|
|
103
|
+
obs.capabilityId,
|
|
104
|
+
component.registrationId,
|
|
105
|
+
{ type: "object", properties: {}, additionalProperties: false },
|
|
106
|
+
`[view \xB7 read] ${obs.description}`,
|
|
107
|
+
true
|
|
61
108
|
);
|
|
62
109
|
}
|
|
63
110
|
for (const act of component.actions) {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
component.registrationId,
|
|
72
|
-
act.inputSchema,
|
|
73
|
-
curated?.description ?? `[view \xB7 ${act.effect}] ${act.description}`
|
|
74
|
-
)
|
|
111
|
+
add(
|
|
112
|
+
act,
|
|
113
|
+
act.capabilityId,
|
|
114
|
+
component.registrationId,
|
|
115
|
+
act.inputSchema,
|
|
116
|
+
`[view \xB7 ${act.effect}] ${act.description}`,
|
|
117
|
+
READ_ONLY_EFFECTS.has(act.effect)
|
|
75
118
|
);
|
|
76
119
|
}
|
|
77
120
|
}
|
|
78
121
|
for (const proc of snapshot.procedures) {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
proc.registrationId,
|
|
87
|
-
proc.inputSchema,
|
|
88
|
-
curated?.description ?? `[domain \xB7 ${proc.effect}${proc.confirmation === "required" ? " \xB7 requires confirmation" : ""}] ${proc.description}`
|
|
89
|
-
)
|
|
122
|
+
add(
|
|
123
|
+
proc,
|
|
124
|
+
proc.procedureId,
|
|
125
|
+
proc.registrationId,
|
|
126
|
+
proc.inputSchema,
|
|
127
|
+
`[domain \xB7 ${proc.effect}${proc.confirmation === "required" ? " \xB7 requires confirmation" : ""}] ${proc.description}`,
|
|
128
|
+
READ_ONLY_EFFECTS.has(proc.effect)
|
|
90
129
|
);
|
|
91
130
|
}
|
|
92
|
-
|
|
131
|
+
return { surfaceVersion: snapshot.surfaceVersion, tools };
|
|
132
|
+
};
|
|
133
|
+
const reconcile = () => {
|
|
134
|
+
if (!state.active) return;
|
|
135
|
+
const { surfaceVersion, tools } = desiredTools();
|
|
136
|
+
const next = /* @__PURE__ */ new Map();
|
|
137
|
+
const toRegister = [];
|
|
138
|
+
for (const desired of tools) {
|
|
139
|
+
const signature = JSON.stringify([
|
|
140
|
+
desired.description,
|
|
141
|
+
desired.inputSchema,
|
|
142
|
+
desired.registrationId,
|
|
143
|
+
desired.capabilityId,
|
|
144
|
+
desired.readOnly
|
|
145
|
+
]);
|
|
146
|
+
const current = state.exposed.get(desired.name);
|
|
147
|
+
if (current && current.signature === signature) {
|
|
148
|
+
current.target.surfaceVersion = surfaceVersion;
|
|
149
|
+
next.set(desired.name, current);
|
|
150
|
+
continue;
|
|
151
|
+
}
|
|
152
|
+
const target = {
|
|
153
|
+
capabilityId: desired.capabilityId,
|
|
154
|
+
registrationId: desired.registrationId,
|
|
155
|
+
surfaceVersion
|
|
156
|
+
};
|
|
157
|
+
const tool = toTool(desired, target);
|
|
158
|
+
next.set(desired.name, { tool, target, signature });
|
|
159
|
+
toRegister.push(tool);
|
|
160
|
+
}
|
|
161
|
+
if (state.incremental) {
|
|
162
|
+
for (const [name, current] of state.exposed) {
|
|
163
|
+
const replacement = next.get(name);
|
|
164
|
+
if (replacement !== current) modelContext.unregisterTool(name);
|
|
165
|
+
}
|
|
166
|
+
for (const tool of toRegister) modelContext.registerTool(tool);
|
|
167
|
+
} else {
|
|
168
|
+
modelContext.provideContext({ tools: [...next.values()].map((entry) => entry.tool) });
|
|
169
|
+
}
|
|
170
|
+
state.exposed = next;
|
|
93
171
|
};
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
172
|
+
session = state;
|
|
173
|
+
reconcile();
|
|
174
|
+
state.unsubscribe = host.registry.subscribe((event) => {
|
|
175
|
+
if (event.type === "surface-changed") reconcile();
|
|
97
176
|
});
|
|
98
177
|
},
|
|
99
178
|
stop() {
|
|
100
|
-
|
|
101
|
-
|
|
179
|
+
const state = session;
|
|
180
|
+
session = void 0;
|
|
181
|
+
if (!state) return;
|
|
182
|
+
state.active = false;
|
|
183
|
+
state.unsubscribe();
|
|
184
|
+
const { modelContext } = state;
|
|
185
|
+
if (state.incremental) {
|
|
186
|
+
for (const name of state.exposed.keys()) {
|
|
187
|
+
try {
|
|
188
|
+
modelContext.unregisterTool(name);
|
|
189
|
+
} catch {
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
} else if (typeof modelContext.clearContext === "function") {
|
|
193
|
+
modelContext.clearContext();
|
|
194
|
+
} else {
|
|
195
|
+
modelContext.provideContext({ tools: [] });
|
|
196
|
+
}
|
|
197
|
+
state.exposed.clear();
|
|
102
198
|
}
|
|
103
199
|
};
|
|
104
200
|
}
|
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 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 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 */\n\nexport interface WebMcpToolInit {\n name: string;\n description: string;\n inputSchema: JsonSchema;\n execute(input: JsonValue): Promise<WebMcpToolResult>;\n}\n\nexport interface WebMcpToolResult {\n content: Array<{ type: \"text\"; text: string }>;\n isError?: boolean;\n}\n\nexport interface WebMcpModelContext {\n provideContext(context: { tools: WebMcpToolInit[] }): 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 /** Test seam: defaults to (navigator as any).modelContext. */\n modelContext?: WebMcpModelContext;\n}\n\n/**\n * Maps the registry onto `navigator.modelContext`, treating WebMCP strictly\n * as transport/discovery: one wire-named tool per AVAILABLE capability,\n * re-provided on every surface-changed; unavailable capabilities are not\n * registered (WebMCP has no disabled state today — accepted limitation);\n * confirmations stay two-phase; absent modelContext ⇒ start() does nothing.\n */\nexport function createWebMcpAdapter(options?: CreateWebMcpAdapterOptions): AgentSurfaceAdapter {\n let unsubscribe: (() => void) | undefined;\n\n return {\n name: \"webmcp\",\n\n start(host: AdapterHost): void {\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 provide = (): void => {\n const snapshot = host.registry.snapshot({\n consumer: host.consumer,\n ...(options?.snapshotContext ?? host.snapshotContext ?? {}),\n includeUnavailable: false,\n });\n\n const tools: WebMcpToolInit[] = [];\n\n const toTool = (\n descriptor: AgentCapabilityDescriptorUnion,\n capabilityId: string,\n registrationId: string,\n inputSchema: JsonSchema,\n description: string,\n ): WebMcpToolInit => ({\n name: encodeWireName(capabilityId),\n description,\n inputSchema,\n execute: async (input: JsonValue): Promise<WebMcpToolResult> => {\n const result = await host.registry.invoke(\n {\n invocationId: randomInvocationId(),\n capabilityId,\n registrationId,\n surfaceVersion: snapshot.surfaceVersion,\n ...(input !== undefined && Object.keys(input as object).length > 0\n ? { input }\n : {}),\n },\n { consumer: host.consumer },\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 for (const component of snapshot.components) {\n for (const obs of component.observations) {\n if (!obs.available) continue;\n const curated = options?.exposeCapability?.(obs);\n if (options?.exposeCapability && curated === null) continue;\n tools.push(\n toTool(\n obs,\n obs.capabilityId,\n component.registrationId,\n { type: \"object\", properties: {}, additionalProperties: false },\n curated?.description ?? `[view · read] ${obs.description}`,\n ),\n );\n }\n for (const act of component.actions) {\n if (!act.available) continue;\n const curated = options?.exposeCapability?.(act);\n if (options?.exposeCapability && curated === null) continue;\n tools.push(\n toTool(\n act,\n act.capabilityId,\n component.registrationId,\n act.inputSchema,\n curated?.description ?? `[view · ${act.effect}] ${act.description}`,\n ),\n );\n }\n }\n for (const proc of snapshot.procedures) {\n if (!proc.available) continue;\n const curated = options?.exposeCapability?.(proc);\n if (options?.exposeCapability && curated === null) continue;\n tools.push(\n toTool(\n proc,\n proc.procedureId,\n proc.registrationId,\n proc.inputSchema,\n curated?.description ??\n `[domain · ${proc.effect}${proc.confirmation === \"required\" ? \" · requires confirmation\" : \"\"}] ${proc.description}`,\n ),\n );\n }\n\n modelContext.provideContext({ tools });\n };\n\n provide();\n unsubscribe = host.registry.subscribe((event) => {\n if (event.type === \"surface-changed\") provide();\n });\n },\n\n stop(): void {\n unsubscribe?.();\n unsubscribe = undefined;\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) ⇒\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":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agent-surface/webmcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.25.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.
|
|
21
|
+
"@agent-surface/core": "^0.25.0"
|
|
22
22
|
},
|
|
23
23
|
"devDependencies": {
|
|
24
24
|
"zod": "^4.1.5",
|
|
25
|
-
"@agent-surface/testing": "0.
|
|
25
|
+
"@agent-surface/testing": "0.25.0"
|
|
26
26
|
},
|
|
27
27
|
"author": "Paolo Barbato",
|
|
28
28
|
"engines": {
|