Skip to content

Commit fb58897

Browse files
authored
Merge pull request #90 from supercorp-ai/rollback-to-v3.2-1
Rollback code to v3.2.0 for upcoming v3.4 release
2 parents 4711c1c + b4197b8 commit fb58897

File tree

9 files changed

+42
-328
lines changed

9 files changed

+42
-328
lines changed

README.md

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,6 @@ npx -y supergateway --stdio "uvx mcp-server-git"
2828
- **`--logLevel debug | info | none`**: Controls logging level (default: `info`). Use `debug` for more verbose logs, `none` to suppress all logs.
2929
- **`--cors`**: Enable CORS (stdio→SSE or stdio→WS mode). Use `--cors` with no values to allow all origins, or supply one or more allowed origins (e.g. `--cors "http://example.com"` or `--cors "/example\\.com$/"` for regex matching).
3030
- **`--healthEndpoint /healthz`**: Register one or more endpoints (stdio→SSE or stdio→WS mode; can be used multiple times) that respond with `"ok"`
31-
- **`--minConcurrency 1`**: Minimum concurrency for stdio server (stdio→SSE; default: `1`).
32-
- **`--maxConcurrency 10`**: Max concurrency for stdio server (stdio→SSE; default: `1`).
3331

3432
## stdio → SSE
3533

@@ -297,9 +295,6 @@ Supergateway emphasizes modularity:
297295

298296
## Contributors
299297

