Repository navigation
Description
Version
codebase-memory-mcp:0.8.1
Platform
Windows (x64)
Install channel
GitHub release archive / install.sh / install.ps1
Binary variant
standard
What happened, and what did you expect?
Hi, I’m seeing a Windows-specific stdio startup issue with codebase-memory-mcp.
Environment
OS: Windows 11 / Windows x64
Binary: codebase-memory-mcp.exe
Binary path: E:\setup\codebase-memory-mcp-windows-amd64\codebase-memory-mcp.exe
codebase-memory-mcp --help reports: 0.8.1
MCP initialize response reports server version: 0.10.0
Client that fails: Hermes Agent MCP client, using Python MCP SDK / AnyIO stdio transport
Client that works: Qwen Code
Problem
When Hermes launches codebase-memory-mcp.exe directly as a stdio MCP server, the process starts but never responds to the MCP initialize request. Hermes eventually times out.
Hermes config:
mcp_servers:
CODEBASE_MEMORY:
command: E:\setup\codebase-memory-mcp-windows-amd64\codebase-memory-mcp.exe
args: []
timeout: 3600000
connect_timeout: 180
enabled: true
Hermes test result:
Testing 'CODEBASE_MEMORY'...
Transport: stdio → E:\setup\codebase-memory-mcp-windows-amd64\codebase-memory-mcp.exe
Auth: none
✗ Connection failed (42703ms): MCP call timed out after 40.7s
The process starts and logs:
level=info msg=mem.init budget_mb=16218 total_ram_mb=32437
But Hermes never receives the initialize response.
Important Observation
The same binary responds correctly when launched with normal Python subprocess.Popen and sent a newline-delimited JSON-RPC initialize request manually.
Example request:
{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-11-25","capabilities":{},"clientInfo":{"name":"manual-test","version":"0"}}}
Response:
{"jsonrpc":"2.0","id":1,"result":{"protocolVersion":"2025-11-25","serverInfo":{"name":"codebase-memory-mcp","version":"0.10.0"},"capabilities":{"tools":{}}}}
tools/list also works manually and returns 14 tools.
So the MCP payload and protocol version appear to be valid.
Reproduction
Configure Hermes to launch codebase-memory-mcp.exe directly over stdio.
Stop any existing MCP process:
Get-Process codebase-memory-mcp -ErrorAction SilentlyContinue | Stop-Process -Force
Run:
hermes mcp test CODEBASE_MEMORY
Result: timeout during initialize.
Additional Evidence
Using a minimal AnyIO-based Python script to launch the binary also hangs waiting for stdout, even after writing the initialize request to stdin.
This suggests the problem is related to Windows async subprocess pipes / AnyIO / asyncio Proactor behavior.
By contrast, a normal blocking subprocess.Popen test works.
Source-Level Suspicion
In src/mcp/mcp.c, the Windows branch of the MCP server loop appears to wait on stdin like this:
HANDLE hStdin = (HANDLE)_get_osfhandle(fd);
DWORD wr = WaitForSingleObject(hStdin, STORE_IDLE_TIMEOUT_S * MCP_TIMEOUT_MS);
Then it calls cbm_getline().
On Windows, this WaitForSingleObject(stdin handle) path may not wake correctly for pipes created by Python AnyIO / asyncio Proactor subprocess transport.
The Unix branch has a more careful poll + FILE* buffer peek workaround for buffered getline() behavior, but the Windows branch does not appear to have an equivalent.
Workaround
A small Python stdio shim fixes the issue. Hermes launches Python, and Python launches codebase-memory-mcp.exe using normal blocking pipes, forwarding newline-delimited JSON-RPC messages.
Hermes config with shim:
mcp_servers:
CODEBASE_MEMORY:
command: C:\Users\Administrator\AppData\Roaming\uv\python\cpython-3.11.15-windows-x86_64-none\python.exe
args:
- E:\setup\codebase-memory-mcp-windows-amd64\codebase-memory-hermes-stdio-shim.py
- E:\setup\codebase-memory-mcp-windows-amd64\codebase-memory-mcp.exe
- '3600000'
timeout: 3600000
connect_timeout: 180
enabled: true
After using the shim:
Testing 'CODEBASE_MEMORY'...
✓ Connected (2141ms)
✓ Tools discovered: 14
Why This Matters
Qwen Code can start this MCP server correctly, likely because it uses a different stdio process model. Hermes / Python MCP SDK / AnyIO direct launch fails on Windows.
So this looks like a compatibility issue between codebase-memory-mcp’s Windows stdio wait loop and some Windows async subprocess pipe implementations.
Request
Could you please check the Windows stdio event loop, especially the WaitForSingleObject usage on stdin handles?
A possible fix may be to avoid waiting directly on the stdin handle for pipe readiness on Windows, or to use a blocking read loop / overlapped-compatible approach instead.
Reproduction
only setup hermes to reproduction
Logs
Project scale (if relevant)
No response
Confirmations
- I searched existing issues and this is not a duplicate.
- My reproduction uses shareable code (a dummy snippet or a public OSS repository), not proprietary code.
Activity
test(windows): add red regressions for hook augmenter and UI drive pi…
DeusData commentedon Jun 29, 2026
Thanks for the report. I’ve triaged this under #394 and #395. We need a Hermes/AnyIO stdio reproduction that proves
initializenever blocks and that stdout/stderr remain protocol-safe during startup.test(windows): add red regressions for hook augmenter and UI drive pi…
github-actions commentedon Jul 8, 2026
Thanks for the report! To move this forward we need a bit more so we can reproduce it ourselves:
codebase-memory-mcp --versionyou're onOnce that's here we'll pick it straight back up. Heads-up: issues left
awaiting-reporterare automatically closed after a few weeks of silence, but a comment reopens the door anytime.DeusData commentedon Jul 8, 2026
v0.9.0 includes Windows runtime and MCP startup reliability fixes that may address this initialize hang. Could you retest the MCP handshake on v0.9.0 and confirm whether initialization still blocks? Marking awaiting-reporter.
Gavinluo commentedon Jul 10, 2026
Nice! Good job! I retested and passed.
ako-v commentedon Jul 19, 2026
I'm on codebase-memory-mcp 0.9.0 and Windows 11, but it does not work with hermes, when I try to test the connection it fails with this message:
But as @Gavinluo said, it works with a shim for me!
DeusData commentedon Jul 19, 2026
Reopening because @ako-v confirms that direct Hermes launch still times out on Windows with v0.9.0 while the shim works. I removed
awaiting-reporterand returned this high-priority bug to the0.9.1-rcmaintainer queue.wengecaitui commentedon Aug 2, 2026
Repro for the Hermes/AnyIO initialize hang (Windows) — minimal, pure-stdlib
Environment
codebase-memory-mcp.exe— CLI--helpreports0.8.1, but the MCPinitializeresponse reportsserverInfo.version = 0.10.0(version mismatch on this build)mcp.client.stdio.stdio_client), configcommand: <exe>with no argsconnect_timeout: 60and180— identical outcomeSymptom
The client spawns the exe, keeps stdin open (normal long-lived MCP stdio), sends
initialize, and never receives a response; afterconnect_timeoutseconds the SDK surfaces an opaqueCancelledError.stderrshows onlylevel=info msg=mem.init budget_mb=... total_ram_mb=....Key experiment — the same exe answers instantly when stdin is closed right after the request:
Output:
Interpretation
The stdio transport appears to read stdin until EOF before handling/flushing messages (read-all-then-handle), so any client that keeps the pipe open hangs forever.
connect_timeoutcannot fix this.Working workaround today
The one-shot
cli <tool> <json>subcommand responds reliably (fresh process per call). A small shim mapping MCP tools toclicalls is fully functional — happy to share it.Could you confirm whether the stdio transport reads stdin until EOF before processing messages? Happy to provide any further detail or a GitHub Actions repro.
DeusData commentedon Aug 14, 2026
@wengecaitui, that A/B script is the entire diagnosis in twenty lines — "responds instantly with stdin closed, no response at all with stdin open" is the signature that mattered, and it lined up with @ako-v's confirmation that a shim works while a direct Hermes launch times out, and with @Gavinluo's original report.
Your interpretation was correct, and it is now confirmed in code: on Windows the stdin wait uses
WaitForSingleObjecton a handle that is not waitable for an anonymous pipe (src/mcp/mcp.c), so a client that keeps the pipe open — which is exactly what MCP stdio is supposed to do — never gets aninitializeresponse. That is being fixed, and it is in scope for tonight's v0.10.5, which is aimed at the issues that make cbm unusable rather than merely awkward.I am sorry this sat for as long as it did while people worked around it with shims. A server that never answers
initializeis about as broken as an MCP server can be, and the version-mismatch detail you both flagged is noted too.DeusData commentedon Sep 26, 2026
Thank you, @Gavinluo, @ako-v and @wengecaitui! The stdin-open vs stdin-closed A/B script in particular was exactly the right experiment.
A correction to the earlier update: since v0.10.0, a stdio session no longer runs the old
WaitForSingleObjectloop at all. It goes through the daemon frontend instead, which reads stdin with a blocking reader on its own thread and answers each message as it arrives, whether or not the client keeps the pipe open.Could one of you retest a direct Hermes launch (no shim) on v0.11.0 and tell us whether
initializenow answers? If it still times out, the stderr from that launch plus the output ofcodebase-memory-mcp --versionwould be the key evidence.github-actions commentedon Sep 26, 2026
Thanks for the report! To move this forward we need a bit more so we can reproduce it ourselves:
codebase-memory-mcp --versionyou're onOnce that's here we'll pick it straight back up. Heads-up: issues left
awaiting-reporterare automatically closed after a few weeks of silence, but a comment reopens the door anytime.github-actions commentedon Oct 18, 2026
This issue has been waiting on more information for 21 days (a version, exact steps, or a public repro), so it's now marked
stale. It will not be closed automatically — a maintainer reviews stale issues by hand. Adding a comment with the details clears the label and puts it straight back in the queue. We're happy to pick it back up the moment we can reproduce it.DeusData commentedon Oct 19, 2026
Thank you again for the direct-launch and shim comparisons. Checking back on the September retest request: does a current direct Hermes launch now complete initialization without the shim? If it still hangs, please include the CBM version and short stderr output; no broad new investigation is being requested.
DeusData commentedon Oct 25, 2026
Thank you again for the report and your patience. If you have already retried a direct Hermes launch, please share the version and whether initialization completes without the shim.