@mcp-b/global 2.1.0 → 2.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -14,14 +14,14 @@
14
14
 
15
15
  ## Why Use @mcp-b/global?
16
16
 
17
- | Feature | Benefit |
18
- |---------|---------|
19
- | **W3C Standard** | Implements the emerging Web Model Context API specification |
20
- | **Drop-in IIFE** | Add AI capabilities with a single `<script>` tag - no build step |
21
- | **Native Chromium Support** | Auto-detects and uses native browser implementation when available |
22
- | **Dual Transport** | Works with both same-window clients AND parent pages (iframe support) |
23
- | **Strict Core Semantics** | `provideContext()` replaces tool context and `registerTool()` is name-based |
24
- | **Works with Any AI** | Claude, ChatGPT, Gemini, Cursor, Copilot, and any MCP client |
17
+ | Feature | Benefit |
18
+ | ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
19
+ | **W3C Standard** | Implements the emerging Web Model Context API specification |
20
+ | **Drop-in IIFE** | Add AI capabilities with a single `<script>` tag - no build step |
21
+ | **Native Chromium Support** | Auto-detects and uses native browser implementation when available |
22
+ | **Dual Transport** | Works with both same-window clients AND parent pages (iframe support) |
23
+ | **Spec-Aware Compatibility** | Tracks the April 23, 2026 WebMCP draft (`registerTool(tool, { signal })`). Deprecated APIs `provideContext()`, `clearContext()`, `unregisterTool(name)`, and the `{ unregister }` return handle are still functional but emit one-time warnings and will be removed in the next major version. |
24
+ | **Works with Any AI** | Claude, ChatGPT, Gemini, Cursor, Copilot, and any MCP client |
25
25
 
26
26
  ## Package Selection
27
27
 
@@ -36,29 +36,25 @@
36
36
  ```html
37
37
  <!DOCTYPE html>
38
38
  <html>
39
- <head>
40
- <script src="https://unpkg.com/@mcp-b/global@latest/dist/index.iife.js"></script>
41
- </head>
42
- <body>
43
- <h1>My AI-Powered App</h1>
44
-
45
- <script>
46
- navigator.modelContext.provideContext({
47
- tools: [
48
- {
49
- name: "get-page-title",
50
- description: "Get the current page title",
51
- inputSchema: { type: "object", properties: {} },
52
- async execute() {
53
- return {
54
- content: [{ type: "text", text: document.title }]
55
- };
56
- }
57
- }
58
- ]
59
- });
60
- </script>
61
- </body>
39
+ <head>
40
+ <script src="https://unpkg.com/@mcp-b/global@latest/dist/index.iife.js"></script>
41
+ </head>
42
+ <body>
43
+ <h1>My AI-Powered App</h1>
44
+
45
+ <script>
46
+ navigator.modelContext.registerTool({
47
+ name: 'get-page-title',
48
+ description: 'Get the current page title',
49
+ inputSchema: { type: 'object', properties: {} },
50
+ async execute() {
51
+ return {
52
+ content: [{ type: 'text', text: document.title }],
53
+ };
54
+ },
55
+ });
56
+ </script>
57
+ </body>
62
58
  </html>
63
59
  ```
64
60
 
@@ -71,7 +67,9 @@
71
67
  ```html
72
68
  <script type="module">
73
69
  import '@mcp-b/global';
74
- navigator.modelContext.provideContext({ tools: [/* your tools */] });
70
+ navigator.modelContext.registerTool({
71
+ /* your tool */
72
+ });
75
73
  </script>
76
74
  ```
77
75
 
@@ -86,8 +84,8 @@ npm install @mcp-b/global
86
84
  ```javascript
87
85
  import '@mcp-b/global';
88
86
 
89
- navigator.modelContext.provideContext({
90
- tools: [/* your tools */]
87
+ navigator.modelContext.registerTool({
88
+ /* your tool */
91
89
  });
92
90
  ```
93
91
 
