@mcp-b/transports 4.1.0-beta.20260702224704 → 5.0.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/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2025 mcp-b
3
+ Copyright (c) 2025 mcp-b contributors
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -20,7 +20,7 @@
20
20
  | **Secure by Default** | Origin validation, CORS configuration, and Chrome's secure messaging APIs |
21
21
  | **AI-Agent Ready** | Built specifically for MCP, the standard protocol for AI tool integration |
22
22
  | **TypeScript First** | Full type safety with comprehensive type definitions |
23
- | **Zero Dependencies** | Only requires `zod` for schema validation |
23
+ | **MCP SDK v2** | Uses the split MCP server and core packages |
24
24
  | **Works Everywhere** | Chrome, Firefox, Edge, and any Chromium-based browser |
25
25
 
26
26
  ## Use Cases
@@ -34,7 +34,7 @@
34
34
  ## Installation
35
35
 
36
36
  ```bash
37
- npm install @mcp-b/transports
37
+ npm install @mcp-b/transports @modelcontextprotocol/client @modelcontextprotocol/server zod
38
38
  ```
39
39
 
40
40
  ## Transport Types
@@ -49,7 +49,8 @@ Use `ExtensionClientTransport` and `ExtensionServerTransport` for communication
49
49
 
50
50
  ### Extension External Transports (Cross-Extension Communication)
51
51
 
52
- Use `ExtensionExternalClientTransport` and `ExtensionExternalServerTransport` for communication between different browser extensions, enabling one extension to access MCP servers hosted by another extension.
52
+ Use `ExtensionClientTransport` and `ExtensionServerTransport` with an extension ID and
53
+ `chrome.runtime.onConnectExternal` for communication between different browser extensions.
53
54
 
54
55
  ## Tab Transport Examples
55
56
 
@@ -59,7 +60,7 @@ Create an MCP server in your web page and expose it via `TabServerTransport`:
59
60
 
60
61
  ```typescript
61
62
  import { TabServerTransport } from '@mcp-b/transports';
62
- import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
63
+ import { McpServer } from '@modelcontextprotocol/server';
63
64
  import { z } from 'zod';
64
65
 
65
66
  // Create MCP server with tools
@@ -74,11 +75,13 @@ const server = new McpServer(
74
75
  );
75
76
 
76
77
  // Register a tool
77
- server.tool(
78
+ server.registerTool(
78
79
  'createTodo',
79
- 'Creates a new todo item for the current user',
80
80
  {
81
- todoText: z.string().describe('The content of the todo item.'),
81
+ description: 'Creates a new todo item for the current user',
82
+ inputSchema: z.object({
83
+ todoText: z.string().describe('The content of the todo item.'),
84
+ }),
82
85
  },
83
86
  async (args) => {
84
87
  // Implementation here
@@ -106,24 +109,23 @@ Connect to the server from within the same page or from an extension content scr
106
109
 
107
110
  ```typescript
108
111
  import { TabClientTransport } from '@mcp-b/transports';
109
- import { Client } from '@modelcontextprotocol/sdk/client/index.js';
112
+ import { Client } from '@modelcontextprotocol/client';
110
113
 
111
114
  // Create transport with target origin
112
115
  const transport = new TabClientTransport({
113
116
  targetOrigin: window.location.origin,
114
117
  });
115
118
 
116
- // Discover available servers
117
- const availableServers = await transport.discover();
118
- if (availableServers.length > 0) {
119
- console.log(`Found server: ${availableServers[0].implementation.name}`);
120
- }
121
-
122
119
  // Create and connect client
123
- const client = new Client({
124
- name: 'ExtensionProxyClient',
125
- version: '1.0.0',
126
- });
120
+ const client = new Client(
121
+ {
122
+ name: 'ExtensionProxyClient',
123
+ version: '1.0.0',
124
+ },
125
+ {
126
+ versionNegotiation: { mode: 'auto' },
127
+ }
128
+ );
127
129
 
128
130
  await client.connect(transport);
129
131
 
@@ -156,28 +158,23 @@ Create an MCP server inside an iframe that can be accessed by the parent page:
156
158
 
