Skip to content

docs(mcp): expand quick-connect matrix to 19 agent ecosystem clients - #57

Open
KevinLi0w0 wants to merge 11 commits into
afx-team:mainfrom
KevinLi0w0:main
Open

docs(mcp): expand quick-connect matrix to 19 agent ecosystem clients#57
KevinLi0w0 wants to merge 11 commits into
afx-team:mainfrom
KevinLi0w0:main

Conversation

@KevinLi0w0

@KevinLi0w0 KevinLi0w0 commented Jul 30, 2026

Copy link
Copy Markdown

Add per-client MCP configuration snippets for the full agent ecosystem tracked in issue #32: Amp, Cline, Copilot, Gemini CLI, Goose, Kiro, LM Studio, opencode, VS Code, Warp, Windsurf, plus the existing Claude Code, Codex, Claude Desktop, and Cursor entries.

Both EN (repo_pages/guide/mcp-integration.md) and zh (repo_pages/zh/guide/mcp-integration.md) are updated together with:

  • A unified 'Quick-Connect Matrix' section organized by delivery type (first-class installer vs config snippet)
  • Exact config file paths and formats verified against each client's official docs
  • Absolute-path guidance per the user-path-ownership constraint (hebb.utils.cli_paths.hebb_mcp_command pattern)
  • An 'Other clients' table for UI-only / evolving-config clients (Antigravity, Factory, Junie, Qodo Gen)
  • Updated architecture diagram to reflect the broader client ecosystem

This addresses the acceptance criterion: 'every client has either a one-command installer or a verified absolute-path config snippet, and the matrix renders in mcp-integration.md with EN + zh updated together.'

Summary

Motivation

Checklist

  • Tests added or updated (pytest tests/ -v) — 25 new tests (14 installer + 11 command-drift CI guard)
  • Documentation updated (repo_pages/, docstrings, or README) if user-facing
  • CHANGELOG.md updated under ## [Unreleased]
  • ruff check src/ passes
  • mypy src/hebb/ passes (project uses strict = true)
  • No secrets, credentials, or local config files committed

Notes for reviewers

Summary by CodeRabbit

  • Documentation
    • Expanded the MCP integration guide with setup instructions for more clients, absolute command-path guidance, remote configuration, and updated English and Chinese content.
  • New Features
    • Added install and uninstall commands for additional MCP clients, with project- and user-level setup where supported.
  • Improvements
    • Configuration updates are repeatable, preserve existing settings, and safely remove only the Hebb integration.
  • Tests
    • Added coverage to verify client setup and prevent documentation or configuration command drift.

Add per-client MCP configuration snippets for the full agent ecosystem
tracked in issue afx-team#32: Amp, Cline, Copilot, Gemini CLI, Goose, Kiro,
LM Studio, opencode, VS Code, Warp, Windsurf, plus the existing
Claude Code, Codex, Claude Desktop, and Cursor entries.

Both EN (repo_pages/guide/mcp-integration.md) and zh
(repo_pages/zh/guide/mcp-integration.md) are updated together with:

- A unified 'Quick-Connect Matrix' section organized by delivery type
  (first-class installer vs config snippet)
- Exact config file paths and formats verified against each client's
  official docs
- Absolute-path guidance per the user-path-ownership constraint
  (hebb.utils.cli_paths.hebb_mcp_command pattern)
- An 'Other clients' table for UI-only / evolving-config clients
  (Antigravity, Factory, Junie, Qodo Gen)
- Updated architecture diagram to reflect the broader client ecosystem

This addresses the acceptance criterion: 'every client has either a
one-command installer or a verified absolute-path config snippet, and
the matrix renders in mcp-integration.md with EN + zh updated together.'
@gemini-code-assist

Copy link
Copy Markdown

Caution

The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased.

@coderabbitai

coderabbitai Bot commented Jul 30, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@KevinLi0w0, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 51 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 2633aaf0-3b9f-4a5c-b9e7-4a40495d09e6

📥 Commits

Reviewing files that changed from the base of the PR and between 66ea3b7 and 514d54d.

📒 Files selected for processing (1)
  • src/hebb/integrations/goose/install.py
📝 Walkthrough

Walkthrough

The PR adds install and uninstall commands for Amp, Gemini CLI, Goose, and opencode. It adds shared configuration helpers, command-drift validation, dependency constraints, and expanded English and Chinese MCP integration guides.

Changes

MCP client integrations