@@ -111,6 +109,7 @@ initializeWebModelContext({
111
109
  ```
112
110
 
113
111
  **Behavior:**
112
+
114
113
  - Only operates in browser environments
115
114
  - Idempotent - calling multiple times is a no-op after first initialization
116
115
  - Preserves native `navigator.modelContext` by default (configurable)
@@ -137,6 +136,8 @@ After initialization, `navigator.modelContext` exposes these methods:
137
136
 
138
137
  #### `provideContext(options?)`
139
138
 
139
+ Deprecated compatibility API. The upstream WebMCP spec removed `provideContext()` on March 5, 2026. `@mcp-b/global` keeps it functional for now, but logs a deprecation warning and will remove it in the next major version.
140
+
140
141
  Replaces all currently registered tools with a new set. This is an atomic replacement - all previous tools are removed first.
141
142
 
142
143
  ```typescript
@@ -174,34 +175,43 @@ navigator.modelContext.provideContext({
174
175
  });
175
176
  ```
176
177
 
177
- #### `registerTool(tool)`
178
+ #### `registerTool(tool, options?)`
178
179
 
179
- Registers a single tool. The tool name must be unique - throws if a tool with the same name already exists.
180
+ Registers a single tool. The tool name must be unique, otherwise throws if a tool with the same name already exists. The recommended unregistration path is `options.signal` (`AbortSignal`):
180
181
 
181
182
  ```typescript
182
- navigator.modelContext.registerTool({
183
- name: 'add-to-cart',
184
- description: 'Add a product to the shopping cart',
185
- inputSchema: {
186
- type: 'object',
187
- properties: {
188
- productId: { type: 'string' },
189
- quantity: { type: 'integer' },
183
+ const ac = new AbortController();
184
+ navigator.modelContext.registerTool(
185
+ {
186
+ name: 'add-to-cart',
187
+ description: 'Add a product to the shopping cart',
188
+ inputSchema: {
189
+ type: 'object',
190
+ properties: {
191
+ productId: { type: 'string' },
192
+ quantity: { type: 'integer' },
193
+ },
194
+ required: ['productId'],
195
+ },
196
+ async execute(args) {
197
+ const item = await addToCart(args.productId, args.quantity ?? 1);
198
+ return {
199
+ content: [{ type: 'text', text: `Added ${item.name} to cart` }],
200
+ };
190
201
  },
191
- required: ['productId'],
192
- },
193
- async execute(args) {
194
- const item = await addToCart(args.productId, args.quantity ?? 1);
195
- return {
196
- content: [{ type: 'text', text: `Added ${item.name} to cart` }],
197
- };
198
202
  },
199
- });
203
+ { signal: ac.signal }
204
+ );
205
+
206
+ // Later — clean up:
207
+ ac.abort();
200
208
  ```
201
209
 
202
- #### `unregisterTool(name)`
210
+ For backwards compatibility, `@mcp-b/global` also returns a deprecated `{ unregister }` handle so existing MCP-B integrations do not break, even though current Chromium and the WebMCP spec return `undefined`. The handle will be removed in the next major version.
211
+
212
+ #### `unregisterTool(nameOrTool)` (deprecated)
203
213
 
204
- Removes a tool by name.
214
+ Removes a tool by name. The April 23, 2026 WebMCP draft removed `unregisterTool` from the spec in favor of `AbortSignal` on `registerTool`. `@mcp-b/global` keeps `unregisterTool` functional for compatibility with older native previews and existing MCP-B integrations, and emits a one-time deprecation warning when called. It will be removed in the next major version.
205
215
 
206
216
  ```typescript
207
217
  navigator.modelContext.unregisterTool('add-to-cart');
@@ -209,6 +219,8 @@ navigator.modelContext.unregisterTool('add-to-cart');
209
219
 
210
220
  #### `clearContext()`
211
221
 
222
+ Deprecated compatibility API. The upstream WebMCP spec removed `clearContext()` on March 5, 2026. `@mcp-b/global` keeps it functional for now, but logs a deprecation warning and will remove it in the next major version.
223
+
212
224
  Removes all registered tools.
213
225
 
214
226
  ```typescript
@@ -238,14 +250,14 @@ const result = await navigator.modelContext.callTool({
238
250
 
239
251
  ### Tool Descriptor
240
252
 
241
- | Property | Type | Required | Description |
242
- |----------|------|----------|-------------|
243
- | `name` | `string` | Yes | Unique identifier for the tool |
244
- | `description` | `string` | Yes | Natural language description of what the tool does |
245
- | `inputSchema` | `InputSchema` | No | JSON Schema describing accepted input. Defaults to `{ type: 'object', properties: {} }` |
246
- | `outputSchema` | `InputSchema` | No | JSON Schema describing the output payload shape |
247
- | `annotations` | `ToolAnnotations` | No | Hints about tool behavior for LLM planners |
248
- | `execute` | `(args, client) => Promise<ToolResponse>` | Yes | Async function implementing the tool logic |
253
+ | Property | Type | Required | Description |
254
+ | -------------- | ----------------------------------------- | -------- | --------------------------------------------------------------------------------------- |
255
+ | `name` | `string` | Yes | Unique identifier for the tool |
256
+ | `description` | `string` | Yes | Natural language description of what the tool does |
257
+ | `inputSchema` | `InputSchema` | No | JSON Schema describing accepted input. Defaults to `{ type: 'object', properties: {} }` |
258
+ | `outputSchema` | `InputSchema` | No | JSON Schema describing the output payload shape |
259
+ | `annotations` | `ToolAnnotations` | No | Hints about tool behavior for LLM planners |
260
+ | `execute` | `(args, client) => Promise<ToolResponse>` | Yes | Async function implementing the tool logic |
249
261
 
250
262
  ### Tool Response Format
251
263
 
@@ -277,12 +289,12 @@ interface WebModelContextInitOptions {
277
289
  }
278
290
  ```
279
291
 
280
- | Option | Default | Description |
281
- |--------|---------|-------------|
282
- | `transport` | Auto-detect | Transport layer configuration (tab server and/or iframe) |
283
- | `autoInitialize` | `true` | Whether to auto-initialize on import |
284
- | `nativeModelContextBehavior` | `'preserve'` | `'preserve'` keeps native implementation untouched. `'patch'` replaces it with a BrowserMcpServer that mirrors to the native object |
285
- | `installTestingShim` | `'if-missing'` | Controls `navigator.modelContextTesting` installation. Only installs when not already present natively |
292
+ | Option | Default | Description |
293
+ | ---------------------------- | -------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
294
+ | `transport` | Auto-detect | Transport layer configuration (tab server and/or iframe) |
295
+ | `autoInitialize` | `true` | Whether to auto-initialize on import |
296
+ | `nativeModelContextBehavior` | `'preserve'` | `'preserve'` keeps native implementation untouched. `'patch'` replaces it with a BrowserMcpServer that mirrors to the native object |
297
+ | `installTestingShim` | `'if-missing'` | Controls `navigator.modelContextTesting` installation. Only installs when not already present natively |
286
298
 
287
299
  ### Transport Configuration
288
300
 
@@ -364,7 +376,9 @@ const result = await navigator.modelContextTesting?.executeTool(
364
376
 
365
377
  ```javascript
366
378
  if ('modelContext' in navigator) {
367
- navigator.modelContext.provideContext({ tools: [...] });
379
+ navigator.modelContext.registerTool({
380
+ /* your tool */
381
+ });
368
382
  }
369
383
  ```
370
384
 
@@ -375,45 +389,44 @@ if ('modelContext' in navigator) {
375
389
  ```typescript
376
390
  import '@mcp-b/global';
377
391
 
378
- navigator.modelContext.provideContext({
379
- tools: [
380
- {
381
- name: 'search-products',
382
- description: 'Search products by keyword, category, or price range',
383
- inputSchema: {
384
- type: 'object',
385
- properties: {
386
- query: { type: 'string', description: 'Search terms' },
387
- category: { type: 'string', description: 'Product category' },
388
- maxPrice: { type: 'number', description: 'Maximum price filter' },
389
- },
390
- required: ['query'],
391
- },
392
- async execute(args) {
393
- const results = await fetch(`/api/products?q=${args.query}&cat=${args.category ?? ''}&max=${args.maxPrice ?? ''}`);
394
- return { content: [{ type: 'text', text: await results.text() }] };
395
- },
392
+ navigator.modelContext.registerTool({
393
+ name: 'search-products',
394
+ description: 'Search products by keyword, category, or price range',
395
+ inputSchema: {
396
+ type: 'object',
397
+ properties: {
398
+ query: { type: 'string', description: 'Search terms' },
399
+ category: { type: 'string', description: 'Product category' },
400
+ maxPrice: { type: 'number', description: 'Maximum price filter' },
396
401
  },
397
- {
398
- name: 'add-to-cart',
399
- description: 'Add a product to the shopping cart',
400
- inputSchema: {
401
- type: 'object',
402
- properties: {
403
- productId: { type: 'string' },
404
- quantity: { type: 'integer' },
405
- },
406
- required: ['productId'],
407
- },
408
- async execute(args) {
409
- await fetch('/api/cart', {
410
- method: 'POST',
411
- body: JSON.stringify({ productId: args.productId, quantity: args.quantity ?? 1 }),
412
- });
413
- return { content: [{ type: 'text', text: `Added to cart` }] };
414
- },
402
+ required: ['query'],
403
+ },
404
+ async execute(args) {
405
+ const results = await fetch(
406
+ `/api/products?q=${args.query}&cat=${args.category ?? ''}&max=${args.maxPrice ?? ''}`
407
+ );
408
+ return { content: [{ type: 'text', text: await results.text() }] };
409
+ },
410
+ });
411
+
412
+ navigator.modelContext.registerTool({
413
+ name: 'add-to-cart',
414
+ description: 'Add a product to the shopping cart',
415
+ inputSchema: {
416
+ type: 'object',
417
+ properties: {
418
+ productId: { type: 'string' },
419
+ quantity: { type: 'integer' },
415
420
  },
416
- ],
421
+ required: ['productId'],
422
+ },
423
+ async execute(args) {
424
+ await fetch('/api/cart', {
425
+ method: 'POST',
426
+ body: JSON.stringify({ productId: args.productId, quantity: args.quantity ?? 1 }),
427
+ });
428
+ return { content: [{ type: 'text', text: `Added to cart` }] };
429
+ },
417
430
  });
418
431
  ```
419
432
 
@@ -423,17 +436,13 @@ navigator.modelContext.provideContext({
423
436
  import '@mcp-b/global';
424
437
 
425
438
  // Start with base tools
426
- navigator.modelContext.provideContext({
427
- tools: [
428
- {
429
- name: 'get-user',
430
- description: 'Get current user info',
431
- inputSchema: { type: 'object', properties: {} },
432
- async execute() {
433
- return { content: [{ type: 'text', text: JSON.stringify(currentUser) }] };
434
- },
435
- },
436
- ],
439
+ navigator.modelContext.registerTool({
440
+ name: 'get-user',
441
+ description: 'Get current user info',
442
+ inputSchema: { type: 'object', properties: {} },
443
+ async execute() {
444
+ return { content: [{ type: 'text', text: JSON.stringify(currentUser) }] };
445
+ },
437
446
  });
438
447
 
439
448
  // Add tools dynamically based on user role
@@ -455,7 +464,7 @@ if (currentUser.isAdmin) {
455
464
 
456
465
  // Remove tools when permissions change
457
466
  function onLogout() {
458
- navigator.modelContext.clearContext();
467
+ navigator.modelContext.unregisterTool('get-user');
459
468
  }
460
469
  ```
461
470
 
@@ -464,48 +473,45 @@ function onLogout() {
464
473
  ```typescript
465
474
  import '@mcp-b/global';
466
475
 
467
- navigator.modelContext.provideContext({
468
- tools: [
469
- {
470
- name: 'fill-contact-form',
471
- description: 'Fill the contact form with provided details',
472
- inputSchema: {
473
- type: 'object',
474
- properties: {
475
- name: { type: 'string' },
476
- email: { type: 'string' },
477
- message: { type: 'string' },
478
- },
479
- required: ['name', 'email', 'message'],
480
- },
481
- async execute(args) {
482
- document.querySelector('#name').value = args.name;
483
- document.querySelector('#email').value = args.email;
484
- document.querySelector('#message').value = args.message;
485
- return { content: [{ type: 'text', text: 'Form filled' }] };
486
- },
487
- },
488
- {
489
- name: 'submit-form',
490
- description: 'Submit the contact form',
491
- inputSchema: { type: 'object', properties: {} },
492
- async execute() {
493
- document.querySelector('#contact-form').submit();
494
- return { content: [{ type: 'text', text: 'Form submitted' }] };
495
- },
476
+ navigator.modelContext.registerTool({
477
+ name: 'fill-contact-form',
478
+ description: 'Fill the contact form with provided details',
479
+ inputSchema: {
480
+ type: 'object',
481
+ properties: {
482
+ name: { type: 'string' },
483
+ email: { type: 'string' },
484
+ message: { type: 'string' },
496
485
  },
497
- ],
486
+ required: ['name', 'email', 'message'],
487
+ },
488
+ async execute(args) {
489
+ document.querySelector('#name').value = args.name;
490
+ document.querySelector('#email').value = args.email;
491
+ document.querySelector('#message').value = args.message;
492
+ return { content: [{ type: 'text', text: 'Form filled' }] };
493
+ },
494
+ });
495
+
496
+ navigator.modelContext.registerTool({
497
+ name: 'submit-form',
498
+ description: 'Submit the contact form',
499
+ inputSchema: { type: 'object', properties: {} },
500
+ async execute() {
501
+ document.querySelector('#contact-form').submit();
502
+ return { content: [{ type: 'text', text: 'Form submitted' }] };
503
+ },
498
504
  });
499
505
  ```
500
506
 
501
507
  ## Browser Compatibility
502
508
 
503
- | Browser | Native Support | Polyfill |
504
- |---------|---------------|----------|
505
- | Chrome/Edge (with flag) | Yes | N/A |
506
- | Chrome/Edge (default) | No | Yes |
507
- | Firefox | No | Yes |
508
- | Safari | No | Yes |
509
+ | Browser | Native Support | Polyfill |
510
+ | ----------------------- | -------------- | -------- |
511
+ | Chrome/Edge (with flag) | Yes | N/A |
512
+ | Chrome/Edge (default) | No | Yes |
513
+ | Firefox | No | Yes |
514
+ | Safari | No | Yes |
509
515
 
510
516
  ## Zod Version Compatibility
511
517
 
package/dist/index.d.ts CHANGED
@@ -29,8 +29,7 @@ declare global {
29
29
  interface Window {
30
30
  __webModelContextOptions?: WebModelContextInitOptions;
31
31
  }
32
- }
33
- //# sourceMappingURL=types.d.ts.map
32
+ } //# sourceMappingURL=types.d.ts.map
34
33
  //#endregion
35
34
  //#region src/global.d.ts
36
35
  declare function initializeWebModelContext(options?: WebModelContextInitOptions): void;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../src/types.ts","../src/global.ts"],"sourcesContent":[],"mappings":";;;UAEiB,sBAAA;cACH,QAAQ;EADL,YAAA,CAAA,EAEA,OAFA,CAEQ,2BAFc,CAAA,GAAA,KAAA;;AACzB,KAIF,0BAAA,GAJE,UAAA,GAAA,OAAA;AACW,UAKR,0BAAA,CALQ;EAAR,SAAA,CAAA,EAMH,sBANG;EAAO,cAAA,CAAA,EAAA,OAAA;EAGZ;AAEZ;AAkBC;;;;;+BAR8B;;;AC4K/B;AA+CA;;;;;;;+BD/M+B;;;;;;iBCgKf,yBAAA,WAAoC;iBA+CpC,sBAAA,CAAA"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../src/types.ts","../src/global.ts"],"mappings":";;;UAEiB,sBAAA;EACf,SAAA,GAAY,OAAA,CAAQ,yBAAA;EACpB,YAAA,GAAe,OAAA,CAAQ,2BAAA;AAAA;AAAA,KAGb,0BAAA;AAAA,UAEK,0BAAA;EACf,SAAA,GAAY,sBAAA;EACZ,cAAA;EAPe;;;;;;;EAef,0BAAA,GAA6B,0BAAA;EAfN;;;AAGzB;;;EAmBE,kBAAA;AAAA;AAAA,QAGM,MAAA;EAAA,UACI,MAAA;IACR,wBAAA,GAA2B,0BAAA;EAAA;AAAA;;;iBCgKf,yBAAA,CAA0B,OAAA,GAAU,0BAAA;AAAA,iBA+CpC,sBAAA,CAAA"}