diff --git a/.changeset/mcp-doctor-race.md b/.changeset/mcp-doctor-race.md new file mode 100644 index 0000000..37c84e4 --- /dev/null +++ b/.changeset/mcp-doctor-race.md @@ -0,0 +1,5 @@ +--- +'incur': patch +--- + +Fixed an intermittent `mcp doctor` failure where the tools/list response could be missed under load. diff --git a/src/Cli.test.ts b/src/Cli.test.ts index b5d158b..5215953 100644 --- a/src/Cli.test.ts +++ b/src/Cli.test.ts @@ -54,6 +54,7 @@ function mockMcpServeResponses(responses: unknown[]) { options!.output?.write( `${typeof response === 'string' ? response : JSON.stringify(response)}\n`, ) + options!.output?.end() }) } diff --git a/src/Cli.ts b/src/Cli.ts index 45976f3..1ebf729 100644 --- a/src/Cli.ts +++ b/src/Cli.ts @@ -2740,7 +2740,6 @@ async function runMcpDoctor( const input = new PassThrough() const output = new PassThrough() const chunks: string[] = [] - output.on('data', (chunk) => chunks.push(chunk.toString())) let serveError: unknown const done = Mcp.serve(name, options.version ?? '0.0.0', commands, { @@ -2768,7 +2767,19 @@ async function runMcpDoctor( })}\n`, ) input.write(`${Json.stringify({ jsonrpc: '2.0', id: 2, method: 'tools/list', params: {} })}\n`) - await new Promise((resolve) => setTimeout(resolve, 20)) + await new Promise((resolve) => { + let lines = 0 + output.on('data', (chunk) => { + const text = chunk.toString() + chunks.push(text) + lines += text.split('\n').length - 1 + if (lines >= 2) resolve() + }) + output.once('end', resolve) + done.then(() => { + if (serveError !== undefined) resolve() + }) + }) input.end() await done