Summary
On Windows, ok registers a macOS/Unix-only MCP server command into both the project .mcp.json and the global ~/.claude.json (Claude Code), and re-writes it on every server spawn (ok init, ok start, and the MCP server's autostart). The generated command is command: "/bin/sh" with a script that only looks for OpenKnowledge.app and Unix npx paths. Windows has no /bin/sh, so the host fails to launch it:
MCP open-knowledge: spawn /bin/sh ENOENT
MCP open-knowledge: Server disconnected.
Could not attach to MCP server open-knowledge
Because the config is regenerated on every server spawn, any manual Windows fix is overwritten the next time ok start runs or the MCP server autostarts — so the error keeps coming back.
Environment
- OS: Windows 11 Pro (10.0.26200)
- Node: v24.11.1
@inkeep/open-knowledge: 0.19.2 (CLI + server), installed via npm i -g
- Host: Claude Code (MCP client). The same generated config also lands in Cursor / Codex / OpenCode config files.
Steps to reproduce
- On Windows,
npm i -g @inkeep/open-knowledge
- In a project dir:
ok init
- Observe the generated
.mcp.json (and the mcpServers.open-knowledge entry written into ~/.claude.json):
{
"mcpServers": {
"open-knowledge": {
"command": "/bin/sh",
"args": ["-l", "-c",
"# ok-mcp-v1\nUSER_BUNDLE=\"$HOME/Applications/OpenKnowledge.app/Contents/Resources/cli/bin/ok.sh\"\n… BUNDLE=\"/Applications/OpenKnowledge.app/…\" … command -v npx … for d in \"$HOME/.nvm/…\" /opt/homebrew/bin /usr/local/bin …; do … done\necho \"OpenKnowledge: install OK Desktop or Node.js 24+, then restart your editor\" >&2\nexit 127"
]
}
}
}
- The MCP client (Claude Code) tries to spawn
/bin/sh → spawn /bin/sh ENOENT, server never attaches.
- Hand-fix the config to a Windows command (below) → it works. Then run
ok start (or let the MCP server autostart a project server) → the file is rewritten back to the /bin/sh form and the error returns.
Expected
- On Windows, generate a launchable command (no
/bin/sh dependency).
- Do not silently overwrite a user-customized MCP config on every server spawn; or provide a flag/env to opt out of MCP-config registration.
Actual
- Only a macOS bundle path + a Unix
npx fallback are emitted; there is no Windows branch, so the command is unlaunchable on Windows.
- The config is (re)written on
ok init, ok start, and MCP autostart, clobbering manual fixes.
Working workaround (Windows)
Replacing the entry with an explicit Windows command makes the MCP server attach and complete the initialize handshake (serverInfo: open-knowledge v0.19.2):
{
"mcpServers": {
"open-knowledge": {
"command": "cmd",
"args": ["/c", "C:\\Users\\<me>\\AppData\\Roaming\\npm\\ok.cmd",
"--cwd", "<project-dir>", "mcp", "--no-bundle-proxy"],
"env": { "HOST": "127.0.0.1" }
}
}
}
But this is overwritten on the next server spawn (see above).
Suggested fixes
- Windows-aware config generation. Emit a Windows-launchable command instead of
/bin/sh — e.g. cmd /c ok.cmd … mcp (or a node <cli> mcp invocation, or platform-branch the generated command).
- Don't clobber user edits. If the
open-knowledge MCP entry already exists and differs, leave it (or merge non-destructively), and/or add an env/flag like OK_SKIP_MCP_REGISTER=1 to skip registration on ok start / autostart.
Related Windows findings (same setup; may be separate issues)
- MCP-autostarted server binds IPv6
::1 only. The MCP client's edit / exec calls connect to 127.0.0.1 and fail with Server unreachable: fetch failed / "actively refused". Confirmed via Get-NetTCPConnection: the autostarted server listens on ::1:<port> only, while the ok ui process dual-stacks. Workaround: start with --host 127.0.0.1 or env HOST=127.0.0.1.
- Auto-sync (
autoSync.enabled in .ok/local/config.yml) is only read at server startup. Toggling "Git auto-sync" ON in the editor UI writes enabled: true, but a server that was already running keeps syncEnabled:false (log: [sync] trigger(sync) ignored — state=disabled); it only takes effect after a server restart. Consider hot-reloading the sync setting, or documenting that a restart is required.
Filed with help from Claude Code. Happy to provide more logs or test a fix on Windows.
Summary
On Windows,
okregisters a macOS/Unix-only MCP server command into both the project.mcp.jsonand the global~/.claude.json(Claude Code), and re-writes it on every server spawn (ok init,ok start, and the MCP server's autostart). The generated command iscommand: "/bin/sh"with a script that only looks forOpenKnowledge.appand Unixnpxpaths. Windows has no/bin/sh, so the host fails to launch it:Because the config is regenerated on every server spawn, any manual Windows fix is overwritten the next time
ok startruns or the MCP server autostarts — so the error keeps coming back.Environment
@inkeep/open-knowledge: 0.19.2 (CLI + server), installed vianpm i -gSteps to reproduce
npm i -g @inkeep/open-knowledgeok init.mcp.json(and themcpServers.open-knowledgeentry written into~/.claude.json):{ "mcpServers": { "open-knowledge": { "command": "/bin/sh", "args": ["-l", "-c", "# ok-mcp-v1\nUSER_BUNDLE=\"$HOME/Applications/OpenKnowledge.app/Contents/Resources/cli/bin/ok.sh\"\n… BUNDLE=\"/Applications/OpenKnowledge.app/…\" … command -v npx … for d in \"$HOME/.nvm/…\" /opt/homebrew/bin /usr/local/bin …; do … done\necho \"OpenKnowledge: install OK Desktop or Node.js 24+, then restart your editor\" >&2\nexit 127" ] } } }/bin/sh→spawn /bin/sh ENOENT, server never attaches.ok start(or let the MCP server autostart a project server) → the file is rewritten back to the/bin/shform and the error returns.Expected
/bin/shdependency).Actual
npxfallback are emitted; there is no Windows branch, so the command is unlaunchable on Windows.ok init,ok start, and MCP autostart, clobbering manual fixes.Working workaround (Windows)
Replacing the entry with an explicit Windows command makes the MCP server attach and complete the
initializehandshake (serverInfo: open-knowledge v0.19.2):{ "mcpServers": { "open-knowledge": { "command": "cmd", "args": ["/c", "C:\\Users\\<me>\\AppData\\Roaming\\npm\\ok.cmd", "--cwd", "<project-dir>", "mcp", "--no-bundle-proxy"], "env": { "HOST": "127.0.0.1" } } } }But this is overwritten on the next server spawn (see above).
Suggested fixes
/bin/sh— e.g.cmd /c ok.cmd … mcp(or anode <cli> mcpinvocation, or platform-branch the generated command).open-knowledgeMCP entry already exists and differs, leave it (or merge non-destructively), and/or add an env/flag likeOK_SKIP_MCP_REGISTER=1to skip registration onok start/ autostart.Related Windows findings (same setup; may be separate issues)
::1only. The MCP client'sedit/execcalls connect to127.0.0.1and fail withServer unreachable: fetch failed/ "actively refused". Confirmed viaGet-NetTCPConnection: the autostarted server listens on::1:<port>only, while theok uiprocess dual-stacks. Workaround: start with--host 127.0.0.1orenv HOST=127.0.0.1.autoSync.enabledin.ok/local/config.yml) is only read at server startup. Toggling "Git auto-sync" ON in the editor UI writesenabled: true, but a server that was already running keepssyncEnabled:false(log:[sync] trigger(sync) ignored — state=disabled); it only takes effect after a server restart. Consider hot-reloading the sync setting, or documenting that a restart is required.Filed with help from Claude Code. Happy to provide more logs or test a fix on Windows.