Skip to content

Add corgea mcp install for agent MCP configs - #163

Open
Ibrahimrahhal wants to merge 5 commits into
mainfrom
cursor/mcp-install-c919
Open

Add corgea mcp install for agent MCP configs#163
Ibrahimrahhal wants to merge 5 commits into
mainfrom
cursor/mcp-install-c919

Conversation

@Ibrahimrahhal

@Ibrahimrahhal Ibrahimrahhal commented Aug 26, 2026

Copy link
Copy Markdown
Member

Adds corgea mcp install --agent <name> so a logged-in CLI can write the Corgea MCP server into an agent's JSON config using the URL and token already stored by corgea login.

Version bumped 1.11.1 → 1.12.0 (minor: new command). Cargo.toml is the release source of truth.

Behavior

  • Requires login, same as scan / skill / ls. An empty or missing token exits with the existing "No token set" message.
  • Writes the client-specific JSON documented at https://docs.corgea.app/modelcontextprotocol:
    • Cursor / Windsurf: mcp-remote with --transport http-only and the token in the header (Cursor does not interpolate ${env:NAME} from the server env block).
    • Claude Desktop (--agent claude): mcp-remote plus an env block, matching the docs.
    • Claude Code: typed HTTP ("type": "http") with url + CORGEA-TOKEN header.
    • VS Code / Gemini CLI / Continue / OpenCode: their native HTTP / provider shapes.
  • If Corgea is already present (the corgea key, or any server whose URL still points at a *.corgea.*/mcp endpoint), that entry is removed and rewritten so a reinstall refreshes URL and token. Neighboring servers and unrelated keys are left intact.
  • --scope user (default) or project; --dir writes a custom path; --set-default persists the agent like corgea skill install.
  • Project-scope installs warn that the file now contains a token.

Tests

  • Unit tests cover path resolution, JSON merge/replace, malformed files, and each client shape.
  • Integration tests drive the real binary: unauthenticated refusal, unknown agent, Cursor install from CORGEA_URL/CORGEA_TOKEN, reinstall refresh, and --agent claude.

This branch is now rebased/merged with main, including the #164 ETXTBSY image-test fix. No further MCP-branch changes.

Open in Web Open in Cursor 

Install (or reinstall) the Corgea MCP server into an agent's JSON config
using the URL and token already stored by `corgea login`. Re-running
removes any existing Corgea entry first so the endpoint and token stay
current. Unauthenticated runs fail through the same login gate as other
commands.

Co-authored-by: Ibrahim Rahhal <ibrahim.rahhal3636@gmail.com>
@Ibrahimrahhal
Ibrahimrahhal marked this pull request as ready for review August 26, 2026 11:36
cursoragent and others added 3 commits August 26, 2026 11:40
CI under cargo-llvm-cov failed save_images_separates_references_differing_only_in_case
with "Text file busy" when execing a stub script that had just been written
in place. Write the stub via fsync+rename, wait until it is executable, and
give each test a unique temp dir.

Co-authored-by: Ibrahim Rahhal <ibrahim.rahhal3636@gmail.com>
New `corgea mcp install` command is a minor SemVer bump. Cargo.toml is
the release source of truth; keep Cargo.lock in sync.

Co-authored-by: Ibrahim Rahhal <ibrahim.rahhal3636@gmail.com>
Comment thread src/mcp.rs
} else {
// Cursor interpolates ${env:NAME} from its own process environment,
// which a Dock/Start-menu launch usually lacks. Write the token.
args.push(format!("CORGEA-TOKEN:{token}"));

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

high: Project installation writes credentials into repository files

Project scope writes the raw Corgea token into files such as .cursor/mcp.json and .vscode/mcp.json, which are commonly committed. Printing a warning only after writing the secret does not prevent accidental disclosure. Project installs should use supported environment-variable or secret mechanisms, or reject project scope where secure indirection is unavailable.

Proof or reproduction:

corgea mcp install --agent cursor --scope project
git add .cursor/mcp.json
git diff --cached
# The diff contains CORGEA-TOKEN:<raw token> because the entry is built with format!("CORGEA-TOKEN:{token}").

Comment thread src/mcp.rs
}

fn mcp_remote_entry(url: &str, token: &str, http_only: bool, use_env_block: bool) -> Value {
let mut args = vec!["-y".to_string(), "mcp-remote".to_string(), url.to_string()];

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

high: Installer executes an unpinned npm package with credential access

Cursor, Windsurf, and Claude Desktop entries run npx -y mcp-remote without a version. Every launch can therefore download and execute whichever release currently owns the npm tag, while exposing the Corgea token through arguments or environment variables. Pin a reviewed version or ship a controlled transport implementation.

Proof or reproduction:

The generated command is equivalent to:
npx -y mcp-remote <url> --header CORGEA-TOKEN:<token>
There is no `mcp-remote@<version>` constraint.

Comment thread src/mcp.rs

pub fn looks_like_corgea_mcp_url(value: &str) -> bool {
let lower = value.to_ascii_lowercase();
lower.contains("corgea.") && lower.contains("/mcp")

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

high: Loose URL matching deletes unrelated MCP servers

looks_like_corgea_mcp_url uses substring checks instead of parsing and validating the hostname. Consequently, reinstalling Corgea removes unrelated entries whose URLs merely contain corgea. and /mcp. Match an explicit trusted Corgea hostname or another unambiguous identifier.

Proof or reproduction:

let existing = r#"{"mcpServers":{"unrelated":{"url":"https://notcorgea.app/mcp"}}}"#;
let (out, _) = upsert_corgea(Agent::Cursor, existing, "https://www.corgea.app/mcp", "tok").unwrap();
let value: Value = serde_json::from_str(&out).unwrap();
assert!(value["mcpServers"].get("unrelated").is_some()); // fails: entry was deleted

Comment thread src/mcp.rs
"httpUrl": url,
"headers": token_header(token)
}),
Agent::Continue => json!({

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

high: Continue installation creates a context provider instead of an MCP server

The Continue branch inserts an arbitrary provider named corgea under contextProviders. Continue does not interpret that object as an MCP server; MCP configuration belongs in its MCP-server configuration structure. Thus the advertised Continue installation succeeds but does not register a usable server.

Proof or reproduction:

let (out, _) = upsert_corgea(Agent::Continue, "{}", "https://www.corgea.app/mcp", "tok").unwrap();
let value: Value = serde_json::from_str(&out).unwrap();
assert!(value.get("mcpServers").is_some()); // fails
assert!(value["contextProviders"][0]["name"] == "corgea"); // confirms the wrong configuration type

@corgea-security corgea-security 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.

Automated review risk: 4/5.

The installer risks credential disclosure, executes an unpinned package, can delete unrelated MCP entries, and generates an invalid Continue configuration.

Critical or high-priority changes must be addressed.

Automatic approval was not submitted: checks failed: rust-tests.

@corgea-security corgea-security added the dennis-reviewed Dennis completed an automated review label Aug 26, 2026
Bring in the merged ETXTBSY image-test fix (#164) so this PR's CI can
pass without any further MCP-branch changes.

Co-authored-by: Ibrahim Rahhal <ibrahim.rahhal3636@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dennis-reviewed Dennis completed an automated review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants