agents 0.11.3 → 0.11.4

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.
@@ -0,0 +1,212 @@
1
+ //#region src/experimental/webmcp.d.ts
2
+ /**
3
+ * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
4
+ * !! WARNING: EXPERIMENTAL — DO NOT USE IN PRODUCTION !!
5
+ * !! !!
6
+ * !! This API is under active development and WILL break between !!
7
+ * !! releases. Google's WebMCP API (navigator.modelContext) is still !!
8
+ * !! in early preview and subject to change. !!
9
+ * !! !!
10
+ * !! If you use this, pin your agents version and expect to rewrite !!
11
+ * !! your code when upgrading. !!
12
+ * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
13
+ *
14
+ * WebMCP adapter for Cloudflare Agents SDK.
15
+ *
16
+ * Bridges tools registered on an McpAgent server to Chrome's native
17
+ * navigator.modelContext API, so browser-native agents can discover
18
+ * and call them without extra infrastructure.
19
+ *
20
+ * @example Bridge a remote McpAgent endpoint into the page
21
+ * ```ts
22
+ * import { registerWebMcp } from "agents/experimental/webmcp";
23
+ *
24
+ * const handle = await registerWebMcp({ url: "/mcp" });
25
+ *
26
+ * // Later, to clean up:
27
+ * await handle.dispose();
28
+ * ```
29
+ *
30
+ * @example Mix in-page tools with bridged tools (recommended pattern)
31
+ * ```ts
32
+ * import { registerWebMcp } from "agents/experimental/webmcp";
33
+ *
34
+ * // 1. Register page-local tools — things only the page can do
35
+ * navigator.modelContext?.registerTool({
36
+ * name: "scroll_to_section",
37
+ * description: "Scroll the page to a named section",
38
+ * inputSchema: {
39
+ * type: "object",
40
+ * properties: { id: { type: "string" } },
41
+ * required: ["id"]
42
+ * },
43
+ * async execute({ id }) {
44
+ * document.getElementById(String(id))?.scrollIntoView({ behavior: "smooth" });
45
+ * return "ok";
46
+ * }
47
+ * });
48
+ *
49
+ * // 2. Bridge server tools — things that need durable storage / auth / DB access
50
+ * const handle = await registerWebMcp({
51
+ * url: "/mcp",
52
+ * prefix: "remote.", // optional namespace to avoid collisions
53
+ * getHeaders: async () => ({ Authorization: `Bearer ${await getToken()}` })
54
+ * });
55
+ *
56
+ * // The browser AI sees both kinds of tools side by side.
57
+ * ```
58
+ *
59
+ * @experimental This API is not yet stable and may change.
60
+ */
61
+ interface ModelContextToolAnnotations {
62
+ readOnlyHint?: boolean;
63
+ }
64
+ interface ModelContextClient {
65
+ requestUserInteraction(callback: () => Promise<unknown>): Promise<unknown>;
66
+ }
67
+ interface ModelContextTool {
68
+ name: string;
69
+ description: string;
70
+ inputSchema?: Record<string, unknown>;
71
+ execute: (input: Record<string, unknown>, client: ModelContextClient) => Promise<unknown>;
72
+ annotations?: ModelContextToolAnnotations;
73
+ }
74
+ interface ModelContextRegisterToolOptions {
75
+ signal?: AbortSignal;
76
+ }
77
+ interface ModelContext {
78
+ registerTool(tool: ModelContextTool, options?: ModelContextRegisterToolOptions): void;
79
+ }
80
+ declare global {
81
+ interface Navigator {
82
+ modelContext?: ModelContext;
83
+ }
84
+ }
85
+ interface McpTool {
86
+ name: string;
87
+ description?: string;
88
+ inputSchema?: Record<string, unknown>;
89
+ annotations?: {
90
+ readOnlyHint?: boolean;
91
+ };
92
+ }
93
+ /**
94
+ * Logger interface for adapter diagnostics. Defaults to `console`.
95
+ * Pass a no-op implementation (or `quiet: true`) to silence output.
96
+ */
97
+ interface WebMcpLogger {
98
+ info(...args: unknown[]): void;
99
+ warn(...args: unknown[]): void;
100
+ error(...args: unknown[]): void;
101
+ }
102
+ interface WebMcpOptions {
103
+ /** URL of the MCP endpoint (absolute or relative, e.g. `"/mcp"`). */
104
+ url: string;
105
+ /**
106
+ * Additional headers to include in every request to the MCP server.
107
+ * Useful for static authentication (e.g. `{ Authorization: "Bearer <token>" }`).
108
+ */
109
+ headers?: Record<string, string>;
110
+ /**
111
+ * Async function that returns headers for each request.
112
+ * Called before every request, useful for tokens that refresh.
113
+ * If both `headers` and `getHeaders` are provided, they are merged
114
+ * with `getHeaders` values taking precedence.
115
+ */
116
+ getHeaders?: () => Promise<Record<string, string>> | Record<string, string>;
117
+ /**
118
+ * If true, listen for `tools/list_changed` notifications and re-sync
119
+ * tools with `navigator.modelContext`. The adapter opens an SSE GET to
120
+ * the MCP endpoint to receive notifications; servers that don't support
121
+ * server-initiated streams (e.g. respond `405` on GET) gracefully degrade.
122
+ * @default true
123
+ */
124
+ watch?: boolean;
125
+ /**
126
+ * Optional namespace prefix prepended to every tool name registered with
127
+ * `navigator.modelContext`. Useful when bridging multiple MCP servers, or
128
+ * when the page also registers in-page tools and you want to avoid
129
+ * collisions. The original (unprefixed) name is still used on the wire
130
+ * when calling the server.
131
+ *
132
+ * @example `prefix: "remote."` turns `search` into `remote.search`.
133
+ */
134
+ prefix?: string;
135
+ /**
136
+ * Per-request timeout (in milliseconds) applied to `tools/list` and
137
+ * `tools/call`. If the server doesn't respond in time, the request is
138
+ * aborted and the resulting error is surfaced through the normal error
139
+ * paths (`onError` for sync, rejection for tool execution).
140
+ */
141
+ timeoutMs?: number;
142
+ /**
143
+ * Custom logger. Defaults to `console` with a `[webmcp-adapter]` prefix.
144
+ * Pass `{ info: () => {}, warn: () => {}, error: () => {} }` to silence.
145
+ */
146
+ logger?: WebMcpLogger;
147
+ /** Convenience shortcut for `logger: SILENT_LOGGER`. @default false */
148
+ quiet?: boolean;
149
+ /**
150
+ * Called whenever the adapter performs a successful sync (initial load
151
+ * and on `tools/list_changed`). Receives the tools as the server returned
152
+ * them (with their original, unprefixed names).
153
+ */
154
+ onSync?: (tools: McpTool[]) => void;
155
+ /**
156
+ * Called when an error occurs during background work that the caller
157
+ * cannot otherwise observe — specifically: a watch-mode re-sync failure.
158
+ *
159
+ * **Not** called for:
160
+ * - Initialization failures (those reject the `registerWebMcp` promise).
161
+ * - Per-tool execution failures (those reject the `execute` promise the
162
+ * browser host awaits; Chrome surfaces them to the AI).
163
+ */
164
+ onError?: (error: Error) => void;
165
+ }
166
+ interface WebMcpHandle {
167
+ /**
168
+ * Currently registered tool names (with `prefix` applied). Returns a fresh
169
+ * snapshot on each access — safe to mutate.
170
+ */
171
+ readonly tools: ReadonlyArray<string>;
172
+ /**
173
+ * Re-fetch the tool list from the server and re-register everything.
174
+ * If a sync is already in flight (from a `tools/list_changed` notification
175
+ * or a previous `refresh()` call), returns the in-flight promise rather
176
+ * than starting a second sync.
177
+ */
178
+ refresh(): Promise<void>;
179
+ /**
180
+ * Unregister all tools, signal any in-flight work to abort, and close the
181
+ * MCP connection. Safe to call multiple times.
182
+ */
183
+ dispose(): Promise<void>;
184
+ /** True after `dispose()` has been called at least once. */
185
+ readonly disposed: boolean;
186
+ }
187
+ /**
188
+ * Discovers tools from a Cloudflare McpAgent endpoint and registers them
189
+ * with Chrome's native `navigator.modelContext` API.
190
+ *
191
+ * On browsers without `navigator.modelContext` (everything except recent
192
+ * Chrome with the relevant flags), this function is a no-op and returns a
193
+ * handle with an empty tools array. No network request is made.
194
+ *
195
+ * @example
196
+ * ```ts
197
+ * import { registerWebMcp } from "agents/experimental/webmcp";
198
+ *
199
+ * const handle = await registerWebMcp({ url: "/mcp" });
200
+ * console.log("Registered tools:", handle.tools);
201
+ *
202
+ * // Clean up when done (e.g. in a React effect cleanup)
203
+ * await handle.dispose();
204
+ * ```
205
+ *
206
+ * See the JSDoc on the module itself for the recommended "in-page tools +
207
+ * remote tools" composition pattern.
208
+ */
209
+ declare function registerWebMcp(options: WebMcpOptions): Promise<WebMcpHandle>;
210
+ //#endregion
211
+ export { WebMcpHandle, WebMcpLogger, WebMcpOptions, registerWebMcp };
212
+ //# sourceMappingURL=webmcp.d.ts.map
@@ -0,0 +1,298 @@
1
+ import { Client } from "@modelcontextprotocol/sdk/client/index.js";
2
+ import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
3
+ import { ToolListChangedNotificationSchema } from "@modelcontextprotocol/sdk/types.js";
4
+ //#region src/experimental/webmcp.ts
5
+ /**
6
+ * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
7
+ * !! WARNING: EXPERIMENTAL — DO NOT USE IN PRODUCTION !!
8
+ * !! !!
9
+ * !! This API is under active development and WILL break between !!
10
+ * !! releases. Google's WebMCP API (navigator.modelContext) is still !!
11
+ * !! in early preview and subject to change. !!
12
+ * !! !!
13
+ * !! If you use this, pin your agents version and expect to rewrite !!
14
+ * !! your code when upgrading. !!
15
+ * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
16
+ *
17
+ * WebMCP adapter for Cloudflare Agents SDK.
18
+ *
19
+ * Bridges tools registered on an McpAgent server to Chrome's native
20
+ * navigator.modelContext API, so browser-native agents can discover
21
+ * and call them without extra infrastructure.
22
+ *
23
+ * @example Bridge a remote McpAgent endpoint into the page
24
+ * ```ts
25
+ * import { registerWebMcp } from "agents/experimental/webmcp";
26
+ *
27
+ * const handle = await registerWebMcp({ url: "/mcp" });
28
+ *
29
+ * // Later, to clean up:
30
+ * await handle.dispose();
31
+ * ```
32
+ *
33
+ * @example Mix in-page tools with bridged tools (recommended pattern)
34
+ * ```ts
35
+ * import { registerWebMcp } from "agents/experimental/webmcp";
36
+ *
37
+ * // 1. Register page-local tools — things only the page can do
38
+ * navigator.modelContext?.registerTool({
39
+ * name: "scroll_to_section",
40
+ * description: "Scroll the page to a named section",
41
+ * inputSchema: {
42
+ * type: "object",
43
+ * properties: { id: { type: "string" } },
44
+ * required: ["id"]
45
+ * },
46
+ * async execute({ id }) {
47
+ * document.getElementById(String(id))?.scrollIntoView({ behavior: "smooth" });
48
+ * return "ok";
49
+ * }
50
+ * });
51
+ *
52
+ * // 2. Bridge server tools — things that need durable storage / auth / DB access
53
+ * const handle = await registerWebMcp({
54
+ * url: "/mcp",
55
+ * prefix: "remote.", // optional namespace to avoid collisions
56
+ * getHeaders: async () => ({ Authorization: `Bearer ${await getToken()}` })
57
+ * });
58
+ *
59
+ * // The browser AI sees both kinds of tools side by side.
60
+ * ```
61
+ *
62
+ * @experimental This API is not yet stable and may change.
63
+ */
64
+ const DEFAULT_LOGGER = {
65
+ info: (...args) => console.info("[webmcp-adapter]", ...args),
66
+ warn: (...args) => console.warn("[webmcp-adapter]", ...args),
67
+ error: (...args) => console.error("[webmcp-adapter]", ...args)
68
+ };
69
+ const SILENT_LOGGER = {
70
+ info: () => {},
71
+ warn: () => {},
72
+ error: () => {}
73
+ };
74
+ var McpHttpClient = class {
75
+ constructor(url, headers, getHeaders, timeoutMs) {
76
+ const resolvedUrl = new URL(url, globalThis.location?.origin);
77
+ this._timeoutMs = timeoutMs;
78
+ const transportOptions = { requestInit: { headers: headers ?? {} } };
79
+ if (getHeaders) transportOptions.fetch = async (input, init) => {
80
+ const dynamic = await getHeaders();
81
+ const merged = new Headers(init?.headers);
82
+ for (const [k, v] of Object.entries(dynamic)) merged.set(k, v);
83
+ return globalThis.fetch(input, {
84
+ ...init,
85
+ headers: merged
86
+ });
87
+ };
88
+ this._transport = new StreamableHTTPClientTransport(resolvedUrl, transportOptions);
89
+ this._client = new Client({
90
+ name: "webmcp-adapter",
91
+ version: "0.1.0"
92
+ }, { capabilities: {} });
93
+ }
94
+ async initialize(signal) {
95
+ await this._client.connect(this._transport);
96
+ this._client.setNotificationHandler(ToolListChangedNotificationSchema, async () => {
97
+ if (signal?.aborted) return;
98
+ this._onToolsChanged?.();
99
+ });
100
+ }
101
+ async listTools(signal) {
102
+ const allTools = [];
103
+ let cursor;
104
+ do {
105
+ if (signal?.aborted) throw new DOMException("Aborted", "AbortError");
106
+ const result = await this._client.listTools(cursor ? { cursor } : void 0, {
107
+ signal,
108
+ timeout: this._timeoutMs
109
+ });
110
+ for (const t of result.tools) allTools.push({
111
+ name: t.name,
112
+ description: t.description,
113
+ inputSchema: t.inputSchema,
114
+ annotations: t.annotations ? { readOnlyHint: t.annotations.readOnlyHint } : void 0
115
+ });
116
+ cursor = result.nextCursor;
117
+ } while (cursor);
118
+ return allTools;
119
+ }
120
+ async callTool(name, args, signal) {
121
+ const result = await this._client.callTool({
122
+ name,
123
+ arguments: args
124
+ }, void 0, {
125
+ signal,
126
+ timeout: this._timeoutMs
127
+ });
128
+ if ("content" in result) return {
129
+ content: result.content.map((c) => ({
130
+ type: c.type,
131
+ text: "text" in c ? c.text : void 0,
132
+ data: "data" in c ? c.data : void 0,
133
+ mimeType: "mimeType" in c ? c.mimeType : void 0
134
+ })),
135
+ isError: "isError" in result ? result.isError : false
136
+ };
137
+ return {
138
+ content: [],
139
+ isError: false
140
+ };
141
+ }
142
+ listenForChanges(onToolsChanged) {
143
+ this._onToolsChanged = onToolsChanged;
144
+ }
145
+ async close() {
146
+ try {
147
+ await this._client.close();
148
+ } catch {}
149
+ }
150
+ };
151
+ /**
152
+ * Discovers tools from a Cloudflare McpAgent endpoint and registers them
153
+ * with Chrome's native `navigator.modelContext` API.
154
+ *
155
+ * On browsers without `navigator.modelContext` (everything except recent
156
+ * Chrome with the relevant flags), this function is a no-op and returns a
157
+ * handle with an empty tools array. No network request is made.
158
+ *
159
+ * @example
160
+ * ```ts
161
+ * import { registerWebMcp } from "agents/experimental/webmcp";
162
+ *
163
+ * const handle = await registerWebMcp({ url: "/mcp" });
164
+ * console.log("Registered tools:", handle.tools);
165
+ *
166
+ * // Clean up when done (e.g. in a React effect cleanup)
167
+ * await handle.dispose();
168
+ * ```
169
+ *
170
+ * See the JSDoc on the module itself for the recommended "in-page tools +
171
+ * remote tools" composition pattern.
172
+ */
173
+ async function registerWebMcp(options) {
174
+ const { url, headers, getHeaders, watch = true, prefix = "", timeoutMs, logger: userLogger, quiet = false, onSync, onError } = options;
175
+ const logger = quiet ? SILENT_LOGGER : userLogger ?? DEFAULT_LOGGER;
176
+ const registeredTools = [];
177
+ const toolControllers = /* @__PURE__ */ new Map();
178
+ const lifecycleController = new AbortController();
179
+ let disposed = false;
180
+ let inflightSync = null;
181
+ if (!navigator.modelContext) {
182
+ logger.info("navigator.modelContext not available — skipping registration. This is expected on non-Chrome browsers.");
183
+ onSync?.([]);
184
+ return {
185
+ get tools() {
186
+ return [];
187
+ },
188
+ get disposed() {
189
+ return disposed;
190
+ },
191
+ refresh: async () => {},
192
+ dispose: async () => {
193
+ disposed = true;
194
+ }
195
+ };
196
+ }
197
+ const modelContext = navigator.modelContext;
198
+ const client = new McpHttpClient(url, headers, getHeaders, timeoutMs);
199
+ function unregisterAll() {
200
+ for (const controller of toolControllers.values()) controller.abort();
201
+ toolControllers.clear();
202
+ registeredTools.length = 0;
203
+ }
204
+ function registerTools(tools) {
205
+ for (const tool of tools) {
206
+ const registeredName = `${prefix}${tool.name}`;
207
+ const toolDef = {
208
+ name: registeredName,
209
+ description: tool.description ?? tool.name,
210
+ ...tool.inputSchema ? { inputSchema: tool.inputSchema } : {},
211
+ ...tool.annotations ? { annotations: { readOnlyHint: tool.annotations.readOnlyHint } } : {},
212
+ execute: async (input) => {
213
+ if (disposed) throw new Error("WebMCP adapter has been disposed");
214
+ const result = await client.callTool(tool.name, input, lifecycleController.signal);
215
+ if (result.isError) {
216
+ const errorText = result.content.map((c) => c.text ?? "").join("\n");
217
+ throw new Error(errorText || "Tool execution failed");
218
+ }
219
+ const parts = [];
220
+ let sawUnsupported = false;
221
+ for (const c of result.content) if (c.type === "text" && c.text) parts.push(c.text);
222
+ else if (c.type === "image" && c.data) parts.push(`data:${c.mimeType ?? "image/png"};base64,${c.data}`);
223
+ else if (c.data) {
224
+ parts.push(c.data);
225
+ sawUnsupported = true;
226
+ } else sawUnsupported = true;
227
+ if (sawUnsupported) logger.warn(`Tool "${tool.name}" returned content type(s) the adapter cannot fully represent as a string.`);
228
+ return parts.join("\n");
229
+ }
230
+ };
231
+ try {
232
+ const controller = new AbortController();
233
+ modelContext.registerTool(toolDef, { signal: controller.signal });
234
+ toolControllers.set(registeredName, controller);
235
+ registeredTools.push(registeredName);
236
+ } catch (err) {
237
+ logger.warn(`Failed to register tool "${registeredName}":`, err);
238
+ }
239
+ }
240
+ }
241
+ function syncTools() {
242
+ if (disposed) return Promise.resolve();
243
+ if (inflightSync) return inflightSync;
244
+ inflightSync = (async () => {
245
+ try {
246
+ const tools = await client.listTools(lifecycleController.signal);
247
+ if (disposed) return;
248
+ unregisterAll();
249
+ registerTools(tools);
250
+ onSync?.(tools);
251
+ } finally {
252
+ inflightSync = null;
253
+ }
254
+ })();
255
+ return inflightSync;
256
+ }
257
+ try {
258
+ await client.initialize(lifecycleController.signal);
259
+ await syncTools();
260
+ if (watch) client.listenForChanges(() => {
261
+ if (disposed) return;
262
+ syncTools().catch((err) => {
263
+ if (disposed) return;
264
+ const error = err instanceof Error ? err : new Error(String(err));
265
+ logger.warn("Watch-mode sync failed:", error);
266
+ onError?.(error);
267
+ });
268
+ });
269
+ } catch (err) {
270
+ const error = err instanceof Error ? err : new Error(String(err));
271
+ logger.error("Initialization failed:", error);
272
+ await client.close();
273
+ throw error;
274
+ }
275
+ return {
276
+ get tools() {
277
+ return [...registeredTools];
278
+ },
279
+ get disposed() {
280
+ return disposed;
281
+ },
282
+ refresh: syncTools,
283
+ async dispose() {
284
+ if (disposed) return;
285
+ disposed = true;
286
+ lifecycleController.abort();
287
+ unregisterAll();
288
+ try {
289
+ await inflightSync;
290
+ } catch {}
291
+ await client.close();
292
+ }
293
+ };
294
+ }
295
+ //#endregion
296
+ export { registerWebMcp };
297
+
298
+ //# sourceMappingURL=webmcp.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webmcp.js","names":[],"sources":["../../src/experimental/webmcp.ts"],"sourcesContent":["/**\n * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n * !! WARNING: EXPERIMENTAL — DO NOT USE IN PRODUCTION !!\n * !! !!\n * !! This API is under active development and WILL break between !!\n * !! releases. Google's WebMCP API (navigator.modelContext) is still !!\n * !! in early preview and subject to change. !!\n * !! !!\n * !! If you use this, pin your agents version and expect to rewrite !!\n * !! your code when upgrading. !!\n * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n *\n * WebMCP adapter for Cloudflare Agents SDK.\n *\n * Bridges tools registered on an McpAgent server to Chrome's native\n * navigator.modelContext API, so browser-native agents can discover\n * and call them without extra infrastructure.\n *\n * @example Bridge a remote McpAgent endpoint into the page\n * ```ts\n * import { registerWebMcp } from \"agents/experimental/webmcp\";\n *\n * const handle = await registerWebMcp({ url: \"/mcp\" });\n *\n * // Later, to clean up:\n * await handle.dispose();\n * ```\n *\n * @example Mix in-page tools with bridged tools (recommended pattern)\n * ```ts\n * import { registerWebMcp } from \"agents/experimental/webmcp\";\n *\n * // 1. Register page-local tools — things only the page can do\n * navigator.modelContext?.registerTool({\n * name: \"scroll_to_section\",\n * description: \"Scroll the page to a named section\",\n * inputSchema: {\n * type: \"object\",\n * properties: { id: { type: \"string\" } },\n * required: [\"id\"]\n * },\n * async execute({ id }) {\n * document.getElementById(String(id))?.scrollIntoView({ behavior: \"smooth\" });\n * return \"ok\";\n * }\n * });\n *\n * // 2. Bridge server tools — things that need durable storage / auth / DB access\n * const handle = await registerWebMcp({\n * url: \"/mcp\",\n * prefix: \"remote.\", // optional namespace to avoid collisions\n * getHeaders: async () => ({ Authorization: `Bearer ${await getToken()}` })\n * });\n *\n * // The browser AI sees both kinds of tools side by side.\n * ```\n *\n * @experimental This API is not yet stable and may change.\n */\n\nimport { Client } from \"@modelcontextprotocol/sdk/client/index.js\";\nimport { StreamableHTTPClientTransport } from \"@modelcontextprotocol/sdk/client/streamableHttp.js\";\nimport { ToolListChangedNotificationSchema } from \"@modelcontextprotocol/sdk/types.js\";\n\n// ── WebMCP browser API surface (Chrome's navigator.modelContext) ─────\n\ninterface ModelContextToolAnnotations {\n readOnlyHint?: boolean;\n}\n\ninterface ModelContextClient {\n requestUserInteraction(callback: () => Promise<unknown>): Promise<unknown>;\n}\n\ninterface ModelContextTool {\n name: string;\n description: string;\n inputSchema?: Record<string, unknown>;\n execute: (\n input: Record<string, unknown>,\n client: ModelContextClient\n ) => Promise<unknown>;\n annotations?: ModelContextToolAnnotations;\n}\n\ninterface ModelContextRegisterToolOptions {\n signal?: AbortSignal;\n}\n\ninterface ModelContext {\n registerTool(\n tool: ModelContextTool,\n options?: ModelContextRegisterToolOptions\n ): void;\n}\n\ndeclare global {\n interface Navigator {\n modelContext?: ModelContext;\n }\n}\n\n// ── Internal types ───────────────────────────────────────────────────\n\ninterface McpTool {\n name: string;\n description?: string;\n inputSchema?: Record<string, unknown>;\n annotations?: { readOnlyHint?: boolean };\n}\n\ninterface McpToolCallResult {\n content: Array<{\n type: string;\n text?: string;\n data?: string;\n mimeType?: string;\n }>;\n isError?: boolean;\n}\n\n/**\n * Logger interface for adapter diagnostics. Defaults to `console`.\n * Pass a no-op implementation (or `quiet: true`) to silence output.\n */\nexport interface WebMcpLogger {\n info(...args: unknown[]): void;\n warn(...args: unknown[]): void;\n error(...args: unknown[]): void;\n}\n\nconst DEFAULT_LOGGER: WebMcpLogger = {\n info: (...args) => console.info(\"[webmcp-adapter]\", ...args),\n warn: (...args) => console.warn(\"[webmcp-adapter]\", ...args),\n error: (...args) => console.error(\"[webmcp-adapter]\", ...args)\n};\n\nconst SILENT_LOGGER: WebMcpLogger = {\n info: () => {},\n warn: () => {},\n error: () => {}\n};\n\n// ── MCP transport wrapper ────────────────────────────────────────────\n\nclass McpHttpClient {\n private _client: Client;\n private _transport: StreamableHTTPClientTransport;\n private _onToolsChanged?: () => void;\n private _timeoutMs?: number;\n\n constructor(\n url: string,\n headers?: Record<string, string>,\n getHeaders?: () => Promise<Record<string, string>> | Record<string, string>,\n timeoutMs?: number\n ) {\n const resolvedUrl = new URL(url, globalThis.location?.origin);\n this._timeoutMs = timeoutMs;\n\n const transportOptions: ConstructorParameters<\n typeof StreamableHTTPClientTransport\n >[1] = {\n requestInit: { headers: headers ?? {} }\n };\n\n if (getHeaders) {\n transportOptions.fetch = async (input, init) => {\n const dynamic = await getHeaders();\n const merged = new Headers(init?.headers);\n for (const [k, v] of Object.entries(dynamic)) {\n merged.set(k, v);\n }\n return globalThis.fetch(input, {\n ...init,\n headers: merged\n });\n };\n }\n\n this._transport = new StreamableHTTPClientTransport(\n resolvedUrl,\n transportOptions\n );\n\n this._client = new Client(\n { name: \"webmcp-adapter\", version: \"0.1.0\" },\n { capabilities: {} }\n );\n }\n\n async initialize(signal?: AbortSignal): Promise<void> {\n await this._client.connect(this._transport);\n\n this._client.setNotificationHandler(\n ToolListChangedNotificationSchema,\n async () => {\n if (signal?.aborted) return;\n this._onToolsChanged?.();\n }\n );\n }\n\n async listTools(signal?: AbortSignal): Promise<McpTool[]> {\n const allTools: McpTool[] = [];\n let cursor: string | undefined;\n do {\n if (signal?.aborted) throw new DOMException(\"Aborted\", \"AbortError\");\n const result = await this._client.listTools(\n cursor ? { cursor } : undefined,\n { signal, timeout: this._timeoutMs }\n );\n for (const t of result.tools) {\n allTools.push({\n name: t.name,\n description: t.description,\n inputSchema: t.inputSchema as Record<string, unknown> | undefined,\n annotations: t.annotations\n ? { readOnlyHint: t.annotations.readOnlyHint }\n : undefined\n });\n }\n cursor = result.nextCursor;\n } while (cursor);\n return allTools;\n }\n\n async callTool(\n name: string,\n args: Record<string, unknown>,\n signal?: AbortSignal\n ): Promise<McpToolCallResult> {\n const result = await this._client.callTool(\n { name, arguments: args },\n undefined,\n { signal, timeout: this._timeoutMs }\n );\n if (\"content\" in result) {\n return {\n content: (\n result.content as Array<{\n type: string;\n text?: string;\n data?: string;\n }>\n ).map((c) => ({\n type: c.type,\n text: \"text\" in c ? (c.text as string) : undefined,\n data: \"data\" in c ? (c.data as string) : undefined,\n mimeType: \"mimeType\" in c ? (c.mimeType as string) : undefined\n })),\n isError: \"isError\" in result ? (result.isError as boolean) : false\n };\n }\n return { content: [], isError: false };\n }\n\n listenForChanges(onToolsChanged: () => void): void {\n this._onToolsChanged = onToolsChanged;\n }\n\n async close(): Promise<void> {\n try {\n await this._client.close();\n } catch {\n // Closing a never-connected or already-closed client is fine.\n }\n }\n}\n\n// ── Public API ───────────────────────────────────────────────────────\n\nexport interface WebMcpOptions {\n /** URL of the MCP endpoint (absolute or relative, e.g. `\"/mcp\"`). */\n url: string;\n /**\n * Additional headers to include in every request to the MCP server.\n * Useful for static authentication (e.g. `{ Authorization: \"Bearer <token>\" }`).\n */\n headers?: Record<string, string>;\n /**\n * Async function that returns headers for each request.\n * Called before every request, useful for tokens that refresh.\n * If both `headers` and `getHeaders` are provided, they are merged\n * with `getHeaders` values taking precedence.\n */\n getHeaders?: () => Promise<Record<string, string>> | Record<string, string>;\n /**\n * If true, listen for `tools/list_changed` notifications and re-sync\n * tools with `navigator.modelContext`. The adapter opens an SSE GET to\n * the MCP endpoint to receive notifications; servers that don't support\n * server-initiated streams (e.g. respond `405` on GET) gracefully degrade.\n * @default true\n */\n watch?: boolean;\n /**\n * Optional namespace prefix prepended to every tool name registered with\n * `navigator.modelContext`. Useful when bridging multiple MCP servers, or\n * when the page also registers in-page tools and you want to avoid\n * collisions. The original (unprefixed) name is still used on the wire\n * when calling the server.\n *\n * @example `prefix: \"remote.\"` turns `search` into `remote.search`.\n */\n prefix?: string;\n /**\n * Per-request timeout (in milliseconds) applied to `tools/list` and\n * `tools/call`. If the server doesn't respond in time, the request is\n * aborted and the resulting error is surfaced through the normal error\n * paths (`onError` for sync, rejection for tool execution).\n */\n timeoutMs?: number;\n /**\n * Custom logger. Defaults to `console` with a `[webmcp-adapter]` prefix.\n * Pass `{ info: () => {}, warn: () => {}, error: () => {} }` to silence.\n */\n logger?: WebMcpLogger;\n /** Convenience shortcut for `logger: SILENT_LOGGER`. @default false */\n quiet?: boolean;\n /**\n * Called whenever the adapter performs a successful sync (initial load\n * and on `tools/list_changed`). Receives the tools as the server returned\n * them (with their original, unprefixed names).\n */\n onSync?: (tools: McpTool[]) => void;\n /**\n * Called when an error occurs during background work that the caller\n * cannot otherwise observe — specifically: a watch-mode re-sync failure.\n *\n * **Not** called for:\n * - Initialization failures (those reject the `registerWebMcp` promise).\n * - Per-tool execution failures (those reject the `execute` promise the\n * browser host awaits; Chrome surfaces them to the AI).\n */\n onError?: (error: Error) => void;\n}\n\nexport interface WebMcpHandle {\n /**\n * Currently registered tool names (with `prefix` applied). Returns a fresh\n * snapshot on each access — safe to mutate.\n */\n readonly tools: ReadonlyArray<string>;\n /**\n * Re-fetch the tool list from the server and re-register everything.\n * If a sync is already in flight (from a `tools/list_changed` notification\n * or a previous `refresh()` call), returns the in-flight promise rather\n * than starting a second sync.\n */\n refresh(): Promise<void>;\n /**\n * Unregister all tools, signal any in-flight work to abort, and close the\n * MCP connection. Safe to call multiple times.\n */\n dispose(): Promise<void>;\n /** True after `dispose()` has been called at least once. */\n readonly disposed: boolean;\n}\n\n/**\n * Discovers tools from a Cloudflare McpAgent endpoint and registers them\n * with Chrome's native `navigator.modelContext` API.\n *\n * On browsers without `navigator.modelContext` (everything except recent\n * Chrome with the relevant flags), this function is a no-op and returns a\n * handle with an empty tools array. No network request is made.\n *\n * @example\n * ```ts\n * import { registerWebMcp } from \"agents/experimental/webmcp\";\n *\n * const handle = await registerWebMcp({ url: \"/mcp\" });\n * console.log(\"Registered tools:\", handle.tools);\n *\n * // Clean up when done (e.g. in a React effect cleanup)\n * await handle.dispose();\n * ```\n *\n * See the JSDoc on the module itself for the recommended \"in-page tools +\n * remote tools\" composition pattern.\n */\nexport async function registerWebMcp(\n options: WebMcpOptions\n): Promise<WebMcpHandle> {\n const {\n url,\n headers,\n getHeaders,\n watch = true,\n prefix = \"\",\n timeoutMs,\n logger: userLogger,\n quiet = false,\n onSync,\n onError\n } = options;\n\n const logger = quiet ? SILENT_LOGGER : (userLogger ?? DEFAULT_LOGGER);\n\n const registeredTools: string[] = [];\n const toolControllers = new Map<string, AbortController>();\n const lifecycleController = new AbortController();\n let disposed = false;\n let inflightSync: Promise<void> | null = null;\n\n if (!navigator.modelContext) {\n logger.info(\n \"navigator.modelContext not available — skipping registration. \" +\n \"This is expected on non-Chrome browsers.\"\n );\n onSync?.([]);\n return {\n get tools() {\n return [];\n },\n get disposed() {\n return disposed;\n },\n refresh: async () => {},\n dispose: async () => {\n disposed = true;\n }\n };\n }\n\n const modelContext: ModelContext = navigator.modelContext;\n const client = new McpHttpClient(url, headers, getHeaders, timeoutMs);\n\n function unregisterAll(): void {\n for (const controller of toolControllers.values()) {\n controller.abort();\n }\n toolControllers.clear();\n registeredTools.length = 0;\n }\n\n function registerTools(tools: McpTool[]): void {\n for (const tool of tools) {\n const registeredName = `${prefix}${tool.name}`;\n const toolDef: ModelContextTool = {\n name: registeredName,\n description: tool.description ?? tool.name,\n ...(tool.inputSchema ? { inputSchema: tool.inputSchema } : {}),\n ...(tool.annotations\n ? { annotations: { readOnlyHint: tool.annotations.readOnlyHint } }\n : {}),\n execute: async (input: Record<string, unknown>) => {\n if (disposed) {\n throw new Error(\"WebMCP adapter has been disposed\");\n }\n const result = await client.callTool(\n tool.name,\n input,\n lifecycleController.signal\n );\n\n if (result.isError) {\n const errorText = result.content\n .map((c) => c.text ?? \"\")\n .join(\"\\n\");\n throw new Error(errorText || \"Tool execution failed\");\n }\n\n const parts: string[] = [];\n let sawUnsupported = false;\n for (const c of result.content) {\n if (c.type === \"text\" && c.text) {\n parts.push(c.text);\n } else if (c.type === \"image\" && c.data) {\n parts.push(`data:${c.mimeType ?? \"image/png\"};base64,${c.data}`);\n } else if (c.data) {\n parts.push(c.data);\n sawUnsupported = true;\n } else {\n sawUnsupported = true;\n }\n }\n if (sawUnsupported) {\n logger.warn(\n `Tool \"${tool.name}\" returned content type(s) the adapter` +\n \" cannot fully represent as a string.\"\n );\n }\n return parts.join(\"\\n\");\n }\n };\n\n try {\n const controller = new AbortController();\n modelContext.registerTool(toolDef, { signal: controller.signal });\n toolControllers.set(registeredName, controller);\n registeredTools.push(registeredName);\n } catch (err) {\n logger.warn(`Failed to register tool \"${registeredName}\":`, err);\n }\n }\n }\n\n // Serialize syncs: if one is already running, share its promise. This\n // prevents the unregister/listTools/registerTools sequence from\n // interleaving when both `refresh()` and a `tools/list_changed`\n // notification fire concurrently.\n function syncTools(): Promise<void> {\n if (disposed) return Promise.resolve();\n if (inflightSync) return inflightSync;\n inflightSync = (async () => {\n try {\n const tools = await client.listTools(lifecycleController.signal);\n if (disposed) return;\n unregisterAll();\n registerTools(tools);\n onSync?.(tools);\n } finally {\n inflightSync = null;\n }\n })();\n return inflightSync;\n }\n\n try {\n await client.initialize(lifecycleController.signal);\n await syncTools();\n\n if (watch) {\n client.listenForChanges(() => {\n if (disposed) return;\n syncTools().catch((err: unknown) => {\n if (disposed) return;\n const error = err instanceof Error ? err : new Error(String(err));\n logger.warn(\"Watch-mode sync failed:\", error);\n onError?.(error);\n });\n });\n }\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err));\n logger.error(\"Initialization failed:\", error);\n // Best-effort cleanup so a failed init doesn't leak the transport.\n await client.close();\n throw error;\n }\n\n return {\n get tools() {\n return [...registeredTools];\n },\n get disposed() {\n return disposed;\n },\n refresh: syncTools,\n async dispose() {\n if (disposed) return;\n disposed = true;\n lifecycleController.abort();\n unregisterAll();\n // Wait for any in-flight sync to settle so callers can rely on\n // a quiet adapter after `await handle.dispose()`.\n try {\n await inflightSync;\n } catch {\n // Already surfaced via onError or thrown to the original caller.\n }\n await client.close();\n }\n };\n}\n"],"mappings":"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"}
@@ -729,7 +729,7 @@ declare class MCPClientConnection {
729
729
  */
730
730
  getTransport(
731
731
  transportType: BaseTransportType
732
- ): StreamableHTTPClientTransport | SSEClientTransport | RPCClientTransport;
732
+ ): RPCClientTransport | SSEClientTransport | StreamableHTTPClientTransport;
733
733
  private tryConnect;
734
734
  private _capabilityErrorHandler;
735
735
  }
@@ -3108,4 +3108,4 @@ export {
3108
3108
  QueueItem as y,
3109
3109
  MCPClientOAuthResult as z
3110
3110
  };
3111
- //# sourceMappingURL=index-D49HdAiY.d.ts.map
3111
+ //# sourceMappingURL=index-D9qo_Inc.d.ts.map
package/dist/index.d.ts CHANGED
@@ -37,7 +37,7 @@ import {
37
37
  w as SqlError,
38
38
  x as RPCResponse,
39
39
  y as QueueItem
40
- } from "./index-D49HdAiY.js";
40
+ } from "./index-D9qo_Inc.js";
41
41
  import {
42
42
  n as AgentsOAuthProvider,
43
43
  r as DurableObjectOAuthClientProvider,