Skip to content

Fix capture-hooks install wiring a non-runnable in-wheel MCP wrapper (#26)#28

Open
danielhertz1999-bit wants to merge 1 commit into
CodeAbra:mainfrom
danielhertz1999-bit:fix/wrapper-deps-resolution
Open

Fix capture-hooks install wiring a non-runnable in-wheel MCP wrapper (#26)#28
danielhertz1999-bit wants to merge 1 commit into
CodeAbra:mainfrom
danielhertz1999-bit:fix/wrapper-deps-resolution

Conversation

@danielhertz1999-bit

Copy link
Copy Markdown
Contributor

Fixes the first half of #26.

The bug

_resolve_wrapper_path() returns the wheel-bundled wrapper (iai_mcp/_wrapper/index.js) as soon as it exists, ahead of a working mcp-wrapper/dist/index.js. But the in-wheel copy ships the JS with no package.json and no node_modules/, so when Claude spawns it Node throws:

Error [ERR_MODULE_NOT_FOUND]: Cannot find package '@modelcontextprotocol/sdk'
  imported from .../site-packages/iai_mcp/_wrapper/index.js

and the iai-mcp MCP entry shows as failed. capture-hooks install overwrites a previously-working dev path with this broken one.

The fix

Prefer a wrapper whose npm deps actually resolve. Node resolves bare imports like @modelcontextprotocol/sdk by walking parent dirs for a node_modules containing the package, so the resolver now does the same: it collects the candidate paths in preference order and returns the first one with a reachable node_modules/@modelcontextprotocol/sdk. The depless in-wheel wrapper is skipped in favour of mcp-wrapper/dist sitting next to its node_modules.

When a wrapper exists but its deps aren't installed (e.g. pip install . with no npm build and no dev tree), it now raises FileNotFoundError with a clear "build it / set IAI_MCP_WRAPPER_PATH" message instead of silently wiring a broken entry — callers already route that through the existing placeholder/warning path (_iai_entry_or_placeholder), so install degrades gracefully rather than producing a failed MCP server.

Verification

Unit-tested the resolver against both layouts: in-wheel-without-node_modules is correctly treated as not-runnable and skipped; dist-with-node_modules is preferred. No behavioral change when the in-wheel wrapper is genuinely runnable (i.e. once the wheel bundles its deps).

Not included here

The second half of #26 (SessionStart hook re-registration / lack of a --components opt-out) is a separate ergonomics change — happy to send a follow-up adding a --components=stop,turn style flag if you'd like that approach.

🤖 Generated with Claude Code

…a#26)

_resolve_wrapper_path() returned the wheel-bundled wrapper
(iai_mcp/_wrapper/index.js) whenever it merely existed, ahead of a working
mcp-wrapper/dist/index.js. The in-wheel copy ships the JS but no
node_modules, so Node fails at spawn with
"ERR_MODULE_NOT_FOUND: @modelcontextprotocol/sdk" and the iai-mcp MCP entry
shows up as failed in Claude.

Prefer a wrapper whose npm deps actually resolve: gather the candidate paths
in preference order, then return the first one that has a reachable
node_modules/@modelcontextprotocol/sdk (matching how Node resolves bare
imports). When a wrapper exists but its deps aren't installed, raise
FileNotFoundError with a clear "build it / set IAI_MCP_WRAPPER_PATH" message;
callers already route that through the placeholder/warning path, so install
no longer silently registers a broken MCP server.

Reported by @Marsu6996 on v1.2.0.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant