perf(mcp): non-blocking startup via background MCP discovery + TUI fast path
Fire-and-forget MCP server connections on a daemon thread so the
gateway / CLI / ACP process becomes interactive immediately instead
of blocking on slow remote MCP servers (HTTP timeouts, sluggish
stdio boot). Previously `hermes --tui` waited 2-5 s after the splash
screen before rendering the UI while `discover_mcp_tools()` ran
synchronously on the critical path.
Changes:
- tools/mcp_tool.py: add `discover_mcp_tools_background()` — thin
wrapper that spawns `discover_mcp_tools()` on a named daemon thread
- tui_gateway/entry.py: call `discover_mcp_tools_background()` before
sending gateway.ready (replaces inline call that blocked the JSON-RPC
pipe for the TUI Ink app)
- hermes_cli/main.py:
- skip `\_prepare_agent_startup()` for TUI path — plugins, MCP, and
shell hooks are only needed by the CLI agent loop; the TUI's
gateway subprocess discovers them independently (~370 ms saved)
- fast-path in `\_make_tui_argv()`: when `dist/entry.js` exists and
is fresh, skip npm install / rebuild checks entirely (~350 ms saved)
- cli.py (`\_prepare_deferred_agent_startup`): same background pattern
for deferred startup (Termux interactive CLI)
- acp_adapter/entry.py: same pattern so ACP server launches asyncio
immediately while MCP connects in parallel
Result:
- TUI Python wrapper: ~730 ms → ~80 ms (9× faster)
- gateway.ready: ~2700 ms → ~400 ms (7× faster)
- Total TUI cold start: ~3400 ms → ~480 ms
Related: #29726, #29184, #19326 (closed stale)
Closes #29726
This commit is contained in:
parent
9b1d8341b2
commit
89f0b63da4
|
|
@ -247,16 +247,22 @@ def main(argv: list[str] | None = None) -> None:
|
|||
import acp
|
||||
from .server import HermesACPAgent
|
||||
|
||||
# MCP tool discovery from config.yaml — run before asyncio.run() so
|
||||
# it's safe to use blocking waits. (ACP also registers per-session
|
||||
# MCP servers dynamically via asyncio.to_thread inside the event
|
||||
# loop; that path is unaffected.) Moved from model_tools.py module
|
||||
# scope to avoid freezing the gateway's loop on lazy import (#16856).
|
||||
# MCP tool discovery from config.yaml — fire-and-forget in a
|
||||
# background daemon thread so the ACP server becomes responsive
|
||||
# immediately while MCP servers connect. Previously this blocked
|
||||
# asyncio.run() for 2-5 s. (ACP also registers per-session MCP
|
||||
# servers dynamically via asyncio.to_thread inside the event loop;
|
||||
# that path is unaffected.) Moved from model_tools.py module scope
|
||||
# to avoid freezing the gateway's loop on lazy import (#16856).
|
||||
# Metadata-only hosts can opt out of unrelated global MCP startup.
|
||||
if os.environ.get("HERMES_ACP_SKIP_CONFIGURED_MCP", "").strip() != "1":
|
||||
try:
|
||||
from tools.mcp_tool import discover_mcp_tools
|
||||
discover_mcp_tools()
|
||||
from hermes_cli.mcp_startup import start_background_mcp_discovery
|
||||
|
||||
start_background_mcp_discovery(
|
||||
logger=logger,
|
||||
thread_name="acp-mcp-discovery",
|
||||
)
|
||||
except Exception:
|
||||
logger.debug("MCP tool discovery failed at ACP startup", exc_info=True)
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue