[GH-ISSUE #2673] fix(cli): mcp doctor drops the requested full output envelope #973

Closed
opened 2026-10-15 18:30:01 +00:00 by bsakaguchi · 1 comment
Owner

Originally created by @coygeek on GitHub (Oct 13, 2026).
Original GitHub issue: https://github.com/morluto/rea/issues/2673

Summary

rea mcp doctor offers --full-output in its own help, but accepting that flag leaves the JSON report unwrapped. A caller requesting the envelope receives neither ok nor meta. The diagnostic report and its failure status remain available, so consumers can use the bare report as a workaround.

Runtime or environment

Verified source revision a2d8b94dd5 with Node 24.18.0 and npm 11.16.0. The executed check used the source CLI entry and an owned child fixture that immediately exits. The published package and a healthy production MCP session were not executed. A source-only recheck at 3ae826ceba confirms that the doctor parser and formatter still discard the requested flag; the current checkout was not executed.

Steps to reproduce

With the checkout's locked dependencies installed, save the following as src/doctor-output-repro.test.ts, then run npm run test:local -- src/doctor-output-repro.test.ts. This is a self-contained rendering of the executed source check, with the fixture directory made portable. The fixture only writes a diagnostic and exits; it needs no analysis provider or client configuration.

import { expect, it } from "vitest";
import { mkdtemp, rm, writeFile } from "node:fs/promises";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { runProductionMcpDoctorCli } from "./mcpDoctor.js";

it("compares doctor output with and without the advertised envelope flag", async () => {
  const root = await mkdtemp(join(tmpdir(), "doctor-output-"));
  try {
    const dispatcherPath = join(root, "doctor-exit.mjs");
    await writeFile(dispatcherPath,
      'process.stderr.write("owned doctor fixture exited\\n");\nprocess.exitCode = 1;\n');
    const input = { dispatcherPath, packageRoot: root };
    const help = await runProductionMcpDoctorCli(["--help"], input);
    expect(help.exitCode).toBe(0);
    expect(help.output).toMatch(/--full-output\s+Show the full output envelope/);
    const bare = await runProductionMcpDoctorCli(["--json"], input);
    const full = await runProductionMcpDoctorCli(["--json", "--full-output"], input);
    const bareReport = JSON.parse(bare.output);
    const fullReport = JSON.parse(full.output);
    expect(bare.exitCode).toBe(1);
    expect(full.exitCode).toBe(1);
    expect(fullReport).toEqual(bareReport);
    expect(fullReport.healthy).toBe(false);
    expect(fullReport.diagnostics.stderr).toBe("owned doctor fixture exited\n");
    expect(fullReport).not.toHaveProperty("ok");
    expect(fullReport).not.toHaveProperty("meta");
    console.log(JSON.stringify({
      bareExit: bare.exitCode,
      fullExit: full.exitCode,
      identicalReports: true,
      keys: Object.keys(fullReport),
    }));
  } finally {
    await rm(root, { recursive: true, force: true });
  }
}, 10000);

The public executable input is rea mcp doctor --json --full-output, compared with rea mcp doctor --json. Those executable commands were not run for this report; source inspection confirms their dispatcher reaches the tested entry when compiled runtime files are present.

Expected behavior

The command's own help promises "Show the full output envelope" for --full-output. Selecting it should produce an envelope carrying the diagnostic result and metadata, with a top-level outcome consistent with the diagnostic health. Omitting it should continue to produce the bare report.

Actual behavior

In the executed source check, adding the flag returned the same decoded report as omitting it. Both calls returned exit status 1, healthy: false, and the fixture's stderr diagnostic. Neither report contained ok or meta. The meaningful comparison output was:

{"bareExit":1,"fullExit":1,"identicalReports":true,"keys":["healthy","adapter","server","inventory","identity","request_flow","checks","diagnostics"]}

The same flag loss applies to a healthy report by source inspection: the formatter receives the bare diagnostic result through the same final return path regardless of health. This healthy case was not executed.

Evidence

  • Expected source: src/mcpDoctor.ts:22-26 declares the command-specific option and description; src/mcpDoctor.ts:43-49 renders them with unrelated global options hidden. Executed help confirmed the advertised flag. src/cli/cliResultOutput.ts:203-221 establishes the ordinary CLI envelope meaning; an executed Writable control confirmed its success envelope contains ok, data and meta.
  • Failure source: the source CLI check above observed identical bare reports. src/mcpDoctor.ts:323-363 accepts the flag without recording it, and src/mcpDoctor.ts:237-245 formats the report directly. scripts/rea.mjs:57-66 calls this entry and writes its output unchanged, bypassing the regular CLI result formatter.
  • Evidence provenance: observed
  • Local verification: reproduced
  • Reproduction completeness: complete

The source boundary check passed alongside the help and ordinary formatter controls, for three focused tests total. The public executable's reachability and the healthy variant are static evidence, rather than built-runtime observations.

Related help issue #1127 covered a rejected help request and is closed; the current help control passes. Related envelope issue #2273 covered ordinary analysis failures being wrapped with ok: true. Neither report covers this command accepting the flag while omitting the envelope entirely.

Restoration check

For the same owned fixture, --json --full-output should return a failure envelope retaining the diagnostic report and metadata, while --json should retain the bare report. Both should continue to report the unhealthy result and return exit status 1. Also check a healthy production diagnostic: adding the flag should select a success envelope without changing the diagnostic result or exit status 0. Keep the help control and confirm the two flag variants differ in document shape; accepting the flag alone does not restore the promised behavior.

Triage assessment

  • Impact level: P2
  • Assessment status: supported
  • Impact basis: The advertised output selector returns the wrong document contract for callers requesting an envelope. This is a bounded behavior failure; diagnostic content and failure status remain available. No downstream consumer failure was executed.
  • Workaround status: available
  • Workaround basis: The executed bare report retains healthy and the fixture diagnostics, and both flag variants return the correct failure exit status. Consumers can read those fields and the exit status directly while this command lacks envelope output.
Originally created by @coygeek on GitHub (Oct 13, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/2673 ## Summary `rea mcp doctor` offers `--full-output` in its own help, but accepting that flag leaves the JSON report unwrapped. A caller requesting the envelope receives neither `ok` nor `meta`. The diagnostic report and its failure status remain available, so consumers can use the bare report as a workaround. ## Runtime or environment Verified source revision a2d8b94dd50dab8d966239dd63ab84718aa8b4b4 with Node 24.18.0 and npm 11.16.0. The executed check used the source CLI entry and an owned child fixture that immediately exits. The published package and a healthy production MCP session were not executed. A source-only recheck at 3ae826ceba6f25b08bce50bcb51001209bc16b57 confirms that the doctor parser and formatter still discard the requested flag; the current checkout was not executed. ## Steps to reproduce With the checkout's locked dependencies installed, save the following as `src/doctor-output-repro.test.ts`, then run `npm run test:local -- src/doctor-output-repro.test.ts`. This is a self-contained rendering of the executed source check, with the fixture directory made portable. The fixture only writes a diagnostic and exits; it needs no analysis provider or client configuration. ```ts import { expect, it } from "vitest"; import { mkdtemp, rm, writeFile } from "node:fs/promises"; import { tmpdir } from "node:os"; import { join } from "node:path"; import { runProductionMcpDoctorCli } from "./mcpDoctor.js"; it("compares doctor output with and without the advertised envelope flag", async () => { const root = await mkdtemp(join(tmpdir(), "doctor-output-")); try { const dispatcherPath = join(root, "doctor-exit.mjs"); await writeFile(dispatcherPath, 'process.stderr.write("owned doctor fixture exited\\n");\nprocess.exitCode = 1;\n'); const input = { dispatcherPath, packageRoot: root }; const help = await runProductionMcpDoctorCli(["--help"], input); expect(help.exitCode).toBe(0); expect(help.output).toMatch(/--full-output\s+Show the full output envelope/); const bare = await runProductionMcpDoctorCli(["--json"], input); const full = await runProductionMcpDoctorCli(["--json", "--full-output"], input); const bareReport = JSON.parse(bare.output); const fullReport = JSON.parse(full.output); expect(bare.exitCode).toBe(1); expect(full.exitCode).toBe(1); expect(fullReport).toEqual(bareReport); expect(fullReport.healthy).toBe(false); expect(fullReport.diagnostics.stderr).toBe("owned doctor fixture exited\n"); expect(fullReport).not.toHaveProperty("ok"); expect(fullReport).not.toHaveProperty("meta"); console.log(JSON.stringify({ bareExit: bare.exitCode, fullExit: full.exitCode, identicalReports: true, keys: Object.keys(fullReport), })); } finally { await rm(root, { recursive: true, force: true }); } }, 10000); ``` The public executable input is `rea mcp doctor --json --full-output`, compared with `rea mcp doctor --json`. Those executable commands were not run for this report; source inspection confirms their dispatcher reaches the tested entry when compiled runtime files are present. ## Expected behavior The command's own help promises "Show the full output envelope" for `--full-output`. Selecting it should produce an envelope carrying the diagnostic result and metadata, with a top-level outcome consistent with the diagnostic health. Omitting it should continue to produce the bare report. ## Actual behavior In the executed source check, adding the flag returned the same decoded report as omitting it. Both calls returned exit status 1, `healthy: false`, and the fixture's stderr diagnostic. Neither report contained `ok` or `meta`. The meaningful comparison output was: ```json {"bareExit":1,"fullExit":1,"identicalReports":true,"keys":["healthy","adapter","server","inventory","identity","request_flow","checks","diagnostics"]} ``` The same flag loss applies to a healthy report by source inspection: the formatter receives the bare diagnostic result through the same final return path regardless of health. This healthy case was not executed. ## Evidence - Expected source: `src/mcpDoctor.ts:22-26` declares the command-specific option and description; `src/mcpDoctor.ts:43-49` renders them with unrelated global options hidden. Executed help confirmed the advertised flag. `src/cli/cliResultOutput.ts:203-221` establishes the ordinary CLI envelope meaning; an executed Writable control confirmed its success envelope contains `ok`, `data` and `meta`. - Failure source: the source CLI check above observed identical bare reports. `src/mcpDoctor.ts:323-363` accepts the flag without recording it, and `src/mcpDoctor.ts:237-245` formats the report directly. `scripts/rea.mjs:57-66` calls this entry and writes its output unchanged, bypassing the regular CLI result formatter. - Evidence provenance: observed - Local verification: reproduced - Reproduction completeness: complete The source boundary check passed alongside the help and ordinary formatter controls, for three focused tests total. The public executable's reachability and the healthy variant are static evidence, rather than built-runtime observations. Related [help issue #1127](https://github.com/morluto/rea/issues/1127) covered a rejected help request and is closed; the current help control passes. Related [envelope issue #2273](https://github.com/morluto/rea/issues/2273) covered ordinary analysis failures being wrapped with `ok: true`. Neither report covers this command accepting the flag while omitting the envelope entirely. ## Restoration check For the same owned fixture, `--json --full-output` should return a failure envelope retaining the diagnostic report and metadata, while `--json` should retain the bare report. Both should continue to report the unhealthy result and return exit status 1. Also check a healthy production diagnostic: adding the flag should select a success envelope without changing the diagnostic result or exit status 0. Keep the help control and confirm the two flag variants differ in document shape; accepting the flag alone does not restore the promised behavior. ## Triage assessment - Impact level: P2 - Assessment status: supported - Impact basis: The advertised output selector returns the wrong document contract for callers requesting an envelope. This is a bounded behavior failure; diagnostic content and failure status remain available. No downstream consumer failure was executed. - Workaround status: available - Workaround basis: The executed bare report retains `healthy` and the fixture diagnostics, and both flag variants return the correct failure exit status. Consumers can read those fields and the exit status directly while this command lacks envelope output.
bsakaguchi 2026-10-15 18:30:01 +00:00
Author
Owner

@morluto commented on GitHub (Oct 14, 2026):

Fixed on published main by cd88163e42cf598c8540a580ed3e3d4de969074a. The CLI was accepting --full-output but dropping the selection before rendering; it now only renders admitted plans and preserves the refusal envelope and metadata. Validation: tests/boundary/mcp/mcpDoctor.test.ts, “preserves the full-output envelope for startup failures,” passed in the phase-five final log. This verifies the owned failing-child case; a healthy external MCP installation was not involved. Thanks for the precise reproduction.

<!-- gh-comment-id:6163978896 --> @morluto commented on GitHub (Oct 14, 2026): Fixed on published main by `cd88163e42cf598c8540a580ed3e3d4de969074a`. The CLI was accepting `--full-output` but dropping the selection before rendering; it now only renders admitted plans and preserves the refusal envelope and metadata. Validation: `tests/boundary/mcp/mcpDoctor.test.ts`, “preserves the full-output envelope for startup failures,” passed in the phase-five final log. This verifies the owned failing-child case; a healthy external MCP installation was not involved. Thanks for the precise reproduction.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
morluto/rea#973
No description provided.