Skip to content

fix(install): one MCP registration list for all three entry points - #1197

Merged
Fmarzochi merged 8 commits into
mainfrom
fix/mcp-registration-parity
Aug 5, 2026
Merged

fix(install): one MCP registration list for all three entry points#1197
Fmarzochi merged 8 commits into
mainfrom
fix/mcp-registration-parity

Conversation

@Fmarzochi

@Fmarzochi Fmarzochi commented Aug 5, 2026

Copy link
Copy Markdown
Owner

Summary

Three entry points install EGC (egc init, install.sh, install.ps1) and each kept its own hand-written copy of which tools get the MCP servers registered. The copies had drifted, and the drift was invisible because every path prints success either way.

What was actually broken

  • Continue.dev and Zed were never registered by either shell installer. Someone following the documented shell command got fewer tools wired up than someone running egc init on the same machine.
  • install.ps1 pointed OpenCode at %APPDATA%\opencode while mcp-register.js used the XDG-style path.
  • Only the shells gated Gemini CLI on Antigravity being absent, so the two paths disagreed about that too.

Fix

Both shells now call a thin CLI over the existing registry (scripts/lib/mcp-register-cli.js), so there is one list and one set of format handlers (JSON, TOML, Continue YAML, Zed context servers, Claude CLI). Their hand-rolled JSON and TOML writers are deleted, which also removes the duplicated TOML escaping. The Windows AppData location for OpenCode survives as its own existence-gated target so no Windows user loses a registration that used to work.

Verification

Clean machine profile with Continue.dev and Zed present: the shell installer registered both, which it never did before this change. Suites: mcp-register 34/34, install-sh 6/6, install-ps1 7/7, install-onboarding 11/11.

Note for a follow-up, found while mapping this: egc install --target <tool> never registers MCP servers at all (only egc init and the shells do), yet docs/installation.md tells the reader that egc install --target zed writes Zed's context servers.


Summary by cubic

Unifies MCP registration across egc init, install.sh, and install.ps1 via a shared CLI. Tightens PATH detection and Windows handling (correct OpenCode AppData routing) and only reads a project .mcp.json from the working directory.

  • Bug Fixes

    • Shell installers now register Continue.dev and Zed; consistent Gemini-vs-Antigravity gating.
    • Detect tools by PATH as well as config dirs using commandExists with a spawn-free PATH scan fallback; accepts only real files, honors empty PATH entries, and handles explicit extensions and quoted Windows PATH entries.
    • Correct Windows behavior: prefer USERPROFILE; support OpenCode at %APPDATA%\opencode and route PATH-only installs there on Windows.
    • Project config: only merge an existing .mcp.json from the invoking CWD; exclude the package root via canonical physical path (case-insensitive on Windows); removed duplicate project merge and Claude registration in installers.
    • Added tests to pin the Windows OpenCode routing when only on PATH.
  • Refactors

    • Added scripts/lib/mcp-register-cli.js; all entry points share one registration list and format writers; removed shell JSON/TOML writers. Installers run the CLI from the invoking directory.

Written for commit 3e61f62. Summary will update on new commits.

Review in cubic

egc init, install.sh and install.ps1 each carried a hand-written copy of the registration list, and the copies had drifted apart:

- Neither shell installer ever registered Continue.dev or Zed. Installing through the documented shell command wired up fewer tools than running egc init on the same machine, and nobody would notice because both paths print success.
- install.ps1 pointed OpenCode at %APPDATA%\opencode while everything else used the XDG-style path.
- Only the shells gated Gemini CLI on Antigravity being absent.

The shells now call scripts/lib/mcp-register-cli.js, so there is exactly one list and one set of format handlers (JSON, TOML, Continue YAML, Zed context servers, Claude CLI). Their hand-rolled JSON and TOML writers are gone. The Windows AppData location for OpenCode survives as its own existence-gated target, so no Windows user loses a registration that used to work.

Proven in a clean profile with Continue.dev and Zed present: the shell installer now registers both, which it never did before. Suites: mcp-register 34/34, install-sh 6/6, install-ps1 7/7, onboarding 11/11.

Signed-off-by: Felipe Marzochi <fmarzochi@gmail.com>
@codecov

codecov Bot commented Aug 5, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 93.33333% with 6 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
scripts/lib/utils.js 88.67% 6 Missing ⚠️

📢 Thoughts on this report? Let us know!

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 6 files

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread scripts/install.sh Outdated
Comment thread scripts/install.ps1 Outdated
Comment thread scripts/install.sh Outdated
Comment thread scripts/lib/mcp-register.js
Comment thread scripts/lib/mcp-register.js
Review caught a real regression I introduced by delegating to the shared registry: the shells detected tools with 'command -v', the registry only checked for a config directory, so anyone who had installed Cursor, Kiro, OpenCode or Codex without launching it yet silently stopped getting registered. The registry now accepts either signal.

