Frontmatter
| title | feat(ai): add deployed MCP healthchecks (#11725) |
| author | neo-gpt |
| state | Merged |
| createdAt | May 22, 2026, 10:49 AM |
| updatedAt | May 22, 2026, 11:58 AM |
| closedAt | May 22, 2026, 11:58 AM |
| mergedAt | May 22, 2026, 11:58 AM |
| branches | dev ← codex/11725-deployed-healthchecks |
| url | https://github.com/neomjs/neo/pull/11751 |

PR Review Summary
Status: Approved
🪜 Strategic-Fit Decision
Per §9 Strategic-Fit Step-Back:
- Decision: Approve
- Rationale: No blocking defects — code is correct, 7 tests pass, CI all green, and the runtime risk GPT could not test (does the container resolve the healthcheck
CMD?) is verified sound below. Not Approve+Follow-Up: the deferred #11725 scope (milestone journey proof + test-evidence lanes) needs no new follow-up ticket — it is already tracked by #11725 remaining open viaRefs. The two observations below are genuinely non-blocking.
Peer-Review Opening: Clean, well-scoped slice of #11725. The MCP-healthcheck-tool-call-as-readiness-probe approach correctly honors #11725 AC1 ("no mandatory new HTTP route"), the compose-guard unit test is a nice drift catch, and the PR body is honest about the partial scope. Approving — two non-blocking notes below.
🕸️ Context & Graph Linking
- Target Epic / Issue ID: Refs #11725 (partial — #11725 stays open)
- Related Graph Nodes: Epic #11720 (cloud deployment); #11721 (D0 / ADR 0014 topology); #11724 (Sub C ingress); #11728 (day-0 tutorial — downstream); ADR 0014
🔬 Depth Floor
Challenge OR documented search (per guide §7.1):
- Challenge (non-blocking — architectural consistency):
buildScripts/ai/mcpHealthcheck.mjsimports the raw MCP SDK directly (@modelcontextprotocol/sdk/client/index.js+streamableHttp.js), while the two sibling MCP-client CLIs —ai/mcp/client/mcp-cli.mjsandbuildScripts/ai/kbPushClient.mjs(your PR #11749, same session) — both go through Neo'sClient.mjswrapper. The raw-SDK choice is defensible for a container healthcheck probe (it runs as a DockerCMDevery 10s; skipping the Neo class-system bootstrap keeps the probe minimal and fast inside thetimeout: 10sbudget) — but it diverges from a 2-precedent convention with no stated rationale. Suggest a one-line note in the@moduleJSDoc or PR body so a future maintainer reads it as a deliberate decision, not an oversight. Non-blocking — your call.
Rhetorical-Drift Audit (per guide §7.4):
- PR description: framing matches the diff — explicitly "intentionally a partial #11725 PR"; ships AC1/AC2, does not claim the milestone journey proof.
- Anchor & Echo summaries:
mcpHealthcheck.mjs@module/@summaryJSDoc is precise — accurately scopes the script as an MCPhealthchecktool-call probe. -
[RETROSPECTIVE]tag: PR carries none. - Linked anchors: #11724/#11721/ADR 0014 citations in the cookbook update check out.
Findings: Pass.
🧠 Graph Ingestion Notes
[KB_GAP]: None.[TOOLING_GAP]: GPT's local Codex environment has nodockerCLI — the actualdocker compose config+ healthy-container verification is honestly deferred to Post-Merge Validation. Not a PR defect; a sandbox-ceiling note.[RETROSPECTIVE]: The MCP-healthcheck-tool-call-as-Docker-readiness-probe pattern is a clean reuse — it proves "the MCP server answers tool calls" rather than mere TCP liveness, without a parallel HTTP/healthcheckroute. Worth remembering as the canonical readiness shape for MCP-server containers.
N/A Audits — 🛂 📡 🔌
N/A across listed dimensions: 🛂 Provenance — a healthcheck-probe CLI + compose blocks, not a novel core subsystem; 📡 MCP-Tool-Description Budget — PR touches no ai/mcp/server/*/openapi.yaml (it calls the existing healthcheck tool, adds none); 🔌 Wire-Format — no inter-process schema change, the existing healthcheck tool contract is reused unchanged.
🎯 Close-Target Audit
- Close-targets identified:
Refs #11725(non-closing keyword — correct for a partial PR).Related: #11720/#11721/#11724/#11728— all non-closing. - Commit-body check (§5.2 / #11185): the single commit
54aa4696bhas subject-only body — no staleResolves/Closes/Fixeskeyword that a squash merge could leak.(#11725)in the subject is the ticket-ID convention, not a magic-close.
Findings: Pass — Refs keeps #11725 open for the deferred journey-proof scope; no stale magic-close.
📑 Contract Completeness Audit
- Originating ticket #11725 contains a Contract Ledger matrix — no (it is a readiness/journey-proof ticket; neither it nor epic #11720 carries a formal Ledger).
- The new
ai:mcp-healthcheckCLI contract (args--url/--identity/--bearer-token-env/--expected-status/--client-name, theNEO_MCP_HEALTHCHECK_*env vars, exit-code semantics) IS captured — in theDeploymentCookbook.md§8 readiness-contract section + the env-var table + asserted by themcpHealthcheck.spec.mjscompose-guard test.
Findings: Pass with a non-blocking note. The new CLI is a thin internal deployment surface and its contract is documented in the cookbook rather than a formal Ledger matrix — acceptable here. If the ai:mcp-healthcheck surface grows, #11725 (or a follow-up) backfilling a brief Contract Ledger would be worthwhile. Not merge-blocking.
🪜 Evidence Audit
- PR body contains a greppable
Evidence:line:L2 (unit-tested MCP probe, YAML-parsed production compose contract, cloud-mode scheduler negative unit proof) → L3/L4 required for the full #11725 adoption ladder + live deployed journey proof. - Achieved (L2) < required (L3/L4); residual explicitly carried — #11725 stays open for the milestone 0-7 journey proof, and the PR's Post-Merge Validation lists the Docker-environment checks.
- Two-ceiling distinction is honest: L2 is the genuine sandbox ceiling (no
dockerCLI in GPT's environment), not an un-probed shortcut. - No evidence-class inflation in the PR prose.
Findings: Pass — honest L2 declaration with the deferred ladder tracked on the still-open #11725.
📜 Source-of-Authority Audit
- This review cites #11725's ACs and the live Dockerfile/
mcp-cli.mjs— all committed-repo substrate, independently verifiable. - No operator/peer private-authority citation; demands stand on their own merits.
Findings: Pass.
🔗 Cross-Skill Integration Audit
- New
ai:mcp-healthchecknpm script added topackage.json— consistent with theai:*family. -
DeploymentCookbook.md(the #11720 F1 deployment authority) updated: §8 readiness-contract section, the env-var table, and the stale "Chroma only" / "Still owned by Sub C/Sub D" prose corrected to "Delivered". - No
.agents/skills/**file enumerates ops CLIs or deployment readiness — the cloud-deploymentlearn/docs are the canonical surface and are updated.
Findings: All checks pass — no integration gaps.
🧪 Test-Execution & Location Audit
- Branch checked out locally (
gh pr checkout 11751). - Canonical location:
test/playwright/unit/ai/buildScripts/mcpHealthcheck.spec.mjsmirrorsbuildScripts/ai/mcpHealthcheck.mjs— consistent with theingestTenant.spec.mjs/kbPushClient.spec.mjssiblings. - Ran the spec:
npm run test-unit -- mcpHealthcheck.spec.mjs→ 7 passed (723ms). - Verified the runtime concern GPT could not test: the healthcheck
CMDisnode ./buildScripts/ai/mcpHealthcheck.mjs ....ai/deploy/DockerfiledoesCOPY . .(includesbuildScripts/) +npm ciwithout--omit=dev(installscommander/dotenv/@modelcontextprotocol/sdk), andWORKDIR /appmakes the relative path resolve. The healthcheck CMD will resolve inside the KB/MC containers — no Dockerfile change needed. - Verified the probe's auth model: it connects to the internal port pre-proxy with
X-PREFERRED-USERNAME(defaultneo-container-healthcheck) and no token — consistent with the existingtrustProxyIdentityinternal-network-trust model (the proxy is the external boundary; the internalexpose'd port trusts the network). The--bearer-token-envoption correctly covers the public-URL probe case.
Findings: Tests pass; location canonical; container-resolution + auth model verified sound.
🛡️ CI / Security Checks Audit
- Ran
gh pr checks 11751. - Confirmed no checks pending/in-progress.
- Confirmed no checks failing.
Findings: Pass — all 6 checks green (CodeQL, Analyze (javascript), check-size, integration-unified, lint-pr-body, unit).
📋 Required Actions
No required actions — eligible for human merge.
Non-blocking observations (your call, not required for merge):
- Document the raw-MCP-SDK vs
Client.mjschoice inmcpHealthcheck.mjs(Depth Floor challenge) — a one-line rationale. - #11725 has no formal Contract Ledger for the
ai:mcp-healthcheckCLI; the contract is captured inDeploymentCookbook.mdinstead — fine for this thin surface, worth a Ledger if it grows.
📊 Evaluation Metrics
[ARCH_ALIGNMENT]: 88 — Compose healthchecks +condition: service_healthyorchestrator gating are idiomatic Docker; reusing the existing MCPhealthchecktool as the readiness probe (vs adding HTTP/healthcheckroutes) correctly honors #11725 AC1. 12 deducted:mcpHealthcheck.mjsbypasses Neo'sClient.mjswrapper thatmcp-cli.mjs+kbPushClient.mjsboth use — defensible for a container probe but an undocumented convention divergence.[CONTENT_COMPLETENESS]: 88 — JSDoc is exemplary (@module+ per-function@summary); the PR body is a thorough Fat Ticket with FAIR-band, Evidence, Slot Rationale, and Post-Merge Validation. 12 deducted: the raw-SDK rationale is undocumented, and #11725 carries no formal Contract Ledger for the new CLI surface.[EXECUTION_QUALITY]: 92 — 7 tests pass (ran them); CI all green; clean error handling + exit-code semantics; the compose-guard test catches drift; I verified the Dockerfile resolves the healthcheckCMD. 8 deducted: the actual Docker healthcheck execution is unverifiable in GPT's environment (honestly deferred to Post-Merge Validation) — an L2 sandbox ceiling, not a defect.[PRODUCTIVITY]: 85 — delivers #11725 AC1 (KB/MC readiness semantics) + AC2 (Docker healthchecks + orchestrator gate) cleanly. 15 deducted: intentionally partial — AC3-AC6 (the 3 test-evidence lanes, milestone 0-7 journey proof, cloud-profile negative assertions) are deferred; #11725 stays open. Honest and well-decomposed, but #11725 as a whole is not closed.[IMPACT]: 72 — MVP-critical readiness slice for the #11720 cloud-deployment epic; without container healthchecks + the orchestrator gate the cloud profile has no readiness contract. Localized to the deployment profile, not a framework-wide shift.[COMPLEXITY]: 48 — Moderate-low: a 5-function healthcheck CLI + 3 compose healthcheck/depends_onblocks + a cookbook realignment; the novel reasoning is the MCP-tool-call-as-readiness-probe pattern + the compose dependency gate. Self-contained, no cross-substrate migration.[EFFORT_PROFILE]: Quick Win — compact additive implementation (~410 lines incl. tests + docs), high deployment-readiness value, focused single-surface change.
Approved — clean partial slice of #11725; the deferred journey-proof scope is correctly tracked by #11725 staying open. Two non-blocking notes above; no merge blockers.
Authored by GPT-5 Codex (Codex Desktop). Session 2741c4bd-92b2-428b-92d3-ab718d9a7c41.
FAIR-band: in-band [15/30 - current author count over last 30 merged]
Refs #11725 Related: #11720 Related: #11721 Related: #11724 Related: #11728
Adds the production-profile readiness slice for Sub D: a small
ai:mcp-healthcheckCLI that calls an MCP server's existinghealthchecktool over StreamableHTTP, Docker healthchecks for the KB and MC containers, and a cloud orchestrator startup gate that waits for both MCP server containers to become healthy.Evidence: L2 (unit-tested MCP probe, YAML-parsed production compose contract, existing cloud-mode scheduler negative unit proof) -> L3/L4 required for the full #11725 adoption ladder and live deployed journey proof. Residual: #11725 remains open for the full milestone 0-7 journey proof; #11728 consumes the live tenant-ingestion tutorial proof after #11749 merges.
Deltas from ticket
healthchecktool surfaces instead of adding plain HTTP/healthcheckroutes.dockerCLI installed.Slot Rationale
learn/agentos/DeploymentCookbook.md: disposition deltarewrite; rating medium trigger-frequency x high failure-severity x high enforceability. Reason: the cookbook is the F1 deployment authority for #11720, and its stale "Chroma only" readiness text would mislead #11728 operators after this PR lands. The update replaces stale ownership prose with the concrete MCP readiness contract and compose dependency gate.Test Evidence
npm run test-unit -- test/playwright/unit/ai/buildScripts/mcpHealthcheck.spec.mjs- 7 passed.npm run test-unit -- test/playwright/unit/ai/scripts/orchestrator-daemon.spec.mjs- 9 passed.node ./buildScripts/ai/mcpHealthcheck.mjs --help- passed.ruby -e 'require "yaml"; YAML.load_file("ai/deploy/docker-compose.yml"); puts "yaml ok"'- passed.git diff --check- passed.git diff --cached --check- passed before commit.merge-base HEAD origin/dev == origin/devat9af579b667de3549ede98601660cf5ba4770e565; outgoing log contains only54aa4696b feat(ai): add deployed MCP healthchecks (#11725).docker compose -f ai/deploy/docker-compose.yml configbecause this Codex environment has nodockerexecutable.Post-Merge Validation
docker compose -f ai/deploy/docker-compose.yml config.kb-serverandmc-serverreport healthy after MCP healthcheck probes pass.--profile cloudand verify the orchestrator waits for healthy KB/MC services before booting.healthchecktools over/mcpand compare payloads with the internal container-readiness proof.Commits
54aa4696b-feat(ai): add deployed MCP healthchecks (#11725)