Skip to content

fix(cli): keep /reload-mcp off the input thread - #39446

Open
LeonSGP43 wants to merge 1 commit into
NousResearch:mainfrom
LeonSGP43:fix/39418-reload-mcp-threaded
Open

fix(cli): keep /reload-mcp off the input thread#39446
LeonSGP43 wants to merge 1 commit into
NousResearch:mainfrom
LeonSGP43:fix/39418-reload-mcp-threaded

Conversation

@LeonSGP43

Copy link
Copy Markdown
Contributor

Summary

Fixes the interactive CLI /reload-mcp freeze by moving the user-triggered reload path onto a worker thread with the same 30s timeout behavior the config-watcher reload path already uses. This keeps the prompt/input thread recoverable even if an MCP server hangs during shutdown or reconnect.

Closes #39418.

What changed

  • route both confirmed and pre-approved /reload-mcp executions through _run_reload_mcp_with_timeout() instead of calling _reload_mcp() inline on the CLI thread
  • warn and return control if the reload thread is still alive after the timeout
  • add CLI regression coverage proving /reload-mcp now executes off the main thread and surfaces the timeout warning without blocking forever

Verification

  • ../.base/.venv/bin/python -m pytest -o addopts='' tests/cli/test_cli_loading_indicator.py
  • ../.base/.venv/bin/python -m ruff check cli.py tests/cli/test_cli_loading_indicator.py
  • git diff --check

@alt-glitch alt-glitch added type/bug Something isn't working comp/cli CLI entry point, hermes_cli/, setup wizard tool/mcp MCP client and OAuth P2 Medium — degraded but workaround exists labels Jun 5, 2026

@teknium1 teknium1 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for tracing the manual reload path; the underlying issue remains present on current main (cli.py:10698 and cli.py:10738 still call _reload_mcp() synchronously).

Problems

  • PR cli.py:10923 starts a worker but then calls join(timeout=timeout_seconds). With the default 30 seconds, the command processor can still be blocked for 30 seconds. Current main deliberately removed the equivalent watcher join in 972aa33d376e8cb308466192ee545c879459fd0d because it froze process_loop.
  • The new timeout test uses a 0.01-second join (tests/cli/test_cli_loading_indicator.py:89-96), so it verifies timeout formatting but not that /reload-mcp returns while reload work remains blocked. It also exercises only the pre-approved route.

Suggested changes

  • Start the daemon worker and return immediately, following current cli.py:10538-10546; report completion from the worker rather than joining it.
  • Add an event-blocked reload test proving both approved paths return before reload completion.

Automated hermes-sweeper review.

Comment thread cli.py
"""Run MCP reload on a worker thread so slash-command input stays recoverable."""
reload_thread = threading.Thread(target=self._reload_mcp, daemon=True)
reload_thread.start()
reload_thread.join(timeout=timeout_seconds)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This join() still blocks the command-processing thread for the default 30 seconds. Current main removed the equivalent config-watcher join in 972aa33d3 because it froze process_loop; please return immediately after starting the daemon worker instead.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/cli CLI entry point, hermes_cli/, setup wizard P2 Medium — degraded but workaround exists sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform sweeper:risk-session-state Sweeper risk: may lose/corrupt/mis-associate session or context state tool/mcp MCP client and OAuth type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

/reload-mcp freezes the CLI terminal when triggered by user — session becomes unresponsive

3 participants