@mcp-b/global 1.2.1 → 1.3.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 +390 -0
- package/dist/index.d.ts +189 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.iife.js +32 -17
- package/dist/index.js +279 -189
- package/dist/index.js.map +1 -1
- package/package.json +21 -8
package/README.md
CHANGED
|
@@ -127,6 +127,316 @@ window.navigator.modelContext.provideContext({
|
|
|
127
127
|
});
|
|
128
128
|
```
|
|
129
129
|
|
|
130
|
+
## 📜 Traditional Web Standard Usage
|
|
131
|
+
|
|
132
|
+
The Web Model Context API follows the same patterns as other browser APIs. Here's how to use it as a traditional web standard:
|
|
133
|
+
|
|
134
|
+
### Basic Pattern (Vanilla JavaScript)
|
|
135
|
+
|
|
136
|
+
```html
|
|
137
|
+
<!DOCTYPE html>
|
|
138
|
+
<html>
|
|
139
|
+
<head>
|
|
140
|
+
<title>Web Model Context API Example</title>
|
|
141
|
+
<script src="https://unpkg.com/@mcp-b/global@latest/dist/index.iife.js"></script>
|
|
142
|
+
</head>
|
|
143
|
+
<body>
|
|
144
|
+
<h1>Counter App</h1>
|
|
145
|
+
<p>Count: <span id="count">0</span></p>
|
|
146
|
+
<button id="increment">+</button>
|
|
147
|
+
<button id="decrement">-</button>
|
|
148
|
+
|
|
149
|
+
<script>
|
|
150
|
+
// State
|
|
151
|
+
let count = 0;
|
|
152
|
+
|
|
153
|
+
// DOM elements
|
|
154
|
+
const countEl = document.getElementById('count');
|
|
155
|
+
const incrementBtn = document.getElementById('increment');
|
|
156
|
+
const decrementBtn = document.getElementById('decrement');
|
|
157
|
+
|
|
158
|
+
// Update UI
|
|
159
|
+
function updateUI() {
|
|
160
|
+
countEl.textContent = count;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// Button handlers
|
|
164
|
+
incrementBtn.addEventListener('click', () => { count++; updateUI(); });
|
|
165
|
+
decrementBtn.addEventListener('click', () => { count--; updateUI(); });
|
|
166
|
+
|
|
167
|
+
// Feature detection (like navigator.geolocation)
|
|
168
|
+
if ('modelContext' in navigator) {
|
|
169
|
+
// Register tools with the Web Model Context API
|
|
170
|
+
navigator.modelContext.provideContext({
|
|
171
|
+
tools: [
|
|
172
|
+
{
|
|
173
|
+
name: 'counter_get',
|
|
174
|
+
description: 'Get the current counter value',
|
|
175
|
+
inputSchema: { type: 'object', properties: {} },
|
|
176
|
+
execute: async () => ({
|
|
177
|
+
content: [{ type: 'text', text: String(count) }]
|
|
178
|
+
})
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
name: 'counter_set',
|
|
182
|
+
description: 'Set the counter to a specific value',
|
|
183
|
+
inputSchema: {
|
|
184
|
+
type: 'object',
|
|
185
|
+
properties: {
|
|
186
|
+
value: { type: 'number', description: 'The new counter value' }
|
|
187
|
+
},
|
|
188
|
+
required: ['value']
|
|
189
|
+
},
|
|
190
|
+
execute: async ({ value }) => {
|
|
191
|
+
count = value;
|
|
192
|
+
updateUI();
|
|
193
|
+
return {
|
|
194
|
+
content: [{ type: 'text', text: `Counter set to ${count}` }]
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
},
|
|
198
|
+
{
|
|
199
|
+
name: 'counter_increment',
|
|
200
|
+
description: 'Increment the counter by a specified amount',
|
|
201
|
+
inputSchema: {
|
|
202
|
+
type: 'object',
|
|
203
|
+
properties: {
|
|
204
|
+
amount: { type: 'number', description: 'Amount to increment by', default: 1 }
|
|
205
|
+
}
|
|
206
|
+
},
|
|
207
|
+
execute: async ({ amount = 1 }) => {
|
|
208
|
+
count += amount;
|
|
209
|
+
updateUI();
|
|
210
|
+
return {
|
|
211
|
+
content: [{ type: 'text', text: `Counter incremented to ${count}` }]
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
]
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
console.log('Web Model Context API: Tools registered');
|
|
219
|
+
} else {
|
|
220
|
+
console.warn('Web Model Context API not supported');
|
|
221
|
+
}
|
|
222
|
+
</script>
|
|
223
|
+
</body>
|
|
224
|
+
</html>
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
### Single Tool Registration Pattern
|
|
228
|
+
|
|
229
|
+
Like `navigator.permissions.query()`, you can register tools one at a time:
|
|
230
|
+
|
|
231
|
+
```javascript
|
|
232
|
+
// Feature detection
|
|
233
|
+
if ('modelContext' in navigator) {
|
|
234
|
+
// Register a single tool (returns an object with unregister method)
|
|
235
|
+
const registration = navigator.modelContext.registerTool({
|
|
236
|
+
name: 'get_page_info',
|
|
237
|
+
description: 'Get information about the current page',
|
|
238
|
+
inputSchema: { type: 'object', properties: {} },
|
|
239
|
+
execute: async () => ({
|
|
240
|
+
content: [{
|
|
241
|
+
type: 'text',
|
|
242
|
+
text: JSON.stringify({
|
|
243
|
+
title: document.title,
|
|
244
|
+
url: location.href,
|
|
245
|
+
timestamp: new Date().toISOString()
|
|
246
|
+
}, null, 2)
|
|
247
|
+
}]
|
|
248
|
+
})
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
// Later, unregister if needed (e.g., when component unmounts)
|
|
252
|
+
// registration.unregister();
|
|
253
|
+
}
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
### Event-Driven Pattern
|
|
257
|
+
|
|
258
|
+
Similar to other DOM events, you can listen for tool calls:
|
|
259
|
+
|
|
260
|
+
```javascript
|
|
261
|
+
if ('modelContext' in navigator) {
|
|
262
|
+
// Listen for tool calls (like 'message' or 'click' events)
|
|
263
|
+
navigator.modelContext.addEventListener('toolcall', (event) => {
|
|
264
|
+
console.log(`Tool "${event.name}" called with:`, event.arguments);
|
|
265
|
+
|
|
266
|
+
// Optionally intercept and provide custom response
|
|
267
|
+
if (event.name === 'custom_handler') {
|
|
268
|
+
event.preventDefault();
|
|
269
|
+
event.respondWith({
|
|
270
|
+
content: [{ type: 'text', text: 'Custom response' }]
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
});
|
|
274
|
+
}
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
### Complete Standalone Example
|
|
278
|
+
|
|
279
|
+
Save this as `index.html` and open in a browser:
|
|
280
|
+
|
|
281
|
+
```html
|
|
282
|
+
<!DOCTYPE html>
|
|
283
|
+
<html lang="en">
|
|
284
|
+
<head>
|
|
285
|
+
<meta charset="UTF-8">
|
|
286
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
287
|
+
<title>WebMCP Demo</title>
|
|
288
|
+
<script src="https://unpkg.com/@mcp-b/global@latest/dist/index.iife.js"></script>
|
|
289
|
+
<style>
|
|
290
|
+
body { font-family: system-ui; max-width: 600px; margin: 2rem auto; padding: 0 1rem; }
|
|
291
|
+
.card { border: 1px solid #ddd; border-radius: 8px; padding: 1rem; margin: 1rem 0; }
|
|
292
|
+
button { padding: 0.5rem 1rem; margin: 0.25rem; cursor: pointer; }
|
|
293
|
+
#log { font-family: monospace; font-size: 0.85rem; background: #f5f5f5; padding: 1rem; max-height: 200px; overflow-y: auto; }
|
|
294
|
+
</style>
|
|
295
|
+
</head>
|
|
296
|
+
<body>
|
|
297
|
+
<h1>🤖 WebMCP Demo</h1>
|
|
298
|
+
|
|
299
|
+
<div class="card">
|
|
300
|
+
<h2>Notes App</h2>
|
|
301
|
+
<input type="text" id="noteInput" placeholder="Enter a note..." style="width: 100%; padding: 0.5rem; box-sizing: border-box;">
|
|
302
|
+
<button id="addNote">Add Note</button>
|
|
303
|
+
<ul id="notesList"></ul>
|
|
304
|
+
</div>
|
|
305
|
+
|
|
306
|
+
<div class="card">
|
|
307
|
+
<h3>Tool Call Log</h3>
|
|
308
|
+
<div id="log">Waiting for AI tool calls...</div>
|
|
309
|
+
</div>
|
|
310
|
+
|
|
311
|
+
<script>
|
|
312
|
+
// Application state
|
|
313
|
+
const notes = [];
|
|
314
|
+
|
|
315
|
+
// DOM elements
|
|
316
|
+
const noteInput = document.getElementById('noteInput');
|
|
317
|
+
const addNoteBtn = document.getElementById('addNote');
|
|
318
|
+
const notesList = document.getElementById('notesList');
|
|
319
|
+
const logEl = document.getElementById('log');
|
|
320
|
+
|
|
321
|
+
// UI functions
|
|
322
|
+
function renderNotes() {
|
|
323
|
+
notesList.innerHTML = notes.map((note, i) =>
|
|
324
|
+
`<li>${note} <button onclick="deleteNote(${i})">×</button></li>`
|
|
325
|
+
).join('');
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
function log(message) {
|
|
329
|
+
const time = new Date().toLocaleTimeString();
|
|
330
|
+
logEl.innerHTML = `[${time}] ${message}\n` + logEl.innerHTML;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
// User interactions
|
|
334
|
+
addNoteBtn.addEventListener('click', () => {
|
|
335
|
+
if (noteInput.value.trim()) {
|
|
336
|
+
notes.push(noteInput.value.trim());
|
|
337
|
+
noteInput.value = '';
|
|
338
|
+
renderNotes();
|
|
339
|
+
}
|
|
340
|
+
});
|
|
341
|
+
|
|
342
|
+
window.deleteNote = (index) => {
|
|
343
|
+
notes.splice(index, 1);
|
|
344
|
+
renderNotes();
|
|
345
|
+
};
|
|
346
|
+
|
|
347
|
+
// Web Model Context API - Register tools for AI agents
|
|
348
|
+
if ('modelContext' in navigator) {
|
|
349
|
+
navigator.modelContext.provideContext({
|
|
350
|
+
tools: [
|
|
351
|
+
{
|
|
352
|
+
name: 'notes_list',
|
|
353
|
+
description: 'Get all notes',
|
|
354
|
+
inputSchema: { type: 'object', properties: {} },
|
|
355
|
+
execute: async () => {
|
|
356
|
+
log('🔧 notes_list called');
|
|
357
|
+
return {
|
|
358
|
+
content: [{
|
|
359
|
+
type: 'text',
|
|
360
|
+
text: notes.length ? notes.map((n, i) => `${i + 1}. ${n}`).join('\n') : 'No notes yet'
|
|
361
|
+
}]
|
|
362
|
+
};
|
|
363
|
+
}
|
|
364
|
+
},
|
|
365
|
+
{
|
|
366
|
+
name: 'notes_add',
|
|
367
|
+
description: 'Add a new note',
|
|
368
|
+
inputSchema: {
|
|
369
|
+
type: 'object',
|
|
370
|
+
properties: {
|
|
371
|
+
text: { type: 'string', description: 'The note text' }
|
|
372
|
+
},
|
|
373
|
+
required: ['text']
|
|
374
|
+
},
|
|
375
|
+
execute: async ({ text }) => {
|
|
376
|
+
log(`🔧 notes_add called: "${text}"`);
|
|
377
|
+
notes.push(text);
|
|
378
|
+
renderNotes();
|
|
379
|
+
return {
|
|
380
|
+
content: [{ type: 'text', text: `Added note: "${text}"` }]
|
|
381
|
+
};
|
|
382
|
+
}
|
|
383
|
+
},
|
|
384
|
+
{
|
|
385
|
+
name: 'notes_delete',
|
|
386
|
+
description: 'Delete a note by index (1-based)',
|
|
387
|
+
inputSchema: {
|
|
388
|
+
type: 'object',
|
|
389
|
+
properties: {
|
|
390
|
+
index: { type: 'number', description: 'Note index (1-based)' }
|
|
391
|
+
},
|
|
392
|
+
required: ['index']
|
|
393
|
+
},
|
|
394
|
+
execute: async ({ index }) => {
|
|
395
|
+
log(`🔧 notes_delete called: index ${index}`);
|
|
396
|
+
if (index < 1 || index > notes.length) {
|
|
397
|
+
return { content: [{ type: 'text', text: 'Invalid index' }], isError: true };
|
|
398
|
+
}
|
|
399
|
+
const deleted = notes.splice(index - 1, 1)[0];
|
|
400
|
+
renderNotes();
|
|
401
|
+
return {
|
|
402
|
+
content: [{ type: 'text', text: `Deleted: "${deleted}"` }]
|
|
403
|
+
};
|
|
404
|
+
}
|
|
405
|
+
},
|
|
406
|
+
{
|
|
407
|
+
name: 'notes_clear',
|
|
408
|
+
description: 'Delete all notes',
|
|
409
|
+
inputSchema: { type: 'object', properties: {} },
|
|
410
|
+
execute: async () => {
|
|
411
|
+
log('🔧 notes_clear called');
|
|
412
|
+
const count = notes.length;
|
|
413
|
+
notes.length = 0;
|
|
414
|
+
renderNotes();
|
|
415
|
+
return {
|
|
416
|
+
content: [{ type: 'text', text: `Cleared ${count} notes` }]
|
|
417
|
+
};
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
]
|
|
421
|
+
});
|
|
422
|
+
|
|
423
|
+
log('✅ Web Model Context API initialized');
|
|
424
|
+
log('📋 Tools: notes_list, notes_add, notes_delete, notes_clear');
|
|
425
|
+
} else {
|
|
426
|
+
log('❌ Web Model Context API not available');
|
|
427
|
+
}
|
|
428
|
+
</script>
|
|
429
|
+
</body>
|
|
430
|
+
</html>
|
|
431
|
+
```
|
|
432
|
+
|
|
433
|
+
This example demonstrates:
|
|
434
|
+
- **Feature detection** using `'modelContext' in navigator`
|
|
435
|
+
- **Tool registration** via `navigator.modelContext.provideContext()`
|
|
436
|
+
- **Standard input schemas** following JSON Schema specification
|
|
437
|
+
- **Async execute functions** returning MCP-compatible responses
|
|
438
|
+
- **Real-time UI updates** when AI agents call tools
|
|
439
|
+
|
|
130
440
|
## ⚙️ Configuration
|
|
131
441
|
|
|
132
442
|
The polyfill exposes `initializeWebModelContext(options?: WebModelContextInitOptions)` to let you control transport behaviour. When you import `@mcp-b/global` as a module it auto-initializes by default, but you can customise or defer initialization:
|
|
@@ -1011,6 +1321,43 @@ if ("modelContext" in navigator) {
|
|
|
1011
1321
|
|
|
1012
1322
|
## 🐛 Debugging
|
|
1013
1323
|
|
|
1324
|
+
### Enable Debug Logging
|
|
1325
|
+
|
|
1326
|
+
The @mcp-b/global library includes a lightweight logging system that can be enabled in the browser console. By default, the console is kept clean (only errors and warnings are shown). You can enable detailed debug logging when troubleshooting:
|
|
1327
|
+
|
|
1328
|
+
```javascript
|
|
1329
|
+
// Enable all debug logging
|
|
1330
|
+
localStorage.setItem('WEBMCP_DEBUG', '*');
|
|
1331
|
+
|
|
1332
|
+
// Enable specific namespaces
|
|
1333
|
+
localStorage.setItem('WEBMCP_DEBUG', 'WebModelContext');
|
|
1334
|
+
localStorage.setItem('WEBMCP_DEBUG', 'NativeAdapter,MCPBridge');
|
|
1335
|
+
|
|
1336
|
+
// Refresh the page to apply changes
|
|
1337
|
+
location.reload();
|
|
1338
|
+
```
|
|
1339
|
+
|
|
1340
|
+
To disable debug logging:
|
|
1341
|
+
|
|
1342
|
+
```javascript
|
|
1343
|
+
localStorage.removeItem('WEBMCP_DEBUG');
|
|
1344
|
+
location.reload();
|
|
1345
|
+
```
|
|
1346
|
+
|
|
1347
|
+
**Available Namespaces:**
|
|
1348
|
+
- `WebModelContext` - Main polyfill implementation
|
|
1349
|
+
- `NativeAdapter` - Native Chromium API adapter
|
|
1350
|
+
- `MCPBridge` - MCP server and transport setup
|
|
1351
|
+
- `ModelContextTesting` - Testing API operations
|
|
1352
|
+
|
|
1353
|
+
**Log Levels:**
|
|
1354
|
+
- **Error** (always shown): Critical failures and exceptions
|
|
1355
|
+
- **Warn** (always shown): Compatibility warnings and potential issues
|
|
1356
|
+
- **Info** (debug mode only): Initialization and setup progress
|
|
1357
|
+
- **Debug** (debug mode only): Detailed operation traces
|
|
1358
|
+
|
|
1359
|
+
### Access Internal Bridge
|
|
1360
|
+
|
|
1014
1361
|
In development mode, access the internal bridge:
|
|
1015
1362
|
|
|
1016
1363
|
```javascript
|
|
@@ -1248,6 +1595,49 @@ test('todo tool creates correct response', async () => {
|
|
|
1248
1595
|
|
|
1249
1596
|
The polyfill automatically detects and defers to the native implementation when available, ensuring forward compatibility as browsers adopt this standard.
|
|
1250
1597
|
|
|
1598
|
+
## Zod Version Compatibility
|
|
1599
|
+
|
|
1600
|
+
This package supports **Zod 3.25+** and **Zod 4.x**. Simply use the standard import:
|
|
1601
|
+
|
|
1602
|
+
```typescript
|
|
1603
|
+
import { z } from 'zod';
|
|
1604
|
+
|
|
1605
|
+
window.navigator.modelContext.provideContext({
|
|
1606
|
+
tools: [{
|
|
1607
|
+
name: "my-tool",
|
|
1608
|
+
inputSchema: {
|
|
1609
|
+
name: z.string().describe('User name'),
|
|
1610
|
+
age: z.number().min(0)
|
|
1611
|
+
},
|
|
1612
|
+
async execute({ name, age }) {
|
|
1613
|
+
return { content: [{ type: "text", text: `Hello, ${name}!` }] };
|
|
1614
|
+
}
|
|
1615
|
+
}]
|
|
1616
|
+
});
|
|
1617
|
+
```
|
|
1618
|
+
|
|
1619
|
+
### JSON Schema Alternative
|
|
1620
|
+
|
|
1621
|
+
JSON Schema is also supported if you prefer not to use Zod:
|
|
1622
|
+
|
|
1623
|
+
```javascript
|
|
1624
|
+
window.navigator.modelContext.provideContext({
|
|
1625
|
+
tools: [{
|
|
1626
|
+
name: "my-tool",
|
|
1627
|
+
inputSchema: {
|
|
1628
|
+
type: "object",
|
|
1629
|
+
properties: {
|
|
1630
|
+
name: { type: "string" }
|
|
1631
|
+
},
|
|
1632
|
+
required: ["name"]
|
|
1633
|
+
},
|
|
1634
|
+
async execute({ name }) {
|
|
1635
|
+
return { content: [{ type: "text", text: `Hello, ${name}!` }] };
|
|
1636
|
+
}
|
|
1637
|
+
}]
|
|
1638
|
+
});
|
|
1639
|
+
```
|
|
1640
|
+
|
|
1251
1641
|
## 📦 What's Included
|
|
1252
1642
|
|
|
1253
1643
|
- **Web Model Context API** - Standard `window.navigator.modelContext` interface
|
package/dist/index.d.ts
CHANGED
|
@@ -65,6 +65,146 @@ type ZodSchemaObject = Record<string, z.ZodTypeAny>;
|
|
|
65
65
|
* @see {@link CallToolResult}
|
|
66
66
|
*/
|
|
67
67
|
type ToolResponse = CallToolResult;
|
|
68
|
+
/**
|
|
69
|
+
* Metadata for tools that trigger page navigation.
|
|
70
|
+
*
|
|
71
|
+
* When a tool needs to navigate the page (e.g., to a different URL), it must include
|
|
72
|
+
* this metadata in its response to signal the navigation intent to the client. This
|
|
73
|
+
* allows the client to distinguish between successful navigation and interrupted execution.
|
|
74
|
+
*
|
|
75
|
+
* **CRITICAL PATTERN**: Tools MUST return their response BEFORE triggering navigation.
|
|
76
|
+
* Use `setTimeout()` with a minimum 100ms delay to ensure the response is transmitted
|
|
77
|
+
* via `postMessage` and received by the client before the page unloads.
|
|
78
|
+
*
|
|
79
|
+
* **Why the pattern is necessary**: During page navigation, the JavaScript context
|
|
80
|
+
* is destroyed. If navigation occurs before the response is sent, the client will
|
|
81
|
+
* never receive the tool's result and cannot distinguish success from failure.
|
|
82
|
+
*
|
|
83
|
+
* @example Correct pattern - Response before navigation
|
|
84
|
+
* ```typescript
|
|
85
|
+
* navigator.modelContext.registerTool({
|
|
86
|
+
* name: 'navigate_to_docs',
|
|
87
|
+
* description: 'Navigate to documentation page',
|
|
88
|
+
* inputSchema: { section: z.string() },
|
|
89
|
+
* async execute(args) {
|
|
90
|
+
* const url = `https://docs.example.com/${args.section}`;
|
|
91
|
+
*
|
|
92
|
+
* // 1. Prepare response with navigation metadata
|
|
93
|
+
* const response = {
|
|
94
|
+
* content: [{ type: 'text', text: `Navigating to ${url}` }],
|
|
95
|
+
* metadata: {
|
|
96
|
+
* willNavigate: true,
|
|
97
|
+
* navigationUrl: url,
|
|
98
|
+
* navigationTiming: 'immediate',
|
|
99
|
+
* },
|
|
100
|
+
* };
|
|
101
|
+
*
|
|
102
|
+
* // 2. Schedule navigation AFTER response is returned (100ms minimum)
|
|
103
|
+
* setTimeout(() => {
|
|
104
|
+
* window.location.href = url;
|
|
105
|
+
* }, 100);
|
|
106
|
+
*
|
|
107
|
+
* // 3. Return response BEFORE navigation occurs
|
|
108
|
+
* return response;
|
|
109
|
+
* },
|
|
110
|
+
* });
|
|
111
|
+
* ```
|
|
112
|
+
*
|
|
113
|
+
* @example Anti-pattern - Navigation before response (DO NOT DO THIS)
|
|
114
|
+
* ```typescript
|
|
115
|
+
* // ❌ WRONG - Response will be lost during navigation
|
|
116
|
+
* async execute(args) {
|
|
117
|
+
* window.location.href = computeUrl(args); // Navigation happens first
|
|
118
|
+
* return { content: [...] }; // This response is never received!
|
|
119
|
+
* }
|
|
120
|
+
* ```
|
|
121
|
+
*
|
|
122
|
+
* @see {@link InterruptionMetadata} for metadata added when navigation interrupts execution
|
|
123
|
+
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage} for postMessage timing
|
|
124
|
+
*/
|
|
125
|
+
interface NavigationMetadata {
|
|
126
|
+
/**
|
|
127
|
+
* Indicates this tool will trigger page navigation.
|
|
128
|
+
* This flag signals to the client that the tool succeeded and navigation is expected.
|
|
129
|
+
*/
|
|
130
|
+
willNavigate: true;
|
|
131
|
+
/**
|
|
132
|
+
* The URL the page will navigate to (if known).
|
|
133
|
+
* Helps clients track navigation targets.
|
|
134
|
+
*/
|
|
135
|
+
navigationUrl?: string;
|
|
136
|
+
/**
|
|
137
|
+
* When navigation will occur relative to the response.
|
|
138
|
+
* - 'immediate': Navigation scheduled immediately after return (within ~100ms)
|
|
139
|
+
* - 'delayed': Navigation will occur after some delay (see navigationDelayMs)
|
|
140
|
+
* @default 'immediate'
|
|
141
|
+
*/
|
|
142
|
+
navigationTiming?: 'immediate' | 'delayed';
|
|
143
|
+
/**
|
|
144
|
+
* Expected delay in milliseconds before navigation (if timing='delayed').
|
|
145
|
+
* Only meaningful when navigationTiming is 'delayed'.
|
|
146
|
+
*/
|
|
147
|
+
navigationDelayMs?: number;
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Metadata indicating a tool call was interrupted by page navigation.
|
|
151
|
+
*
|
|
152
|
+
* This metadata is automatically added by the transport layer (`TabServerTransport`)
|
|
153
|
+
* when a page navigation occurs while a tool is executing. The transport layer's
|
|
154
|
+
* `beforeunload` event handler detects the navigation and sends an interrupted
|
|
155
|
+
* response for any pending tool calls.
|
|
156
|
+
*
|
|
157
|
+
* **When this occurs**:
|
|
158
|
+
* - User clicks browser back/forward buttons during tool execution
|
|
159
|
+
* - User manually navigates to a different URL
|
|
160
|
+
* - Tool triggers immediate navigation without following the response-first pattern
|
|
161
|
+
* - Page is reloaded or closed during tool execution
|
|
162
|
+
*
|
|
163
|
+
* **How to distinguish from successful navigation**:
|
|
164
|
+
* - Tool succeeded and navigated: Response includes `NavigationMetadata` with `willNavigate: true`
|
|
165
|
+
* - Tool was interrupted: Response includes `InterruptionMetadata` with `navigationInterrupted: true`
|
|
166
|
+
*
|
|
167
|
+
* **Client handling**:
|
|
168
|
+
* ```typescript
|
|
169
|
+
* const response = await client.callTool('my_tool', args);
|
|
170
|
+
*
|
|
171
|
+
* if (response.metadata?.willNavigate) {
|
|
172
|
+
* // Tool succeeded and will navigate - expected behavior
|
|
173
|
+
* console.log('Tool navigated successfully');
|
|
174
|
+
* } else if (response.metadata?.navigationInterrupted) {
|
|
175
|
+
* // Tool was interrupted - may not have completed
|
|
176
|
+
* console.warn('Tool execution interrupted by navigation');
|
|
177
|
+
* } else {
|
|
178
|
+
* // Normal tool response - no navigation
|
|
179
|
+
* console.log('Tool completed normally');
|
|
180
|
+
* }
|
|
181
|
+
* ```
|
|
182
|
+
*
|
|
183
|
+
* @see {@link NavigationMetadata} for metadata indicating intentional navigation
|
|
184
|
+
* @see {@link TabServerTransport._handleBeforeUnload} for the implementation
|
|
185
|
+
* @internal This metadata is added automatically by the transport layer
|
|
186
|
+
*/
|
|
187
|
+
interface InterruptionMetadata {
|
|
188
|
+
/**
|
|
189
|
+
* Indicates the tool execution was interrupted by page navigation.
|
|
190
|
+
* When `true`, the tool may not have completed its operation successfully.
|
|
191
|
+
*/
|
|
192
|
+
navigationInterrupted: true;
|
|
193
|
+
/**
|
|
194
|
+
* The original JSON-RPC method that was interrupted.
|
|
195
|
+
* Typically `'tools/call'` for tool invocations, but could be other MCP methods.
|
|
196
|
+
*
|
|
197
|
+
* @example 'tools/call' | 'resources/read' | 'prompts/get'
|
|
198
|
+
*/
|
|
199
|
+
originalMethod: string;
|
|
200
|
+
/**
|
|
201
|
+
* Unix timestamp (milliseconds since epoch) when the interruption was detected.
|
|
202
|
+
* Useful for logging, debugging, and understanding the timeline of events.
|
|
203
|
+
*
|
|
204
|
+
* @example 1704067200000 (January 1, 2024, 00:00:00 UTC)
|
|
205
|
+
*/
|
|
206
|
+
timestamp: number;
|
|
207
|
+
}
|
|
68
208
|
/**
|
|
69
209
|
* Transport configuration for initializing the Web Model Context polyfill.
|
|
70
210
|
*
|
|
@@ -712,9 +852,15 @@ interface ModelContext {
|
|
|
712
852
|
interface InternalModelContext extends ModelContext {
|
|
713
853
|
/**
|
|
714
854
|
* Execute a tool (internal use only by MCP bridge)
|
|
855
|
+
* @param toolName - Name of the tool to execute
|
|
856
|
+
* @param args - Arguments to pass to the tool
|
|
857
|
+
* @param options - Optional execution options
|
|
858
|
+
* @param options.skipValidation - Skip input validation (used when SDK already validated)
|
|
715
859
|
* @internal
|
|
716
860
|
*/
|
|
717
|
-
executeTool(toolName: string, args: Record<string, unknown
|
|
861
|
+
executeTool(toolName: string, args: Record<string, unknown>, options?: {
|
|
862
|
+
skipValidation?: boolean;
|
|
863
|
+
}): Promise<ToolResponse>;
|
|
718
864
|
/**
|
|
719
865
|
* Read a resource by URI (internal use only by MCP bridge)
|
|
720
866
|
* @internal
|
|
@@ -907,15 +1053,50 @@ declare function initializeWebModelContext(options?: WebModelContextInitOptions)
|
|
|
907
1053
|
*/
|
|
908
1054
|
declare function cleanupWebModelContext(): void;
|
|
909
1055
|
//#endregion
|
|
910
|
-
//#region src/
|
|
1056
|
+
//#region src/logger.d.ts
|
|
1057
|
+
/**
|
|
1058
|
+
* @license
|
|
1059
|
+
* Copyright 2025 Google LLC
|
|
1060
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
1061
|
+
*/
|
|
911
1062
|
/**
|
|
912
|
-
*
|
|
913
|
-
* Uses zod-to-json-schema package for comprehensive conversion
|
|
1063
|
+
* Logger interface with standard log levels
|
|
914
1064
|
*
|
|
915
|
-
*
|
|
916
|
-
*
|
|
1065
|
+
* All methods accept the same argument patterns as their console.* equivalents,
|
|
1066
|
+
* supporting format strings, object inspection, and multiple arguments.
|
|
917
1067
|
*/
|
|
918
|
-
|
|
1068
|
+
interface Logger {
|
|
1069
|
+
/** Debug-level logging (disabled by default, enable via WEBMCP_DEBUG) */
|
|
1070
|
+
debug(message?: unknown, ...optionalParams: unknown[]): void;
|
|
1071
|
+
/** Info-level logging (disabled by default, enable via WEBMCP_DEBUG) */
|
|
1072
|
+
info(message?: unknown, ...optionalParams: unknown[]): void;
|
|
1073
|
+
/** Warning-level logging (enabled by default, not gated by WEBMCP_DEBUG) */
|
|
1074
|
+
warn(message?: unknown, ...optionalParams: unknown[]): void;
|
|
1075
|
+
/** Error-level logging (enabled by default, not gated by WEBMCP_DEBUG) */
|
|
1076
|
+
error(message?: unknown, ...optionalParams: unknown[]): void;
|
|
1077
|
+
}
|
|
1078
|
+
/**
|
|
1079
|
+
* Create a namespaced logger
|
|
1080
|
+
*
|
|
1081
|
+
* Uses .bind() to prepend namespace prefixes to console methods without manual
|
|
1082
|
+
* string concatenation. Debug enablement is determined at logger creation time
|
|
1083
|
+
* for performance - changes to localStorage after creation won't affect existing
|
|
1084
|
+
* loggers. Refresh the page to apply new WEBMCP_DEBUG settings.
|
|
1085
|
+
*
|
|
1086
|
+
* @param namespace - Namespace for the logger (e.g., 'WebModelContext', 'NativeAdapter')
|
|
1087
|
+
* @returns Logger instance with debug, info, warn, error methods
|
|
1088
|
+
*
|
|
1089
|
+
* @example
|
|
1090
|
+
* ```typescript
|
|
1091
|
+
* const logger = createLogger('WebModelContext');
|
|
1092
|
+
* logger.debug('Tool registered:', toolName); // Only shown if WEBMCP_DEBUG includes 'WebModelContext'
|
|
1093
|
+
* logger.error('Execution failed:', error); // Always enabled
|
|
1094
|
+
* ```
|
|
1095
|
+
*/
|
|
1096
|
+
declare function createLogger(namespace: string): Logger;
|
|
1097
|
+
//#endregion
|
|
1098
|
+
//#region src/validation.d.ts
|
|
1099
|
+
declare function zodToJsonSchema(schema: ZodSchemaObject): InputSchema;
|
|
919
1100
|
//#endregion
|
|
920
|
-
export { type CallToolResult, type CreateMessageRequest, type CreateMessageResult, type ElicitRequest, type ElicitResult, ElicitationFormParams, ElicitationParams, ElicitationResult, ElicitationUrlParams, InputSchema, InternalModelContext, MCPBridge, ModelContext, ModelContextInput, ModelContextTesting, type Prompt, PromptDescriptor, type PromptMessage, RegistrationHandle, type Resource, type ResourceContents, ResourceDescriptor, type ResourceTemplate, ResourceTemplateInfo, SamplingRequestParams, SamplingResult, type ToolAnnotations, ToolCallEvent, ToolDescriptor, ToolInfo, ToolListItem, ToolResponse, TransportConfiguration, ValidatedPromptDescriptor, ValidatedResourceDescriptor, ValidatedToolDescriptor, WebModelContextInitOptions, ZodSchemaObject, cleanupWebModelContext, initializeWebModelContext, zodToJsonSchema };
|
|
1101
|
+
export { type CallToolResult, type CreateMessageRequest, type CreateMessageResult, type ElicitRequest, type ElicitResult, ElicitationFormParams, ElicitationParams, ElicitationResult, ElicitationUrlParams, InputSchema, InternalModelContext, InterruptionMetadata, MCPBridge, ModelContext, ModelContextInput, ModelContextTesting, NavigationMetadata, type Prompt, PromptDescriptor, type PromptMessage, RegistrationHandle, type Resource, type ResourceContents, ResourceDescriptor, type ResourceTemplate, ResourceTemplateInfo, SamplingRequestParams, SamplingResult, type ToolAnnotations, ToolCallEvent, ToolDescriptor, ToolInfo, ToolListItem, ToolResponse, TransportConfiguration, ValidatedPromptDescriptor, ValidatedResourceDescriptor, ValidatedToolDescriptor, WebModelContextInitOptions, ZodSchemaObject, cleanupWebModelContext, createLogger, initializeWebModelContext, zodToJsonSchema };
|
|
921
1102
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/types.ts","../src/global.ts","../src/validation.ts"],"sourcesContent":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/types.ts","../src/global.ts","../src/logger.ts","../src/validation.ts"],"sourcesContent":[],"mappings":"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"}
|