Skip to content

feat(mcp): wire flare MCP server into codex, cursor, windsurf, vscode-copilot - #171

Merged
getappz merged 1 commit into
masterfrom
feat/mcp-host-wiring
Jul 13, 2026
Merged

feat(mcp): wire flare MCP server into codex, cursor, windsurf, vscode-copilot#171
getappz merged 1 commit into
masterfrom
feat/mcp-host-wiring

Conversation

@getappz

@getappz getappz commented Jul 13, 2026

Copy link
Copy Markdown
Owner

Closes the gap in components.rs's agentflare-mcp component: 4 of 20 registered agents got real flare MCP server registration on 'agentflare init --agent X' (claude-code, cline, continue, opencode); codex/cursor/windsurf/vscode-copilot silently no-op'd.

  • merge_json generalized with a root_key param: mcpServers for cursor/windsurf, servers for vscode-copilot
  • codex: check via substring match on ~/.codex/config.toml, apply via codex mcp add flare -- mcp
  • cursor: ~/.cursor/mcp.json, mcpServers key
  • windsurf: ~/.codeium/windsurf/mcp_config.json, mcpServers key
  • vscode-copilot: /.vscode/mcp.json, servers key + type:stdio field
  • describe() text updated to match

Known limitation (non-blocking): the codex check is a raw substring match on config.toml, not validated against real codex mcp add output — risks a false positive on a commented-out line, or a false negative if the real format differs in spacing/quoting. Same trust level as the existing claude-code/cline paths otherwise.

Scope: these 4 hosts only (highest usage after Claude Code); the remaining 12 registered agents are deferred to a follow-up. Consent model stays opt-in per --agent run.

Rebased onto current master (which now already includes the tool consolidation) from its original stale fork point.

Verification

  • 355/355 tests pass in the main crate (6 new: codex substring check, cursor/windsurf/vscode-copilot check+apply round-trips, cursor no-clobber safety, vscode-copilot servers-key+type:stdio)
  • cargo fmt --check clean
  • cargo clippy --workspace --all-targets -- -D warnings -A unsafe_code -A clippy::pedantic clean

Summary by CodeRabbit

  • New Features

    • Added MCP configuration support for Codex, Cursor, Windsurf, and VS Code Copilot.
    • Registration now applies each host’s required configuration format, including standard server type metadata.
    • Status checks and configuration descriptions now reflect supported host-specific setups.
  • Bug Fixes

    • Corrected MCP entry placement across different configuration file structures.
    • Improved detection of existing Flare MCP configurations.

…-copilot

Closes the gap in components.rs's agentflare-mcp component: 4 of 20
registered agents got real 'flare' MCP server registration on
'agentflare init --agent X' (claude-code, cline, continue, opencode);
codex/cursor/windsurf/vscode-copilot silently no-op'd.

- merge_json generalized with a root_key param: mcpServers for
  cursor/windsurf, servers for vscode-copilot
- codex: check via substring match on ~/.codex/config.toml, apply via
  `codex mcp add flare -- <bin> mcp`
- cursor: ~/.cursor/mcp.json, mcpServers key
- windsurf: ~/.codeium/windsurf/mcp_config.json, mcpServers key
- vscode-copilot: <cwd>/.vscode/mcp.json, servers key + type:stdio field
- describe() text: codex gets its own line; cursor/windsurf/vscode-copilot
  join the manual-MCP-registration group

Known limitation: the codex check is a raw substring match on
config.toml, not validated against real `codex mcp add` output — risks
a false positive on a commented-out line, or a false negative if the
actual format differs in spacing/quoting from the assumed literal
'[mcp_servers.flare]'. Same trust level as the existing claude-code/cline
paths otherwise. Consent model stays opt-in per --agent run.

Scope: these 4 hosts only (highest usage after Claude Code); the
remaining 12 registered agents are deferred to a follow-up.

Rebased onto current master (which now already includes the tool
consolidation) from its original stale fork point.
@coderabbitai

