LearnNewsExamplesServices
Frontmatter
id13877
titleEcho fatal MCP startup errors to stderr
stateClosed
labels
bugaimodel-experience
assigneesneo-gpt
createdAtJun 22, 2026, 11:22 PM
updatedAtJun 22, 2026, 11:40 PM
githubUrlhttps://github.com/neomjs/neo/issues/13877
authorneo-gpt
commentsCount0
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[]
blocking[]
closedAtJun 22, 2026, 11:40 PM

Echo fatal MCP startup errors to stderr

Closed v13.1.0/archive-v13-1-0-chunk-5 bugaimodel-experience
neo-gpt
neo-gpt commented on Jun 22, 2026, 11:22 PM

Context

A same-day operator report showed Claude marking neo-mjs-knowledge-base and neo-mjs-github-workflow as Server disconnected immediately after initialize, while the MCP client log had no useful stderr. Live reproduction against current dev confirmed the process exited with code 1 and empty stderr.

The repo-local server log did contain the actionable root cause: assertConfigFresh() detected stale gitignored config overlays and told the operator to run npm run prepare -- --migrate-config. Running node ./ai/scripts/setup/initServerConfigs.mjs --migrate-config in the affected sibling checkouts repaired the local failure; both exact server entrypoints then stayed alive after the same initialize payload.

Release classification: post-release / boardless. This improves diagnostics for an already-guarded failure mode; it is not required for #13875 or the v13 release line.

The Problem

The config-freshness contract is already present and tested, but fatal MCP startup errors are only logged through the per-server logger. For stdio MCP clients, that means the client sees a transport disconnect with no stderr explanation, even though the repo log has the actionable --migrate-config message.

This turns a solved stale-overlay class into avoidable operator friction: the right diagnosis exists, but it is hidden from the surface the operator is actually looking at.

The Architectural Reality

  • ai/mcp/server/knowledge-base/mcp-server.mjs, ai/mcp/server/github-workflow/mcp-server.mjs, ai/mcp/server/memory-core/mcp-server.mjs, ai/mcp/server/gitlab-workflow/mcp-server.mjs, and ai/mcp/server/neural-link/mcp-server.mjs catch boot failures, call logger.error('Fatal error during server initialization:', error), then process.exit(1).
  • ai/scripts/setup/initServerConfigs.mjs owns assertConfigFresh(), which already names stale overlay leaves and the --migrate-config remediation.
  • Prior freshness-guard tickets covered fail-fast behavior, not this stderr visibility gap.

The Fix

When a fatal MCP boot error is caught, also write a concise stack/message to stderr before exiting. Keep stdout untouched because stdio MCP protocol frames use stdout. Prefer a shared tiny helper if that avoids duplicating formatting across MCP entrypoints without adding broader startup machinery.

Contract Ledger Matrix

Target Surface Source of Authority Proposed Behavior Fallback Docs Evidence
Stdio MCP startup failure diagnostics MCP clients surface stderr when a server exits during startup Fatal boot failures include the same actionable reason on stderr that is currently written to repo logs Existing per-server log remains authoritative if stderr is unavailable Inline comments only if formatting is non-obvious Unit/source test or isolated spawn test proving stale-overlay failure writes stderr and exits non-zero

Decision Record impact

none

Acceptance Criteria

  • A stale config overlay that trips assertConfigFresh() during MCP startup exits non-zero and writes the actionable stale-overlay message to stderr.
  • stdout remains reserved for MCP protocol frames; no diagnostic prose is written to stdout.
  • Existing per-server log behavior remains intact.
  • Coverage proves at least one guarded MCP entrypoint reports the fatal reason to stderr, and source coverage prevents sibling entrypoints from regressing to logger-only exits.

Out of Scope

  • Changing the config migration semantics.
  • Auto-mutating ignored config files during MCP startup.
  • Changing Claude/Codex/other client configuration files.
  • Broad MCP server lifecycle redesign.

Related

Related: #13560 Related: #13570 Related: #13875

Origin Session ID: db5b2ecf-db91-4b7d-9498-ccef00426a1c

Handoff Retrieval Hints: MCP startup stale config overlay stderr, assertConfigFresh logger-only fatal exit, Claude Server disconnected empty stderr.

tobiu referenced in commit d33c1e0 - "fix(ai): echo MCP startup failures to stderr (#13877) (#13878)" on Jun 22, 2026, 11:40 PM
tobiu closed this issue on Jun 22, 2026, 11:40 PM