Skip to content

Commit 94fdc8e

Browse files
cdeustclaude
andcommitted
fix(pipeline): resolve AP from the marketplace install, not a self-built symlink
discover_pipeline_command() now resolves the automatised-pipeline binary from installed_plugins.json first — the same source AP's own .mcp.json uses (installPath -> target/release/automatised-pipeline). This makes Cortex spawn the exact AP plugin the user installed via the marketplace, instead of a self-cloned/built copy behind a ~/.claude/methodology/bin symlink (the source of stale-version drift: a 0.0.9 self-build shadowing a 0.2.2 marketplace install). Also fixes the source-checkout fallback binary name (the build emits `automatised-pipeline`, not `ai-architect-mcp`). Self-install symlink / PATH / sibling-checkout remain as fallbacks for users without the plugin. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 14f057d commit 94fdc8e

1 file changed

Lines changed: 61 additions & 7 deletions

File tree

mcp_server/infrastructure/pipeline_discovery.py

Lines changed: 61 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,16 @@
55
``codebase`` MCP server wired up without manual config editing. The
66
discovery mirrors ``cortex-doctor``'s optional-capability probe:
77
8-
1. Binaries on PATH: ``cortex-pipeline``, ``automatised-pipeline``,
9-
``ai-automatised-pipeline``, ``ai-architect-mcp``.
10-
2. Sibling git checkout at ``../anthropic/ai-automatised-pipeline``
8+
1. Marketplace install (canonical): the AP plugin installed via
9+
``claude plugin install`` — resolved from ``installed_plugins.json``
10+
the same way AP's own ``.mcp.json`` does. Always preferred so Cortex
11+
spawns the exact plugin the user installed (no symlink, no drift).
12+
2. Binaries on PATH: ``cortex-pipeline``, ``automatised-pipeline``,
13+
``ai-automatised-pipeline``.
14+
3. Sibling git checkout at ``../anthropic/ai-automatised-pipeline``
1115
with a built Cargo release binary at
12-
``target/release/ai-architect-mcp``.
13-
3. Otherwise: no change to mcp-connections.json.
16+
``target/release/automatised-pipeline``.
17+
4. Otherwise: no change to mcp-connections.json.
1418
1519
If the file already exists AND already has a ``codebase`` server entry,
1620
we leave it alone — users who customized their config keep their
@@ -50,7 +54,46 @@
5054
"../ai-automatised-pipeline",
5155
)
5256

53-
_BUILT_RELATIVE = ("target/release/ai-architect-mcp",)
57+
_BUILT_RELATIVE = (
58+
"target/release/automatised-pipeline",
59+
"target/release/ai-architect-mcp",
60+
)
61+
62+
# ── Marketplace install (canonical) ─────────────────────────────────────
63+
64+
# The AP plugin installed via its marketplace. This is the SAME source AP's
65+
# own .mcp.json resolves from: installed_plugins.json -> installPath ->
66+
# target/release/automatised-pipeline. Preferring it means Cortex spawns the
67+
# exact plugin the user installed — no self-built symlink, no version drift.
68+
_INSTALLED_PLUGINS_PATH = (
69+
Path.home() / ".claude" / "plugins" / "installed_plugins.json"
70+
)
71+
_AP_PLUGIN_KEY = "automatised-pipeline@automatised-pipeline-marketplace"
72+
_AP_BINARY_RELATIVE = Path("target") / "release" / "automatised-pipeline"
73+
74+
75+
def _marketplace_pipeline_binary() -> Optional[str]:
76+
"""Resolve the AP binary from the marketplace install, or None.
77+
78+
Mirrors AP's own ``.mcp.json``: read ``installed_plugins.json``, take the
79+
plugin's ``installPath``, and point at ``target/release/automatised-pipeline``.
80+
Returns None when AP isn't installed or its binary hasn't been
81+
materialised yet (``bin/ensure-binary.sh`` runs on AP's first launch).
82+
"""
83+
try:
84+
data = read_json(_INSTALLED_PLUGINS_PATH) or {}
85+
entries = (data.get("plugins") or {}).get(_AP_PLUGIN_KEY) or []
86+
for entry in entries:
87+
install_path = entry.get("installPath")
88+
if not install_path:
89+
continue
90+
binary = Path(install_path) / _AP_BINARY_RELATIVE
91+
if binary.is_file() and os.access(binary, os.X_OK):
92+
return str(binary)
93+
except Exception:
94+
return None
95+
return None
96+
5497

5598
# ── Install paths (shared with pipeline_installer) ──────────────────────
5699

@@ -69,8 +112,19 @@ def discover_pipeline_command() -> Optional[list[str]]:
69112
None means "no pipeline found" — callers should leave the mcp
70113
config alone and let ingest_codebase fail with the standard
71114
McpConnectionError when invoked (ingestion is explicitly opt-in).
115+
116+
Resolution order, canonical install first:
117+
1. Marketplace install (installed_plugins.json) — the plugin the
118+
user installed via ``claude plugin install``. Always preferred.
119+
2. Self-installed symlink / PATH / sibling source checkout —
120+
legacy fallbacks for users without the marketplace plugin.
72121
"""
73-
# Auto-installed location — preferred when present.
122+
# Canonical: the marketplace-installed AP plugin.
123+
marketplace = _marketplace_pipeline_binary()
124+
if marketplace:
125+
return [marketplace]
126+
127+
# Legacy self-installed location.
74128
if _INSTALL_SYMLINK.exists() and os.access(_INSTALL_SYMLINK, os.X_OK):
75129
return [str(_INSTALL_SYMLINK)]
76130

0 commit comments

Comments
 (0)