coderabbitai Bot commented Jul 13, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The MCP component now supports host-specific configuration roots, detection logic, descriptions, and registration for codex, cursor, windsurf, vscode-copilot, and cline.

Changes

MCP host support

Layer / File(s) Summary
Host-specific merge contract
src/components.rs
merge_json now accepts a configurable root key, and codex receives dedicated mcp add registration instructions.
Host checks and registration
src/components.rs
Checks and apply operations handle each host’s MCP configuration format, including codex CLI registration and vscode-copilot’s "type": "stdio" entry. Tests cover placement, preservation, and check transitions.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant AgentflareMcp
  participant CodexMcpCli
  participant HostMcpConfig
  AgentflareMcp->>CodexMcpCli: run codex mcp add
  CodexMcpCli->>HostMcpConfig: write flare server
  AgentflareMcp->>HostMcpConfig: merge flare under host root key
  HostMcpConfig-->>AgentflareMcp: check flare configuration
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: wiring Flare MCP into Codex, Cursor, Windsurf, and VS Code Copilot.
Description check ✅ Passed The description covers the change, verification, scope, and reviewer notes, though it doesn't match the template headings exactly.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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 docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/mcp-host-wiring

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: 1

Caution

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

⚠️ Outside diff range comments (1)
src/components.rs (1)

83-104: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

merge_json silently discards the entire existing config on any parse failure.

If fs::read_to_string succeeds but serde_json::from_str fails (malformed JSON, or JSONC comments/trailing commas), existing falls back to json!({}) and the whole file gets overwritten with only the new flare entry — every other configured server is lost. This risk is now exercised more broadly: .vscode/mcp.json sits alongside tasks.json/launch.json in VS Code's own editable-config family, which is documented to support comments, so a hand-annotated file would trigger this silent wipe on the very first agentflare init --agent vscode-copilot.

