feat(health): add mcporter health for at-a-glance server status#176
feat(health): add mcporter health for at-a-glance server status#176mvanhorn wants to merge 1 commit into
Conversation
mcporter health pings every configured MCP server (in parallel via Promise.allSettled) and reports per-server status, initialize latency, tool count, and OAuth token state in one table. Exits non-zero when any server is not ok, so it works as a CI/uptime monitor. Flags: - --server <name>: check only this server - --timeout <seconds>: per-server timeout (default 10) - --json: machine-readable JSON output Classification handles common failure modes: - auth_required for 401/forbidden/token errors - unreachable for ECONNREFUSED/ETIMEDOUT/ENOTFOUND - error for anything else - ok with latency and tool count when healthy
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 941097ca59
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
|
||
| export async function handleHealth(runtime: Runtime, args: string[]): Promise<void> { | ||
| const flags = parseHealthFlags(args); | ||
| const previousStdioLogMode = flags.server ? undefined : setStdioLogMode('silent'); |
There was a problem hiding this comment.
Silence stdio logs for single-server JSON/quiet health checks
When mcporter health --server <stdio-server> --json or --quiet checks a stdio server that writes stderr before failing, this leaves stdio log mode at auto, so sdk-patches can print the captured stderr to stdout during the runtime.listTools(..., autoAuthorize: false) close path. That pollutes the JSON payload and also violates --quiet; the all-server path already silences these logs, so the single-server path should do the same at least for JSON/quiet output.
Useful? React with 👍 / 👎.
Summary
mcporter health. Pings every configured MCP server in parallel (viaPromise.allSettled), reports per-server status, initialize latency, tool count, and OAuth token state in one table. Exits non-zero when any server is not ok, so it works as a CI/uptime monitor.--server <name>to check one,--timeout <seconds>per-server (default 10),--jsonfor machine-readable output.auth_requiredfor 401 / forbidden / token errorsunreachablefor ECONNREFUSED / ETIMEDOUT / ENOTFOUNDerrorfor anything else (with a 200-char preview from the error message)okwith measured latency and tool count when healthylist-command.ts/daemon-command.tspattern: commander registration, reusesoutput-utils.ts/json-output.ts/terminal.tsfor formatting. No new runtime deps.Why this matters
mcporter listshows the servers configured for the current workspace and their tool counts, but not whether those servers are actually reachable or whether their cached OAuth tokens are still valid. At 10+ MCPs configured — the audience that exists at 4.4K stars — there is no way to check "is everything ok before I start a run" short of calling each tool manually.This is operational quality-of-life that compounds at scale:
Parallel execution means one slow or dead server does not block the others.
Demo
Simulated demo:
The demo shows a 5-server config: 3 healthy (linear / context7 / vercel with latency + tool counts + OAuth state), 1 with an expired token (supabase →
auth_required), 1 unreachable (internal-api on ECONNREFUSED). Exit code 1 because not everything is ok.Testing
corepack pnpm typecheckcorepack pnpm lint(oxlint clean, oxfmt clean)corepack pnpm test— 648 tests pass; newtests/cli-health-command.test.tscovers:auth_required, exit code 1unreachablewith error preview--jsonproduces a valid JSON array conforming to the HealthRow shape--server <name>filter checks only the named server--timeout 1enforces per-server timeout via stubbed slow transport