157
159
  ```typescript
158
160
  import { IframeChildTransport } from '@mcp-b/transports';
159
- import { Server } from '@modelcontextprotocol/sdk/server/index.js';
161
+ import { McpServer } from '@modelcontextprotocol/server';
160
162
  import { z } from 'zod';
161
163
 
162
164
  // Create MCP server
163
- const server = new Server(
164
- {
165
- name: 'IframeApp',
166
- version: '1.0.0',
167
- },
168
- {
169
- capabilities: {
170
- tools: {},
171
- },
172
- }
173
- );
165
+ const server = new McpServer({
166
+ name: 'IframeApp',
167
+ version: '1.0.0',
168
+ });
174
169
 
175
170
  // Register tools
176
- server.tool(
171
+ server.registerTool(
177
172
  'getIframeData',
178
- 'Get data from the iframe application',
179
173
  {
180
- key: z.string().describe('Data key to retrieve'),
174
+ description: 'Get data from the iframe application',
175
+ inputSchema: z.object({
176
+ key: z.string().describe('Data key to retrieve'),
177
+ }),
181
178
  },
182
179
  async (args) => {
183
180
  return {
@@ -206,7 +203,7 @@ Connect from the parent page to the iframe's MCP server:
206
203
 
207
204
  ```typescript
208
205
  import { IframeParentTransport } from '@mcp-b/transports';
209
- import { Client } from '@modelcontextprotocol/sdk/client/index.js';
206
+ import { Client } from '@modelcontextprotocol/client';
210
207
 
211
208
  // Get reference to iframe element
212
209
  const iframe = document.querySelector('iframe');
@@ -220,10 +217,15 @@ iframe.addEventListener('load', async () => {
220
217
  });
221
218
 
222
219
  // Create MCP client
223
- const client = new Client({
224
- name: 'ParentPage',
225
- version: '1.0.0',
226
- });
220
+ const client = new Client(
221
+ {
222
+ name: 'ParentPage',
223
+ version: '1.0.0',
224
+ },
225
+ {
226
+ versionNegotiation: { mode: 'auto' },
227
+ }
228
+ );
227
229
 
228
230
  // Connect and use
229
231
  await client.connect(transport);