Layer / File(s) Summary
Shared configuration and CLI wiring
src/hebb/integrations/_json_config.py, src/hebb/cli/main.py, pyproject.toml
Adds reusable JSON configuration operations, registers new integration command groups, and constrains the mcp dependency to version 1.x.
Client installers
src/hebb/integrations/amp/*, src/hebb/integrations/gemini_cli/*, src/hebb/integrations/opencode/*
Adds client-specific install and uninstall flows for JSON MCP configurations, including scope handling where supported.
Goose YAML installer
src/hebb/integrations/goose/*
Adds install and uninstall flows that update Goose YAML extensions with atomic writes.
Installer validation and command-drift checks
tests/unit/integrations/test_mcp_client_installers.py, tests/unit/test_command_drift.py
Tests installation, removal, idempotence, preservation, scope handling, CLI registration, documentation references, generated hooks, and the hebb-mcp entrypoint.
Connection guidance and onboarding
repo_pages/guide/mcp-integration.md, repo_pages/zh/guide/mcp-integration.md, CHANGELOG.md
Expands client setup instructions, absolute-path and remote-service guidance, supported-client listings, flow descriptions, usage notes, and unreleased changelog entries.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Possibly related issues

Possibly related PRs

Suggested reviewers: afx-team

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 65.38% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the primary change: expanding the MCP quick-connect documentation for the agent ecosystem.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@repo_pages/guide/mcp-integration.md`:
- Around line 128-130: Specify the text language on both command-palette code
fences: update the fence around the MCP configuration in
repo_pages/guide/mcp-integration.md lines 128-130 and apply the same change in
repo_pages/zh/guide/mcp-integration.md lines 128-130 by using text after each
opening fence.
- Around line 110-122: The MCP configuration instructions incorrectly reference
the CLI settings path and scope. Update the Cline configuration guidance in
repo_pages/guide/mcp-integration.md lines 110-122 to use
~/.cline/data/settings/cline_mcp_settings.json and describe the supported CLI
scope; apply the same correction in repo_pages/zh/guide/mcp-integration.md lines
110-122 while preserving the existing MCP example.

In `@repo_pages/zh/guide/mcp-integration.md`:
- Line 110: 更新中文 MCP 集成指南,统一正文中的语言:将可翻译的说明和界面术语本地化,并将不可避免的产品名、命令及精确 UI
标签统一用代码格式隔离。检查该页面全文,避免中文正文中混入未标记的英文,同时保留必要的配置文件名和实际界面标签。
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 7ed2b180-7eff-49a7-81e1-649b43def3a3

📥 Commits

Reviewing files that changed from the base of the PR and between 36ce983 and b5221c9.

📒 Files selected for processing (2)
  • repo_pages/guide/mcp-integration.md
  • repo_pages/zh/guide/mcp-integration.md

Comment thread repo_pages/guide/mcp-integration.md Outdated
Comment thread repo_pages/guide/mcp-integration.md Outdated
Comment thread repo_pages/zh/guide/mcp-integration.md Outdated
康惟 added 6 commits July 30, 2026 12:00
…se, opencode, and Amp

Add hebb <client> install/uninstall commands for four MCP clients that
have on-disk config files, following the pattern established by
hebb codex install.

New commands:
- hebb gemini install / hebb gemini uninstall — writes ~/.gemini/settings.json
  with a mcpServers.hebb entry (command + args)
- hebb goose install / hebb goose uninstall — writes ~/.config/goose/config.yaml
  with an extensions.hebb block (type: stdio, cmd, args)
- hebb opencode install --scope project|user / hebb opencode uninstall — writes
  opencode.json with a mcp.hebb entry (type: local, command as flat array)
- hebb amp install --scope project|user / hebb amp uninstall — writes
  .amp/settings.json with an amp.mcpServers.hebb entry

All installers:
- Resolve the absolute hebb-mcp path via hebb_mcp_command() (user-path-ownership)
- Are idempotent (re-running replaces the prior hebb entry)
- Preserve unrelated config entries in the target file
- Use atomic writes (tempfile + os.replace)

Shared JSON config helpers extracted into integrations/_json_config.py to
avoid duplication across the four installers.

Tests: 14 unit tests covering install, idempotency, config preservation, and
uninstall for all four clients. Ruff clean.

Addresses: afx-team#32 (type (a) one-command installers for clients with CLI/config files)
…bit review

Address 3 review comments from CodeRabbit on PR afx-team#57:

1. (Major) Fix Cline MCP config file path: the authoritative location is
   ~/.cline/data/settings/cline_mcp_settings.json, not ~/.cline/mcp.json.
   Updated in both EN and zh docs.

2. (Minor) Add `text` language to command-palette code fences (markdownlint
   MD040). Fixed in both EN and zh docs.

3. (Minor) Isolate English UI labels (Settings, Program, etc.) with code
   formatting in the zh doc to avoid raw English in Chinese prose.
CodeRabbit suggested ~/.cline/data/settings/cline_mcp_settings.json, but
Cline's official docs (docs.cline.bot/mcp/mcp-overview) state:
- CLI: ~/.cline/mcp.json
- IDE extension: opened via UI button, file in VS Code global storage

Updated both EN and zh to describe both paths accurately rather than
using the unverified path from the bot review.
…config

Implements the S1 command-drift CI guard proposed in issue afx-team#32. The test
suite (tests/unit/test_command_drift.py) asserts that every hebb command
reference resolves to a real Click command or entrypoint:

1. TestCLIRegistration — verifies expected top-level commands (amp,
   claude-code, codex, gemini, goose, opencode, mcp, setup, service) and
   their subcommands are registered on the root CLI.

2. TestDocCommandDrift — scans mcp-integration.md (EN + zh) for hebb
   command references inside code blocks and inline code, asserts each
   resolves to a registered command.

3. TestGeneratedConfigDrift — builds Codex hook config in-process and
   verifies every hebb subcommand referenced in hook commands exists.

4. TestEntrypoint — verifies the hebb-mcp console script module
   (hebb.mcp.server) is importable and exposes main().

11 tests, all passing. Ruff clean.

Addresses: afx-team#32 (acceptance criterion: S1 command-drift CI guard)

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🧹 Nitpick comments (9)
src/hebb/integrations/_json_config.py (2)

44-115: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Missing Raises docstring sections.

atomic_write, upsert_server, and remove_server all call load_json (documented to raise click.ClickException) but none document this in a Raises section, unlike load_json itself.

As per path instructions, "All public APIs in Python MUST have docstrings with Args, Returns, and Raises sections" (src/**/*.py).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/hebb/integrations/_json_config.py` around lines 44 - 115, Add a Raises
section to the docstrings of atomic_write, upsert_server, and remove_server
documenting that load_json failures raise click.ClickException. Preserve their
existing Args and Returns documentation and do not alter implementation
behavior.

Source: Path instructions


44-62: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

atomic_write silently drops the original file's permissions.

tempfile.mkstemp always creates the temp file at mode 0600 regardless of umask, and os.replace carries that mode onto the destination. So every call to atomic_write on an existing config file (e.g. one previously created at 0644 by the client itself) silently tightens it to 0600 — every install/uninstall invocation quietly re-narrows permissions. This is a well-documented gotcha (Click's own atomic file writer had the same bug and was patched to preserve/derive permissions).

🔧 Proposed fix to preserve existing permissions (or respect umask for new files)
+import stat
+
 def atomic_write(path: Path, content: str) -> None:
     """Atomically replace a UTF-8 text file, creating its parent dir.
 
     Args:
         path: Destination file.
         content: Complete replacement content.
     """
     path.parent.mkdir(parents=True, exist_ok=True)
+    try:
+        mode = stat.S_IMODE(path.stat().st_mode)
+    except OSError:
+        mode = None
     fd, temp_name = tempfile.mkstemp(prefix=f".{path.name}.", dir=path.parent)
     try:
         with os.fdopen(fd, "w", encoding="utf-8") as stream:
             stream.write(content)
+        if mode is not None:
+            os.chmod(temp_name, mode)
         os.replace(temp_name, path)
     except Exception:
         try:
             os.unlink(temp_name)
         except OSError:
             pass
         raise
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/hebb/integrations/_json_config.py` around lines 44 - 62, Update
atomic_write to preserve the existing destination file’s permission mode before
replacing it, applying that mode to the temporary file; when the destination
does not exist, retain mkstemp’s umask-respecting default. Keep the current
atomic replacement and cleanup behavior unchanged.
tests/unit/integrations/test_mcp_client_installers.py (1)

