@mcp-fe/mcp-worker 0.1.11 → 0.2.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/docs/index.md +1 -0
- package/docs/native-webmcp.md +232 -0
- package/index.js +288 -0
- package/package.json +1 -1
- package/src/client/index.d.ts +2 -0
- package/src/client/index.d.ts.map +1 -1
- package/src/client/web-mcp-adapter.d.ts +97 -0
- package/src/client/web-mcp-adapter.d.ts.map +1 -0
- package/src/client/web-mcp-types.d.ts +122 -0
- package/src/client/web-mcp-types.d.ts.map +1 -0
- package/src/client/worker-client.d.ts +31 -0
- package/src/client/worker-client.d.ts.map +1 -1
package/docs/index.md
CHANGED
|
@@ -11,6 +11,7 @@ Complete guide to all documentation and examples in the MCP Worker library.
|
|
|
11
11
|
| **Learn step-by-step** | [Guide](./guide.md) |
|
|
12
12
|
| **Complete API reference** | [API Reference](./api.md) |
|
|
13
13
|
| **Multi-tab applications** | [Multi-Tab Guide](./multi-tab.md) |
|
|
14
|
+
| **WebMCP integration** | [WebMCP](./native-webmcp.md) |
|
|
14
15
|
| **Worker implementation** | [Worker Details](./worker-details.md) |
|
|
15
16
|
| **Understand codebase structure** | [Project Structure](./project-structure.md) |
|
|
16
17
|
| **Use with React** | [React Hooks Guide](../../react-event-tracker/REACT_MCP_TOOLS.md) |
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
# WebMCP Integration
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
The MCP Worker library includes a built-in adapter for the **WebMCP API** (`navigator.modelContext`), a browser-native mechanism for registering MCP tools directly with the user-agent. When the browser supports this API, tools registered via `WorkerClient` are **automatically** advertised through the native channel as well, enabling browser-level tool discovery by AI agents, browser's agents, and assistive technologies.
|
|
6
|
+
|
|
7
|
+
**Enabled by default** — if the browser supports `navigator.modelContext`, it just works. No configuration needed. You can explicitly disable it if needed.
|
|
8
|
+
|
|
9
|
+
Based on the [WebMCP specification](https://webmachinelearning.github.io/webmcp/) published by the W3C Web Machine Learning Community Group.
|
|
10
|
+
|
|
11
|
+
## How It Works
|
|
12
|
+
|
|
13
|
+
```
|
|
14
|
+
┌──────────────────────────────────────────────────────────┐
|
|
15
|
+
│ WorkerClient │
|
|
16
|
+
│ │
|
|
17
|
+
│ registerTool('my-tool', ...) │
|
|
18
|
+
│ │ │
|
|
19
|
+
│ ├──→ ToolRegistry (local, immediate) │
|
|
20
|
+
│ │ │
|
|
21
|
+
│ ├──→ SharedWorker / ServiceWorker (transport) │
|
|
22
|
+
│ │ └──→ WebSocket → Backend MCP Server │
|
|
23
|
+
│ │ │
|
|
24
|
+
│ └──→ WebMcpAdapter (auto-enabled if supported) │
|
|
25
|
+
│ └──→ navigator.modelContext.registerTool() │
|
|
26
|
+
│ (browser-native registration) │
|
|
27
|
+
└──────────────────────────────────────────────────────────┘
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
**Key principle**: The worker transport remains the **primary** channel. WebMCP registration is a **secondary, additive** channel for browser-level discovery. Both systems coexist.
|
|
31
|
+
|
|
32
|
+
## WebMCP Spec API Surface
|
|
33
|
+
|
|
34
|
+
The adapter maps to the following browser API (per spec §5):
|
|
35
|
+
|
|
36
|
+
```webidl
|
|
37
|
+
// §5.1 Navigator extension
|
|
38
|
+
partial interface Navigator {
|
|
39
|
+
[SecureContext, SameObject] readonly attribute ModelContext modelContext;
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
// §5.2 ModelContext interface
|
|
43
|
+
interface ModelContext {
|
|
44
|
+
undefined provideContext(optional ModelContextOptions options = {});
|
|
45
|
+
undefined clearContext();
|
|
46
|
+
undefined registerTool(ModelContextTool tool);
|
|
47
|
+
undefined unregisterTool(DOMString name);
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
// §5.2.2 ModelContextTool dictionary
|
|
51
|
+
dictionary ModelContextTool {
|
|
52
|
+
required DOMString name;
|
|
53
|
+
required DOMString description;
|
|
54
|
+
object inputSchema;
|
|
55
|
+
required ToolExecuteCallback execute;
|
|
56
|
+
ToolAnnotations annotations;
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
dictionary ToolAnnotations {
|
|
60
|
+
boolean readOnlyHint;
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
callback ToolExecuteCallback = Promise<any> (object input, ModelContextClient client);
|
|
64
|
+
|
|
65
|
+
// §5.2.3 ModelContextClient
|
|
66
|
+
interface ModelContextClient {
|
|
67
|
+
Promise<any> requestUserInteraction(UserInteractionCallback callback);
|
|
68
|
+
};
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Feature Detection
|
|
72
|
+
|
|
73
|
+
```typescript
|
|
74
|
+
import { WorkerClient, WebMcpAdapter } from '@anthropic/mcp-worker';
|
|
75
|
+
|
|
76
|
+
// Static check: does the browser support navigator.modelContext?
|
|
77
|
+
if (WorkerClient.isWebMcpSupported()) {
|
|
78
|
+
console.log('Browser supports WebMCP!');
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Or use the adapter directly:
|
|
82
|
+
if (WebMcpAdapter.isSupported()) {
|
|
83
|
+
console.log('navigator.modelContext is available');
|
|
84
|
+
}
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Configuration
|
|
88
|
+
|
|
89
|
+
### Default behavior (auto-enabled)
|
|
90
|
+
|
|
91
|
+
No configuration needed. If `navigator.modelContext` is available, tools are automatically registered via WebMCP:
|
|
92
|
+
|
|
93
|
+
```typescript
|
|
94
|
+
import { workerClient } from '@anthropic/mcp-worker';
|
|
95
|
+
|
|
96
|
+
await workerClient.init({
|
|
97
|
+
sharedWorkerUrl: '/mcp-shared-worker.js',
|
|
98
|
+
backendWsUrl: 'ws://localhost:3001',
|
|
99
|
+
// enableWebMcp defaults to true — auto-detects browser support
|
|
100
|
+
});
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### Explicitly disable
|
|
104
|
+
|
|
105
|
+
```typescript
|
|
106
|
+
await workerClient.init({
|
|
107
|
+
sharedWorkerUrl: '/mcp-shared-worker.js',
|
|
108
|
+
backendWsUrl: 'ws://localhost:3001',
|
|
109
|
+
enableWebMcp: false, // ← disable WebMCP registration
|
|
110
|
+
});
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### Toggle at runtime
|
|
114
|
+
|
|
115
|
+
```typescript
|
|
116
|
+
// Disable — calls navigator.modelContext.clearContext()
|
|
117
|
+
workerClient.setWebMcpEnabled(false);
|
|
118
|
+
|
|
119
|
+
// Re-enable — syncs all existing tools to navigator.modelContext
|
|
120
|
+
workerClient.setWebMcpEnabled(true);
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
## Registering Tools
|
|
124
|
+
|
|
125
|
+
No changes to tool registration are needed. When WebMCP is available, `registerTool()` automatically registers in both systems:
|
|
126
|
+
|
|
127
|
+
```typescript
|
|
128
|
+
await workerClient.registerTool(
|
|
129
|
+
'get-user-profile',
|
|
130
|
+
'Fetch the current user profile',
|
|
131
|
+
{
|
|
132
|
+
type: 'object',
|
|
133
|
+
properties: {
|
|
134
|
+
userId: { type: 'string', description: 'User ID' },
|
|
135
|
+
},
|
|
136
|
+
required: ['userId'],
|
|
137
|
+
},
|
|
138
|
+
async (args: unknown) => {
|
|
139
|
+
const { userId } = args as { userId: string };
|
|
140
|
+
const profile = await fetchProfile(userId);
|
|
141
|
+
return {
|
|
142
|
+
content: [{ type: 'text', text: JSON.stringify(profile) }],
|
|
143
|
+
};
|
|
144
|
+
},
|
|
145
|
+
{ annotations: { readOnlyHint: true } },
|
|
146
|
+
);
|
|
147
|
+
|
|
148
|
+
// Check where the tool is registered:
|
|
149
|
+
workerClient.isToolRegistered('get-user-profile'); // true (local + worker)
|
|
150
|
+
workerClient.isToolRegisteredViaWebMcp('get-user-profile'); // true (navigator.modelContext)
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
## Querying WebMCP Registrations
|
|
154
|
+
|
|
155
|
+
```typescript
|
|
156
|
+
// Check if a specific tool is registered via WebMCP
|
|
157
|
+
workerClient.isToolRegisteredViaWebMcp('my-tool'); // boolean
|
|
158
|
+
|
|
159
|
+
// Get all WebMCP-registered tool names
|
|
160
|
+
workerClient.getWebMcpRegisteredTools(); // string[]
|
|
161
|
+
|
|
162
|
+
// Check if WebMCP is currently enabled AND supported
|
|
163
|
+
workerClient.isWebMcpAvailable(); // boolean
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
## Cleanup
|
|
167
|
+
|
|
168
|
+
WebMCP registrations are cleaned up automatically:
|
|
169
|
+
|
|
170
|
+
- **On `unregisterTool()`** — calls `navigator.modelContext.unregisterTool(name)`
|
|
171
|
+
- **On page unload** (`beforeunload` / `pagehide`) — calls `navigator.modelContext.clearContext()`
|
|
172
|
+
- **On `setWebMcpEnabled(false)`** — calls `navigator.modelContext.clearContext()`
|
|
173
|
+
|
|
174
|
+
## Architecture
|
|
175
|
+
|
|
176
|
+
### Files
|
|
177
|
+
|
|
178
|
+
| File | Purpose |
|
|
179
|
+
|------|---------|
|
|
180
|
+
| `web-mcp-types.ts` | TypeScript types matching the WebMCP spec (`ModelContext`, `ModelContextTool`, `ModelContextClient`, etc.) |
|
|
181
|
+
| `web-mcp-adapter.ts` | Adapter that bridges ToolRegistry ↔ `navigator.modelContext` |
|
|
182
|
+
| `worker-client.ts` | Integration point (uses adapter internally) |
|
|
183
|
+
|
|
184
|
+
### Type Augmentation
|
|
185
|
+
|
|
186
|
+
The `web-mcp-types.ts` file extends the global `Navigator` interface:
|
|
187
|
+
|
|
188
|
+
```typescript
|
|
189
|
+
declare global {
|
|
190
|
+
interface Navigator {
|
|
191
|
+
readonly modelContext?: ModelContext;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
### WebMcpAdapter
|
|
197
|
+
|
|
198
|
+
The adapter is a standalone class, enabled by default:
|
|
199
|
+
|
|
200
|
+
- **`isSupported()`** — static, checks `navigator.modelContext` existence
|
|
201
|
+
- **`isAvailable()`** — instance, respects enabled flag + browser support
|
|
202
|
+
- **`registerTool()`** — builds `ModelContextTool` dict and calls `navigator.modelContext.registerTool(tool)` (synchronous)
|
|
203
|
+
- **`unregisterTool()`** — calls `navigator.modelContext.unregisterTool(name)` (synchronous)
|
|
204
|
+
- **`clearAll()`** — calls `navigator.modelContext.clearContext()` (per spec §5.2)
|
|
205
|
+
- **`toModelContextTool()`** — static utility to convert internal `ToolDefinition` + handler
|
|
206
|
+
|
|
207
|
+
### Handler Mapping
|
|
208
|
+
|
|
209
|
+
The spec defines `ToolExecuteCallback` as:
|
|
210
|
+
|
|
211
|
+
```typescript
|
|
212
|
+
callback ToolExecuteCallback = Promise<any> (object input, ModelContextClient client);
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
The adapter wraps the internal `ToolHandler` (which takes `args: unknown` and returns `{ content: [...] }`) into this format. The `ModelContextClient` parameter gives access to `requestUserInteraction()` for user consent flows.
|
|
216
|
+
|
|
217
|
+
## Error Handling
|
|
218
|
+
|
|
219
|
+
All WebMCP operations are **best-effort**:
|
|
220
|
+
|
|
221
|
+
- Registration failures are logged as warnings, never thrown
|
|
222
|
+
- The worker-based system is unaffected by WebMCP errors
|
|
223
|
+
- Per spec, `registerTool()` throws if a duplicate name exists — the adapter unregisters first
|
|
224
|
+
- `clearAll()` falls back to individual `unregisterTool()` calls if `clearContext()` throws
|
|
225
|
+
|
|
226
|
+
## Browser Support
|
|
227
|
+
|
|
228
|
+
The WebMCP specification is a CG-DRAFT published by the W3C Web Machine Learning Community Group (February 2026). The adapter is forward-compatible:
|
|
229
|
+
|
|
230
|
+
- When the API is unavailable, all WebMCP operations are silent no-ops
|
|
231
|
+
- Zero runtime cost when browser doesn't support it (no feature detection on hot paths)
|
|
232
|
+
- The type definitions follow the spec and can be updated as the standard evolves
|
package/index.js
CHANGED
|
@@ -208,6 +208,197 @@ var ToolRegistry = class {
|
|
|
208
208
|
}
|
|
209
209
|
};
|
|
210
210
|
|
|
211
|
+
// libs/mcp-worker/src/client/web-mcp-adapter.ts
|
|
212
|
+
var WebMcpAdapter = class _WebMcpAdapter {
|
|
213
|
+
/** Tracks names of tools currently registered via WebMCP API */
|
|
214
|
+
registeredTools = /* @__PURE__ */ new Set();
|
|
215
|
+
/** Whether the adapter is enabled (enabled by default — auto-detects browser support) */
|
|
216
|
+
enabled = true;
|
|
217
|
+
// --------------------------------------------------------------------------
|
|
218
|
+
// Feature detection
|
|
219
|
+
// --------------------------------------------------------------------------
|
|
220
|
+
/**
|
|
221
|
+
* Check if the browser exposes the WebMCP API (`navigator.modelContext`).
|
|
222
|
+
*
|
|
223
|
+
* Safe to call in any environment (SSR, workers, older browsers).
|
|
224
|
+
*
|
|
225
|
+
* @see https://webmachinelearning.github.io/webmcp/#navigator-extension
|
|
226
|
+
*/
|
|
227
|
+
static isSupported() {
|
|
228
|
+
try {
|
|
229
|
+
return typeof navigator !== "undefined" && "modelContext" in navigator && navigator.modelContext != null && typeof navigator.modelContext.registerTool === "function";
|
|
230
|
+
} catch {
|
|
231
|
+
return false;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Convenience: instance-level check that also respects the `enabled` flag.
|
|
236
|
+
*/
|
|
237
|
+
isAvailable() {
|
|
238
|
+
return this.enabled && _WebMcpAdapter.isSupported();
|
|
239
|
+
}
|
|
240
|
+
// --------------------------------------------------------------------------
|
|
241
|
+
// Configuration
|
|
242
|
+
// --------------------------------------------------------------------------
|
|
243
|
+
/**
|
|
244
|
+
* Enable or disable the WebMCP adapter.
|
|
245
|
+
*
|
|
246
|
+
* When disabled, `registerTool` / `unregisterTool` become silent no-ops
|
|
247
|
+
* even if the browser supports the API.
|
|
248
|
+
*/
|
|
249
|
+
setEnabled(value) {
|
|
250
|
+
this.enabled = value;
|
|
251
|
+
logger.log(`[WebMcpAdapter] Enabled: ${value}`);
|
|
252
|
+
}
|
|
253
|
+
// --------------------------------------------------------------------------
|
|
254
|
+
// Registration
|
|
255
|
+
// --------------------------------------------------------------------------
|
|
256
|
+
/**
|
|
257
|
+
* Register a tool with the WebMCP API (`navigator.modelContext.registerTool()`).
|
|
258
|
+
*
|
|
259
|
+
* Silently returns if the API is unavailable or the adapter is disabled.
|
|
260
|
+
* Per spec, `registerTool()` throws if a tool with the same name already exists,
|
|
261
|
+
* so we unregister first if needed (idempotent update).
|
|
262
|
+
*
|
|
263
|
+
* @param name - Tool name
|
|
264
|
+
* @param description - Human-readable description (required by spec)
|
|
265
|
+
* @param inputSchema - JSON Schema for tool inputs
|
|
266
|
+
* @param handler - Async handler executed in the main thread
|
|
267
|
+
* @param options - Additional MCP tool options (annotations, …)
|
|
268
|
+
*/
|
|
269
|
+
registerTool(name, description, inputSchema, handler, options) {
|
|
270
|
+
if (!this.isAvailable()) {
|
|
271
|
+
return;
|
|
272
|
+
}
|
|
273
|
+
if (this.registeredTools.has(name)) {
|
|
274
|
+
this.unregisterTool(name);
|
|
275
|
+
}
|
|
276
|
+
try {
|
|
277
|
+
const modelContext = navigator.modelContext;
|
|
278
|
+
const tool = {
|
|
279
|
+
name,
|
|
280
|
+
description: description ?? name,
|
|
281
|
+
inputSchema,
|
|
282
|
+
execute: async (input) => {
|
|
283
|
+
return handler(input);
|
|
284
|
+
},
|
|
285
|
+
annotations: this.mapAnnotations(options?.annotations)
|
|
286
|
+
};
|
|
287
|
+
modelContext.registerTool(tool);
|
|
288
|
+
this.registeredTools.add(name);
|
|
289
|
+
logger.log(
|
|
290
|
+
`[WebMcpAdapter] Registered tool '${name}' via navigator.modelContext`
|
|
291
|
+
);
|
|
292
|
+
} catch (error) {
|
|
293
|
+
logger.warn(`[WebMcpAdapter] Failed to register '${name}':`, error);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* Unregister a tool from the WebMCP API (`navigator.modelContext.unregisterTool()`).
|
|
298
|
+
*
|
|
299
|
+
* Safe to call even if the tool was never registered via WebMCP.
|
|
300
|
+
*
|
|
301
|
+
* @param name - Tool name to unregister
|
|
302
|
+
* @returns `true` if the tool was found and unregistered, `false` otherwise
|
|
303
|
+
*/
|
|
304
|
+
unregisterTool(name) {
|
|
305
|
+
if (!this.registeredTools.has(name)) {
|
|
306
|
+
return false;
|
|
307
|
+
}
|
|
308
|
+
try {
|
|
309
|
+
if (_WebMcpAdapter.isSupported()) {
|
|
310
|
+
const modelContext = navigator.modelContext;
|
|
311
|
+
modelContext.unregisterTool(name);
|
|
312
|
+
}
|
|
313
|
+
this.registeredTools.delete(name);
|
|
314
|
+
logger.log(
|
|
315
|
+
`[WebMcpAdapter] Unregistered tool '${name}' from navigator.modelContext`
|
|
316
|
+
);
|
|
317
|
+
return true;
|
|
318
|
+
} catch (error) {
|
|
319
|
+
logger.warn(`[WebMcpAdapter] Failed to unregister '${name}':`, error);
|
|
320
|
+
this.registeredTools.delete(name);
|
|
321
|
+
return false;
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
/**
|
|
325
|
+
* Unregister ALL tools registered via WebMCP.
|
|
326
|
+
*
|
|
327
|
+
* Uses `navigator.modelContext.clearContext()` when available (per spec, clears
|
|
328
|
+
* all tools at once), otherwise falls back to individual unregisterTool calls.
|
|
329
|
+
*/
|
|
330
|
+
clearAll() {
|
|
331
|
+
if (this.registeredTools.size === 0)
|
|
332
|
+
return;
|
|
333
|
+
logger.log(`[WebMcpAdapter] Clearing ${this.registeredTools.size} tool(s)`);
|
|
334
|
+
try {
|
|
335
|
+
if (_WebMcpAdapter.isSupported()) {
|
|
336
|
+
const modelContext = navigator.modelContext;
|
|
337
|
+
modelContext.clearContext();
|
|
338
|
+
}
|
|
339
|
+
} catch (error) {
|
|
340
|
+
logger.warn(
|
|
341
|
+
"[WebMcpAdapter] clearContext() failed, falling back to individual unregister:",
|
|
342
|
+
error
|
|
343
|
+
);
|
|
344
|
+
const names = Array.from(this.registeredTools);
|
|
345
|
+
names.forEach((name) => {
|
|
346
|
+
try {
|
|
347
|
+
if (_WebMcpAdapter.isSupported()) {
|
|
348
|
+
navigator.modelContext.unregisterTool(name);
|
|
349
|
+
}
|
|
350
|
+
} catch {
|
|
351
|
+
}
|
|
352
|
+
});
|
|
353
|
+
}
|
|
354
|
+
this.registeredTools.clear();
|
|
355
|
+
}
|
|
356
|
+
// --------------------------------------------------------------------------
|
|
357
|
+
// Query
|
|
358
|
+
// --------------------------------------------------------------------------
|
|
359
|
+
/**
|
|
360
|
+
* Check if a tool is registered via WebMCP.
|
|
361
|
+
*/
|
|
362
|
+
isRegistered(name) {
|
|
363
|
+
return this.registeredTools.has(name);
|
|
364
|
+
}
|
|
365
|
+
/**
|
|
366
|
+
* Get names of all tools registered via WebMCP.
|
|
367
|
+
*/
|
|
368
|
+
getRegisteredTools() {
|
|
369
|
+
return Array.from(this.registeredTools);
|
|
370
|
+
}
|
|
371
|
+
// --------------------------------------------------------------------------
|
|
372
|
+
// Mapping helpers
|
|
373
|
+
// --------------------------------------------------------------------------
|
|
374
|
+
/**
|
|
375
|
+
* Map internal ToolAnnotations to WebMCP ToolAnnotations.
|
|
376
|
+
* The spec currently only defines `readOnlyHint`.
|
|
377
|
+
*/
|
|
378
|
+
mapAnnotations(annotations) {
|
|
379
|
+
if (!annotations)
|
|
380
|
+
return void 0;
|
|
381
|
+
return {
|
|
382
|
+
readOnlyHint: annotations.readOnlyHint
|
|
383
|
+
};
|
|
384
|
+
}
|
|
385
|
+
/**
|
|
386
|
+
* Convert internal ToolDefinition to ModelContextTool format (utility).
|
|
387
|
+
* Requires an execute callback to be provided separately.
|
|
388
|
+
*/
|
|
389
|
+
static toModelContextTool(tool, handler) {
|
|
390
|
+
return {
|
|
391
|
+
name: tool.name,
|
|
392
|
+
description: tool.description ?? tool.name,
|
|
393
|
+
inputSchema: tool.inputSchema,
|
|
394
|
+
execute: async (input) => {
|
|
395
|
+
return handler(input);
|
|
396
|
+
},
|
|
397
|
+
annotations: tool.annotations ? { readOnlyHint: tool.annotations.readOnlyHint } : void 0
|
|
398
|
+
};
|
|
399
|
+
}
|
|
400
|
+
};
|
|
401
|
+
|
|
211
402
|
// libs/mcp-worker/src/client/worker-client.ts
|
|
212
403
|
var WorkerClient = class _WorkerClient {
|
|
213
404
|
// Configurable worker script URLs (defaults kept for backward compatibility)
|
|
@@ -229,6 +420,8 @@ var WorkerClient = class _WorkerClient {
|
|
|
229
420
|
initResolvers = [];
|
|
230
421
|
// Tool registry for managing tool lifecycle
|
|
231
422
|
toolRegistry = new ToolRegistry();
|
|
423
|
+
// WebMCP adapter for browser-level tool registration via navigator.modelContext
|
|
424
|
+
webMcpAdapter = new WebMcpAdapter();
|
|
232
425
|
// Tab tracking for multi-tab support
|
|
233
426
|
tabId;
|
|
234
427
|
static TAB_ID_STORAGE_KEY = "mcp_fe_tab_id";
|
|
@@ -339,6 +532,7 @@ var WorkerClient = class _WorkerClient {
|
|
|
339
532
|
logger.log(
|
|
340
533
|
`[WorkerClient] Page unloading, cleaning up ${toolNames.length} tool(s)`
|
|
341
534
|
);
|
|
535
|
+
this.webMcpAdapter.clearAll();
|
|
342
536
|
toolNames.forEach((toolName) => {
|
|
343
537
|
const existing = this.toolRegistry.getInfo(toolName);
|
|
344
538
|
if (!existing)
|
|
@@ -383,6 +577,14 @@ var WorkerClient = class _WorkerClient {
|
|
|
383
577
|
this.serviceWorkerUrl = opts.serviceWorkerUrl;
|
|
384
578
|
if (opts.backendWsUrl)
|
|
385
579
|
this.backendWsUrl = opts.backendWsUrl;
|
|
580
|
+
if (opts.enableWebMcp !== void 0) {
|
|
581
|
+
this.webMcpAdapter.setEnabled(opts.enableWebMcp);
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
if (this.webMcpAdapter.isAvailable()) {
|
|
585
|
+
logger.log(
|
|
586
|
+
"[WorkerClient] WebMCP: auto-enabled (navigator.modelContext detected)"
|
|
587
|
+
);
|
|
386
588
|
}
|
|
387
589
|
if (this.initPromise) {
|
|
388
590
|
return this.initPromise.then(async () => {
|
|
@@ -459,6 +661,7 @@ var WorkerClient = class _WorkerClient {
|
|
|
459
661
|
const details = this.toolRegistry.getDetails(toolName);
|
|
460
662
|
if (!details)
|
|
461
663
|
return;
|
|
664
|
+
const handler = this.toolRegistry.getHandler(toolName);
|
|
462
665
|
try {
|
|
463
666
|
await this.registerToolInWorker(
|
|
464
667
|
details.name,
|
|
@@ -473,6 +676,22 @@ var WorkerClient = class _WorkerClient {
|
|
|
473
676
|
title: details.title
|
|
474
677
|
}
|
|
475
678
|
);
|
|
679
|
+
if (handler) {
|
|
680
|
+
this.webMcpAdapter.registerTool(
|
|
681
|
+
details.name,
|
|
682
|
+
details.description,
|
|
683
|
+
details.inputSchema,
|
|
684
|
+
handler,
|
|
685
|
+
{
|
|
686
|
+
outputSchema: details.outputSchema,
|
|
687
|
+
annotations: details.annotations,
|
|
688
|
+
execution: details.execution,
|
|
689
|
+
_meta: details._meta,
|
|
690
|
+
icons: details.icons,
|
|
691
|
+
title: details.title
|
|
692
|
+
}
|
|
693
|
+
);
|
|
694
|
+
}
|
|
476
695
|
} catch (error) {
|
|
477
696
|
logger.error(
|
|
478
697
|
`[WorkerClient] Failed to sync tool '${toolName}' to worker:`,
|
|
@@ -1003,6 +1222,13 @@ var WorkerClient = class _WorkerClient {
|
|
|
1003
1222
|
}
|
|
1004
1223
|
if (isNew) {
|
|
1005
1224
|
await this.registerToolInWorker(name, description, inputSchema, options);
|
|
1225
|
+
this.webMcpAdapter.registerTool(
|
|
1226
|
+
name,
|
|
1227
|
+
description,
|
|
1228
|
+
inputSchema,
|
|
1229
|
+
handler,
|
|
1230
|
+
options
|
|
1231
|
+
);
|
|
1006
1232
|
}
|
|
1007
1233
|
}
|
|
1008
1234
|
/**
|
|
@@ -1060,6 +1286,7 @@ var WorkerClient = class _WorkerClient {
|
|
|
1060
1286
|
"UNREGISTER_TOOL",
|
|
1061
1287
|
{ name, tabId: this.tabId }
|
|
1062
1288
|
);
|
|
1289
|
+
this.webMcpAdapter.unregisterTool(name);
|
|
1063
1290
|
logger.log(`[WorkerClient] Unregistered tool '${name}'`);
|
|
1064
1291
|
return workerResult?.success ?? false;
|
|
1065
1292
|
}
|
|
@@ -1096,6 +1323,66 @@ var WorkerClient = class _WorkerClient {
|
|
|
1096
1323
|
isToolRegistered(toolName) {
|
|
1097
1324
|
return this.toolRegistry.isRegistered(toolName);
|
|
1098
1325
|
}
|
|
1326
|
+
// --------------------------------------------------------------------------
|
|
1327
|
+
// WebMCP API
|
|
1328
|
+
// --------------------------------------------------------------------------
|
|
1329
|
+
/**
|
|
1330
|
+
* Check if the browser supports the WebMCP API (`navigator.modelContext`).
|
|
1331
|
+
*/
|
|
1332
|
+
static isWebMcpSupported() {
|
|
1333
|
+
return WebMcpAdapter.isSupported();
|
|
1334
|
+
}
|
|
1335
|
+
/**
|
|
1336
|
+
* Check if WebMCP is both enabled AND supported.
|
|
1337
|
+
*/
|
|
1338
|
+
isWebMcpAvailable() {
|
|
1339
|
+
return this.webMcpAdapter.isAvailable();
|
|
1340
|
+
}
|
|
1341
|
+
/**
|
|
1342
|
+
* Enable or disable WebMCP registration at runtime.
|
|
1343
|
+
* When enabled and the browser supports it, newly registered tools will also
|
|
1344
|
+
* be advertised via `navigator.modelContext`. Existing tools are synced immediately.
|
|
1345
|
+
*/
|
|
1346
|
+
setWebMcpEnabled(enabled) {
|
|
1347
|
+
this.webMcpAdapter.setEnabled(enabled);
|
|
1348
|
+
if (enabled && WebMcpAdapter.isSupported() && this.isInitialized) {
|
|
1349
|
+
const toolNames = this.toolRegistry.getRegisteredTools();
|
|
1350
|
+
toolNames.forEach((toolName) => {
|
|
1351
|
+
const details = this.toolRegistry.getDetails(toolName);
|
|
1352
|
+
const handler = this.toolRegistry.getHandler(toolName);
|
|
1353
|
+
if (!details || !handler)
|
|
1354
|
+
return;
|
|
1355
|
+
this.webMcpAdapter.registerTool(
|
|
1356
|
+
details.name,
|
|
1357
|
+
details.description,
|
|
1358
|
+
details.inputSchema,
|
|
1359
|
+
handler,
|
|
1360
|
+
{
|
|
1361
|
+
outputSchema: details.outputSchema,
|
|
1362
|
+
annotations: details.annotations,
|
|
1363
|
+
execution: details.execution,
|
|
1364
|
+
_meta: details._meta,
|
|
1365
|
+
icons: details.icons,
|
|
1366
|
+
title: details.title
|
|
1367
|
+
}
|
|
1368
|
+
);
|
|
1369
|
+
});
|
|
1370
|
+
} else if (!enabled) {
|
|
1371
|
+
this.webMcpAdapter.clearAll();
|
|
1372
|
+
}
|
|
1373
|
+
}
|
|
1374
|
+
/**
|
|
1375
|
+
* Check if a specific tool is registered via the WebMCP API.
|
|
1376
|
+
*/
|
|
1377
|
+
isToolRegisteredViaWebMcp(toolName) {
|
|
1378
|
+
return this.webMcpAdapter.isRegistered(toolName);
|
|
1379
|
+
}
|
|
1380
|
+
/**
|
|
1381
|
+
* Get names of tools registered via the WebMCP API.
|
|
1382
|
+
*/
|
|
1383
|
+
getWebMcpRegisteredTools() {
|
|
1384
|
+
return this.webMcpAdapter.getRegisteredTools();
|
|
1385
|
+
}
|
|
1099
1386
|
/**
|
|
1100
1387
|
* Handle tool call from worker - execute handler in main thread and return result
|
|
1101
1388
|
* @private
|
|
@@ -1235,6 +1522,7 @@ async function queryEvents(filters) {
|
|
|
1235
1522
|
});
|
|
1236
1523
|
}
|
|
1237
1524
|
export {
|
|
1525
|
+
WebMcpAdapter,
|
|
1238
1526
|
WorkerClient,
|
|
1239
1527
|
logger,
|
|
1240
1528
|
queryEvents,
|
package/package.json
CHANGED
package/src/client/index.d.ts
CHANGED
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
* Use this in your application code
|
|
4
4
|
*/
|
|
5
5
|
export { WorkerClient, type WorkerClientInitOptions } from './worker-client';
|
|
6
|
+
export { WebMcpAdapter } from './web-mcp-adapter';
|
|
7
|
+
export type { ModelContext, ModelContextTool, ModelContextOptions, ModelContextClient, ToolExecuteCallback, UserInteractionCallback, WebMcpToolAnnotations, } from './web-mcp-types';
|
|
6
8
|
export type { ToolHandler, ToolDefinition, Icon, ToolAnnotations, ToolExecution, UserEvent, EventFilters, TabInfo, } from '../shared/types';
|
|
7
9
|
export { logger } from '../shared/logger';
|
|
8
10
|
import { WorkerClient } from './worker-client';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../libs/mcp-worker/src/client/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,YAAY,EAAE,KAAK,uBAAuB,EAAE,MAAM,iBAAiB,CAAC;AAG7E,YAAY,EACV,WAAW,EACX,cAAc,EACd,IAAI,EACJ,eAAe,EACf,aAAa,EACb,SAAS,EACT,YAAY,EACZ,OAAO,GACR,MAAM,iBAAiB,CAAC;AAGzB,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAG1C,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,eAAO,MAAM,YAAY,cAAqB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../libs/mcp-worker/src/client/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,YAAY,EAAE,KAAK,uBAAuB,EAAE,MAAM,iBAAiB,CAAC;AAG7E,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAClD,YAAY,EACV,YAAY,EACZ,gBAAgB,EAChB,mBAAmB,EACnB,kBAAkB,EAClB,mBAAmB,EACnB,uBAAuB,EACvB,qBAAqB,GACtB,MAAM,iBAAiB,CAAC;AAGzB,YAAY,EACV,WAAW,EACX,cAAc,EACd,IAAI,EACJ,eAAe,EACf,aAAa,EACb,SAAS,EACT,YAAY,EACZ,OAAO,GACR,MAAM,iBAAiB,CAAC;AAGzB,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAG1C,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,eAAO,MAAM,YAAY,cAAqB,CAAC"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WebMcpAdapter — bridge between WorkerClient's tool system and the WebMCP API.
|
|
3
|
+
*
|
|
4
|
+
* Responsibilities:
|
|
5
|
+
* - Feature-detect `navigator.modelContext` availability
|
|
6
|
+
* - Map internal ToolDefinition + ToolHandler to the ModelContextTool format
|
|
7
|
+
* - Track which tools have been registered via WebMCP for cleanup
|
|
8
|
+
* - Provide register / unregister / cleanup that are safe no-ops when API is absent
|
|
9
|
+
*
|
|
10
|
+
* Design principles:
|
|
11
|
+
* - The adapter is ADDITIVE: the worker-based system remains the primary transport.
|
|
12
|
+
* WebMCP registration is a secondary channel for browser-level tool discovery.
|
|
13
|
+
* - Enabled by default — auto-detects browser support. Can be explicitly disabled.
|
|
14
|
+
* - All public methods are safe to call even when the API is unavailable —
|
|
15
|
+
* they silently return without throwing.
|
|
16
|
+
* - The WebMCP API (§5.2) is synchronous: registerTool() and unregisterTool()
|
|
17
|
+
* return `undefined`. The adapter wraps them in try/catch for safety.
|
|
18
|
+
*
|
|
19
|
+
* @see https://webmachinelearning.github.io/webmcp/
|
|
20
|
+
*/
|
|
21
|
+
import type { ToolDefinition } from '../shared/types';
|
|
22
|
+
import type { ToolHandler, ToolOptions } from './tool-registry';
|
|
23
|
+
import type { ModelContextTool } from './web-mcp-types';
|
|
24
|
+
export declare class WebMcpAdapter {
|
|
25
|
+
/** Tracks names of tools currently registered via WebMCP API */
|
|
26
|
+
private registeredTools;
|
|
27
|
+
/** Whether the adapter is enabled (enabled by default — auto-detects browser support) */
|
|
28
|
+
private enabled;
|
|
29
|
+
/**
|
|
30
|
+
* Check if the browser exposes the WebMCP API (`navigator.modelContext`).
|
|
31
|
+
*
|
|
32
|
+
* Safe to call in any environment (SSR, workers, older browsers).
|
|
33
|
+
*
|
|
34
|
+
* @see https://webmachinelearning.github.io/webmcp/#navigator-extension
|
|
35
|
+
*/
|
|
36
|
+
static isSupported(): boolean;
|
|
37
|
+
/**
|
|
38
|
+
* Convenience: instance-level check that also respects the `enabled` flag.
|
|
39
|
+
*/
|
|
40
|
+
isAvailable(): boolean;
|
|
41
|
+
/**
|
|
42
|
+
* Enable or disable the WebMCP adapter.
|
|
43
|
+
*
|
|
44
|
+
* When disabled, `registerTool` / `unregisterTool` become silent no-ops
|
|
45
|
+
* even if the browser supports the API.
|
|
46
|
+
*/
|
|
47
|
+
setEnabled(value: boolean): void;
|
|
48
|
+
/**
|
|
49
|
+
* Register a tool with the WebMCP API (`navigator.modelContext.registerTool()`).
|
|
50
|
+
*
|
|
51
|
+
* Silently returns if the API is unavailable or the adapter is disabled.
|
|
52
|
+
* Per spec, `registerTool()` throws if a tool with the same name already exists,
|
|
53
|
+
* so we unregister first if needed (idempotent update).
|
|
54
|
+
*
|
|
55
|
+
* @param name - Tool name
|
|
56
|
+
* @param description - Human-readable description (required by spec)
|
|
57
|
+
* @param inputSchema - JSON Schema for tool inputs
|
|
58
|
+
* @param handler - Async handler executed in the main thread
|
|
59
|
+
* @param options - Additional MCP tool options (annotations, …)
|
|
60
|
+
*/
|
|
61
|
+
registerTool(name: string, description: string | undefined, inputSchema: Record<string, unknown>, handler: ToolHandler, options?: ToolOptions): void;
|
|
62
|
+
/**
|
|
63
|
+
* Unregister a tool from the WebMCP API (`navigator.modelContext.unregisterTool()`).
|
|
64
|
+
*
|
|
65
|
+
* Safe to call even if the tool was never registered via WebMCP.
|
|
66
|
+
*
|
|
67
|
+
* @param name - Tool name to unregister
|
|
68
|
+
* @returns `true` if the tool was found and unregistered, `false` otherwise
|
|
69
|
+
*/
|
|
70
|
+
unregisterTool(name: string): boolean;
|
|
71
|
+
/**
|
|
72
|
+
* Unregister ALL tools registered via WebMCP.
|
|
73
|
+
*
|
|
74
|
+
* Uses `navigator.modelContext.clearContext()` when available (per spec, clears
|
|
75
|
+
* all tools at once), otherwise falls back to individual unregisterTool calls.
|
|
76
|
+
*/
|
|
77
|
+
clearAll(): void;
|
|
78
|
+
/**
|
|
79
|
+
* Check if a tool is registered via WebMCP.
|
|
80
|
+
*/
|
|
81
|
+
isRegistered(name: string): boolean;
|
|
82
|
+
/**
|
|
83
|
+
* Get names of all tools registered via WebMCP.
|
|
84
|
+
*/
|
|
85
|
+
getRegisteredTools(): string[];
|
|
86
|
+
/**
|
|
87
|
+
* Map internal ToolAnnotations to WebMCP ToolAnnotations.
|
|
88
|
+
* The spec currently only defines `readOnlyHint`.
|
|
89
|
+
*/
|
|
90
|
+
private mapAnnotations;
|
|
91
|
+
/**
|
|
92
|
+
* Convert internal ToolDefinition to ModelContextTool format (utility).
|
|
93
|
+
* Requires an execute callback to be provided separately.
|
|
94
|
+
*/
|
|
95
|
+
static toModelContextTool(tool: ToolDefinition, handler: ToolHandler): ModelContextTool;
|
|
96
|
+
}
|
|
97
|
+
//# sourceMappingURL=web-mcp-adapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"web-mcp-adapter.d.ts","sourceRoot":"","sources":["../../../../../libs/mcp-worker/src/client/web-mcp-adapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAGH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAChE,OAAO,KAAK,EAEV,gBAAgB,EAEjB,MAAM,iBAAiB,CAAC;AAEzB,qBAAa,aAAa;IACxB,gEAAgE;IAChE,OAAO,CAAC,eAAe,CAAqB;IAE5C,yFAAyF;IACzF,OAAO,CAAC,OAAO,CAAQ;IAMvB;;;;;;OAMG;WACW,WAAW,IAAI,OAAO;IAapC;;OAEG;IACI,WAAW,IAAI,OAAO;IAQ7B;;;;;OAKG;IACI,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI;IASvC;;;;;;;;;;;;OAYG;IACI,YAAY,CACjB,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,MAAM,GAAG,SAAS,EAC/B,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACpC,OAAO,EAAE,WAAW,EACpB,OAAO,CAAC,EAAE,WAAW,GACpB,IAAI;IAuCP;;;;;;;OAOG;IACI,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAyB5C;;;;;OAKG;IACI,QAAQ,IAAI,IAAI;IAoCvB;;OAEG;IACI,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAI1C;;OAEG;IACI,kBAAkB,IAAI,MAAM,EAAE;IAQrC;;;OAGG;IACH,OAAO,CAAC,cAAc;IAUtB;;;OAGG;WACW,kBAAkB,CAC9B,IAAI,EAAE,cAAc,EACpB,OAAO,EAAE,WAAW,GACnB,gBAAgB;CAapB"}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WebMCP API type definitions
|
|
3
|
+
*
|
|
4
|
+
* These types model the browser API (`navigator.modelContext`)
|
|
5
|
+
* based on the WebMCP specification (webmachinelearning.github.io/webmcp).
|
|
6
|
+
*
|
|
7
|
+
* The API allows web pages to register MCP tools with the browser/user-agent,
|
|
8
|
+
* enabling AI agents, browser's agents, and assistive technologies to discover and
|
|
9
|
+
* invoke them without relying on custom worker transports.
|
|
10
|
+
*
|
|
11
|
+
* When the API is not available, the existing worker-based transport is used
|
|
12
|
+
* as the sole registration path. When the API IS available, tools are registered
|
|
13
|
+
* in BOTH systems (worker for backward compat + browser-level for discovery).
|
|
14
|
+
*
|
|
15
|
+
* @see https://webmachinelearning.github.io/webmcp/
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* Callback invoked to perform user interaction (e.g., showing a confirmation dialog).
|
|
19
|
+
*
|
|
20
|
+
* @see https://webmachinelearning.github.io/webmcp/#callbackdef-userinteractioncallback
|
|
21
|
+
*/
|
|
22
|
+
export type UserInteractionCallback = () => Promise<unknown>;
|
|
23
|
+
/**
|
|
24
|
+
* Represents an agent executing a tool provided by the site through the ModelContext API.
|
|
25
|
+
*
|
|
26
|
+
* @see https://webmachinelearning.github.io/webmcp/#modelcontextclient
|
|
27
|
+
*/
|
|
28
|
+
export interface ModelContextClient {
|
|
29
|
+
/**
|
|
30
|
+
* Asynchronously requests user input during the execution of a tool.
|
|
31
|
+
* The callback function is invoked to perform the user interaction,
|
|
32
|
+
* and the promise resolves with the result of the callback.
|
|
33
|
+
*/
|
|
34
|
+
requestUserInteraction(callback: UserInteractionCallback): Promise<unknown>;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Callback invoked when an agent calls a tool.
|
|
38
|
+
* Receives the input parameters and a ModelContextClient object.
|
|
39
|
+
*
|
|
40
|
+
* @see https://webmachinelearning.github.io/webmcp/#callbackdef-toolexecutecallback
|
|
41
|
+
*/
|
|
42
|
+
export type ToolExecuteCallback = (input: object, client: ModelContextClient) => Promise<unknown>;
|
|
43
|
+
/**
|
|
44
|
+
* Optional annotations providing additional metadata about a tool's behavior.
|
|
45
|
+
*
|
|
46
|
+
* @see https://webmachinelearning.github.io/webmcp/#dictdef-toolannotations
|
|
47
|
+
*/
|
|
48
|
+
export interface WebMcpToolAnnotations {
|
|
49
|
+
/**
|
|
50
|
+
* If true, indicates the tool does not modify any state and only reads data.
|
|
51
|
+
* This hint helps agents decide when it is safe to call the tool.
|
|
52
|
+
*/
|
|
53
|
+
readOnlyHint?: boolean;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Describes a tool that can be invoked by agents.
|
|
57
|
+
*
|
|
58
|
+
* @see https://webmachinelearning.github.io/webmcp/#dictdef-modelcontexttool
|
|
59
|
+
*/
|
|
60
|
+
export interface ModelContextTool {
|
|
61
|
+
/** A unique identifier for the tool. Used by agents to reference the tool. */
|
|
62
|
+
name: string;
|
|
63
|
+
/** A natural language description of the tool's functionality. */
|
|
64
|
+
description: string;
|
|
65
|
+
/** A JSON Schema object describing the expected input parameters. */
|
|
66
|
+
inputSchema?: object;
|
|
67
|
+
/** Callback invoked when an agent calls the tool. */
|
|
68
|
+
execute: ToolExecuteCallback;
|
|
69
|
+
/** Optional annotations providing additional metadata about the tool's behavior. */
|
|
70
|
+
annotations?: WebMcpToolAnnotations;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Options for `provideContext()`.
|
|
74
|
+
*
|
|
75
|
+
* @see https://webmachinelearning.github.io/webmcp/#dictdef-modelcontextoptions
|
|
76
|
+
*/
|
|
77
|
+
export interface ModelContextOptions {
|
|
78
|
+
/** A list of tools to register with the browser. Each tool name must be unique. */
|
|
79
|
+
tools?: ModelContextTool[];
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* The `ModelContext` interface provides methods for web applications to register
|
|
83
|
+
* and manage tools that can be invoked by agents.
|
|
84
|
+
*
|
|
85
|
+
* Accessed via `navigator.modelContext`.
|
|
86
|
+
*
|
|
87
|
+
* @see https://webmachinelearning.github.io/webmcp/#model-context-container
|
|
88
|
+
*/
|
|
89
|
+
export interface ModelContext {
|
|
90
|
+
/**
|
|
91
|
+
* Registers the provided context (tools) with the browser.
|
|
92
|
+
* Clears any pre-existing tools and other context before registering the new ones.
|
|
93
|
+
*/
|
|
94
|
+
provideContext(options?: ModelContextOptions): void;
|
|
95
|
+
/**
|
|
96
|
+
* Unregisters all context (tools) with the browser.
|
|
97
|
+
*/
|
|
98
|
+
clearContext(): void;
|
|
99
|
+
/**
|
|
100
|
+
* Registers a single tool without clearing the existing set of tools.
|
|
101
|
+
* Throws an error if a tool with the same name already exists,
|
|
102
|
+
* or if the inputSchema is invalid.
|
|
103
|
+
*/
|
|
104
|
+
registerTool(tool: ModelContextTool): void;
|
|
105
|
+
/**
|
|
106
|
+
* Removes the tool with the specified name from the registered set.
|
|
107
|
+
*/
|
|
108
|
+
unregisterTool(name: string): void;
|
|
109
|
+
}
|
|
110
|
+
declare global {
|
|
111
|
+
interface Navigator {
|
|
112
|
+
/**
|
|
113
|
+
* WebMCP API — available when the browser supports the WebMCP specification.
|
|
114
|
+
* Use `WebMcpAdapter.isSupported()` for safe feature detection.
|
|
115
|
+
*
|
|
116
|
+
* @see https://webmachinelearning.github.io/webmcp/#navigator-extension
|
|
117
|
+
*/
|
|
118
|
+
readonly modelContext?: ModelContext;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
export {};
|
|
122
|
+
//# sourceMappingURL=web-mcp-types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"web-mcp-types.d.ts","sourceRoot":"","sources":["../../../../../libs/mcp-worker/src/client/web-mcp-types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAMH;;;;GAIG;AACH,MAAM,MAAM,uBAAuB,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;AAE7D;;;;GAIG;AACH,MAAM,WAAW,kBAAkB;IACjC;;;;OAIG;IACH,sBAAsB,CAAC,QAAQ,EAAE,uBAAuB,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CAC7E;AAMD;;;;;GAKG;AACH,MAAM,MAAM,mBAAmB,GAAG,CAChC,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,kBAAkB,KACvB,OAAO,CAAC,OAAO,CAAC,CAAC;AAEtB;;;;GAIG;AACH,MAAM,WAAW,qBAAqB;IACpC;;;OAGG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED;;;;GAIG;AACH,MAAM,WAAW,gBAAgB;IAC/B,8EAA8E;IAC9E,IAAI,EAAE,MAAM,CAAC;IACb,kEAAkE;IAClE,WAAW,EAAE,MAAM,CAAC;IACpB,qEAAqE;IACrE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,qDAAqD;IACrD,OAAO,EAAE,mBAAmB,CAAC;IAC7B,oFAAoF;IACpF,WAAW,CAAC,EAAE,qBAAqB,CAAC;CACrC;AAMD;;;;GAIG;AACH,MAAM,WAAW,mBAAmB;IAClC,mFAAmF;IACnF,KAAK,CAAC,EAAE,gBAAgB,EAAE,CAAC;CAC5B;AAMD;;;;;;;GAOG;AACH,MAAM,WAAW,YAAY;IAC3B;;;OAGG;IACH,cAAc,CAAC,OAAO,CAAC,EAAE,mBAAmB,GAAG,IAAI,CAAC;IAEpD;;OAEG;IACH,YAAY,IAAI,IAAI,CAAC;IAErB;;;;OAIG;IACH,YAAY,CAAC,IAAI,EAAE,gBAAgB,GAAG,IAAI,CAAC;IAE3C;;OAEG;IACH,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CACpC;AAMD,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,SAAS;QACjB;;;;;WAKG;QACH,QAAQ,CAAC,YAAY,CAAC,EAAE,YAAY,CAAC;KACtC;CACF;AAGD,OAAO,EAAE,CAAC"}
|
|
@@ -45,6 +45,14 @@ export type WorkerClientInitOptions = {
|
|
|
45
45
|
serviceWorkerUrl?: string;
|
|
46
46
|
/** Backend WebSocket URL to configure inside the worker (optional) */
|
|
47
47
|
backendWsUrl?: string;
|
|
48
|
+
/**
|
|
49
|
+
* Enable WebMCP API registration via `navigator.modelContext`.
|
|
50
|
+
* When `true` (default) and the browser supports the WebMCP spec, tools will be
|
|
51
|
+
* registered both in the worker transport AND via the browser API.
|
|
52
|
+
* Set to `false` to explicitly disable WebMCP registration.
|
|
53
|
+
* Defaults to `true`.
|
|
54
|
+
*/
|
|
55
|
+
enableWebMcp?: boolean;
|
|
48
56
|
};
|
|
49
57
|
export declare class WorkerClient {
|
|
50
58
|
private sharedWorkerUrl;
|
|
@@ -60,6 +68,7 @@ export declare class WorkerClient {
|
|
|
60
68
|
private isInitialized;
|
|
61
69
|
private initResolvers;
|
|
62
70
|
private toolRegistry;
|
|
71
|
+
private webMcpAdapter;
|
|
63
72
|
private tabId;
|
|
64
73
|
private static readonly TAB_ID_STORAGE_KEY;
|
|
65
74
|
constructor();
|
|
@@ -226,6 +235,28 @@ export declare class WorkerClient {
|
|
|
226
235
|
* Check if a tool is registered
|
|
227
236
|
*/
|
|
228
237
|
isToolRegistered(toolName: string): boolean;
|
|
238
|
+
/**
|
|
239
|
+
* Check if the browser supports the WebMCP API (`navigator.modelContext`).
|
|
240
|
+
*/
|
|
241
|
+
static isWebMcpSupported(): boolean;
|
|
242
|
+
/**
|
|
243
|
+
* Check if WebMCP is both enabled AND supported.
|
|
244
|
+
*/
|
|
245
|
+
isWebMcpAvailable(): boolean;
|
|
246
|
+
/**
|
|
247
|
+
* Enable or disable WebMCP registration at runtime.
|
|
248
|
+
* When enabled and the browser supports it, newly registered tools will also
|
|
249
|
+
* be advertised via `navigator.modelContext`. Existing tools are synced immediately.
|
|
250
|
+
*/
|
|
251
|
+
setWebMcpEnabled(enabled: boolean): void;
|
|
252
|
+
/**
|
|
253
|
+
* Check if a specific tool is registered via the WebMCP API.
|
|
254
|
+
*/
|
|
255
|
+
isToolRegisteredViaWebMcp(toolName: string): boolean;
|
|
256
|
+
/**
|
|
257
|
+
* Get names of tools registered via the WebMCP API.
|
|
258
|
+
*/
|
|
259
|
+
getWebMcpRegisteredTools(): string[];
|
|
229
260
|
/**
|
|
230
261
|
* Handle tool call from worker - execute handler in main thread and return result
|
|
231
262
|
* @private
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"worker-client.d.ts","sourceRoot":"","sources":["../../../../../libs/mcp-worker/src/client/worker-client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AAGH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,EAEL,KAAK,WAAW,EAChB,KAAK,WAAW,EACjB,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"worker-client.d.ts","sourceRoot":"","sources":["../../../../../libs/mcp-worker/src/client/worker-client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AAGH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,EAEL,KAAK,WAAW,EAChB,KAAK,WAAW,EACjB,MAAM,iBAAiB,CAAC;AAMzB,MAAM,MAAM,uBAAuB,GAAG;IACpC,gDAAgD;IAChD,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,iDAAiD;IACjD,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,sEAAsE;IACtE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;;;OAMG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB,CAAC;AAEF,qBAAa,YAAY;IAEvB,OAAO,CAAC,eAAe,CAA2B;IAClD,OAAO,CAAC,gBAAgB,CAA4B;IAEpD,OAAO,CAAC,YAAY,CAAwC;IAE5D,OAAO,CAAC,yBAAyB,CAA0C;IAC3E,OAAO,CAAC,YAAY,CAA6B;IACjD,OAAO,CAAC,gBAAgB,CAA4B;IACpD,OAAO,CAAC,UAAU,CAA2B;IAC7C,OAAO,CAAC,gBAAgB,CAAuB;IAE/C,OAAO,CAAC,yBAAyB,CACrB;IAGZ,OAAO,CAAC,WAAW,CAA8B;IAGjD,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,aAAa,CAAyB;IAG9C,OAAO,CAAC,YAAY,CAAsB;IAG1C,OAAO,CAAC,aAAa,CAAuB;IAG5C,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,kBAAkB,CAAmB;;IA+B7D;;;OAGG;IACH,OAAO,CAAC,gBAAgB;IAwBxB;;;OAGG;IACH,OAAO,CAAC,WAAW;IAWnB;;;OAGG;IACH,OAAO,CAAC,YAAY;IAOpB;;;OAGG;IACI,QAAQ,IAAI,MAAM;IAIzB;;;OAGG;IACI,UAAU,IAAI;QACnB,KAAK,EAAE,MAAM,CAAC;QACd,GAAG,EAAE,MAAM,CAAC;QACZ,KAAK,EAAE,MAAM,CAAC;KACf;IAQD;;;OAGG;WACW,UAAU,IAAI,IAAI;IAShC;;;OAGG;IACH,OAAO,CAAC,eAAe;IA2CV,IAAI,CACf,qBAAqB,CAAC,EAAE,yBAAyB,GAAG,uBAAuB,GAC1E,OAAO,CAAC,IAAI,CAAC;IAiGhB;;;OAGG;IACH,OAAO,CAAC,iBAAiB;IAmBzB;;;OAGG;YACW,iBAAiB;IA4D/B;;;OAGG;IACU,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC;IAiBzC;;OAEG;IACH,IAAW,WAAW,IAAI,OAAO,CAEhC;YAEa,gBAAgB;YAqHhB,yBAAyB;IA4F1B,OAAO,CAAC,CAAC,GAAG,OAAO,EAC9B,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACjC,SAAS,SAAO,GACf,OAAO,CAAC,CAAC,CAAC;IAuKA,IAAI,CACf,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAChC,OAAO,CAAC,IAAI,CAAC;IAkDhB,OAAO,CAAC,4BAA4B;IAmC7B,kBAAkB,CAAC,EAAE,EAAE,CAAC,SAAS,EAAE,OAAO,KAAK,IAAI,GAAG,IAAI;IAI1D,mBAAmB,CAAC,EAAE,EAAE,CAAC,SAAS,EAAE,OAAO,KAAK,IAAI,GAAG,IAAI;IAIrD,mBAAmB,IAAI,OAAO,CAAC,OAAO,CAAC;IAe7C,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAqBxC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA+CG;IACU,YAAY,CACvB,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,MAAM,GAAG,SAAS,EAC/B,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACpC,OAAO,EAAE,WAAW,EACpB,OAAO,CAAC,EAAE,WAAW,GACpB,OAAO,CAAC,IAAI,CAAC;IAiChB;;;OAGG;IACH,OAAO,CAAC,sBAAsB;IAqB9B;;;OAGG;YACW,oBAAoB;IA6BlC;;;;OAIG;IACU,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IA0B3D;;;OAGG;IACI,YAAY,CACjB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,CACR,IAAI,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI,KACrD,IAAI,GACR,MAAM,IAAI;IAIb;;OAEG;IACI,WAAW,CAChB,QAAQ,EAAE,MAAM,GACf;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI;IAIrD;;OAEG;IACI,cAAc,CAAC,QAAQ,EAAE,MAAM,GAClC,CAAC,cAAc,GAAG;QAChB,QAAQ,EAAE,MAAM,CAAC;QACjB,YAAY,EAAE,OAAO,CAAC;KACvB,CAAC,GACF,IAAI;IAIR;;OAEG;IACI,kBAAkB,IAAI,MAAM,EAAE;IAIrC;;OAEG;IACI,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;IAQlD;;OAEG;WACW,iBAAiB,IAAI,OAAO;IAI1C;;OAEG;IACI,iBAAiB,IAAI,OAAO;IAInC;;;;OAIG;IACI,gBAAgB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAgC/C;;OAEG;IACI,yBAAyB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;IAI3D;;OAEG;IACI,wBAAwB,IAAI,MAAM,EAAE;IAI3C;;;OAGG;YACW,cAAc;IAiC5B;;;OAGG;IACH,OAAO,CAAC,kBAAkB;CAmC3B"}
|