Skip to content

v2.3.1 — Windows MCP hang hotfix (#46, #136)

Choose a tag to compare

@tirth8205 tirth8205 released this 11 Apr 21:07
· 91 commits to main since this release
02a7bc5

Summary

Hotfix for the Windows long-running MCP tool hang. v2.2.4 shipped the event-loop policy fix, but @dev-limucc's test on #136 showed that was necessary but not sufficient — read-only tools worked, but build_or_update_graph_tool and embed_graph_tool still hung indefinitely on Windows 11 / Python 3.14.

uvx --reinstall code-review-graph
# or
pip install -U code-review-graph

If you were affected by either #46 or #136 on v2.2.4, this release should fix it.

What's fixed

FastMCP 2.x dispatches sync handlers inline on the only event-loop thread. When a handler runs for more than a few seconds — especially one that spawns subprocesses (full_build uses ProcessPoolExecutor) or does CPU-bound inference (sentence-transformers) — the loop stops pumping stdin/stdout, Claude Code's request never gets a response, and the MCP client shows "Synthesizing…" forever.

Fix: the five heavy tools are now async def and offload their blocking work with asyncio.to_thread. The event loop stays responsive and stdio keeps pumping.

Tools now async

  • build_or_update_graph_toolfull_build / incremental_update
  • run_postprocess_tool — community detection can take 20s+ on large graphs
  • embed_graph_tool — sentence-transformers / Gemini inference
  • detect_changes_toolgit diff subprocess + BFS traversal
  • generate_wiki_tool — many SQLite reads + file writes

The other 19 tools are fast SQLite-read paths and stay sync.

Lock-in tests

Two new regression tests in tests/test_main.py::TestLongRunningToolsAreAsync:

  1. test_heavy_tools_are_coroutines — asserts via mcp.get_tools() introspection that all 5 heavy tools register as coroutine functions.
  2. test_heavy_tool_source_uses_to_thread — greps each tool's source for a literal asyncio.to_thread call, so we don't accidentally make a tool async def without actually offloading the work.

These will fail at collection time if someone converts one of the 5 tools back to sync in a future refactor.

Verification

macOS / Python 3.11:

  • All 24 tools register, 5 heavy ones as coroutines
  • 737 tests pass (+2 new lock-in tests), coverage 74.63%
  • ruff / mypy / bandit clean
  • CI matrix 3.10 / 3.11 / 3.12 / 3.13 green

Windows: will be verified by @dev-limucc post-release against the original repro (build_or_update_graph_tool(full_rebuild=True) + embed_graph_tool).

Upgrade notes

  • Nothing to do beyond upgrading. The async wrappers are transparent to MCP clients — they still call the tools the same way.
  • If you're coming from v2.2.2 or earlier, the usual code-review-graph install is still needed to pick up the v2.2.3 hook schema rewrite.

Closes (pending final Windows test)

  • #46 (build hangs on Windows)
  • #136 (embed_graph_tool hangs on Windows)