Summary
claude/.mcp.json resolves ijfw-memory through ${CLAUDE_PLUGIN_ROOT}/../mcp-server/src/server.js. That path is correct in the source tree, but wrong once Claude Code copies the plugin into its plugin cache — the sibling mcp-server/ is outside the plugin directory and is not copied. The server then fails to start on every session with CONNECTION_CLOSED, and no IJFW memory tools are exposed.
Still present on main today (claude/.mcp.json, unchanged).
Mechanism
claude/ is the plugin root, so ../mcp-server/ reaches the repo root — fine in-tree:
~/.ijfw/claude/../mcp-server/src/server.js -> EXISTS (117.7 KB)
Claude Code installs the plugin by copying claude/ into its cache and pointing CLAUDE_PLUGIN_ROOT at the copy. .. now escapes into the cache namespace, where no mcp-server/ exists:
~/.claude/plugins/cache/ijfw/ijfw/1.5.4/../mcp-server/src/server.js -> NO SUCH FILE
The cached bundle contains only what lives under claude/:
.claude-plugin/ agents/ bin/ commands/ hooks/ rules/ skills/
.claudeignore .mcp.json
No mcp-server/ at any level. node <nonexistent> exits immediately, which the host reports as a closed connection.
Reproduce
- Install the plugin from the marketplace (here:
extraKnownMarketplaces.ijfw -> directory source C:\Users\aqten\.ijfw\claude, plugin ijfw@ijfw enabled).
- Start a session.
Observed:
plugin:ijfw:ijfw-memory (CONNECTION_CLOSED): "Connection closed"
No mcp__ijfw-memory__* tools are available for the session.
The server itself is healthy — pointed at the real path it initializes cleanly:
$ echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{...}}' \
| node ~/.ijfw/mcp-server/src/server.js
{"jsonrpc":"2.0","id":1,"result":{"protocolVersion":"2024-11-05",
"capabilities":{"tools":{},"resources":{},"prompts":{}},
"serverInfo":{"name":"ijfw-memory","version":"1.5.4","schemaVersion":1}}}
So this is purely the path, not the server.
Impact
Silent. scripts/doctor.sh reports [MCP server] [ok] MCP server responds cleanly, because check-mcp.sh tests the standalone launcher in the install tree — the path that works — not the plugin registration that the host actually loads. A user running doctor is told MCP is fine while the plugin copy has never once started. Every memory feature routed through the MCP is absent, and CLAUDE.md still instructs the model to call ijfw_memory_prelude, which does not exist in that session.
Environment
- IJFW plugin
1.5.4, mcp-server reports 1.5.4
- Claude Code, Windows 11 (26200), Node via
node on PATH
- Marketplace source: local directory
Suggested fixes
- Ship
mcp-server/ inside the plugin and reference it without ..:
"${CLAUDE_PLUGIN_ROOT}/mcp-server/src/server.js". Self-contained, survives any install layout.
- Or have the installer rewrite
.mcp.json to an absolute path at install time, since ijfw install already knows $IJFW_HOME.
- Either way, make
doctor check the registration the host loads, not only the in-tree launcher — the current check cannot fail in this scenario, so it reports green on a broken install.
Workaround
Repointing the cached .mcp.json at the absolute install path works, but is per-machine and is reverted by the next ijfw update:
{"mcpServers":{"ijfw-memory":{"command":"node",
"args":["C:/Users/aqten/.ijfw/mcp-server/src/server.js"],"env":{}}}}
Summary
claude/.mcp.jsonresolvesijfw-memorythrough${CLAUDE_PLUGIN_ROOT}/../mcp-server/src/server.js. That path is correct in the source tree, but wrong once Claude Code copies the plugin into its plugin cache — the siblingmcp-server/is outside the plugin directory and is not copied. The server then fails to start on every session withCONNECTION_CLOSED, and no IJFW memory tools are exposed.Still present on
maintoday (claude/.mcp.json, unchanged).Mechanism
claude/is the plugin root, so../mcp-server/reaches the repo root — fine in-tree:Claude Code installs the plugin by copying
claude/into its cache and pointingCLAUDE_PLUGIN_ROOTat the copy...now escapes into the cache namespace, where nomcp-server/exists:The cached bundle contains only what lives under
claude/:No
mcp-server/at any level.node <nonexistent>exits immediately, which the host reports as a closed connection.Reproduce
extraKnownMarketplaces.ijfw-> directory sourceC:\Users\aqten\.ijfw\claude, pluginijfw@ijfwenabled).Observed:
No
mcp__ijfw-memory__*tools are available for the session.The server itself is healthy — pointed at the real path it initializes cleanly:
So this is purely the path, not the server.
Impact
Silent.
scripts/doctor.shreports[MCP server] [ok] MCP server responds cleanly, becausecheck-mcp.shtests the standalone launcher in the install tree — the path that works — not the plugin registration that the host actually loads. A user running doctor is told MCP is fine while the plugin copy has never once started. Every memory feature routed through the MCP is absent, andCLAUDE.mdstill instructs the model to callijfw_memory_prelude, which does not exist in that session.Environment
1.5.4, mcp-server reports1.5.4nodeon PATHSuggested fixes
mcp-server/inside the plugin and reference it without..:"${CLAUDE_PLUGIN_ROOT}/mcp-server/src/server.js". Self-contained, survives any install layout..mcp.jsonto an absolute path at install time, sinceijfw installalready knows$IJFW_HOME.doctorcheck the registration the host loads, not only the in-tree launcher — the current check cannot fail in this scenario, so it reports green on a broken install.Workaround
Repointing the cached
.mcp.jsonat the absolute install path works, but is per-machine and is reverted by the nextijfw update:{"mcpServers":{"ijfw-memory":{"command":"node", "args":["C:/Users/aqten/.ijfw/mcp-server/src/server.js"],"env":{}}}}