@@ -247,13 +249,12 @@ iframe.addEventListener('load', async () => {
247
249
  - `iframe` (required): Reference to the HTMLIFrameElement
248
250
  - `targetOrigin` (required): Expected origin of the iframe (for security)
249
251
  - `channelId`: Override the default channel identifier (default: `mcp-iframe`)
250
- - `checkReadyRetryMs`: Interval to retry the ready handshake if iframe isn't ready yet (default: 250ms)
252
+ - `checkReadyRetryMs`: Retry interval while `iframe.contentWindow` is unavailable (default: 250ms)
251
253
 
252
254
  #### IframeChildTransport Options
253
255
 
254
256
  - `allowedOrigins` (required): Whitelist of parent origins allowed to connect (for security)
255
257
  - `channelId`: Override the default channel identifier (default: `mcp-iframe`)
256
- - `serverReadyRetryMs`: Interval to retry broadcasting ready signal to parent (default: 250ms)
257
258
 
258
259
  ### Cross-Origin Support
259
260
 
@@ -262,7 +263,7 @@ Iframe transports are designed for cross-origin communication:
262
263
  - Parent and iframe can be on different domains
263
264
  - Origin validation is performed on both sides
264
265
  - Uses secure `postMessage` API
265
- - Retry mechanisms handle iframe loading timing issues
266
+ - The parent retries its ready check until the iframe window is available
266
267
 
267
268
  ## Extension Transport Examples
268
269
 
@@ -272,18 +273,20 @@ The extension background script acts as a hub, aggregating tools from multiple t
272
273
 
273
274
  ```typescript
274
275
  import { ExtensionServerTransport } from '@mcp-b/transports';
275
- import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
276
+ import { McpServer } from '@modelcontextprotocol/server';
276
277
 
277
278
  class McpHub {
278
- private server: McpServer;
279
-
280
279
  constructor() {
281
- this.server = new McpServer({
280
+ this.setupConnections();
281
+ }
282
+
283
+ private createServer() {
284
+ const server = new McpServer({
282
285
  name: 'Extension-Hub',
283
286
  version: '1.0.0',
284
287
  });
285
-
286
- this.setupConnections();
288
+ // Register tools backed by the hub's shared application state here.
289
+ return server;
287
290
  }
288
291
 
289
292
  private setupConnections() {
@@ -297,29 +300,38 @@ class McpHub {
297
300
  }
298
301
 
299
302
  private async handleUiConnection(port: chrome.runtime.Port) {
303
+ const server = this.createServer();
300
304
  const transport = new ExtensionServerTransport(port);
301
- await this.server.connect(transport);
305
+ await server.connect(transport);
302
306
  }
303
307
  }
304
308
  ```
305
309
 
310
+ Each `McpServer` owns one protocol session, so every accepted port gets a fresh server. Keep the
311
+ hub's shared application state outside the per-connection server.
312
+
306
313
  ### Content Script Bridge
307
314
 
308
315
  Content scripts act as a bridge between the page's MCP server and the extension:
309
316
 
310
317
  ```typescript
311
318
  import { TabClientTransport } from '@mcp-b/transports';
312
- import { Client } from '@modelcontextprotocol/sdk/client/index.js';
319
+ import { Client } from '@modelcontextprotocol/client';
313
320
 
314
321
  // Connect to the page's MCP server
315
322
  const transport = new TabClientTransport({
316
323
  targetOrigin: window.location.origin,
317
324
  });
318
325
 
319
- const client = new Client({
320
- name: 'ExtensionProxyClient',
321
- version: '1.0.0',
322
- });
326
+ const client = new Client(
327
+ {
328
+ name: 'ExtensionProxyClient',
329
+ version: '1.0.0',
330
+ },
331
+ {
332
+ versionNegotiation: { mode: 'auto' },
333
+ }
334
+ );
323
335
 
324
336
  // Connect to extension background
325
337
  const backgroundPort = chrome.runtime.connect({
@@ -359,7 +371,7 @@ Connect from the extension's sidebar or popup to use tools from all connected pa
359
371
 
360
372
  ```typescript
361
373
  import { ExtensionClientTransport } from '@mcp-b/transports';
362
- import { Client } from '@modelcontextprotocol/sdk/client/index.js';
374
+ import { Client } from '@modelcontextprotocol/client';
363
375
 
364
376
  // Create transport - connects to the extension's background script
365
377
  const transport = new ExtensionClientTransport({
@@ -367,10 +379,15 @@ const transport = new ExtensionClientTransport({
367
379
  });
368
380
 
369
381
  // Create MCP client
370
- const client = new Client({
371
- name: 'Extension Sidepanel',
372
- version: '1.0.0',
373
- });
382
+ const client = new Client(
383
+ {
384
+ name: 'Extension Sidepanel',
385
+ version: '1.0.0',
386
+ },
387
+ {
388
+ versionNegotiation: { mode: 'auto' },
389
+ }
390
+ );
374
391
 
375
392
  // Connect and use
376
393
  await client.connect(transport);
@@ -392,33 +409,41 @@ const result = await client.callTool({
392
409
  Create an MCP server in Extension 1 that can be accessed by other extensions:
393
410
 
394
411
  ```typescript
395
- import { ExtensionExternalServerTransport } from '@mcp-b/transports';
396
- import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
412
+ import { ExtensionServerTransport } from '@mcp-b/transports';
413
+ import { McpServer } from '@modelcontextprotocol/server';
397
414
  import { z } from 'zod';
398
415
 
399
- // Create MCP server with tools
400
- const server = new McpServer(
401
- {
402
- name: 'MyExtensionAPI',
403
- version: '1.0.0',
404
- },
405
- {
406
- instructions: 'Extension API for cross-extension communication',
407
- }
408
- );
416
+ function createServer() {
417
+ const server = new McpServer(
418
+ {
419
+ name: 'MyExtensionAPI',
420
+ version: '1.0.0',
421
+ },
422
+ {
423
+ instructions: 'Extension API for cross-extension communication',
424
+ }
425
+ );
409
426
 
410
- // Register tools
411
- server.tool('getBookmarks', 'Retrieves user bookmarks', {}, async () => {
412
- const bookmarks = await chrome.bookmarks.getTree();
413
- return {
414
- content: [
415
- {
416
- type: 'text',
417
- text: JSON.stringify(bookmarks, null, 2),
418
- },
419
- ],
420
- };
421
- });
427
+ server.registerTool(
428
+ 'getBookmarks',
429
+ {
430
+ description: 'Retrieves user bookmarks',
431
+ inputSchema: z.object({}),
432
+ },
433
+ async () => {
434
+ const bookmarks = await chrome.bookmarks.getTree();
435
+ return {
436
+ content: [
437
+ {
438
+ type: 'text',
439
+ text: JSON.stringify(bookmarks, null, 2),
440
+ },
441
+ ],
442
+ };
443
+ }
444
+ );
445
+ return server;
446
+ }
422
447
 
423
448
  // Set up external connection listener in background script
424
449
  chrome.runtime.onConnectExternal.addListener(async (port) => {
@@ -429,6 +454,7 @@ chrome.runtime.onConnectExternal.addListener(async (port) => {
429
454
  return;
430
455
  }
431
456
 
457
+ const server = createServer();
432
458
  const transport = new ExtensionServerTransport(port);
433
459
  await server.connect(transport);
434
460
  }
@@ -440,8 +466,8 @@ chrome.runtime.onConnectExternal.addListener(async (port) => {
440
466
  Connect from Extension 2 to use Extension 1's MCP server:
441
467
 
442
468
  ```typescript
443
- import { ExtensionExternalClientTransport } from '@mcp-b/transports';
444
- import { Client } from '@modelcontextprotocol/sdk/client/index.js';
469
+ import { ExtensionClientTransport } from '@mcp-b/transports';
470
+ import { Client } from '@modelcontextprotocol/client';
445
471
 
446
472
  // Create transport targeting Extension 1
447
473
  const transport = new ExtensionClientTransport({
@@ -450,10 +476,15 @@ const transport = new ExtensionClientTransport({
450
476
  });
451
477
 
452
478
  // Create MCP client
453
- const client = new Client({
454
- name: 'ClientExtension',
455
- version: '1.0.0',
456
- });
479
+ const client = new Client(
480
+ {
481
+ name: 'ClientExtension',
482
+ version: '1.0.0',
483
+ },
484
+ {
485
+ versionNegotiation: { mode: 'auto' },
486
+ }
487
+ );
457
488
 
458
489
  // Connect and use
459
490
  await client.connect(transport);
@@ -493,18 +524,17 @@ const result = await client.callTool({
493
524
 
494
525
  ### Extension External Transport Flow
495
526
 
496
- 1. Extension 1 creates `ExtensionExternalServerTransport` and listens on `chrome.runtime.onConnectExternal`
497
- 2. Extension 2 creates `ExtensionExternalClientTransport` targeting Extension 1's ID
527
+ 1. Extension 1 creates `ExtensionServerTransport` instances from `chrome.runtime.onConnectExternal`
528
+ 2. Extension 2 creates an `ExtensionClientTransport` with Extension 1's ID
498
529
  3. Communication happens through Chrome's secure cross-extension messaging
499
530
  4. Server extension can validate connections and control access
500
531
 
501
532
  ## Key Features
502
533
 
503
- - **Automatic Server Discovery**: Tab clients can discover available servers
504
- - **Cross-Origin Support**: Configure CORS for tab transports
534
+ - **Ready Handshake**: Tab and iframe clients wait for their server before sending
535
+ - **Origin Controls**: Restrict incoming and outgoing `postMessage` origins
505
536
  - **Cross-Extension Communication**: Extensions can expose APIs to other extensions
506
537
  - **Tool Namespacing**: Extension hub prefixes tools to avoid conflicts
507
- - **Connection Management**: Automatic cleanup when tabs close
508
538
  - **Type Safety**: Full TypeScript support with proper typing
509
539
 
510
540
  ## Security Considerations
@@ -524,12 +554,12 @@ MCP is an open protocol that standardizes how AI applications connect to externa
524
554
 
525
555
  ### Which transport should I use?
526
556
 
527
- | Scenario | Recommended Transport |
528
- | ---------------------------- | ----------------------------------------------------------------------- |
529
- | Same-page communication | `TabServerTransport` / `TabClientTransport` |
530
- | Parent page to iframe | `IframeParentTransport` / `IframeChildTransport` |
531
- | Browser extension to webpage | `ExtensionClientTransport` / `ExtensionServerTransport` |
532
- | Extension to extension | `ExtensionExternalClientTransport` / `ExtensionExternalServerTransport` |
557
+ | Scenario | Recommended Transport |
558
+ | ---------------------------- | ------------------------------------------------------- |
559
+ | Same-page communication | `TabServerTransport` / `TabClientTransport` |
560
+ | Parent page to iframe | `IframeParentTransport` / `IframeChildTransport` |
561
+ | Browser extension to webpage | `ExtensionClientTransport` / `ExtensionServerTransport` |
562
+ | Extension to extension | `ExtensionClientTransport` / `ExtensionServerTransport` |
533
563
 
534
564
  ### Is this compatible with Claude Desktop, Cursor, or VS Code Copilot?
535
565
 
@@ -557,9 +587,8 @@ Yes! `TabServerTransport` and `TabClientTransport` work entirely within a web pa
557
587
 
558
588
  - [`@mcp-b/global`](https://docs.mcp-b.ai/packages/global/reference) - Full MCP-B browser runtime
559
589
  - [`@mcp-b/react-webmcp`](https://docs.mcp-b.ai/packages/react-webmcp/reference) - React hooks for MCP tool registration
560
- - [`@mcp-b/extension-tools`](https://docs.mcp-b.ai/packages/extension-tools/reference) - 62+ Chrome Extension API tools for MCP
561
590
  - [`chrome-devtools-mcp`](https://github.com/ChromeDevTools/chrome-devtools-mcp) - Upstream Chrome DevTools MCP server
562
- - [`@modelcontextprotocol/sdk`](https://www.npmjs.com/package/@modelcontextprotocol/sdk) - Official MCP SDK
591
+ - [`@modelcontextprotocol/client`](https://www.npmjs.com/package/@modelcontextprotocol/client) and [`@modelcontextprotocol/server`](https://www.npmjs.com/package/@modelcontextprotocol/server) - Official MCP TypeScript SDK v2 packages
563
592
 
564
593
  ## Resources
565
594