🛡️ Proposed fix: fail safe instead of silently overwriting
 fn merge_json(path: &PathBuf, root_key: &str, key: &str, value: Value) -> bool {
-    let mut existing: Value = fs::read_to_string(path)
-        .ok()
-        .and_then(|s| serde_json::from_str(&s).ok())
-        .unwrap_or_else(|| serde_json::json!({}));
+    let raw = fs::read_to_string(path).ok();
+    let mut existing: Value = match raw {
+        None => serde_json::json!({}),
+        Some(s) => match serde_json::from_str(&s) {
+            Ok(v) => v,
+            Err(_) => return false, // don't clobber an existing-but-unparseable file
+        },
+    };
🤖 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/components.rs` around lines 83 - 104, Update merge_json so an existing
file that cannot be parsed is treated as an error rather than replaced with an
empty object. Preserve the current file unchanged and return false on read or
JSON/JSONC parse failure; only create a new empty configuration when the file is
absent, while retaining the existing merge and write behavior for valid input.
🧹 Nitpick comments (1)
src/components.rs (1)

383-397: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Codex check uses a raw TOML substring match — known limitation with concrete failure modes.

s.contains("[mcp_servers.flare]") doesn't account for a disabled entry (codex supports enabled = false on a server table to disable it without deleting it), so a disabled flare entry would report "satisfied" when it isn't actually active. More importantly, a false negative here (e.g. non-canonical formatting from a hand-edited file) causes apply to invoke codex mcp add flare again — and duplicate [mcp_servers.*] tables in config.toml are a documented cause of the Codex app hanging silently ("App becomes unresponsive with no error UI when config.toml has duplicate [mcp_servers.*] blocks").

Parsing with the toml crate (already a natural fit alongside serde_json in this file) and checking doc["mcp_servers"]["flare"] would remove both failure modes.

🤖 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/components.rs` around lines 383 - 397, Replace the raw substring check in
the "codex" branch with TOML parsing using the existing TOML dependency, then
inspect the parsed mcp_servers.flare table and require it to be present and
enabled rather than merely matching its header. Preserve the false result for
missing, invalid, or disabled entries so the check reflects whether the server
is active without creating duplicate configuration blocks.
🤖 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/components.rs`:
- Around line 371-372: Update the host description branch around the host
matching expression so cursor, windsurf, and vscode-copilot no longer claim
manual MCP registration; describe them as automatically registered by the
existing apply/merge_json flow. Preserve the current manual-registration wording
for cline, continue, and opencode.

---

Outside diff comments:
In `@src/components.rs`:
- Around line 83-104: Update merge_json so an existing file that cannot be
parsed is treated as an error rather than replaced with an empty object.
Preserve the current file unchanged and return false on read or JSON/JSONC parse
failure; only create a new empty configuration when the file is absent, while
retaining the existing merge and write behavior for valid input.

---

Nitpick comments:
In `@src/components.rs`:
- Around line 383-397: Replace the raw substring check in the "codex" branch
with TOML parsing using the existing TOML dependency, then inspect the parsed
mcp_servers.flare table and require it to be present and enabled rather than
merely matching its header. Preserve the false result for missing, invalid, or
disabled entries so the check reflects whether the server is active without
creating duplicate configuration blocks.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: ba78f105-a773-4ab4-a7d2-a7d95a76f84c

📥 Commits

Reviewing files that changed from the base of the PR and between 133b6dd and 858ca06.

📒 Files selected for processing (1)
  • src/components.rs

Comment thread src/components.rs
Comment on lines +371 to 372
} else if matches!(host_owned.as_str(), "cline" | "continue" | "opencode" | "cursor" | "windsurf" | "vscode-copilot") {
format!("agentflare MCP server (skill_search/skill_load) — manual MCP registration for {host_owned}")

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Description text is now inconsistent with actual behavior for cursor/windsurf/vscode-copilot.

This branch still describes cursor/windsurf/vscode-copilot as needing "manual MCP registration for {host}", but the apply logic added in this same PR (lines 440-467) auto-registers flare via merge_json for all three — no manual steps required. Users running agentflare init --agent cursor will see a misleading message implying they still need to do something by hand.

✏️ Proposed fix
             } else if host_owned == "codex" {
                 "agentflare MCP server (skill_search/skill_load) — codex mcp add flare -- agentflare mcp".to_string()
-            } else if matches!(host_owned.as_str(), "cline" | "continue" | "opencode" | "cursor" | "windsurf" | "vscode-copilot") {
+            } else if matches!(host_owned.as_str(), "cursor" | "windsurf" | "vscode-copilot" | "cline") {
+                "agentflare MCP server (skill_search/skill_load) — registered automatically via mcp.json".to_string()
+            } else if matches!(host_owned.as_str(), "continue" | "opencode") {
                 format!("agentflare MCP server (skill_search/skill_load) — manual MCP registration for {host_owned}")
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
} else if matches!(host_owned.as_str(), "cline" | "continue" | "opencode" | "cursor" | "windsurf" | "vscode-copilot") {
format!("agentflare MCP server (skill_search/skill_load) — manual MCP registration for {host_owned}")
} else if matches!(host_owned.as_str(), "cursor" | "windsurf" | "vscode-copilot" | "cline") {
"agentflare MCP server (skill_search/skill_load) — registered automatically via mcp.json".to_string()
} else if matches!(host_owned.as_str(), "continue" | "opencode") {
format!("agentflare MCP server (skill_search/skill_load) — manual MCP registration for {host_owned}")
🤖 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/components.rs` around lines 371 - 372, Update the host description branch
around the host matching expression so cursor, windsurf, and vscode-copilot no
longer claim manual MCP registration; describe them as automatically registered
by the existing apply/merge_json flow. Preserve the current manual-registration
wording for cline, continue, and opencode.

@getappz
getappz merged commit 61a3c9e into master Jul 13, 2026
14 checks passed
@getappz
getappz deleted the feat/mcp-host-wiring branch July 13, 2026 18:17
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