@mohou/mcp-client 1.0.32 → 1.0.34
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/package.json +1 -1
- package/src/client.ts +29 -2
package/package.json
CHANGED
package/src/client.ts
CHANGED
|
@@ -218,12 +218,20 @@ export class McpClient {
|
|
|
218
218
|
if (current?.generation === generation) this.sessions.delete(serverId)
|
|
219
219
|
if (!this.recovering.has(serverId)) this.dropped.add(serverId)
|
|
220
220
|
}
|
|
221
|
+
const transport = transportFor(spec, scrubEnv(this.parentEnv)) as Transport
|
|
222
|
+
const stderr = collectStderr(transport)
|
|
221
223
|
try {
|
|
222
|
-
await client.connect(
|
|
224
|
+
await client.connect(transport)
|
|
223
225
|
return { client, generation }
|
|
224
226
|
} catch (error) {
|
|
225
227
|
await client.close().catch(() => undefined)
|
|
226
|
-
|
|
228
|
+
// A stdio server that exits reports nothing but "Connection closed", and its own last words
|
|
229
|
+
// are on stderr. Give the pipe a moment: they often land just after the socket closes.
|
|
230
|
+
await new Promise(resolve => setTimeout(resolve, STDERR_GRACE_MS))
|
|
231
|
+
const said = stderr.read()
|
|
232
|
+
const base = error instanceof Error ? error.message : 'mcp server did not start'
|
|
233
|
+
const message = said === undefined ? base : `${base} — ${said}`
|
|
234
|
+
throw new McpError('mcp-start-failed', this.redact(message, spec), { cause: error })
|
|
227
235
|
}
|
|
228
236
|
}
|
|
229
237
|
|
|
@@ -288,6 +296,25 @@ function transportFor(spec: McpServerSpec, parent: Record<string, string>) {
|
|
|
288
296
|
})
|
|
289
297
|
}
|
|
290
298
|
|
|
299
|
+
/** The child's own last words, capped: a server that dies says why on stderr, and nothing else does. */
|
|
300
|
+
const STDERR_TAIL_CHARS = 600
|
|
301
|
+
const STDERR_GRACE_MS = 100
|
|
302
|
+
|
|
303
|
+
function collectStderr(transport: Transport): { read(): string | undefined } {
|
|
304
|
+
const stream = (transport as { stderr?: NodeJS.ReadableStream | null }).stderr
|
|
305
|
+
if (stream === null || stream === undefined) return { read: () => undefined }
|
|
306
|
+
let tail = ''
|
|
307
|
+
stream.on('data', (chunk: Buffer | string) => {
|
|
308
|
+
tail = `${tail}${chunk.toString()}`.slice(-STDERR_TAIL_CHARS)
|
|
309
|
+
})
|
|
310
|
+
return {
|
|
311
|
+
read() {
|
|
312
|
+
const text = tail.trim()
|
|
313
|
+
return text.length === 0 ? undefined : text
|
|
314
|
+
},
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
|
|
291
318
|
function scrubEnv(env: NodeJS.ProcessEnv): Record<string, string> {
|
|
292
319
|
const next: Record<string, string> = {}
|
|
293
320
|
for (const [key, value] of Object.entries(env)) {
|