perf(tui): stop slow/dead MCP servers from freezing TUI startup#35273
Merged
Conversation
The 'summoning hermes…' phase blocked on gateway.ready, which ran MCP tool discovery inline. Any configured-but-unreachable MCP server burned its full connect-retry backoff (1+2+4s ≈ 7s) before the composer appeared — startup went from instant to ~7.5s of dead air for anyone with a down stdio/http server in mcp_servers. Move discovery into a background daemon thread so gateway.ready fires immediately; tools register into the shared registry as servers connect, and the agent isn't built until the first prompt. Measured spawn→ready: ~7500ms → ~115ms (dead twozero_td server in config). Also drop rich.console + prompt_toolkit off banner.py's import path (lazy-imported inside cprint/build_welcome_banner). tui_gateway.server imports banner only to reach the lightweight prefetch_update_check helper; the eager rich/pt imports added ~45ms before gateway.ready for no benefit. tui_gateway.server import: ~115ms → ~69ms.
Contributor
🔎 Lint report:
|
| Rule | Count |
|---|---|
invalid-assignment |
1 |
First entries
tests/tui_gateway/test_wait_for_mcp_discovery.py:70: [invalid-assignment] invalid-assignment: Object of type `Thread` is not assignable to attribute `_mcp_discovery_thread` of type `None`
✅ Fixed issues: none
Unchanged: 4929 pre-existing issues carried over.
Diagnostics are surfaced as warnings — this check never fails the build.
Collaborator
|
Salvage of #35245 (by @kshitijk4poor) cherry-picked onto current main. Competes with #32811 (background MCP discovery via daemon thread). Both address the same startup blocking pattern first fixed in #16899 (module-level side effect) and #19326 (async discovery). |
1 task
1 task
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
TUI startup no longer freezes on a configured-but-dead MCP server. Discovery moves to a background daemon thread so
gateway.readyfires immediately (~7,500ms → ~115ms with a dead server), with a bounded first-build wait so reachable servers still land in the tool snapshot.Salvage of #35245 by @kshitijk4poor, cherry-picked onto current
main(authorship preserved).Changes
tui_gateway/entry.py: rundiscover_mcp_tools()in a daemon thread; exposewait_for_mcp_discovery(timeout=0.75); log background failures withexc_info=Trueinstead of swallowing.tui_gateway/server.py:_make_agentbriefly joins discovery (bounded) before the first agent build, since AIAgent snapshots its tool list once and never re-reads./reload-mcpnow actually rebuilds the cached agent's tool snapshot (the oldhasattr(agent, "refresh_tools")guard was dead code — no such method exists on main), mirroringgateway/run.py::_execute_mcp_reload.hermes_cli/banner.py: lazyrich/prompt_toolkitimports (~45ms off the TUI critical path;Consoleannotation underTYPE_CHECKING).tests/tui_gateway/test_wait_for_mcp_discovery.py: 4 new tests (no-thread no-op, finished no-op, fast-join, hung-thread bounded).Validation
gateway.ready(dead MCP server)import tui_gateway.serverrefresh_toolsconfirmed absent from main — old/reload-mcppath was dead, only/newrecovered late servers.discover_mcp_toolsis_lock-guarded/idempotent — safe for thread + reload.tests/tui_gateway/(94) +tests/hermes_cli/test_banner.pypass locally.Infographic