212-229: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Missing "uninstall when absent" test coverage for Amp/opencode.

amp/uninstall.py's "not configured" branch (lines 20-22) and the analogous opencode path aren't exercised here, unlike Gemini's test_gemini_uninstall_when_absent.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/unit/integrations/test_mcp_client_installers.py` around lines 212 -
229, Add coverage for uninstalling when no MCP server is configured in the Amp
and analogous opencode uninstall tests. Extend the relevant test modules near
test_amp_uninstall and the corresponding opencode test to invoke the CLI with an
empty or missing configuration, then assert the command succeeds and preserves
the expected “not configured” behavior, matching Gemini’s
test_gemini_uninstall_when_absent pattern.
src/hebb/integrations/amp/install.py (1)

35-40: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Several public functions lack Args/Returns docstring sections. Per path instructions, src/**/*.py requires "All public APIs in Python MUST have docstrings with Args, Returns, and Raises sections"; the build_entry helpers and Amp's parameterized CLI commands only have one-line summaries.

  • src/hebb/integrations/amp/install.py#L35-L40: add Args/Returns sections to build_entry.
  • src/hebb/integrations/amp/cli.py#L13-L40: document scope in an Args section for install/uninstall.
  • src/hebb/integrations/gemini_cli/install.py#L22-L27: add Args/Returns sections to build_entry.
  • src/hebb/integrations/opencode/install.py#L34-L44: add formal Args/Returns headers to build_entry's existing docstring.

As per path instructions, "All public APIs in Python MUST have docstrings with Args, Returns, and Raises sections."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/hebb/integrations/amp/install.py` around lines 35 - 40, Complete the
public API docstrings with the required sections: in
src/hebb/integrations/amp/install.py:35-40, document mcp_argv under Args and the
returned entry under Returns for build_entry; in
src/hebb/integrations/amp/cli.py:13-40, document scope under Args for install
and uninstall; in src/hebb/integrations/gemini_cli/install.py:22-27, add Args
and Returns to build_entry; and in
src/hebb/integrations/opencode/install.py:34-44, convert build_entry’s existing
documentation to formal Args and Returns sections. No direct Raises
documentation is needed unless those APIs declare or propagate specific
exceptions.

Source: Path instructions

tests/unit/test_command_drift.py (1)

166-193: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Claude Code hooks aren't covered by the generated-config drift check.

The module docstring says both Codex and Claude Code installers are checked for command drift, but TestGeneratedConfigDrift only tests hebb.integrations.codex.install.hooks_config(). A stale/renamed hebb claude-code ... hook command wouldn't be caught.

✅ Proposed addition
     def test_codex_hooks_reference_real_commands(self) -> None:
         from hebb.integrations.codex.install import hooks_config
         ...
         assert not failures, "Codex hooks reference unregistered commands:\n" + "\n".join(failures)
+
+    def test_claude_code_hooks_reference_real_commands(self) -> None:
+        from hebb.integrations.claude_code.install import hooks_config
+
+        top_level = _registered_commands()
+        failures: list[str] = []
+        for event, handlers in hooks_config().items():
+            for handler in handlers:
+                for h in handler.get("hooks", []):
+                    cmd_str = str(h.get("command", ""))
+                    for m in re.finditer(r"hebb\s+([a-z][-a-z]*(?:\s+[a-z][-a-z]*)?)", cmd_str):
+                        parts = m.group(1).strip().split()
+                        cmd = parts[0]
+                        if cmd not in top_level:
+                            failures.append(f"  hooks_config '{cmd_str}' — '{cmd}' not registered")
+                        elif len(parts) > 1 and parts[1] not in _registered_subcommands(cmd):
+                            failures.append(
+                                f"  hooks_config '{cmd_str}' — '{parts[1]}' not a subcommand of `hebb {cmd}`"
+                            )
+        assert not failures, "Claude Code hooks reference unregistered commands:\n" + "\n".join(failures)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/unit/test_command_drift.py` around lines 166 - 193, Extend
TestGeneratedConfigDrift.test_codex_hooks_reference_real_commands to validate
Claude Code installer hooks as well as Codex hooks. Import and invoke the Claude
Code hooks_config alongside the existing Codex configuration, run both through
the same registered-command and subcommand validation, and preserve the existing
aggregated failure assertion.
src/hebb/integrations/opencode/cli.py (1)

13-25: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Document the scope parameter in docstrings.

Both install and uninstall accept scope but their docstrings don't include an Args section describing it (valid values, default).

📝 Proposed docstring fix
 def install(scope: str) -> None:
-    """Install Hebb Mind MCP into opencode."""
+    """Install Hebb Mind MCP into opencode.
+
+    Args:
+        scope: ``"project"`` writes ``opencode.json`` in cwd; ``"user"``
+            writes the global config. Defaults to ``"user"``.
+    """
     from hebb.integrations.opencode.install import handle

     handle(scope)
 def uninstall(scope: str) -> None:
-    """Remove Hebb Mind MCP from opencode."""
+    """Remove Hebb Mind MCP from opencode.
+
+    Args:
+        scope: ``"project"`` or ``"user"``. Defaults to ``"user"``.
+    """
     from hebb.integrations.opencode.uninstall import handle

     handle(scope)
As per coding guidelines, "All public APIs in Python MUST have docstrings with Args, Returns, and Raises sections."

Also applies to: 28-40

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/hebb/integrations/opencode/cli.py` around lines 13 - 25, Update the
public install and uninstall command docstrings to include an Args section for
scope, describing the valid project/user values and the user default. Preserve
their existing behavior and add Returns and Raises sections as required by the
project’s public API docstring convention, documenting the actual behavior
without inventing exceptions.

Source: Coding guidelines

src/hebb/integrations/goose/install.py (2)

90-123: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Wrap filesystem I/O with click.ClickException instead of letting OSError propagate raw. All three handle() functions read/write config files without catching failures (permission denied, disk full, etc.), producing a Python traceback instead of a clean CLI error.

  • src/hebb/integrations/goose/install.py#L90-L123: wrap path.read_text() / atomic_write() in handle() with try/except raising click.ClickException(str(e)).
  • src/hebb/integrations/gemini_cli/uninstall.py#L11-L21: wrap config_path() / remove_server() in handle() similarly.
  • src/hebb/integrations/goose/uninstall.py#L10-L27: wrap path.read_text() / atomic_write() in handle() similarly.

As per coding guidelines, "Keep CLI exits via click.ClickException; reserve SystemExit(1) for unrecoverable failures."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/hebb/integrations/goose/install.py` around lines 90 - 123, Wrap
filesystem operations in each affected handle() with OSError handling that
raises click.ClickException(str(e)): in src/hebb/integrations/goose/install.py
lines 90-123, cover path.read_text() and atomic_write(); in
src/hebb/integrations/gemini_cli/uninstall.py lines 11-21, cover config_path()
and remove_server(); and in src/hebb/integrations/goose/uninstall.py lines
10-27, cover path.read_text() and atomic_write(). Preserve normal success
behavior and avoid raw OSError propagation or SystemExit for these CLI failures.

Source: Coding guidelines


74-87: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Reuse the shared atomic-write helper for Goose.

src/hebb/integrations/goose/install.py has a local atomic_write, and src/hebb/integrations/goose/uninstall.py imports it from that module. Move to hebb.integrations._json_config.atomic_write, then re-export atomic_write and config_path from this module so the installer/import contract stays stable.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/hebb/integrations/goose/install.py` around lines 74 - 87, Replace the
local atomic_write implementation in install.py with imports from
hebb.integrations._json_config, while preserving the module’s public contract by
re-exporting both atomic_write and config_path. Update dependent imports as
needed so uninstall.py continues using the stable install-module symbols.
src/hebb/integrations/opencode/uninstall.py (1)

11-35: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Reuse remove_server for opencode uninstall.

handle() reimplements the load/delete/write flow and _dump_json, while _json_config.remove_server() already handles this for any key/server_name pair and returns whether something was changed. Delegate to that helper so opencode uninstall matches the shared removal path.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/hebb/integrations/opencode/uninstall.py` around lines 11 - 35, Update
handle() to delegate server removal to _json_config.remove_server() using the
opencode config path, SERVER_KEY, and SERVER_NAME instead of manually loading,
deleting, and writing JSON. Use its boolean result to preserve the existing
not-configured and successful output behavior, and remove the now-unused
_dump_json helper.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@CHANGELOG.md`:
- Around line 33-38: Update the MCP integration guide changelog entry to
reconcile the stated 19-client count with the entries listed: either add the two
omitted client names and their corresponding documentation details, or change
the count to match the existing 17 clients.

In `@src/hebb/integrations/amp/install.py`:
- Around line 43-69: Use the shared _json_config helpers instead of duplicating
configuration mutation logic: in src/hebb/integrations/amp/install.py lines
43-69, replace the manual load/merge/write flow in handle with upsert_server; in
src/hebb/integrations/amp/uninstall.py lines 11-32, replace manual deletion with
remove_server and use its boolean result for the not-configured message; in
src/hebb/integrations/opencode/install.py lines 47-76, replace the merge and
_dump_json flow with upsert_server and remove the redundant _dump_json helper.

In `@src/hebb/integrations/goose/install.py`:
- Around line 90-117: Update handle’s extensions-key detection and insertion
flow to ensure the Hebb block is always inserted when installation reports
success. Only treat a standalone YAML `extensions:` line as an existing key; if
no such line is found, append the key and block using the existing fallback
path, then write the resulting configuration.
- Around line 21-40: Fix _build_yaml_block so the no-extra-arguments case emits
[] indented beneath args: rather than at column zero, while preserving correctly
indented list entries for additional arguments. Update the installer test to
parse the generated content with yaml.safe_load and assert it succeeds, in
addition to the existing checks.

---

Nitpick comments:
In `@src/hebb/integrations/_json_config.py`:
- Around line 44-115: Add a Raises section to the docstrings of atomic_write,
upsert_server, and remove_server documenting that load_json failures raise
click.ClickException. Preserve their existing Args and Returns documentation and
do not alter implementation behavior.
- Around line 44-62: Update atomic_write to preserve the existing destination
file’s permission mode before replacing it, applying that mode to the temporary
file; when the destination does not exist, retain mkstemp’s umask-respecting
default. Keep the current atomic replacement and cleanup behavior unchanged.

In `@src/hebb/integrations/amp/install.py`:
- Around line 35-40: Complete the public API docstrings with the required
sections: in src/hebb/integrations/amp/install.py:35-40, document mcp_argv under
Args and the returned entry under Returns for build_entry; in
src/hebb/integrations/amp/cli.py:13-40, document scope under Args for install
and uninstall; in src/hebb/integrations/gemini_cli/install.py:22-27, add Args
and Returns to build_entry; and in
src/hebb/integrations/opencode/install.py:34-44, convert build_entry’s existing
documentation to formal Args and Returns sections. No direct Raises
documentation is needed unless those APIs declare or propagate specific
exceptions.

In `@src/hebb/integrations/goose/install.py`:
- Around line 90-123: Wrap filesystem operations in each affected handle() with
OSError handling that raises click.ClickException(str(e)): in
src/hebb/integrations/goose/install.py lines 90-123, cover path.read_text() and
atomic_write(); in src/hebb/integrations/gemini_cli/uninstall.py lines 11-21,
cover config_path() and remove_server(); and in
src/hebb/integrations/goose/uninstall.py lines 10-27, cover path.read_text() and
atomic_write(). Preserve normal success behavior and avoid raw OSError
propagation or SystemExit for these CLI failures.
- Around line 74-87: Replace the local atomic_write implementation in install.py
with imports from hebb.integrations._json_config, while preserving the module’s
public contract by re-exporting both atomic_write and config_path. Update
dependent imports as needed so uninstall.py continues using the stable
install-module symbols.

In `@src/hebb/integrations/opencode/cli.py`:
- Around line 13-25: Update the public install and uninstall command docstrings
to include an Args section for scope, describing the valid project/user values
and the user default. Preserve their existing behavior and add Returns and
Raises sections as required by the project’s public API docstring convention,
documenting the actual behavior without inventing exceptions.

In `@src/hebb/integrations/opencode/uninstall.py`:
- Around line 11-35: Update handle() to delegate server removal to
_json_config.remove_server() using the opencode config path, SERVER_KEY, and
SERVER_NAME instead of manually loading, deleting, and writing JSON. Use its
boolean result to preserve the existing not-configured and successful output
behavior, and remove the now-unused _dump_json helper.

In `@tests/unit/integrations/test_mcp_client_installers.py`:
- Around line 212-229: Add coverage for uninstalling when no MCP server is
configured in the Amp and analogous opencode uninstall tests. Extend the
relevant test modules near test_amp_uninstall and the corresponding opencode
test to invoke the CLI with an empty or missing configuration, then assert the
command succeeds and preserves the expected “not configured” behavior, matching
Gemini’s test_gemini_uninstall_when_absent pattern.

In `@tests/unit/test_command_drift.py`:
- Around line 166-193: Extend
TestGeneratedConfigDrift.test_codex_hooks_reference_real_commands to validate
Claude Code installer hooks as well as Codex hooks. Import and invoke the Claude
Code hooks_config alongside the existing Codex configuration, run both through
the same registered-command and subcommand validation, and preserve the existing
aggregated failure assertion.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: b9643315-65c6-47cd-8d61-433ccb44493a

📥 Commits

Reviewing files that changed from the base of the PR and between b5221c9 and eba4302.

📒 Files selected for processing (23)
  • CHANGELOG.md
  • repo_pages/guide/mcp-integration.md
  • repo_pages/zh/guide/mcp-integration.md
  • src/hebb/cli/main.py
  • src/hebb/integrations/_json_config.py
  • src/hebb/integrations/amp/__init__.py
  • src/hebb/integrations/amp/cli.py
  • src/hebb/integrations/amp/install.py
  • src/hebb/integrations/amp/uninstall.py
  • src/hebb/integrations/gemini_cli/__init__.py
  • src/hebb/integrations/gemini_cli/cli.py
  • src/hebb/integrations/gemini_cli/install.py
  • src/hebb/integrations/gemini_cli/uninstall.py
  • src/hebb/integrations/goose/__init__.py
  • src/hebb/integrations/goose/cli.py
  • src/hebb/integrations/goose/install.py
  • src/hebb/integrations/goose/uninstall.py
  • src/hebb/integrations/opencode/__init__.py
  • src/hebb/integrations/opencode/cli.py
  • src/hebb/integrations/opencode/install.py
  • src/hebb/integrations/opencode/uninstall.py
  • tests/unit/integrations/test_mcp_client_installers.py
  • tests/unit/test_command_drift.py
🚧 Files skipped from review as they are similar to previous changes (2)
  • repo_pages/zh/guide/mcp-integration.md
  • repo_pages/guide/mcp-integration.md

Comment thread CHANGELOG.md Outdated
Comment thread src/hebb/integrations/amp/install.py
Comment thread src/hebb/integrations/goose/install.py
Comment thread src/hebb/integrations/goose/install.py
@KevinLi0w0

Copy link
Copy Markdown
Author

#32

…pers, changelog

1. (Critical) Fix Goose YAML args format when hebb-mcp has no extra args:
   `args: []` was emitted at column 0, breaking YAML structure. Now uses
   inline `args: []` on the same indentation level.

2. (Major) Fix Goose insertion fallback: `extensions:` substring check
   could match inside comments without a real `extensions:` line, causing
   the hebb block to silently not be inserted. Now checks for a standalone
   line and adds a fallback if insertion fails.

3. (Major) Refactor Amp and opencode installers to use shared
   _json_config.upsert_server/remove_server instead of hand-rolling the
   same read/merge/write logic. Removes redundant _dump_json helpers.

4. (Minor) Fix CHANGELOG client list to include Claude Code and Codex
   in the 19-client count.

25 tests passing, ruff clean.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/hebb/integrations/amp/install.py (1)

43-60: 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Complete the public API docstrings.

Each public handle function has type hints, but its docstring is missing required sections.

  • src/hebb/integrations/amp/install.py#L43-L60: add Returns and Raises.
  • src/hebb/integrations/amp/uninstall.py#L11-L25: add Returns and Raises.
  • src/hebb/integrations/opencode/install.py#L47-L63: add Returns and Raises.
  • src/hebb/integrations/opencode/uninstall.py#L11-L25: add Returns and Raises.
  • src/hebb/integrations/goose/install.py#L92-L132: add Args, Returns, and Raises.

As per coding guidelines, all public Python APIs must include Args, Returns, and Raises sections.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/hebb/integrations/amp/install.py` around lines 43 - 60, Complete the
public API docstrings for handle in src/hebb/integrations/amp/install.py
(43-60), src/hebb/integrations/amp/uninstall.py (11-25),
src/hebb/integrations/opencode/install.py (47-63), and
src/hebb/integrations/opencode/uninstall.py (11-25) by adding accurate Returns
and Raises sections; update handle in src/hebb/integrations/goose/install.py
(92-132) with accurate Args, Returns, and Raises sections, matching the existing
signatures and behavior.

Source: Coding guidelines

src/hebb/integrations/goose/install.py (1)

102-124: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Only match a root-level block extensions: key.

line.strip() == "extensions:" also matches nested mappings. A config containing profile:\n extensions: enters this branch and inserts hebb as a sibling of that nested key, not as Goose’s top-level extension. Conversely, extensions: {} is treated as absent and a duplicate root key is appended, which can shadow existing extension settings.

Detect only an unindented block-style extensions: header; if a root extensions key uses an unsupported inline form, raise click.ClickException instead of writing ambiguous YAML.

Proposed direction
-    has_extensions_line = any(line.strip() == "extensions:" for line in cleaned.splitlines())
+    # Match only Goose's root-level block mapping header.
+    has_extensions_line = any(
+        line.rstrip("\r\n") == "extensions:" for line in cleaned.splitlines(keepends=True)
+    )
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/hebb/integrations/goose/install.py` around lines 102 - 124, Update the
extensions detection and insertion logic around cleaned.splitlines() so it
recognizes only an unindented root-level block-style “extensions:” header.
Ignore indented nested headers, and treat any root-level extensions key using an
inline form such as “extensions: {}” as unsupported by raising
click.ClickException rather than appending a duplicate key. Preserve insertion
after a valid root block header and creation of a root block when no root key
exists.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@src/hebb/integrations/amp/install.py`:
- Around line 43-60: Complete the public API docstrings for handle in
src/hebb/integrations/amp/install.py (43-60),
src/hebb/integrations/amp/uninstall.py (11-25),
src/hebb/integrations/opencode/install.py (47-63), and
src/hebb/integrations/opencode/uninstall.py (11-25) by adding accurate Returns
and Raises sections; update handle in src/hebb/integrations/goose/install.py
(92-132) with accurate Args, Returns, and Raises sections, matching the existing
signatures and behavior.

In `@src/hebb/integrations/goose/install.py`:
- Around line 102-124: Update the extensions detection and insertion logic
around cleaned.splitlines() so it recognizes only an unindented root-level
block-style “extensions:” header. Ignore indented nested headers, and treat any
root-level extensions key using an inline form such as “extensions: {}” as
unsupported by raising click.ClickException rather than appending a duplicate
key. Preserve insertion after a valid root block header and creation of a root
block when no root key exists.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 50f67b02-6cd0-4feb-8994-791cba12f190

📥 Commits

Reviewing files that changed from the base of the PR and between eba4302 and 54a3ea5.

📒 Files selected for processing (6)
  • CHANGELOG.md
  • src/hebb/integrations/amp/install.py
  • src/hebb/integrations/amp/uninstall.py
  • src/hebb/integrations/goose/install.py
  • src/hebb/integrations/opencode/install.py
  • src/hebb/integrations/opencode/uninstall.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • CHANGELOG.md

康惟 added 2 commits July 30, 2026 16:44
…compliance

1. (Major) Goose installer now matches only root-level (unindented) block-style
   "extensions:" header. Indented nested "extensions:" no longer triggers
   insertion. Inline "extensions: {}" raises click.ClickException instead of
   silently appending a duplicate root key.