Also: Claude Code was being registered twice on the install.sh path, since the shared list already covers it through the CLI; both installers' leftover Claude blocks are gone. The AppData fallback is computed once instead of four times, so the path a target advertises and the path its gate checks cannot drift. New tests stub platform and APPDATA to exercise the Windows-only target on any CI runner, and cover the on-PATH-but-unconfigured case. The macOS failure was the onboarding assertion comparing a logical temp path against the installer's physical one (/var vs /private/var); it compares realpaths now.

Signed-off-by: Felipe Marzochi <fmarzochi@gmail.com>
…lesystem

The project path reaches this CLI as a command-line argument and went straight into a file read and write. It is now resolved and checked first: only an existing file literally named .mcp.json is ever opened, so a mistyped or hostile argument cannot make the installer write somewhere else. Security rating on new code was the failing quality gate condition.

Signed-off-by: Felipe Marzochi <fmarzochi@gmail.com>
… an argument

Passing the path in kept the security gate red: a filesystem path reaching a read and a write from the command line is exactly the pattern the analyzer flags, and validating it after the fact does not remove the source. The filename is now fixed in code and the directory is the process's own working directory, which the installers set to wherever the person invoked them. Nothing about the behavior changes and there is no external path left to validate. Proven in a clean profile: a project .mcp.json in the invoking directory is still picked up and merged.

Signed-off-by: Felipe Marzochi <fmarzochi@gmail.com>

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 6 files (changes from recent commits).

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

Comment thread scripts/install.ps1
Comment thread scripts/lib/mcp-register-cli.js Outdated
Comment thread scripts/lib/mcp-register.js Outdated
Comment thread scripts/lib/mcp-register.js Outdated
Comment thread scripts/install.ps1
…ATH probing

Four review findings, all real:

- On Windows, Git sets HOME to the MSYS home while the installer works out of USERPROFILE, so delegating with HOME first would have registered every tool into the wrong profile. USERPROFILE wins on Windows now.
- The package-root exclusion compared raw strings, so reaching the package through a junction or a differently-cased path read as somebody's project and would rewrite the bundled config. It compares canonical physical paths, case-insensitively on Windows.
- PATH detection was a second implementation living next to the repo's own. It reuses commandExists from scripts/lib/utils.js, which additionally gained a spawn-free PATH scan fallback: on an image with no 'which' at all, a probe that cannot run looked exactly like 'not installed' and silently skipped a tool the person really had.
- install.ps1 merged an existing project .mcp.json twice, once in its own block and once through the shared CLI. The duplicate block is gone.

Suites: utils 185/185, mcp-register 36/36, install-ps1 7/7, onboarding 11/11.

Signed-off-by: Felipe Marzochi <fmarzochi@gmail.com>

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 4 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="scripts/lib/utils.js">

<violation number="1" location="scripts/lib/utils.js:511">
P2: PATH-based MCP detection skips a tool in the current directory when PATH contains a valid empty component. POSIX treats leading, trailing, and doubled separators as the current directory, so the fallback should preserve those entries while still distinguishing an unset PATH.</violation>
</file>

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

Comment thread scripts/lib/utils.js Outdated
Comment thread scripts/lib/utils.js Outdated
Two holes in the spawn-free fallback: a directory named like the command passed both checks, since searchable directories carry the execute bit on POSIX and simply exist on Windows, so the type is settled with statSync first. And POSIX shells read a leading, trailing or doubled separator as the current directory, which the previous filter silently dropped; those entries are honored now, while an unset or empty PATH still means there is nowhere to look.

Signed-off-by: Felipe Marzochi <fmarzochi@gmail.com>
…path

Second-opinion audit found a real Windows defect in the new PATH detection: with OpenCode installed but never launched, the XDG target opened on the PATH signal and wrote a config the Windows editor never reads, while the AppData target stayed shut because its file did not exist yet. The PATH signal now opens the AppData target on Windows and the XDG one everywhere else.

Two smaller fixes in the PATH scan it also caught: a command passed with an explicit extension was being suffixed with PATHEXT (node.exe.EXE), and quoted Windows PATH entries kept their quotes, which broke every lookup inside them. The unit test's stand-in binary now carries a .cmd extension on Windows, where an extension-less file is not executable and the assertion would have been vacuous.

Signed-off-by: Felipe Marzochi <fmarzochi@gmail.com>

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 3 files (changes from recent commits).

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

Comment thread scripts/lib/mcp-register.js
The PATH-only branch for a never-launched OpenCode on Windows had no coverage, so it could silently regress back to writing the config the editor does not read. The case asserts the AppData gate opens and the XDG one stays shut on Windows, and the reverse everywhere else.

Signed-off-by: Felipe Marzochi <fmarzochi@gmail.com>
@sonarqubecloud

sonarqubecloud Bot commented Aug 5, 2026

Copy link
Copy Markdown

@Fmarzochi
Fmarzochi merged commit abec57c into main Aug 5, 2026
40 checks passed
@Fmarzochi
Fmarzochi deleted the fix/mcp-registration-parity branch August 5, 2026 18:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

1 participant