Skip to content

Capture stdio server stderr for debugging connection failures#198

Merged
jancurn merged 6 commits into
mainfrom
claude/review-issue-195-S4JLM
Apr 24, 2026
Merged

Capture stdio server stderr for debugging connection failures#198
jancurn merged 6 commits into
mainfrom
claude/review-issue-195-S4JLM

Conversation

@jancurn

@jancurn jancurn commented Apr 24, 2026

Copy link
Copy Markdown
Member

Summary

Makes stdio MCP server failures debuggable instead of silent (fixes #195).

Previously, stderr from a stdio server was either inherited (only in --verbose, and even then dropped to /dev/null since the bridge is spawned with stdio: 'ignore') or discarded. A child crashing because NODE_EXTRA_CA_CERTS wasn't forwarded — the scenario in #195 — looked like a silent hang.

Changes

  • Transport (src/core/transports.ts, src/core/factory.ts): createStdioTransport accepts an onStderrLine(line) callback. When set, stderr is piped and split with readline.createInterface (handles \r\n / partial lines). Plumbed through CreateTransportOptions and CreateMcpClientOptions.
  • Bridge (src/bridge/index.ts): every line is logged to ~/.mcpc/logs/bridge-<session>.log with a [server stderr] prefix and kept in a bounded tail (50 lines / 8 KB, lines trimmed to 8 KB on push so a single giant stack trace doesn't evict itself). On connect failure, the tail is appended to the error message sent back to the CLI.
  • Docs (src/cli/index.ts, README.md, CHANGELOG.md): mcpc connect --help and the README now document the SDK's env whitelist and where stderr is captured. Earlier --verbose pointer was removed (it didn't actually work for stdio via the bridge).

User-visible behavior

$ mcpc connect my-stdio-server.json:apify @apify
[@apify → node my-stdio-server.js]

⚠ Session @apify created but server is not responding: TLS/SSL error. Check the server's certificate.
  Original error: Failed to connect to MCP server: MCP error -32000: Connection closed

Recent server stderr:
  cannot verify TLS: self-signed certificate in chain
  tried https://api.upstream.example.com
  exiting
For details, check logs at ~/.mcpc/logs/bridge-@apify.log

Test plan

  • npm run lint
  • npm run build
  • npm run test:unit (532/532)
  • Smoke-tested with a fake stdio server that writes to stderr and exits — verified tail is captured in both the log file and the CLI error output
  • Smoke-tested with a 20 KB-long line — verified it's trimmed to 8 KB with indicator instead of being evicted

https://claude.ai/code/session_01PsfRHoKCVFnmxGqQfGEB1o

claude added 3 commits April 24, 2026 12:45
Stdio MCP servers inherit only a minimal whitelist of env vars from the
MCP SDK (PATH, HOME, SHELL, ...). Vars like NODE_EXTRA_CA_CERTS,
HTTPS_PROXY, and SSL_CERT_FILE must be forwarded explicitly via the
config "env" block. Without this, stdio servers in TLS-intercepting
proxy environments fail to reach their upstream APIs and mcpc connect
appears to hang silently (stderr is suppressed unless --verbose).

Documented in both `mcpc connect --help` and the README stdio config
section, including a pointer to --verbose for diagnosing silent hangs.

Refs #195
…ures

Previously, stderr from a stdio MCP server was either inherited (verbose
mode, but never visible since the bridge is spawned with stdio: 'ignore')
or dropped entirely. That made failures like the one in #195 — a child
server crashing because NODE_EXTRA_CA_CERTS wasn't forwarded — look like
a silent hang on the CLI.

Now the bridge always pipes the child's stderr, writes each line to
~/.mcpc/logs/bridge-<session>.log with a [server stderr] prefix, and
keeps a bounded tail (50 lines / 8KB). On connect failure it appends
the tail to the error message so the CLI shows the root cause.

Refs #195
claude added 3 commits April 24, 2026 13:46
…tion

- Replace hand-rolled line-buffering in createStdioTransport with
  readline.createInterface, which already handles \r\n / partial lines.
- Trim "Stdio environment" block in `mcpc help connect` to 3 lines.
- Cap each stderr line to STDERR_TAIL_MAX_CHARS on push and skip eviction
  when only one line remains, so a single oversized line (e.g. a long
  stack trace) can't squeeze itself out of the tail.
…help

Both sections covered stdio-specific concerns; combine them into a single
"Stdio servers" block.
@jancurn jancurn merged commit 3441c29 into main Apr 24, 2026
6 checks passed
@jancurn jancurn deleted the claude/review-issue-195-S4JLM branch April 24, 2026 15:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

stdio connect hangs silently in TLS-proxy environments due to stripped NODE_EXTRA_CA_CERTS

3 participants