89 lines
4.0 KiB
Markdown
89 lines
4.0 KiB
Markdown
---
|
||
summary: 'Checklist for diagnosing mcporter commands that never exit, using tmux and active-handle dumps.'
|
||
read_when:
|
||
- 'Seeing the CLI hang after tool completion'
|
||
---
|
||
|
||
# Debugging Hanging mcporter Calls
|
||
|
||
When `mcporter call` prints a tool response but the process never exits, it
|
||
usually means Node still has active handles it is waiting on. The most common
|
||
culprit is a child MCP server process that keeps the stdio transport alive.
|
||
|
||
## Quick Checklist
|
||
|
||
1. **Run under tmux** – launch the command inside tmux so you can inspect the
|
||
pane even after Cursor or another agent times out.
|
||
2. **Enable hang diagnostics** – set `MCPORTER_DEBUG_HANG=1` when invoking the
|
||
CLI. mcporter will dump the active handles/requests after the tool finishes
|
||
and around the `runtime.close()` call.
|
||
3. **Inspect the handle list** – look for `ChildProcess (pid=…)` entries. If a
|
||
child remains, mcporter will now unref and force-kill it, but the debug list
|
||
tells you exactly what was keeping the event loop alive.
|
||
4. **Capture the pane output** – run `tmux capture-pane -p -t <session> -S
|
||
-200` to save the diagnostic log for later review.
|
||
5. **Retry with `--timeout`** – if the tool itself hangs, use
|
||
`--timeout <ms>` or `MCPORTER_CALL_TIMEOUT` to fail fast while still
|
||
gathering diagnostics.
|
||
6. **Clamp OAuth waits** – when the browser-based sign-in never completes,
|
||
run with `--oauth-timeout <ms>` (or `MCPORTER_OAUTH_TIMEOUT_MS`) so the CLI
|
||
tears down the pending flow instead of waiting the full minute.
|
||
|
||
## Example Session
|
||
|
||
```bash
|
||
tmux new-session -d -s mcphang \
|
||
'cd /path/to/project && \
|
||
MCPORTER_DEBUG_HANG=1 \
|
||
CHROME_DEVTOOLS_MCP_BROWSER_URL=http://127.0.0.1:9222 \
|
||
pnpm --dir "$HOME/projects/mcporter" exec tsx \
|
||
"$HOME/projects/mcporter/src/cli.ts" call \
|
||
--config "$PWD/config/mcporter.json" \
|
||
--root "$PWD" \
|
||
chrome-devtools --tool list_pages'
|
||
|
||
sleep 5
|
||
tmux capture-pane -p -t mcphang -S -200
|
||
```
|
||
|
||
Sample diagnostic output (abridged):
|
||
|
||
```
|
||
[mcporter] [debug] after call (object result): 6 active handle(s), 0 request(s)
|
||
[mcporter] [debug] handle => ChildProcess (pid=78480)
|
||
[mcporter] [debug] beginning runtime.close()
|
||
[mcporter] [debug] after runtime.close: 6 active handle(s), 0 request(s)
|
||
[mcporter] [debug] forcibly killed child pid=78480 (runtime.finally)
|
||
```
|
||
|
||
This confirms the CLI response completed and that the lingering handle was a
|
||
child process, which mcporter will now terminate during shutdown.
|
||
|
||
## Notes
|
||
|
||
- The diagnostics only appear when `MCPORTER_DEBUG_HANG=1` is set.
|
||
- Killing residual children is best-effort; if you see repeated `kill-failed`
|
||
messages, manually terminate the PID listed in the log.
|
||
- Always keep tmux sessions tidy after debugging: `tmux kill-session -t
|
||
<session>`.
|
||
- The CLI now forces `process.exit(0)` after cleanup by default so Node never
|
||
lingers on leaked handles. Export `MCPORTER_NO_FORCE_EXIT=1` if you’re
|
||
debugging and need the process to stay alive.
|
||
- You can still set `MCPORTER_FORCE_EXIT=1` explicitly when you want to force
|
||
termination even with `MCPORTER_NO_FORCE_EXIT` in play.
|
||
- Stdio servers have their stderr output suppressed by default; set
|
||
`MCPORTER_STDIO_LOGS=1` to print their logs (they’re also surfaced whenever a
|
||
child exits with a non-zero status).
|
||
|
||
## Upstream Tracking
|
||
|
||
- `@modelcontextprotocol/sdk` **1.21.0** is the latest release pulled into mcporter.
|
||
- Open SDK issues related to stdio shutdown:
|
||
- [#579 StdioClientTransport does not follow the spec on close](https://github.com/modelcontextprotocol/typescript-sdk/issues/579)
|
||
- [#780 onerror listeners not removed after client close (stdio)](https://github.com/modelcontextprotocol/typescript-sdk/issues/780)
|
||
- [#1049 stdio client crashes when spawned server exits unexpectedly](https://github.com/modelcontextprotocol/typescript-sdk/issues/1049)
|
||
|
||
We keep a local checkout of the SDK under `~/Projects/typescript-sdk/` so we can
|
||
diff against upstream and craft repros/patches quickly. Any mcporter-specific
|
||
workarounds live in `src/sdk-patches.ts` until the upstream fixes land.
|