300-
- [@rsonghuster](https://github.com/rsonghuster)
301-
- [@zxypro1](https://github.com/zxypro1)
302-
- [@nicojahn](https://github.com/nicojahn)
303298
- [@griffinqiu](https://github.com/griffinqiu)
304299
- [@folkvir](https://github.com/folkvir)
305300
- [@wizizm](https://github.com/wizizm)

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "supergateway",
3-
"version": "3.3.0",
3+
"version": "3.2.0",
44
"description": "Run MCP stdio servers over SSE, Streamable HTTP or visa versa",
55
"repository": {
66
"type": "git",

src/gateways/stdioToSse.ts

Lines changed: 38 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import { Logger } from '../types.js'
99
import { getVersion } from '../lib/getVersion.js'
1010
import { onSignals } from '../lib/onSignals.js'
1111
import { serializeCorsOrigin } from '../lib/serializeCorsOrigin.js'
12-
import { StdioChildProcessPool } from '../lib/stdioProcessPool.js'
1312

1413
export interface StdioToSseArgs {
1514
stdioCmd: string
@@ -21,8 +20,6 @@ export interface StdioToSseArgs {
2120
corsOrigin: CorsOptions['origin']
2221
healthEndpoints: string[]
2322
headers: Record<string, string>
24-
minConcurrency: number
25-
maxConcurrency: number
2623
}
2724

2825
const setResponseHeaders = ({
@@ -47,8 +44,6 @@ export async function stdioToSse(args: StdioToSseArgs) {
4744
corsOrigin,
4845
healthEndpoints,
4946
headers,
50-
minConcurrency,
51-
maxConcurrency,
5247
} = args
5348

5449
logger.info(
@@ -68,20 +63,20 @@ export async function stdioToSse(args: StdioToSseArgs) {
6863
logger.info(
6964
` - Health endpoints: ${healthEndpoints.length ? healthEndpoints.join(', ') : '(none)'}`,
7065
)
71-
if (minConcurrency > 1 || maxConcurrency > 1) {
72-
logger.info(` - minConcurrency: ${minConcurrency}`)
73-
logger.info(` - maxConcurrency: ${maxConcurrency}`)
74-
}
7566

7667
onSignals({ logger })
7768

78-
const pool = new StdioChildProcessPool({
79-
stdioCmd,
80-
minConcurrency,
81-
maxConcurrency,
82-
logger,
69+
const child: ChildProcessWithoutNullStreams = spawn(stdioCmd, { shell: true })
70+
child.on('exit', (code, signal) => {
71+
logger.error(`Child exited: code=${code}, signal=${signal}`)
72+
process.exit(code ?? 1)
8373
})
8474

75+
const server = new Server(
76+
{ name: 'supergateway', version: getVersion() },
77+
{ capabilities: {} },
78+
)
79+
8580
const sessions: Record<
8681
string,
8782
{ transport: SSEServerTransport; response: express.Response }
@@ -116,20 +111,7 @@ export async function stdioToSse(args: StdioToSseArgs) {
116111
headers,
117112
})
118113

119-
let child: ChildProcessWithoutNullStreams
120-
try {
121-
child = await pool.acquire()
122-
} catch (err) {
123-
logger.error('Failed to acquire child process:', err)
124-
res.status(503).send('Service unavailable')
125-
return
126-
}
127-
128114
const sseTransport = new SSEServerTransport(`${baseUrl}${messagePath}`, res)
129-
const server = new Server(
130-
{ name: 'supergateway', version: getVersion() },
131-
{ capabilities: {} },
132-
)
133115
await server.connect(sseTransport)
134116

135117
const sessionId = sseTransport.sessionId
@@ -152,37 +134,9 @@ export async function stdioToSse(args: StdioToSseArgs) {
152134
delete sessions[sessionId]
153135
}
154136

155-
let buffer = ''
156-
const onStdoutData = (chunk: Buffer) => {
157-
buffer += chunk.toString('utf8')
158-
const lines = buffer.split(/\r?\n/)
159-
buffer = lines.pop() ?? ''
160-
lines.forEach((line) => {
161-
if (!line.trim()) return
162-
try {
163-
const jsonMsg = JSON.parse(line)
164-
logger.info(`Child → SSE (session ${sessionId}):`, jsonMsg)
165-
sseTransport.send(jsonMsg)
166-
} catch (err) {
167-
logger.error(`Child non-JSON (session ${sessionId}): ${line}`, err)
168-
}
169-
})
170-
}
171-
child.stdout.on('data', onStdoutData)
172-
const onExit = (code: number | null, signal: NodeJS.Signals | null) => {
173-
logger.error(
174-
`Child process exited (session ${sessionId}): code=${code}, signal=${signal}`,
175-
)
176-
server.close()
177-
}
178-
child.on('exit', onExit)
179-
180137
req.on('close', () => {
181138
logger.info(`Client disconnected (session ${sessionId})`)
182-
server.close()
183-
child.stdout.off('data', onStdoutData)
184-
child.off('exit', onExit)
185-
pool.release(child)
139+
delete sessions[sessionId]
186140
})
187141
})
188142

@@ -213,4 +167,32 @@ export async function stdioToSse(args: StdioToSseArgs) {
213167
logger.info(`SSE endpoint: http://localhost:${port}${ssePath}`)
214168
logger.info(`POST messages: http://localhost:${port}${messagePath}`)
215169
})
170+
171+
let buffer = ''
172+
child.stdout.on('data', (chunk: Buffer) => {
173+
buffer += chunk.toString('utf8')
174+
const lines = buffer.split(/\r?\n/)
175+
buffer = lines.pop() ?? ''
176+
lines.forEach((line) => {
177+
if (!line.trim()) return
178+
try {
179+
const jsonMsg = JSON.parse(line)
180+
logger.info('Child → SSE:', jsonMsg)
181+
for (const [sid, session] of Object.entries(sessions)) {
182+
try {
183+
session.transport.send(jsonMsg)
184+
} catch (err) {
185+
logger.error(`Failed to send to session ${sid}:`, err)
186+
delete sessions[sid]
187+
}
188+
}
189+
} catch {
190+
logger.error(`Child non-JSON: ${line}`)
191+
}
192+
})
193+
})
194+
195+
child.stderr.on('data', (chunk: Buffer) => {
196+
logger.error(`Child stderr: ${chunk.toString('utf8')}`)
197+
})
216198
}

src/index.ts

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -123,18 +123,6 @@ async function main() {
123123
description:
124124
'Session timeout in milliseconds. Only supported for stateful stdio→StreamableHttp. If not set, the session will only be deleted when client transport explicitly terminates the session.',
125125
})
126-
.option('minConcurrency', {
127-
type: 'number',
128-
default: 1,
129-
description:
130-
'Minimum number of concurrent processes (stdio→SSE). Default is 1.',
131-
})
132-
.option('maxConcurrency', {
133-
type: 'number',
134-
default: 1,
135-
description:
136-
'Maximum number of concurrent processes (stdio→SSE). Default is 1.',
137-
})
138126
.help()
139127
.parseSync()
140128

@@ -185,8 +173,6 @@ async function main() {
185173
argv,
186174
logger,
187175
}),
188-
minConcurrency: argv.minConcurrency,
189-
maxConcurrency: argv.maxConcurrency,
190176
})
191177
} else if (argv.outputTransport === 'ws') {
192178
await stdioToWs({

src/lib/stdioProcessPool.ts

Lines changed: 0 additions & 108 deletions
This file was deleted.

supergateway.png

-14.7 KB
Loading

tests/concurrency.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { SSEClientTransport } from '@modelcontextprotocol/sdk/client/sse.js'
88

99
const BASE_URL = 'http://localhost:11001'
1010
const SSE_PATH = '/sse'
11-
const CONCURRENCY = 100
11+
const CONCURRENCY = 1
1212

1313
function makeLimiter(maxConcurrency: number) {
1414
let active = 0

0 commit comments

Comments
 (0)