2. (Major) Add Raises sections to all handle() docstrings across Gemini CLI,
   Goose, opencode, and Amp install/uninstall functions, matching the project
   convention used by the existing Codex installer.

25 tests passing, ruff clean.
mcp 2.0.0 (released 2026-07-28) removed the mcp.server.fastmcp module
that src/hebb/mcp/server.py imports. The pyproject.toml constraint
"mcp>=1.0.0" allowed pip to install 2.0.0 in CI, breaking mypy,
pytest, and e2e checks across all OS/Python matrix cells.

This is a pre-existing issue — upstream main would also fail CI now.
Pinning to "mcp>=1.0.0,<2.0.0" until the codebase migrates to the
new mcp 2.x API.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/hebb/integrations/gemini_cli/install.py`:
- Around line 31-35: Complete the public handle API docstrings: in
src/hebb/integrations/gemini_cli/install.py lines 31-35 and
src/hebb/integrations/goose/install.py lines 93-99, add accurate Args and
Returns sections; in src/hebb/integrations/opencode/install.py lines 48-55 and
src/hebb/integrations/opencode/uninstall.py lines 12-19, add accurate Returns
sections. Preserve the existing Raises documentation and describe each API’s
actual parameters and return value.

In `@src/hebb/integrations/goose/install.py`:
- Around line 112-121: Update the extensions-header detection in the install
configuration flow to match only root-level keys, preserving indentation rather
than using lstrip(). Treat root-level lines containing only whitespace or a
comment suffix, such as “extensions: # managed config”, as block headers; ignore
nested and commented-out headers. Ensure nested-only keys cause a new root-level
extensions block to be appended instead of raising ClickException.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 925985bc-cedc-441d-a6cf-69976871fd25

📥 Commits

Reviewing files that changed from the base of the PR and between 54a3ea5 and 66ea3b7.

📒 Files selected for processing (9)
  • pyproject.toml
  • src/hebb/integrations/amp/install.py
  • src/hebb/integrations/amp/uninstall.py
  • src/hebb/integrations/gemini_cli/install.py
  • src/hebb/integrations/gemini_cli/uninstall.py
  • src/hebb/integrations/goose/install.py
  • src/hebb/integrations/goose/uninstall.py
  • src/hebb/integrations/opencode/install.py
  • src/hebb/integrations/opencode/uninstall.py
🚧 Files skipped from review as they are similar to previous changes (4)
  • src/hebb/integrations/gemini_cli/uninstall.py
  • src/hebb/integrations/goose/uninstall.py
  • src/hebb/integrations/amp/uninstall.py
  • src/hebb/integrations/amp/install.py

Comment on lines +31 to +35
"""Install Hebb Mind MCP into Gemini CLI.

Raises:
click.ClickException: If the config file exists but cannot be parsed.
"""

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Complete the required public-API docstring sections.

These public handle APIs omit required docstring sections.

  • src/hebb/integrations/gemini_cli/install.py#L31-L35: Add Args and Returns sections.
  • src/hebb/integrations/opencode/install.py#L48-L55: Add a Returns section.
  • src/hebb/integrations/opencode/uninstall.py#L12-L19: Add a Returns section.
  • src/hebb/integrations/goose/install.py#L93-L99: Add Args and Returns sections.

As per coding guidelines, “Include docstring with Args, Returns, and Raises sections for all public APIs.”

📍 Affects 4 files
  • src/hebb/integrations/gemini_cli/install.py#L31-L35 (this comment)
  • src/hebb/integrations/opencode/install.py#L48-L55
  • src/hebb/integrations/opencode/uninstall.py#L12-L19
  • src/hebb/integrations/goose/install.py#L93-L99
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/hebb/integrations/gemini_cli/install.py` around lines 31 - 35, Complete
the public handle API docstrings: in src/hebb/integrations/gemini_cli/install.py
lines 31-35 and src/hebb/integrations/goose/install.py lines 93-99, add accurate
Args and Returns sections; in src/hebb/integrations/opencode/install.py lines
48-55 and src/hebb/integrations/opencode/uninstall.py lines 12-19, add accurate
Returns sections. Preserve the existing Raises documentation and describe each
API’s actual parameters and return value.

Source: Coding guidelines

Comment thread src/hebb/integrations/goose/install.py
…ents

Fix two edge cases in Goose installer's extensions: detection:

1. A nested "  extensions:" (indented under another key) no longer
   triggers ClickException. Only root-level lines are checked for
   inline form.

2. A root-level "extensions: # managed config" (block header with
   trailing comment) is now correctly recognized as a block header,
   not an inline form. Uses regex to distinguish block headers
   (colon followed by only whitespace or comment) from inline forms
   (colon followed by non-comment content like "{}").

The import re is placed inline to match the existing code style.
25 tests passing, ruff clean.
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