We set out to build a memory layer for AI agents. We ended up debugging Groq's app before they did. This is Part 1 — the quest begins, the dragons emerge, and Windows does what Windows does.
The idea was straightforward: build persistent memory for AI agents using local SQLite. No cloud. No subscriptions. No vendor lock-in. A graph database that lives on your machine and gives every AI app a brain that actually remembers things between sessions.
What we didn't anticipate was the labyrinth between "working Node.js package" and "seamlessly installed across six different AI apps on Windows." That journey involved Windows path hell, a Node ABI mismatch, a PowerShell popup dragon, and ultimately fixing a bug in Groq's own desktop app before their engineers did.
"Anyone who tells you cross-platform AI tooling is easy has never tried to ship a native Node binary across nvm versions on Windows."
This is that story. Three parts. Real code, real errors, real blood on the floor. And at the end — a 34-tool MCP server that configures itself across Claude Desktop, Cursor, Windsurf, VS Code, Continue, and Groq Desktop in 60 seconds.
The Model Context Protocol is Anthropic's open standard for connecting AI models to external tools. Think of it as a universal adapter: instead of every AI app needing a custom integration for every tool, MCP defines one protocol that any app can speak and any tool can implement.
An MCP server is a process that runs locally on your machine and exposes a set of tools via JSON-RPC over stdio. When Claude Desktop starts, it reads a config file, spawns your MCP server as a child process, discovers its tools, and makes them available in every conversation. The AI can then call those tools — and your server executes real code in response.
// The config that wires everything together
{
"mcpServers": {
"vektor-slipstream": {
"command": "node",
"args": ["/path/to/vektor.mjs", "mcp"],
"env": {
"VEKTOR_LICENCE_KEY": "your-key-here"
}
}
}
}That's the basic pattern. Claude Desktop reads this, spawns node /path/to/vektor.mjs mcp, and your server sits waiting on stdin for tool calls. Clean, simple, powerful.
DXT — Desktop Extension — is Anthropic's packaging format for MCP servers. A .dxt file is a small manifest that tells Claude Desktop everything it needs to know: where to find the server, what environment variables to ask the user for, what the tool descriptions are. Drag it onto Claude Desktop's Extensions page and it configures everything automatically.
Before DXT, every user had to manually edit a JSON config file. On Windows, this was a minefield — one wrong character, one BOM (Byte Order Mark) injected by Notepad, and the entire MCP connection silently fails. DXT eliminates that entirely. One drag-and-drop, done.
The first major obstacle wasn't the code — it was Windows itself. Node Version Manager on Windows (nvm4w) installs Node binaries in a non-standard location. When npm installs global packages, they land somewhere like C:\nvm4w\nodejs2\nodejs\node_modules\. When your DXT config says "command": "node", Windows has to find that binary — and depending on PATH configuration, it sometimes doesn't.
The fix was obvious in hindsight: use process.execPath instead of the string "node". This gives you the absolute path to the exact Node binary that's currently running — no PATH lookup, no ambiguity.
// WRONG — relies on PATH resolution
const serverEntry = {
command: 'node',
args: [vektorMjs, 'mcp']
}
// RIGHT — absolute path, always works
const serverEntry = {
command: process.execPath, // e.g. C:\nvm4w\nodejs2\nodejs\node.exe
args: [vektorMjs, 'mcp']
}Then came the popup dragon. Every time any npm-installed binary ran on Windows, a PowerShell console window would flash open and close. Open an app, popup. Run a command, popup. It was everywhere, suddenly, on every tool.
The cause: npm on Windows creates three shim files for every package — a .cmd file, a no-extension file, and a .ps1 PowerShell file. Something had changed in our environment that made Windows prefer the .ps1 shim — and PowerShell shims always spawn a visible console window.
The nuclear option: delete every .ps1 shim in the Node bin directory. The .cmd shims do exactly the same job. Nothing breaks. The popups vanish permanently.
# Delete all .ps1 shims — .cmd takes over, no more popups
Get-ChildItem "C:\nvm4w\nodejs2\nodejs" -Filter "*.ps1" | Remove-Item -Force
Get-ChildItem "C:\Users\minimaxa\AppData\Local\nvm\v24.1.0\node_modules\.bin" `
-Filter "*.ps1" -Recurse | Remove-Item -ForceTwo commands. Dragon slain. Zero popups from that point forward — across every app, every tool, every install.
VEKTOR's memory engine uses better-sqlite3 — a native Node addon that compiles to a .node binary. Native addons are compiled against a specific Node ABI version. If your MCP server runs on a different Node version than the one that compiled the binary, you get a cryptic error and a dead server.
The deeper problem: better-sqlite3 inside our obfuscated core module uses the bindings package to locate its compiled binary. bindings resolves the binary relative to the current working directory — not the package directory. So when Claude Desktop spawned the MCP server from C:\Users\minimaxa\, it looked for the binary relative to the home folder and found nothing.
The fix: a process.chdir() call before loading the core module, setting the working directory to the package folder where better-sqlite3 lives. One line. Hours of debugging to find it.
This is what nobody writes about. The real work of shipping developer tools isn't the algorithms or the architecture — it's the 47 environmental assumptions that silently fail on someone else's machine. Every one of those assumptions is a dragon in the labyrinth.
After solving the path problems, the ABI issues, and the popup dragon, we had a working MCP server. But customers still had to manually configure each app. Different apps use different config file locations, different JSON formats, different root keys (mcpServers vs servers). It was a documentation nightmare.
So we built a setup wizard. Run vektor setup and it scans for installed AI apps, shows you what it found, asks for confirmation per app, and writes the correct config for each one automatically. It backs up existing configs before touching them. It validates JSON before and after writing. It uses process.execPath so the paths are always correct.
// Step 6 output
✓ Claude Desktop — found
✓ Cursor — found
✓ Windsurf — found
✓ VS Code — found
✓ Continue — found
✓ Groq Desktop — found
Configure Claude Desktop? [y/N]: y
✓ Claude Desktop configured
✓ Profile: full (34 tools)
Configure Cursor? [y/N]: y
✓ Cursor configured
✓ Profile: dev (15 tools — optimised for 40-tool limit)Each app gets the right config format. Cursor gets a warning about its 40-tool limit and a dev-optimised profile. VS Code gets servers as the root key instead of mcpServers. Continue gets a YAML-format drop file. All handled automatically, transparently, without the user needing to know any of it.
"The best developer experience is the one where the developer never has to think about the infrastructure at all."
We had six apps configured. Then we tested Groq Desktop — and every single tool call failed with a JSON schema error. The trail led directly into Groq Desktop's source code, to a comment that said "Removed additionalProperties to be less strict."
We found the bug, fixed it, rebuilt their app, and sent them the bug report. All before they knew it existed.