@mcp-web/bridge 0.1.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 +201 -0
- package/README.md +311 -0
- package/dist/adapters/bun.d.ts +95 -0
- package/dist/adapters/bun.d.ts.map +1 -0
- package/dist/adapters/bun.js +286 -0
- package/dist/adapters/bun.js.map +1 -0
- package/dist/adapters/deno.d.ts +89 -0
- package/dist/adapters/deno.d.ts.map +1 -0
- package/dist/adapters/deno.js +249 -0
- package/dist/adapters/deno.js.map +1 -0
- package/dist/adapters/index.d.ts +21 -0
- package/dist/adapters/index.d.ts.map +1 -0
- package/dist/adapters/index.js +21 -0
- package/dist/adapters/index.js.map +1 -0
- package/dist/adapters/node.d.ts +112 -0
- package/dist/adapters/node.d.ts.map +1 -0
- package/dist/adapters/node.js +309 -0
- package/dist/adapters/node.js.map +1 -0
- package/dist/adapters/partykit.d.ts +153 -0
- package/dist/adapters/partykit.d.ts.map +1 -0
- package/dist/adapters/partykit.js +372 -0
- package/dist/adapters/partykit.js.map +1 -0
- package/dist/bridge.d.ts +38 -0
- package/dist/bridge.d.ts.map +1 -0
- package/dist/bridge.js +1004 -0
- package/dist/bridge.js.map +1 -0
- package/dist/core.d.ts +75 -0
- package/dist/core.d.ts.map +1 -0
- package/dist/core.js +1508 -0
- package/dist/core.js.map +1 -0
- package/dist/index.d.ts +38 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +42 -0
- package/dist/index.js.map +1 -0
- package/dist/runtime/index.d.ts +11 -0
- package/dist/runtime/index.d.ts.map +1 -0
- package/dist/runtime/index.js +9 -0
- package/dist/runtime/index.js.map +1 -0
- package/dist/runtime/scheduler.d.ts +69 -0
- package/dist/runtime/scheduler.d.ts.map +1 -0
- package/dist/runtime/scheduler.js +88 -0
- package/dist/runtime/scheduler.js.map +1 -0
- package/dist/runtime/types.d.ts +144 -0
- package/dist/runtime/types.d.ts.map +1 -0
- package/dist/runtime/types.js +82 -0
- package/dist/runtime/types.js.map +1 -0
- package/dist/schemas.d.ts +6 -0
- package/dist/schemas.d.ts.map +1 -0
- package/dist/schemas.js +6 -0
- package/dist/schemas.js.map +1 -0
- package/dist/types.d.ts +130 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +28 -0
- package/src/adapters/bun.ts +354 -0
- package/src/adapters/deno.ts +282 -0
- package/src/adapters/index.ts +28 -0
- package/src/adapters/node.ts +385 -0
- package/src/adapters/partykit.ts +482 -0
- package/src/bridge.test.ts +64 -0
- package/src/core.ts +2176 -0
- package/src/index.ts +90 -0
- package/src/limits.test.ts +436 -0
- package/src/remote-mcp.test.ts +770 -0
- package/src/runtime/index.ts +24 -0
- package/src/runtime/scheduler.ts +130 -0
- package/src/runtime/types.ts +229 -0
- package/src/schemas.ts +6 -0
- package/src/session-naming.test.ts +443 -0
- package/src/types.ts +180 -0
- package/tsconfig.json +12 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/adapters/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AACrD,YAAY,EAAE,sBAAsB,EAAE,yBAAyB,EAAE,MAAM,WAAW,CAAC;AAGnF,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAC7C,YAAY,EAAE,sBAAsB,EAAE,MAAM,WAAW,CAAC;AAGxD,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAC3C,YAAY,EAAE,qBAAqB,EAAE,MAAM,UAAU,CAAC;AAGtD,OAAO,EAAE,cAAc,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AACxF,YAAY,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bridge adapters for different JavaScript runtimes.
|
|
3
|
+
*
|
|
4
|
+
* Each adapter wraps the core MCPWebBridge class and provides
|
|
5
|
+
* runtime-specific I/O implementations.
|
|
6
|
+
*
|
|
7
|
+
* Available adapters:
|
|
8
|
+
* - `MCPWebBridgeNode` - Node.js (production ready)
|
|
9
|
+
* - `MCPWebBridgeDeno` - Deno / Deno Deploy
|
|
10
|
+
* - `MCPWebBridgeBun` - Bun runtime
|
|
11
|
+
* - `MCPWebBridgeParty` / `createPartyKitBridge` - PartyKit / Cloudflare
|
|
12
|
+
*/
|
|
13
|
+
// Node.js adapter (production ready)
|
|
14
|
+
export { Bridge, MCPWebBridgeNode } from './node.js';
|
|
15
|
+
// Deno adapter
|
|
16
|
+
export { MCPWebBridgeDeno } from './deno.js';
|
|
17
|
+
// Bun adapter
|
|
18
|
+
export { MCPWebBridgeBun } from './bun.js';
|
|
19
|
+
// PartyKit adapter
|
|
20
|
+
export { AlarmScheduler, createPartyKitBridge, MCPWebBridgeParty } from './partykit.js';
|
|
21
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/adapters/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,qCAAqC;AACrC,OAAO,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAGrD,eAAe;AACf,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAG7C,cAAc;AACd,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAG3C,mBAAmB;AACnB,OAAO,EAAE,cAAc,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC"}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCPWebBridgeNode - Node.js adapter for the MCP Web Bridge.
|
|
3
|
+
*
|
|
4
|
+
* Uses a single port for both HTTP and WebSocket connections.
|
|
5
|
+
* WebSocket connections are upgraded from HTTP via the `upgrade` event.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```typescript
|
|
9
|
+
* import { MCPWebBridgeNode } from '@mcp-web/bridge';
|
|
10
|
+
*
|
|
11
|
+
* const bridge = new MCPWebBridgeNode({
|
|
12
|
+
* name: 'My App',
|
|
13
|
+
* description: 'My awesome app',
|
|
14
|
+
* port: 3001,
|
|
15
|
+
* });
|
|
16
|
+
*
|
|
17
|
+
* // Bridge is now listening on ws://localhost:3001 and http://localhost:3001
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
import type { MCPWebConfig } from '@mcp-web/types';
|
|
21
|
+
import { MCPWebBridge } from '../core.js';
|
|
22
|
+
/**
|
|
23
|
+
* Configuration for the Node.js bridge adapter.
|
|
24
|
+
*/
|
|
25
|
+
/**
|
|
26
|
+
* SSL/TLS configuration for secure connections.
|
|
27
|
+
*/
|
|
28
|
+
export interface MCPWebBridgeNodeSSLConfig {
|
|
29
|
+
/** Private key in PEM format (string content, not file path) */
|
|
30
|
+
key: string | Buffer;
|
|
31
|
+
/** Certificate in PEM format (string content, not file path) */
|
|
32
|
+
cert: string | Buffer;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Configuration for the Node.js bridge adapter.
|
|
36
|
+
*/
|
|
37
|
+
export interface MCPWebBridgeNodeConfig extends Omit<MCPWebConfig, 'bridgeUrl'> {
|
|
38
|
+
/** Port to listen on (default: 3001) */
|
|
39
|
+
port?: number;
|
|
40
|
+
/** Host to bind to (default: '0.0.0.0') */
|
|
41
|
+
host?: string;
|
|
42
|
+
/**
|
|
43
|
+
* SSL/TLS configuration for HTTPS/WSS support.
|
|
44
|
+
* When provided, the bridge will use secure connections.
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* ```typescript
|
|
48
|
+
* import { readFileSync } from 'node:fs';
|
|
49
|
+
*
|
|
50
|
+
* const bridge = new MCPWebBridgeNode({
|
|
51
|
+
* name: 'My App',
|
|
52
|
+
* port: 3001,
|
|
53
|
+
* ssl: {
|
|
54
|
+
* key: readFileSync('./localhost-key.pem'),
|
|
55
|
+
* cert: readFileSync('./localhost.pem'),
|
|
56
|
+
* },
|
|
57
|
+
* });
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
60
|
+
ssl?: MCPWebBridgeNodeSSLConfig;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Node.js adapter for MCPWebBridge.
|
|
64
|
+
* Provides a single-port server for both WebSocket and HTTP traffic.
|
|
65
|
+
*/
|
|
66
|
+
export declare class MCPWebBridgeNode {
|
|
67
|
+
#private;
|
|
68
|
+
constructor(config: MCPWebBridgeNodeConfig);
|
|
69
|
+
/**
|
|
70
|
+
* Returns a promise that resolves when the server is ready to accept connections.
|
|
71
|
+
* Rejects if the server fails to start (e.g., port already in use).
|
|
72
|
+
*
|
|
73
|
+
* @example
|
|
74
|
+
* ```typescript
|
|
75
|
+
* const bridge = new MCPWebBridgeNode({ name: 'My App', port: 3001 });
|
|
76
|
+
* await bridge.ready();
|
|
77
|
+
* console.log('Bridge is ready!');
|
|
78
|
+
* ```
|
|
79
|
+
*/
|
|
80
|
+
ready(): Promise<void>;
|
|
81
|
+
/**
|
|
82
|
+
* Whether the server is ready to accept connections.
|
|
83
|
+
*/
|
|
84
|
+
get isReady(): boolean;
|
|
85
|
+
/**
|
|
86
|
+
* Get the underlying MCPWebBridge core instance.
|
|
87
|
+
* Useful for advanced usage or custom integrations.
|
|
88
|
+
*/
|
|
89
|
+
get core(): MCPWebBridge;
|
|
90
|
+
/**
|
|
91
|
+
* Get the bridge handlers for custom integrations.
|
|
92
|
+
*/
|
|
93
|
+
getHandlers(): import("../runtime/types.js").BridgeHandlers;
|
|
94
|
+
/**
|
|
95
|
+
* Get the port the server is listening on.
|
|
96
|
+
*/
|
|
97
|
+
get port(): number;
|
|
98
|
+
/**
|
|
99
|
+
* Whether the server is using SSL/TLS (HTTPS/WSS).
|
|
100
|
+
*/
|
|
101
|
+
get isSecure(): boolean;
|
|
102
|
+
/**
|
|
103
|
+
* Gracefully shut down the bridge.
|
|
104
|
+
*/
|
|
105
|
+
close(): Promise<void>;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* For backwards compatibility, also export as Bridge
|
|
109
|
+
* @deprecated Use MCPWebBridgeNode instead
|
|
110
|
+
*/
|
|
111
|
+
export declare const Bridge: typeof MCPWebBridgeNode;
|
|
112
|
+
//# sourceMappingURL=node.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"node.d.ts","sourceRoot":"","sources":["../../src/adapters/node.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAUH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAK1C;;GAEG;AACH;;GAEG;AACH,MAAM,WAAW,yBAAyB;IACxC,gEAAgE;IAChE,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC;IAErB,gEAAgE;IAChE,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;CACvB;AAED;;GAEG;AACH,MAAM,WAAW,sBAAuB,SAAQ,IAAI,CAAC,YAAY,EAAE,WAAW,CAAC;IAC7E,wCAAwC;IACxC,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd,2CAA2C;IAC3C,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd;;;;;;;;;;;;;;;;;OAiBG;IACH,GAAG,CAAC,EAAE,yBAAyB,CAAC;CACjC;AA8DD;;;GAGG;AACH,qBAAa,gBAAgB;;gBAUf,MAAM,EAAE,sBAAsB;IAkJ1C;;;;;;;;;;OAUG;IACH,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAItB;;OAEG;IACH,IAAI,OAAO,IAAI,OAAO,CAErB;IAED;;;OAGG;IACH,IAAI,IAAI,IAAI,YAAY,CAEvB;IAED;;OAEG;IACH,WAAW;IAIX;;OAEG;IACH,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED;;OAEG;IACH,IAAI,QAAQ,IAAI,OAAO,CAEtB;IAED;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAyB7B;AAED;;;GAGG;AACH,eAAO,MAAM,MAAM,yBAAmB,CAAC"}
|
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCPWebBridgeNode - Node.js adapter for the MCP Web Bridge.
|
|
3
|
+
*
|
|
4
|
+
* Uses a single port for both HTTP and WebSocket connections.
|
|
5
|
+
* WebSocket connections are upgraded from HTTP via the `upgrade` event.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```typescript
|
|
9
|
+
* import { MCPWebBridgeNode } from '@mcp-web/bridge';
|
|
10
|
+
*
|
|
11
|
+
* const bridge = new MCPWebBridgeNode({
|
|
12
|
+
* name: 'My App',
|
|
13
|
+
* description: 'My awesome app',
|
|
14
|
+
* port: 3001,
|
|
15
|
+
* });
|
|
16
|
+
*
|
|
17
|
+
* // Bridge is now listening on ws://localhost:3001 and http://localhost:3001
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
21
|
+
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
22
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
23
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
24
|
+
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
25
|
+
};
|
|
26
|
+
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
27
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
28
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
29
|
+
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
30
|
+
};
|
|
31
|
+
var _MCPWebBridgeNode_core, _MCPWebBridgeNode_server, _MCPWebBridgeNode_wss, _MCPWebBridgeNode_port, _MCPWebBridgeNode_host, _MCPWebBridgeNode_isSecure, _MCPWebBridgeNode_readyPromise, _MCPWebBridgeNode_isReady;
|
|
32
|
+
import { createServer as createHttpServer, } from 'node:http';
|
|
33
|
+
import { createServer as createHttpsServer } from 'node:https';
|
|
34
|
+
import { WebSocket, WebSocketServer } from 'ws';
|
|
35
|
+
import { MCPWebBridge } from '../core.js';
|
|
36
|
+
import { TimerScheduler } from '../runtime/scheduler.js';
|
|
37
|
+
import { readyStateToString, isSSEResponse } from '../runtime/types.js';
|
|
38
|
+
/**
|
|
39
|
+
* Wraps a Node.js ws WebSocket in our runtime-agnostic interface.
|
|
40
|
+
*/
|
|
41
|
+
function wrapWebSocket(ws) {
|
|
42
|
+
const messageHandlers = new Set();
|
|
43
|
+
ws.on('message', (data) => {
|
|
44
|
+
const str = data.toString();
|
|
45
|
+
for (const handler of messageHandlers) {
|
|
46
|
+
handler(str);
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
return {
|
|
50
|
+
send(data) {
|
|
51
|
+
if (ws.readyState === WebSocket.OPEN) {
|
|
52
|
+
ws.send(data);
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
close(code, reason) {
|
|
56
|
+
ws.close(code, reason);
|
|
57
|
+
},
|
|
58
|
+
get readyState() {
|
|
59
|
+
return readyStateToString(ws.readyState);
|
|
60
|
+
},
|
|
61
|
+
onMessage(handler) {
|
|
62
|
+
messageHandlers.add(handler);
|
|
63
|
+
},
|
|
64
|
+
offMessage(handler) {
|
|
65
|
+
messageHandlers.delete(handler);
|
|
66
|
+
},
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Wraps a Node.js IncomingMessage in our runtime-agnostic HttpRequest interface.
|
|
71
|
+
*/
|
|
72
|
+
function wrapRequest(req, body) {
|
|
73
|
+
return {
|
|
74
|
+
method: req.method || 'GET',
|
|
75
|
+
url: `http://${req.headers.host || 'localhost'}${req.url || '/'}`,
|
|
76
|
+
headers: {
|
|
77
|
+
get(name) {
|
|
78
|
+
const value = req.headers[name.toLowerCase()];
|
|
79
|
+
if (Array.isArray(value)) {
|
|
80
|
+
return value[0] || null;
|
|
81
|
+
}
|
|
82
|
+
return value || null;
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
text() {
|
|
86
|
+
return Promise.resolve(body);
|
|
87
|
+
},
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Node.js adapter for MCPWebBridge.
|
|
92
|
+
* Provides a single-port server for both WebSocket and HTTP traffic.
|
|
93
|
+
*/
|
|
94
|
+
export class MCPWebBridgeNode {
|
|
95
|
+
constructor(config) {
|
|
96
|
+
_MCPWebBridgeNode_core.set(this, void 0);
|
|
97
|
+
_MCPWebBridgeNode_server.set(this, void 0);
|
|
98
|
+
_MCPWebBridgeNode_wss.set(this, void 0);
|
|
99
|
+
_MCPWebBridgeNode_port.set(this, void 0);
|
|
100
|
+
_MCPWebBridgeNode_host.set(this, void 0);
|
|
101
|
+
_MCPWebBridgeNode_isSecure.set(this, void 0);
|
|
102
|
+
_MCPWebBridgeNode_readyPromise.set(this, void 0);
|
|
103
|
+
_MCPWebBridgeNode_isReady.set(this, false);
|
|
104
|
+
__classPrivateFieldSet(this, _MCPWebBridgeNode_port, config.port ?? 3001, "f");
|
|
105
|
+
__classPrivateFieldSet(this, _MCPWebBridgeNode_host, config.host ?? '0.0.0.0', "f");
|
|
106
|
+
__classPrivateFieldSet(this, _MCPWebBridgeNode_isSecure, !!config.ssl, "f");
|
|
107
|
+
// Create the core with a timer-based scheduler
|
|
108
|
+
const scheduler = new TimerScheduler();
|
|
109
|
+
__classPrivateFieldSet(this, _MCPWebBridgeNode_core, new MCPWebBridge(config, scheduler), "f");
|
|
110
|
+
const handlers = __classPrivateFieldGet(this, _MCPWebBridgeNode_core, "f").getHandlers();
|
|
111
|
+
// Request handler (shared between HTTP and HTTPS)
|
|
112
|
+
const requestHandler = (req, res) => {
|
|
113
|
+
// Collect body
|
|
114
|
+
let body = '';
|
|
115
|
+
req.on('data', (chunk) => {
|
|
116
|
+
body += chunk;
|
|
117
|
+
});
|
|
118
|
+
req.on('end', () => {
|
|
119
|
+
const wrappedReq = wrapRequest(req, body);
|
|
120
|
+
handlers.onHttpRequest(wrappedReq).then((response) => {
|
|
121
|
+
// Check if this is an SSE response
|
|
122
|
+
if (isSSEResponse(response)) {
|
|
123
|
+
// Set headers for SSE
|
|
124
|
+
res.writeHead(response.status, response.headers);
|
|
125
|
+
// Create writer function that sends SSE-formatted data
|
|
126
|
+
const writer = (data) => {
|
|
127
|
+
res.write(`data: ${data}\n\n`);
|
|
128
|
+
};
|
|
129
|
+
// Track if connection is still open
|
|
130
|
+
let isOpen = true;
|
|
131
|
+
// Handle client disconnect
|
|
132
|
+
req.on('close', () => {
|
|
133
|
+
isOpen = false;
|
|
134
|
+
});
|
|
135
|
+
// Set up the SSE stream
|
|
136
|
+
response.setup(writer, () => {
|
|
137
|
+
if (isOpen) {
|
|
138
|
+
res.end();
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
// Keep connection alive with periodic comments
|
|
142
|
+
const keepAlive = setInterval(() => {
|
|
143
|
+
if (isOpen) {
|
|
144
|
+
res.write(': keepalive\n\n');
|
|
145
|
+
}
|
|
146
|
+
else {
|
|
147
|
+
clearInterval(keepAlive);
|
|
148
|
+
}
|
|
149
|
+
}, 30000);
|
|
150
|
+
// Clean up on close
|
|
151
|
+
res.on('close', () => {
|
|
152
|
+
clearInterval(keepAlive);
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
else {
|
|
156
|
+
// Regular HTTP response
|
|
157
|
+
res.writeHead(response.status, response.headers);
|
|
158
|
+
res.end(response.body);
|
|
159
|
+
}
|
|
160
|
+
});
|
|
161
|
+
});
|
|
162
|
+
};
|
|
163
|
+
// Create HTTP or HTTPS server based on SSL config
|
|
164
|
+
if (config.ssl) {
|
|
165
|
+
__classPrivateFieldSet(this, _MCPWebBridgeNode_server, createHttpsServer({ key: config.ssl.key, cert: config.ssl.cert }, requestHandler), "f");
|
|
166
|
+
}
|
|
167
|
+
else {
|
|
168
|
+
__classPrivateFieldSet(this, _MCPWebBridgeNode_server, createHttpServer(requestHandler), "f");
|
|
169
|
+
}
|
|
170
|
+
// Create WebSocket server without its own port (noServer mode)
|
|
171
|
+
__classPrivateFieldSet(this, _MCPWebBridgeNode_wss, new WebSocketServer({ noServer: true }), "f");
|
|
172
|
+
// Handle WebSocket upgrade requests
|
|
173
|
+
__classPrivateFieldGet(this, _MCPWebBridgeNode_server, "f").on('upgrade', (req, socket, head) => {
|
|
174
|
+
const urlStr = `http://${req.headers.host || 'localhost'}${req.url || '/'}`;
|
|
175
|
+
const url = new URL(urlStr);
|
|
176
|
+
const sessionId = url.searchParams.get('session');
|
|
177
|
+
if (!sessionId) {
|
|
178
|
+
socket.write('HTTP/1.1 400 Bad Request\r\n\r\n');
|
|
179
|
+
socket.destroy();
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
__classPrivateFieldGet(this, _MCPWebBridgeNode_wss, "f").handleUpgrade(req, socket, head, (ws) => {
|
|
183
|
+
const wrapped = wrapWebSocket(ws);
|
|
184
|
+
if (handlers.onWebSocketConnect(sessionId, wrapped, url)) {
|
|
185
|
+
ws.on('message', (data) => {
|
|
186
|
+
handlers.onWebSocketMessage(sessionId, wrapped, data.toString());
|
|
187
|
+
});
|
|
188
|
+
ws.on('close', () => {
|
|
189
|
+
handlers.onWebSocketClose(sessionId);
|
|
190
|
+
});
|
|
191
|
+
ws.on('error', (error) => {
|
|
192
|
+
console.error(`WebSocket error for session ${sessionId}:`, error);
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
else {
|
|
196
|
+
ws.close(1008, 'Connection rejected');
|
|
197
|
+
}
|
|
198
|
+
});
|
|
199
|
+
});
|
|
200
|
+
// Create a promise that resolves when the server is ready or rejects on error
|
|
201
|
+
__classPrivateFieldSet(this, _MCPWebBridgeNode_readyPromise, new Promise((resolve, reject) => {
|
|
202
|
+
// Handle server errors (including EADDRINUSE)
|
|
203
|
+
__classPrivateFieldGet(this, _MCPWebBridgeNode_server, "f").on('error', (error) => {
|
|
204
|
+
if (error.code === 'EADDRINUSE') {
|
|
205
|
+
const displayHost = __classPrivateFieldGet(this, _MCPWebBridgeNode_host, "f") === '0.0.0.0' ? 'localhost' : __classPrivateFieldGet(this, _MCPWebBridgeNode_host, "f");
|
|
206
|
+
console.error(`\n❌ Port ${__classPrivateFieldGet(this, _MCPWebBridgeNode_port, "f")} is already in use.`);
|
|
207
|
+
console.error(` Another process is listening on ${displayHost}:${__classPrivateFieldGet(this, _MCPWebBridgeNode_port, "f")}`);
|
|
208
|
+
console.error(`\n To fix this, either:`);
|
|
209
|
+
console.error(` 1. Stop the other process using port ${__classPrivateFieldGet(this, _MCPWebBridgeNode_port, "f")}:`);
|
|
210
|
+
console.error(` lsof -i :${__classPrivateFieldGet(this, _MCPWebBridgeNode_port, "f")} # Find the process`);
|
|
211
|
+
console.error(` kill <PID> # Kill it`);
|
|
212
|
+
console.error(` 2. Or use a different port in your bridge config\n`);
|
|
213
|
+
}
|
|
214
|
+
else {
|
|
215
|
+
console.error(`\n❌ Failed to start bridge server:`, error.message);
|
|
216
|
+
}
|
|
217
|
+
reject(error);
|
|
218
|
+
});
|
|
219
|
+
// Start listening
|
|
220
|
+
__classPrivateFieldGet(this, _MCPWebBridgeNode_server, "f").listen(__classPrivateFieldGet(this, _MCPWebBridgeNode_port, "f"), __classPrivateFieldGet(this, _MCPWebBridgeNode_host, "f"), () => {
|
|
221
|
+
__classPrivateFieldSet(this, _MCPWebBridgeNode_isReady, true, "f");
|
|
222
|
+
const displayHost = __classPrivateFieldGet(this, _MCPWebBridgeNode_host, "f") === '0.0.0.0' ? 'localhost' : __classPrivateFieldGet(this, _MCPWebBridgeNode_host, "f");
|
|
223
|
+
const wsProtocol = __classPrivateFieldGet(this, _MCPWebBridgeNode_isSecure, "f") ? 'wss' : 'ws';
|
|
224
|
+
const httpProtocol = __classPrivateFieldGet(this, _MCPWebBridgeNode_isSecure, "f") ? 'https' : 'http';
|
|
225
|
+
console.log(`🌉 MCP Web Bridge listening on ${displayHost}:${__classPrivateFieldGet(this, _MCPWebBridgeNode_port, "f")}`);
|
|
226
|
+
console.log(` WebSocket: ${wsProtocol}://${displayHost}:${__classPrivateFieldGet(this, _MCPWebBridgeNode_port, "f")}`);
|
|
227
|
+
console.log(` HTTP/MCP: ${httpProtocol}://${displayHost}:${__classPrivateFieldGet(this, _MCPWebBridgeNode_port, "f")}`);
|
|
228
|
+
resolve();
|
|
229
|
+
});
|
|
230
|
+
}), "f");
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Returns a promise that resolves when the server is ready to accept connections.
|
|
234
|
+
* Rejects if the server fails to start (e.g., port already in use).
|
|
235
|
+
*
|
|
236
|
+
* @example
|
|
237
|
+
* ```typescript
|
|
238
|
+
* const bridge = new MCPWebBridgeNode({ name: 'My App', port: 3001 });
|
|
239
|
+
* await bridge.ready();
|
|
240
|
+
* console.log('Bridge is ready!');
|
|
241
|
+
* ```
|
|
242
|
+
*/
|
|
243
|
+
ready() {
|
|
244
|
+
return __classPrivateFieldGet(this, _MCPWebBridgeNode_readyPromise, "f");
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* Whether the server is ready to accept connections.
|
|
248
|
+
*/
|
|
249
|
+
get isReady() {
|
|
250
|
+
return __classPrivateFieldGet(this, _MCPWebBridgeNode_isReady, "f");
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* Get the underlying MCPWebBridge core instance.
|
|
254
|
+
* Useful for advanced usage or custom integrations.
|
|
255
|
+
*/
|
|
256
|
+
get core() {
|
|
257
|
+
return __classPrivateFieldGet(this, _MCPWebBridgeNode_core, "f");
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* Get the bridge handlers for custom integrations.
|
|
261
|
+
*/
|
|
262
|
+
getHandlers() {
|
|
263
|
+
return __classPrivateFieldGet(this, _MCPWebBridgeNode_core, "f").getHandlers();
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* Get the port the server is listening on.
|
|
267
|
+
*/
|
|
268
|
+
get port() {
|
|
269
|
+
return __classPrivateFieldGet(this, _MCPWebBridgeNode_port, "f");
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* Whether the server is using SSL/TLS (HTTPS/WSS).
|
|
273
|
+
*/
|
|
274
|
+
get isSecure() {
|
|
275
|
+
return __classPrivateFieldGet(this, _MCPWebBridgeNode_isSecure, "f");
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* Gracefully shut down the bridge.
|
|
279
|
+
*/
|
|
280
|
+
async close() {
|
|
281
|
+
// Close the core (cleans up sessions, timers)
|
|
282
|
+
await __classPrivateFieldGet(this, _MCPWebBridgeNode_core, "f").close();
|
|
283
|
+
// Force close all WebSocket connections
|
|
284
|
+
for (const client of __classPrivateFieldGet(this, _MCPWebBridgeNode_wss, "f").clients) {
|
|
285
|
+
client.terminate();
|
|
286
|
+
}
|
|
287
|
+
// Close WebSocket server with timeout
|
|
288
|
+
await Promise.race([
|
|
289
|
+
new Promise((resolve) => {
|
|
290
|
+
__classPrivateFieldGet(this, _MCPWebBridgeNode_wss, "f").close(() => resolve());
|
|
291
|
+
}),
|
|
292
|
+
new Promise((resolve) => setTimeout(resolve, 1000)),
|
|
293
|
+
]);
|
|
294
|
+
// Close HTTP server with timeout
|
|
295
|
+
await Promise.race([
|
|
296
|
+
new Promise((resolve) => {
|
|
297
|
+
__classPrivateFieldGet(this, _MCPWebBridgeNode_server, "f").close(() => resolve());
|
|
298
|
+
}),
|
|
299
|
+
new Promise((resolve) => setTimeout(resolve, 1000)),
|
|
300
|
+
]);
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
_MCPWebBridgeNode_core = new WeakMap(), _MCPWebBridgeNode_server = new WeakMap(), _MCPWebBridgeNode_wss = new WeakMap(), _MCPWebBridgeNode_port = new WeakMap(), _MCPWebBridgeNode_host = new WeakMap(), _MCPWebBridgeNode_isSecure = new WeakMap(), _MCPWebBridgeNode_readyPromise = new WeakMap(), _MCPWebBridgeNode_isReady = new WeakMap();
|
|
304
|
+
/**
|
|
305
|
+
* For backwards compatibility, also export as Bridge
|
|
306
|
+
* @deprecated Use MCPWebBridgeNode instead
|
|
307
|
+
*/
|
|
308
|
+
export const Bridge = MCPWebBridgeNode;
|
|
309
|
+
//# sourceMappingURL=node.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"node.js","sourceRoot":"","sources":["../../src/adapters/node.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCPWebBridgeParty - PartyKit adapter for the MCP Web Bridge.
|
|
3
|
+
*
|
|
4
|
+
* Enables deployment to Cloudflare's edge network via PartyKit.
|
|
5
|
+
* Uses PartyKit's Party.Server interface with Durable Objects for state management.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```typescript
|
|
9
|
+
* // server.ts - PartyKit server entry point
|
|
10
|
+
* import { createPartyKitBridge } from '@mcp-web/bridge';
|
|
11
|
+
*
|
|
12
|
+
* export default createPartyKitBridge({
|
|
13
|
+
* name: 'My App',
|
|
14
|
+
* description: 'My awesome app on the edge',
|
|
15
|
+
* });
|
|
16
|
+
* ```
|
|
17
|
+
*
|
|
18
|
+
* @example With partykit.json configuration
|
|
19
|
+
* ```json
|
|
20
|
+
* {
|
|
21
|
+
* "name": "my-mcp-bridge",
|
|
22
|
+
* "main": "server.ts",
|
|
23
|
+
* "compatibility_date": "2024-01-01"
|
|
24
|
+
* }
|
|
25
|
+
* ```
|
|
26
|
+
*
|
|
27
|
+
* @example Deploy to PartyKit
|
|
28
|
+
* ```bash
|
|
29
|
+
* npx partykit deploy
|
|
30
|
+
* ```
|
|
31
|
+
*
|
|
32
|
+
* @remarks
|
|
33
|
+
* PartyKit provides:
|
|
34
|
+
* - Global edge deployment via Cloudflare
|
|
35
|
+
* - Durable Objects for stateful WebSocket handling
|
|
36
|
+
* - Hibernation support for cost efficiency
|
|
37
|
+
* - Alarms for scheduled tasks (used instead of setInterval)
|
|
38
|
+
*
|
|
39
|
+
* Key differences from other adapters:
|
|
40
|
+
* - No explicit port configuration (managed by PartyKit/Cloudflare)
|
|
41
|
+
* - Uses `Party.storage.setAlarm()` for session timeout checks
|
|
42
|
+
* - State can persist across hibernation cycles
|
|
43
|
+
*
|
|
44
|
+
* @see https://docs.partykit.io/
|
|
45
|
+
* @see https://docs.partykit.io/guides/scheduling-tasks-with-alarms/
|
|
46
|
+
*/
|
|
47
|
+
import type { MCPWebConfig } from '@mcp-web/types';
|
|
48
|
+
import type { Scheduler } from '../runtime/scheduler.js';
|
|
49
|
+
/**
|
|
50
|
+
* PartyKit connection interface (simplified).
|
|
51
|
+
* @see https://docs.partykit.io/reference/partyserver-api/
|
|
52
|
+
*/
|
|
53
|
+
interface PartyConnection {
|
|
54
|
+
id: string;
|
|
55
|
+
send(message: string | ArrayBuffer): void;
|
|
56
|
+
close(code?: number, reason?: string): void;
|
|
57
|
+
readyState: number;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* PartyKit room interface (simplified).
|
|
61
|
+
*/
|
|
62
|
+
interface PartyRoom {
|
|
63
|
+
id: string;
|
|
64
|
+
storage: {
|
|
65
|
+
get<T>(key: string): Promise<T | undefined>;
|
|
66
|
+
put<T>(key: string, value: T): Promise<void>;
|
|
67
|
+
delete(key: string): Promise<boolean>;
|
|
68
|
+
setAlarm(time: number | Date): Promise<void>;
|
|
69
|
+
getAlarm(): Promise<number | null>;
|
|
70
|
+
deleteAlarm(): Promise<void>;
|
|
71
|
+
};
|
|
72
|
+
broadcast(message: string, exclude?: string[]): void;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* PartyKit connection context (simplified).
|
|
76
|
+
*/
|
|
77
|
+
interface PartyConnectionContext {
|
|
78
|
+
request: Request;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* PartyKit server interface that bridge implements.
|
|
82
|
+
*/
|
|
83
|
+
interface PartyServer {
|
|
84
|
+
onConnect?(connection: PartyConnection, ctx: PartyConnectionContext): void | Promise<void>;
|
|
85
|
+
onMessage?(message: string, sender: PartyConnection): void | Promise<void>;
|
|
86
|
+
onClose?(connection: PartyConnection): void | Promise<void>;
|
|
87
|
+
onError?(connection: PartyConnection, error: Error): void | Promise<void>;
|
|
88
|
+
onRequest?(request: Request): Response | Promise<Response>;
|
|
89
|
+
onAlarm?(): void | Promise<void>;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Configuration for the PartyKit bridge adapter.
|
|
93
|
+
* Note: Port is not configurable - PartyKit manages this.
|
|
94
|
+
*/
|
|
95
|
+
export interface MCPWebBridgePartyConfig extends Omit<MCPWebConfig, 'bridgeUrl'> {
|
|
96
|
+
/**
|
|
97
|
+
* Session timeout check interval in milliseconds.
|
|
98
|
+
* PartyKit uses alarms instead of setInterval, so this determines
|
|
99
|
+
* how often the alarm fires to check for expired sessions.
|
|
100
|
+
* Default: 60000 (1 minute)
|
|
101
|
+
*/
|
|
102
|
+
sessionCheckIntervalMs?: number;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Scheduler implementation using PartyKit alarms.
|
|
106
|
+
*
|
|
107
|
+
* PartyKit only supports one alarm at a time per room, so this scheduler
|
|
108
|
+
* tracks multiple scheduled callbacks and uses the alarm for the soonest one.
|
|
109
|
+
*
|
|
110
|
+
* @see https://docs.partykit.io/guides/scheduling-tasks-with-alarms/
|
|
111
|
+
*/
|
|
112
|
+
export declare class AlarmScheduler implements Scheduler {
|
|
113
|
+
#private;
|
|
114
|
+
constructor(room: PartyRoom);
|
|
115
|
+
schedule(callback: () => void, delayMs: number): string;
|
|
116
|
+
cancel(id: string): void;
|
|
117
|
+
scheduleInterval(callback: () => void, intervalMs: number): string;
|
|
118
|
+
cancelInterval(id: string): void;
|
|
119
|
+
dispose(): void;
|
|
120
|
+
/**
|
|
121
|
+
* Called by the PartyKit server's onAlarm() handler.
|
|
122
|
+
* Executes due callbacks and reschedules the next alarm.
|
|
123
|
+
*/
|
|
124
|
+
handleAlarm(): Promise<void>;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Creates a PartyKit-compatible bridge server class.
|
|
128
|
+
*
|
|
129
|
+
* @example
|
|
130
|
+
* ```typescript
|
|
131
|
+
* // server.ts
|
|
132
|
+
* import { createPartyKitBridge } from '@mcp-web/bridge';
|
|
133
|
+
*
|
|
134
|
+
* export default createPartyKitBridge({
|
|
135
|
+
* name: 'My Bridge',
|
|
136
|
+
* description: 'MCP Web bridge on the edge',
|
|
137
|
+
* });
|
|
138
|
+
* ```
|
|
139
|
+
*/
|
|
140
|
+
export declare function createPartyKitBridge(config: MCPWebBridgePartyConfig): new (room: PartyRoom) => PartyServer;
|
|
141
|
+
/**
|
|
142
|
+
* Pre-configured bridge class for direct export.
|
|
143
|
+
* Use `createPartyKitBridge()` if you need custom configuration.
|
|
144
|
+
*
|
|
145
|
+
* @example
|
|
146
|
+
* ```typescript
|
|
147
|
+
* // For simple cases where you configure via environment
|
|
148
|
+
* export { MCPWebBridgeParty } from '@mcp-web/bridge';
|
|
149
|
+
* ```
|
|
150
|
+
*/
|
|
151
|
+
export declare const MCPWebBridgeParty: new (room: PartyRoom) => PartyServer;
|
|
152
|
+
export {};
|
|
153
|
+
//# sourceMappingURL=partykit.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"partykit.d.ts","sourceRoot":"","sources":["../../src/adapters/partykit.ts"],"names":[],"mappings":"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"}
|