@platf/bridge 0.0.2

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.
Files changed (47) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +53 -0
  3. package/dist/gateways/statefulBridge.d.ts +22 -0
  4. package/dist/gateways/statefulBridge.js +211 -0
  5. package/dist/gateways/statefulBridge.js.map +1 -0
  6. package/dist/gateways/statelessBridge.d.ts +22 -0
  7. package/dist/gateways/statelessBridge.js +234 -0
  8. package/dist/gateways/statelessBridge.js.map +1 -0
  9. package/dist/index.d.ts +2 -0
  10. package/dist/index.js +117 -0
  11. package/dist/index.js.map +1 -0
  12. package/dist/lib/authMiddleware.d.ts +12 -0
  13. package/dist/lib/authMiddleware.js +41 -0
  14. package/dist/lib/authMiddleware.js.map +1 -0
  15. package/dist/lib/cors.d.ts +3 -0
  16. package/dist/lib/cors.js +29 -0
  17. package/dist/lib/cors.js.map +1 -0
  18. package/dist/lib/discoveryRoutes.d.ts +14 -0
  19. package/dist/lib/discoveryRoutes.js +86 -0
  20. package/dist/lib/discoveryRoutes.js.map +1 -0
  21. package/dist/lib/getLogger.d.ts +3 -0
  22. package/dist/lib/getLogger.js +34 -0
  23. package/dist/lib/getLogger.js.map +1 -0
  24. package/dist/lib/headers.d.ts +2 -0
  25. package/dist/lib/headers.js +19 -0
  26. package/dist/lib/headers.js.map +1 -0
  27. package/dist/lib/onSignals.d.ts +6 -0
  28. package/dist/lib/onSignals.js +16 -0
  29. package/dist/lib/onSignals.js.map +1 -0
  30. package/dist/lib/sessionAccessCounter.d.ts +11 -0
  31. package/dist/lib/sessionAccessCounter.js +72 -0
  32. package/dist/lib/sessionAccessCounter.js.map +1 -0
  33. package/dist/types.d.ts +11 -0
  34. package/dist/types.js +2 -0
  35. package/dist/types.js.map +1 -0
  36. package/package.json +41 -0
  37. package/src/gateways/statefulBridge.ts +271 -0
  38. package/src/gateways/statelessBridge.ts +310 -0
  39. package/src/index.ts +121 -0
  40. package/src/lib/authMiddleware.ts +58 -0
  41. package/src/lib/cors.ts +30 -0
  42. package/src/lib/discoveryRoutes.ts +95 -0
  43. package/src/lib/getLogger.ts +49 -0
  44. package/src/lib/headers.ts +26 -0
  45. package/src/lib/onSignals.ts +24 -0
  46. package/src/lib/sessionAccessCounter.ts +98 -0
  47. package/src/types.ts +12 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 platf.ai
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,53 @@
1
+ # platf-mcp-bridge
2
+
3
+ Stdio-to-Streamable HTTP bridge for MCP servers — part of the Platf AI Hub.
4
+
5
+ Wraps any MCP server that speaks JSON-RPC over **stdio** and exposes it as a **Streamable HTTP** (`/mcp`) endpoint. Built with [Bun](https://bun.sh).
6
+
7
+ ## Modes
8
+
9
+ | Flag | Mode | Description |
10
+ |------|------|-------------|
11
+ | _(default)_ | **Stateless** | Spawns a fresh child process per request. Auto-initializes if the incoming message isn't an `initialize` request. |
12
+ | `--stateful` | **Stateful** | One child process per session (`Mcp-Session-Id` header). Optional inactivity timeout via `--sessionTimeout`. |
13
+
14
+ ## Usage
15
+
16
+ ```bash
17
+ # Stateless (default)
18
+ bun run src/index.ts --stdio "npx -y @modelcontextprotocol/server-everything" --port 8000 --cors '*' --healthEndpoint /healthz
19
+
20
+ # Stateful with 10 min session timeout
21
+ bun run src/index.ts --stdio "npx -y @modelcontextprotocol/server-everything" --stateful --sessionTimeout 600000 --cors '*'
22
+ ```
23
+
24
+ ## Docker
25
+
26
+ ```bash
27
+ docker build -t platf-mcp-bridge .
28
+
29
+ docker run -p 8000:8000 platf-mcp-bridge \
30
+ --stdio "npx -y @modelcontextprotocol/server-everything" \
31
+ --cors '*' --healthEndpoint /healthz
32
+ ```
33
+
34
+ ## Options
35
+
36
+ | Option | Default | Description |
37
+ |--------|---------|-------------|
38
+ | `--stdio` | _(required)_ | Shell command for the stdio MCP server |
39
+ | `--port` | `8000` | HTTP listen port |
40
+ | `--path` | `/mcp` | HTTP endpoint path |
41
+ | `--stateful` | `false` | Enable stateful session mode |
42
+ | `--sessionTimeout` | — | Inactivity timeout (ms), stateful only |
43
+ | `--protocolVersion` | `2025-03-26` | MCP protocol version for auto-init |
44
+ | `--logLevel` | `info` | `none` / `info` / `debug` |
45
+ | `--cors` | — | CORS origins (omit=disabled, `*`=all) |
46
+ | `--healthEndpoint` | — | Health-check path(s) returning 200 |
47
+ | `--header` | — | Extra response headers (`Key: Value`) |
48
+
49
+ ```bash
50
+ bun run index.ts
51
+ ```
52
+
53
+ This project was created using `bun init` in bun v1.3.7. [Bun](https://bun.com) is a fast all-in-one JavaScript runtime.
@@ -0,0 +1,22 @@
1
+ import { type CorsOptions } from 'cors';
2
+ import type { AuthConfig, Logger } from '../types.js';
3
+ export interface StatefulBridgeArgs {
4
+ stdioCmd: string;
5
+ port: number;
6
+ path: string;
7
+ logger: Logger;
8
+ corsOrigin: CorsOptions['origin'];
9
+ healthEndpoints: string[];
10
+ headers: Record<string, string>;
11
+ sessionTimeout: number | null;
12
+ auth: AuthConfig | null;
13
+ }
14
+ /**
15
+ * Stateful stdio-to-Streamable HTTP bridge.
16
+ *
17
+ * Maintains session state via `Mcp-Session-Id` header. Each session
18
+ * spawns one child process; subsequent requests for the same session
19
+ * reuse the existing transport and process. Sessions are cleaned up
20
+ * after an optional inactivity timeout.
21
+ */
22
+ export declare function startStatefulBridge(args: StatefulBridgeArgs): Promise<void>;
@@ -0,0 +1,211 @@
1
+ import express from 'express';
2
+ import cors from 'cors';
3
+ import { spawn } from 'child_process';
4
+ import { randomUUID } from 'node:crypto';
5
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
6
+ import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
7
+ import { isInitializeRequest } from '@modelcontextprotocol/sdk/types.js';
8
+ import { onSignals } from '../lib/onSignals.js';
9
+ import { serializeCorsOrigin } from '../lib/cors.js';
10
+ import { SessionAccessCounter } from '../lib/sessionAccessCounter.js';
11
+ import { createAuthMiddleware } from '../lib/authMiddleware.js';
12
+ import { createDiscoveryRouter } from '../lib/discoveryRoutes.js';
13
+ const VERSION = '1.0.0';
14
+ const setResponseHeaders = (res, headers) => Object.entries(headers).forEach(([key, value]) => res.setHeader(key, value));
15
+ /**
16
+ * Stateful stdio-to-Streamable HTTP bridge.
17
+ *
18
+ * Maintains session state via `Mcp-Session-Id` header. Each session
19
+ * spawns one child process; subsequent requests for the same session
20
+ * reuse the existing transport and process. Sessions are cleaned up
21
+ * after an optional inactivity timeout.
22
+ */
23
+ export async function startStatefulBridge(args) {
24
+ const { stdioCmd, port, path, logger, corsOrigin, healthEndpoints, headers, sessionTimeout, auth, } = args;
25
+ logger.info(`[stateful] Starting platf-bridge`);
26
+ logger.info(` - Headers: ${Object.keys(headers).length ? JSON.stringify(headers) : '(none)'}`);
27
+ logger.info(` - port: ${port}`);
28
+ logger.info(` - stdio: ${stdioCmd}`);
29
+ logger.info(` - path: ${path}`);
30
+ logger.info(` - CORS: ${corsOrigin ? `enabled (${serializeCorsOrigin(corsOrigin)})` : 'disabled'}`);
31
+ logger.info(` - Health endpoints: ${healthEndpoints.length ? healthEndpoints.join(', ') : '(none)'}`);
32
+ logger.info(` - Session timeout: ${sessionTimeout ? `${sessionTimeout}ms` : 'disabled'}`);
33
+ onSignals({ logger });
34
+ const app = express();
35
+ app.use(express.json());
36
+ if (corsOrigin) {
37
+ app.use(cors({ origin: corsOrigin, exposedHeaders: ['Mcp-Session-Id'] }));
38
+ }
39
+ for (const ep of healthEndpoints) {
40
+ app.get(ep, (_req, res) => {
41
+ setResponseHeaders(res, headers);
42
+ res.send('ok');
43
+ });
44
+ }
45
+ // --- OAuth discovery & auth middleware (when auth is enabled) ---
46
+ if (auth) {
47
+ app.use(createDiscoveryRouter(auth, logger));
48
+ app.use(path, createAuthMiddleware(auth, logger));
49
+ logger.info(` - Auth: enabled (issuer=${auth.issuer})`);
50
+ }
51
+ // Session state
52
+ const transports = {};
53
+ const sessionCounter = sessionTimeout
54
+ ? new SessionAccessCounter(sessionTimeout, (sessionId) => {
55
+ logger.info(`Session ${sessionId} timed out, cleaning up`);
56
+ const transport = transports[sessionId];
57
+ if (transport)
58
+ transport.close();
59
+ delete transports[sessionId];
60
+ }, logger)
61
+ : null;
62
+ // --- POST handler ---
63
+ app.post(path, async (req, res) => {
64
+ const sessionId = req.headers['mcp-session-id'];
65
+ let transport;
66
+ if (sessionId && transports[sessionId]) {
67
+ // Reuse existing session
68
+ transport = transports[sessionId];
69
+ sessionCounter?.inc(sessionId, 'POST request for existing session');
70
+ }
71
+ else if (!sessionId && isInitializeRequest(req.body)) {
72
+ // New session — spawn child process
73
+ const server = new Server({ name: 'platf-bridge', version: VERSION }, { capabilities: {} });
74
+ transport = new StreamableHTTPServerTransport({
75
+ sessionIdGenerator: () => randomUUID(),
76
+ onsessioninitialized: (newSessionId) => {
77
+ transports[newSessionId] = transport;
78
+ sessionCounter?.inc(newSessionId, 'session initialization');
79
+ },
80
+ });
81
+ await server.connect(transport);
82
+ const child = spawn(stdioCmd, { shell: true });
83
+ const pendingRequestIds = new Set();
84
+ let stderrOutput = '';
85
+ child.on('exit', (code, signal) => {
86
+ logger.error(`Child exited: code=${code}, signal=${signal}`);
87
+ // Send JSON-RPC error responses for all pending requests
88
+ for (const id of pendingRequestIds) {
89
+ const detail = stderrOutput.trim().slice(0, 1000);
90
+ const message = detail
91
+ ? `Child process exited (code=${code}): ${detail}`
92
+ : `Child process exited unexpectedly (code=${code}, signal=${signal})`;
93
+ try {
94
+ transport.send({
95
+ jsonrpc: '2.0',
96
+ error: { code: -32603, message },
97
+ id,
98
+ });
99
+ }
100
+ catch (e) {
101
+ logger.error(`Failed to send error response for request ${id}`, e);
102
+ }
103
+ }
104
+ pendingRequestIds.clear();
105
+ transport.close();
106
+ });
107
+ let buffer = '';
108
+ child.stdout.on('data', (chunk) => {
109
+ buffer += chunk.toString('utf8');
110
+ const lines = buffer.split(/\r?\n/);
111
+ buffer = lines.pop() ?? '';
112
+ for (const line of lines) {
113
+ if (!line.trim())
114
+ continue;
115
+ try {
116
+ const jsonMsg = JSON.parse(line);
117
+ if ('id' in jsonMsg && jsonMsg.id !== undefined) {
118
+ pendingRequestIds.delete(jsonMsg.id);
119
+ }
120
+ logger.info('Child → HTTP:', line);
121
+ try {
122
+ transport.send(jsonMsg);
123
+ }
124
+ catch (e) {
125
+ logger.error('Failed to send to HTTP transport', e);
126
+ }
127
+ }
128
+ catch {
129
+ logger.error(`Child non-JSON: ${line}`);
130
+ }
131
+ }
132
+ });
133
+ child.stderr.on('data', (chunk) => {
134
+ const text = chunk.toString('utf8');
135
+ stderrOutput += text;
136
+ logger.error(`Child stderr: ${text}`);
137
+ });
138
+ transport.onmessage = (msg) => {
139
+ logger.info(`HTTP → Child: ${JSON.stringify(msg)}`);
140
+ if ('id' in msg && msg.id !== undefined) {
141
+ pendingRequestIds.add(msg.id);
142
+ }
143
+ child.stdin.write(JSON.stringify(msg) + '\n');
144
+ };
145
+ transport.onclose = () => {
146
+ logger.info(`HTTP connection closed (session ${sessionId})`);
147
+ if (transport.sessionId) {
148
+ sessionCounter?.clear(transport.sessionId, false, 'transport closed');
149
+ delete transports[transport.sessionId];
150
+ }
151
+ child.kill();
152
+ };
153
+ transport.onerror = (err) => {
154
+ logger.error(`HTTP transport error (session ${sessionId}):`, err);
155
+ if (transport.sessionId) {
156
+ sessionCounter?.clear(transport.sessionId, false, 'transport error');
157
+ delete transports[transport.sessionId];
158
+ }
159
+ child.kill();
160
+ };
161
+ }
162
+ else {
163
+ res.status(400).json({
164
+ jsonrpc: '2.0',
165
+ error: { code: -32000, message: 'Bad Request: No valid session ID provided' },
166
+ id: null,
167
+ });
168
+ return;
169
+ }
170
+ // Track response lifecycle for session cleanup
171
+ let responseEnded = false;
172
+ const handleResponseEnd = (event) => {
173
+ if (!responseEnded && transport.sessionId) {
174
+ responseEnded = true;
175
+ logger.info(`Response ${event}`, transport.sessionId);
176
+ sessionCounter?.dec(transport.sessionId, `POST response ${event}`);
177
+ }
178
+ };
179
+ res.on('finish', () => handleResponseEnd('finished'));
180
+ res.on('close', () => handleResponseEnd('closed'));
181
+ await transport.handleRequest(req, res, req.body);
182
+ });
183
+ // --- GET / DELETE handler (session-bound) ---
184
+ const handleSessionRequest = async (req, res) => {
185
+ const sessionId = req.headers['mcp-session-id'];
186
+ if (!sessionId || !transports[sessionId]) {
187
+ res.status(400).send('Invalid or missing session ID');
188
+ return;
189
+ }
190
+ sessionCounter?.inc(sessionId, `${req.method} request for existing session`);
191
+ let responseEnded = false;
192
+ const handleResponseEnd = (event) => {
193
+ if (!responseEnded) {
194
+ responseEnded = true;
195
+ logger.info(`Response ${event}`, sessionId);
196
+ sessionCounter?.dec(sessionId, `${req.method} response ${event}`);
197
+ }
198
+ };
199
+ res.on('finish', () => handleResponseEnd('finished'));
200
+ res.on('close', () => handleResponseEnd('closed'));
201
+ const transport = transports[sessionId];
202
+ await transport.handleRequest(req, res);
203
+ };
204
+ app.get(path, handleSessionRequest);
205
+ app.delete(path, handleSessionRequest);
206
+ app.listen(port, () => {
207
+ logger.info(`Listening on port ${port}`);
208
+ logger.info(`Streamable HTTP endpoint: http://localhost:${port}${path}`);
209
+ });
210
+ }
211
+ //# sourceMappingURL=statefulBridge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"statefulBridge.js","sourceRoot":"","sources":["../../src/gateways/statefulBridge.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ import { type CorsOptions } from 'cors';
2
+ import type { AuthConfig, Logger } from '../types.js';
3
+ export interface StatelessBridgeArgs {
4
+ stdioCmd: string;
5
+ port: number;
6
+ path: string;
7
+ logger: Logger;
8
+ corsOrigin: CorsOptions['origin'];
9
+ healthEndpoints: string[];
10
+ headers: Record<string, string>;
11
+ protocolVersion: string;
12
+ auth: AuthConfig | null;
13
+ }
14
+ /**
15
+ * Stateless stdio-to-Streamable HTTP bridge.
16
+ *
17
+ * For every incoming POST request, spawns a fresh child process,
18
+ * auto-initializes it if the request is not an initialize request,
19
+ * and proxies JSON-RPC messages between the HTTP transport and the
20
+ * child's stdin/stdout.
21
+ */
22
+ export declare function startStatelessBridge(args: StatelessBridgeArgs): Promise<void>;
@@ -0,0 +1,234 @@
1
+ import express from 'express';
2
+ import cors from 'cors';
3
+ import { spawn } from 'child_process';
4
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
5
+ import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
6
+ import { isInitializeRequest, } from '@modelcontextprotocol/sdk/types.js';
7
+ import { onSignals } from '../lib/onSignals.js';
8
+ import { serializeCorsOrigin } from '../lib/cors.js';
9
+ import { createAuthMiddleware } from '../lib/authMiddleware.js';
10
+ import { createDiscoveryRouter } from '../lib/discoveryRoutes.js';
11
+ const VERSION = '1.0.0';
12
+ const setResponseHeaders = (res, headers) => Object.entries(headers).forEach(([key, value]) => res.setHeader(key, value));
13
+ /** Create a synthetic MCP initialize request */
14
+ const createInitializeRequest = (id, protocolVersion) => ({
15
+ jsonrpc: '2.0',
16
+ id,
17
+ method: 'initialize',
18
+ params: {
19
+ protocolVersion,
20
+ capabilities: {
21
+ roots: { listChanged: true },
22
+ sampling: {},
23
+ },
24
+ clientInfo: {
25
+ name: 'platf-bridge',
26
+ version: VERSION,
27
+ },
28
+ },
29
+ });
30
+ const createInitializedNotification = () => ({
31
+ jsonrpc: '2.0',
32
+ method: 'notifications/initialized',
33
+ });
34
+ /**
35
+ * Stateless stdio-to-Streamable HTTP bridge.
36
+ *
37
+ * For every incoming POST request, spawns a fresh child process,
38
+ * auto-initializes it if the request is not an initialize request,
39
+ * and proxies JSON-RPC messages between the HTTP transport and the
40
+ * child's stdin/stdout.
41
+ */
42
+ export async function startStatelessBridge(args) {
43
+ const { stdioCmd, port, path, logger, corsOrigin, healthEndpoints, headers, protocolVersion, auth, } = args;
44
+ logger.info(`[stateless] Starting platf-bridge`);
45
+ logger.info(` - Headers: ${Object.keys(headers).length ? JSON.stringify(headers) : '(none)'}`);
46
+ logger.info(` - port: ${port}`);
47
+ logger.info(` - stdio: ${stdioCmd}`);
48
+ logger.info(` - path: ${path}`);
49
+ logger.info(` - protocolVersion: ${protocolVersion}`);
50
+ logger.info(` - CORS: ${corsOrigin ? `enabled (${serializeCorsOrigin(corsOrigin)})` : 'disabled'}`);
51
+ logger.info(` - Health endpoints: ${healthEndpoints.length ? healthEndpoints.join(', ') : '(none)'}`);
52
+ onSignals({ logger });
53
+ const app = express();
54
+ app.use(express.json());
55
+ if (corsOrigin) {
56
+ app.use(cors({ origin: corsOrigin }));
57
+ }
58
+ for (const ep of healthEndpoints) {
59
+ app.get(ep, (_req, res) => {
60
+ setResponseHeaders(res, headers);
61
+ res.send('ok');
62
+ });
63
+ }
64
+ // --- OAuth discovery & auth middleware (when auth is enabled) ---
65
+ if (auth) {
66
+ app.use(createDiscoveryRouter(auth, logger));
67
+ app.use(path, createAuthMiddleware(auth, logger));
68
+ logger.info(` - Auth: enabled (issuer=${auth.issuer})`);
69
+ }
70
+ app.post(path, async (req, res) => {
71
+ try {
72
+ const server = new Server({ name: 'platf-bridge', version: VERSION }, { capabilities: {} });
73
+ const transport = new StreamableHTTPServerTransport({
74
+ sessionIdGenerator: undefined,
75
+ });
76
+ await server.connect(transport);
77
+ const child = spawn(stdioCmd, { shell: true });
78
+ const pendingRequestIds = new Set();
79
+ let stderrOutput = '';
80
+ child.on('exit', (code, signal) => {
81
+ logger.error(`Child exited: code=${code}, signal=${signal}`);
82
+ // Include queued original message's ID if it was never sent to the child
83
+ if (pendingOriginalMessage && 'id' in pendingOriginalMessage && pendingOriginalMessage.id !== undefined) {
84
+ pendingRequestIds.add(pendingOriginalMessage.id);
85
+ pendingOriginalMessage = null;
86
+ }
87
+ // Remove auto-init ID — the client doesn't expect a response for it
88
+ if (isAutoInitializing && initializeRequestId !== null) {
89
+ pendingRequestIds.delete(initializeRequestId);
90
+ }
91
+ // Send JSON-RPC error responses for all pending client requests
92
+ for (const id of pendingRequestIds) {
93
+ const detail = stderrOutput.trim().slice(0, 1000);
94
+ const message = detail
95
+ ? `Child process exited (code=${code}): ${detail}`
96
+ : `Child process exited unexpectedly (code=${code}, signal=${signal})`;
97
+ try {
98
+ transport.send({
99
+ jsonrpc: '2.0',
100
+ error: { code: -32603, message },
101
+ id,
102
+ });
103
+ }
104
+ catch (e) {
105
+ logger.error(`Failed to send error response for request ${id}`, e);
106
+ }
107
+ }
108
+ pendingRequestIds.clear();
109
+ transport.close();
110
+ });
111
+ // --- Auto-initialization state ---
112
+ let isInitialized = false;
113
+ let initializeRequestId = null;
114
+ let isAutoInitializing = false;
115
+ let pendingOriginalMessage = null;
116
+ let buffer = '';
117
+ child.stdout.on('data', (chunk) => {
118
+ buffer += chunk.toString('utf8');
119
+ const lines = buffer.split(/\r?\n/);
120
+ buffer = lines.pop() ?? '';
121
+ for (const line of lines) {
122
+ if (!line.trim())
123
+ continue;
124
+ try {
125
+ const jsonMsg = JSON.parse(line);
126
+ if ('id' in jsonMsg && jsonMsg.id !== undefined) {
127
+ pendingRequestIds.delete(jsonMsg.id);
128
+ }
129
+ logger.info('Child → HTTP:', line);
130
+ // Handle initialize response (auto or client-initiated)
131
+ if (initializeRequestId && jsonMsg.id === initializeRequestId) {
132
+ logger.info('Initialize response received');
133
+ isInitialized = true;
134
+ if (isAutoInitializing) {
135
+ // Send initialized notification then the queued original message
136
+ const notification = createInitializedNotification();
137
+ logger.info(`HTTP → Child (initialized): ${JSON.stringify(notification)}`);
138
+ child.stdin.write(JSON.stringify(notification) + '\n');
139
+ if (pendingOriginalMessage) {
140
+ logger.info(`HTTP → Child (original): ${JSON.stringify(pendingOriginalMessage)}`);
141
+ child.stdin.write(JSON.stringify(pendingOriginalMessage) + '\n');
142
+ pendingOriginalMessage = null;
143
+ }
144
+ isAutoInitializing = false;
145
+ initializeRequestId = null;
146
+ return; // don't forward auto-init response to client
147
+ }
148
+ initializeRequestId = null;
149
+ }
150
+ try {
151
+ transport.send(jsonMsg);
152
+ }
153
+ catch (e) {
154
+ logger.error('Failed to send to HTTP transport', e);
155
+ }
156
+ }
157
+ catch {
158
+ logger.error(`Child non-JSON: ${line}`);
159
+ }
160
+ }
161
+ });
162
+ child.stderr.on('data', (chunk) => {
163
+ const text = chunk.toString('utf8');
164
+ stderrOutput += text;
165
+ logger.error(`Child stderr: ${text}`);
166
+ });
167
+ transport.onmessage = (msg) => {
168
+ logger.info(`HTTP → Child: ${JSON.stringify(msg)}`);
169
+ // Track client request IDs for error reporting on child exit
170
+ if ('id' in msg && msg.id !== undefined) {
171
+ pendingRequestIds.add(msg.id);
172
+ }
173
+ // Auto-initialize if the first message is not an initialize request
174
+ if (!isInitialized && !isInitializeRequest(msg)) {
175
+ pendingOriginalMessage = msg;
176
+ initializeRequestId = `init_${Date.now()}_${Math.random().toString(36).slice(2, 11)}`;
177
+ isAutoInitializing = true;
178
+ logger.info('Non-initialize message detected, sending auto-initialize first');
179
+ const initReq = createInitializeRequest(initializeRequestId, protocolVersion);
180
+ logger.info(`HTTP → Child (auto-init): ${JSON.stringify(initReq)}`);
181
+ child.stdin.write(JSON.stringify(initReq) + '\n');
182
+ return;
183
+ }
184
+ // Track client-initiated initialize
185
+ if (isInitializeRequest(msg) && 'id' in msg && msg.id !== undefined) {
186
+ initializeRequestId = msg.id;
187
+ isAutoInitializing = false;
188
+ logger.info(`Tracking initialize request ID: ${msg.id}`);
189
+ }
190
+ child.stdin.write(JSON.stringify(msg) + '\n');
191
+ };
192
+ transport.onclose = () => {
193
+ logger.info('HTTP connection closed');
194
+ child.kill();
195
+ };
196
+ transport.onerror = (err) => {
197
+ logger.error('HTTP transport error:', err);
198
+ child.kill();
199
+ };
200
+ await transport.handleRequest(req, res, req.body);
201
+ }
202
+ catch (error) {
203
+ logger.error('Error handling MCP request:', error);
204
+ if (!res.headersSent) {
205
+ res.status(500).json({
206
+ jsonrpc: '2.0',
207
+ error: { code: -32603, message: 'Internal server error' },
208
+ id: null,
209
+ });
210
+ }
211
+ }
212
+ });
213
+ app.get(path, (_req, res) => {
214
+ logger.info('Received GET — method not allowed in stateless mode');
215
+ res.writeHead(405).end(JSON.stringify({
216
+ jsonrpc: '2.0',
217
+ error: { code: -32000, message: 'Method not allowed.' },
218
+ id: null,
219
+ }));
220
+ });
221
+ app.delete(path, (_req, res) => {
222
+ logger.info('Received DELETE — method not allowed in stateless mode');
223
+ res.writeHead(405).end(JSON.stringify({
224
+ jsonrpc: '2.0',
225
+ error: { code: -32000, message: 'Method not allowed.' },
226
+ id: null,
227
+ }));
228
+ });
229
+ app.listen(port, () => {
230
+ logger.info(`Listening on port ${port}`);
231
+ logger.info(`Streamable HTTP endpoint: http://localhost:${port}${path}`);
232
+ });
233
+ }
234
+ //# sourceMappingURL=statelessBridge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"statelessBridge.js","sourceRoot":"","sources":["../../src/gateways/statelessBridge.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};