-
-
Notifications
You must be signed in to change notification settings - Fork 2k
Description
Bug Description
On Windows, the chroma-mcp vector search backend fails to connect with MCP error -32000: Connection closed. The search MCP tool is completely non-functional — every call returns this error or chroma-mcp connection in backoff (Xs remaining).
Environment
- OS: Windows 11 Pro 10.0.26200
- claude-mem version: 10.3.1 (main branch, latest as of Feb 20, 2026)
- Node.js: v24.13.0
- Bun: installed at
~/.bun/bin/bun.exe - Python/uvx: uvx 0.9.28, Python 3.13
- uvx location:
C:\Users\<user>\.local\bin\uvx.exe
Root Cause
In worker-service.cjs, the connectInternal() method spawns chroma-mcp using:
let i = process.platform === "win32" ? "uvx.cmd" : "uvx";On Windows, uvx.cmd is a batch file wrapper. When StdioClientTransport spawns it as a child process, the .cmd wrapper adds an indirection layer that breaks the stdin/stdout MCP handshake. The connection closes within milliseconds (~4ms) before initialization completes.
Logs
[CHROMA_MCP] Connecting to chroma-mcp via MCP stdio {command=uvx.cmd, args=chroma-mcp --client-type persistent --data-dir C:\Users\<user>\.claude-mem\chroma}
[CHROMA_MCP] Connection failed, killing subprocess to prevent zombie {error=MCP error -32000: Connection closed}
[CHROMA] SDK chroma sync failed, continuing without vector search
This is the same class of bug as #695 (macOS), but with a Windows-specific cause.
Fix / Workaround
Changing uvx.cmd to the full path of uvx.exe resolves the issue completely:
// Before (broken on Windows):
let i = process.platform === "win32" ? "uvx.cmd" : "uvx";
// After (works):
let i = process.platform === "win32" ? "uvx.exe" : "uvx";Using uvx.exe directly bypasses the .cmd batch wrapper and allows the MCP stdio transport to function correctly. After this one-line change, all search/vector operations work perfectly.
Suggested robust fix:
const { execSync } = require('child_process');
function resolveUvx() {
if (process.platform !== 'win32') return 'uvx';
// Prefer .exe directly to avoid .cmd stdio issues
try {
const resolved = execSync('where uvx.exe', { encoding: 'utf-8', timeout: 5000 }).trim().split('\n')[0];
if (resolved) return resolved;
} catch {}
return 'uvx.exe'; // fallback — .exe suffix still avoids .cmd
}Steps to Reproduce
- Install claude-mem 10.3.1 on Windows 11
- Ensure
uvxis installed (viapip install uvor standalone installer) - Use any search MCP tool (e.g.,
searchwith any query) - Observe
MCP error -32000: Connection closedin response and logs
Related
- macOS: Chroma MCP connection fails with 'MCP error -32000: Connection closed' #695 — Same symptom (chroma-mcp connection failure) on macOS, different root cause
- PR fix: prevent chroma-mcp spawn storm with 5-layer defense (641 processes → max 2) #1065 — 5-layer defense fix for macOS: Chroma MCP connection fails with 'MCP error -32000: Connection closed' #695 (does not resolve this Windows-specific
.cmdwrapper issue)
Impact
All MCP search functionality (semantic/vector search) is broken on Windows. The SQLite FTS fallback doesn't activate for MCP tool calls — they just error out. The worker itself runs fine (/api/health returns OK), but the internal chroma-mcp child process can never connect.