-
Notifications
You must be signed in to change notification settings - Fork 781
add install command to CLI #565
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
Note Other AI code review bot(s) detectedCodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review. WalkthroughAdds a new top-level Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant CLI
participant MCPClient as MCPAppClient
participant Config
participant FS as FileSystem
User->>CLI: install <server_identifier> --client <target> [--dry-run/--force]
CLI->>CLI: validate args, resolve api_key
CLI->>MCPClient: fetch server info / validate URL
alt server requires auth & client is chatgpt
MCPClient-->>CLI: auth required
CLI-->>User: exit with guidance (unauthenticated required)
else proceed
MCPClient-->>CLI: server metadata
CLI->>Config: _build_server_config(server_url, api_key, client)
Config->>Config: _merge_mcp_json(existing, server_name, server_config)
alt dry-run
CLI-->>User: show redacted merged config and target path
else write
Config->>FS: _write_json(path, data) (atomic + perms)
FS-->>Config: success
CLI-->>User: summary + post-install notes
end
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~50 minutes Possibly related PRs
Suggested reviewers
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 8
🧹 Nitpick comments (8)
src/mcp_agent/cli/commands/install.py (3)
240-245: Don’t require API key for ChatGPT-only flowChatGPT installs don’t need our API. Allow proceeding without a key and skip cloud lookups when absent.
- effective_api_key = api_key or settings.API_KEY or load_api_key_credentials() - if not effective_api_key: + effective_api_key = api_key or settings.API_KEY or load_api_key_credentials() + if not effective_api_key and client_lc != "chatgpt": raise CLIError( "Must be logged in to install. Run 'mcp-agent login', set MCP_API_KEY environment variable, or specify --api-key option." )Optionally instantiate
MCPAppClientonly if an API key is present or when verification is desired.
66-69: Minor: Unused path for Claude Code in CLIENT_CONFIGSFor
claude_codewe never write the file; consider noting that indescriptionor removingpathto avoid confusion.
361-385: VSCode writes project-local secrets; warn about GitStoring API keys in
.vscode/mcp.jsonrisks accidental commits. Consider:
- A warning advising
.vscode/mcp.jsonin.gitignore.- A
--no-embed-secretor--use-envoption to avoid writing the key.tests/cli/commands/test_install.py (5)
445-465: Add dry-run redaction assertionAfter implementing redaction, assert that printed JSON does not contain the API key.
I can add a test capturing stdout and asserting
"Bearer test-key"is absent.
422-443: Add ChatGPT SSE URL testsAdd cases for:
- Input ending with
/sse(no duplicate/sse).- Input ending with
/mcp(display/sse).
Capture output and assert the displayed URL.
253-285: File permission test (POSIX-only)After hardening
_write_json, add a POSIX-only test to assert0o600on created files.
396-420: Optional: ChatGPT flow without API keyIf you relax the API-key requirement for ChatGPT, add a test to ensure it proceeds and shows instructions when no key is available.
287-322: Cursor format expectationYou’re asserting
mcpServersfor Cursor. Once docs are fixed, consider adding a test ensuring merge preserves unrelated keys in existing configs.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
src/mcp_agent/cli/commands/__init__.py(2 hunks)src/mcp_agent/cli/commands/install.py(1 hunks)src/mcp_agent/cli/main.py(2 hunks)tests/cli/commands/test_install.py(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (4)
src/mcp_agent/cli/commands/__init__.py (1)
src/mcp_agent/cli/commands/install.py (1)
install(181-448)
src/mcp_agent/cli/commands/install.py (3)
src/mcp_agent/cli/auth/main.py (1)
load_api_key_credentials(108-115)src/mcp_agent/cli/exceptions.py (1)
CLIError(4-10)src/mcp_agent/cli/utils/ux.py (2)
print_info(32-49)print_success(52-63)
src/mcp_agent/cli/main.py (1)
src/mcp_agent/cli/commands/install.py (1)
install(181-448)
tests/cli/commands/test_install.py (2)
src/mcp_agent/cli/commands/install.py (3)
install(181-448)_build_server_config(132-177)_merge_mcp_json(81-123)src/mcp_agent/cli/exceptions.py (1)
CLIError(4-10)
🔇 Additional comments (3)
src/mcp_agent/cli/commands/__init__.py (1)
25-26: Wiring looks good
installis properly imported and exported for CLI discovery.Also applies to: 45-46
src/mcp_agent/cli/main.py (2)
41-42: Import OK
installgroup is correctly imported asinstall_cmd.
190-192: Top-level command registration is correct
installis mounted at root with clear help.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What does the secrets file setting do?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 7
🧹 Nitpick comments (2)
tests/cli/commands/test_install.py (2)
415-441: Move typer import to module level.The
typerimport on line 417 should be at the module level (top of file) rather than inside the test function for consistency and clarity.Apply this diff:
import json from unittest.mock import AsyncMock, MagicMock, patch import pytest +import typer from mcp_agent.cli.commands.install import (Then remove line 417 from the test function.
1-533: Consider adding tests for additional scenarios.While the current test coverage is good, consider adding tests for:
- Claude Code subprocess installation path (currently untested)
- Claude Desktop installation flow
- Error handling: subprocess failures, JSON decode errors, file permission errors
- Output message verification in dry-run mode
These additions would provide more comprehensive coverage of edge cases and error paths.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
src/mcp_agent/cli/commands/install.py(1 hunks)tests/cli/commands/test_install.py(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- src/mcp_agent/cli/commands/install.py
🧰 Additional context used
🧬 Code graph analysis (1)
tests/cli/commands/test_install.py (1)
src/mcp_agent/cli/commands/install.py (4)
install(255-520)_build_server_config(206-251)_server_hostname(176-203)_merge_mcp_json(86-128)
🔇 Additional comments (4)
tests/cli/commands/test_install.py (4)
1-14: LGTM!Clean import structure with appropriate test dependencies and functions under test.
16-42: LGTM!Well-structured fixtures that appropriately mock authenticated and unauthenticated app scenarios.
45-214: LGTM!Comprehensive test coverage for helper functions including hostname extraction, server config building, and JSON merging across multiple client formats.
217-271: LGTM!Good coverage of error validation paths. Minor note:
tmp_pathparameter on line 217 is unused but harmless.
| def test_install_vscode(tmp_path): | ||
| """Test install to VSCode.""" | ||
| vscode_config = tmp_path / ".vscode" / "mcp.json" | ||
|
|
||
| with patch("mcp_agent.cli.commands.install.load_api_key_credentials", return_value="test-key"): | ||
| with patch("mcp_agent.cli.commands.install.settings") as mock_settings: | ||
| mock_settings.API_KEY = "test-key" | ||
| mock_settings.API_BASE_URL = "http://test-api" | ||
|
|
||
| with patch("mcp_agent.cli.commands.install.Path.cwd", return_value=tmp_path): | ||
| install( | ||
| server_identifier=MOCK_APP_SERVER_URL, | ||
| client="vscode", | ||
| name="test-server", | ||
| dry_run=False, | ||
| force=False, | ||
| api_url="http://test-api", | ||
| api_key="test-key", | ||
| ) | ||
|
|
||
| # Verify config file was created | ||
| assert vscode_config.exists() | ||
|
|
||
| # Verify config contents (VSCode format) | ||
| config = json.loads(vscode_config.read_text()) | ||
| assert "servers" in config | ||
| assert "inputs" in config | ||
| assert "test-server" in config["servers"] | ||
| server = config["servers"]["test-server"] | ||
| assert server["url"] == MOCK_APP_SERVER_URL | ||
| assert server["type"] == "sse" | ||
| assert server["headers"]["Authorization"] == "Bearer test-key" | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mock MCPAppClient to avoid real API calls.
The test doesn't mock MCPAppClient, which means the install function will attempt to call mcp_client.get_app() during testing. While the implementation has a try-except that catches failures, making real API calls in unit tests creates reliability issues and can cause flaky tests.
Apply this pattern (similar to the ChatGPT tests) to mock the API client:
def test_install_vscode(tmp_path):
"""Test install to VSCode."""
vscode_config = tmp_path / ".vscode" / "mcp.json"
with patch("mcp_agent.cli.commands.install.load_api_key_credentials", return_value="test-key"):
with patch("mcp_agent.cli.commands.install.settings") as mock_settings:
mock_settings.API_KEY = "test-key"
mock_settings.API_BASE_URL = "http://test-api"
- with patch("mcp_agent.cli.commands.install.Path.cwd", return_value=tmp_path):
- install(
+ with patch("mcp_agent.cli.commands.install.MCPAppClient") as mock_client_class:
+ mock_client = MagicMock()
+ mock_client.get_app = AsyncMock(return_value=None)
+ mock_client_class.return_value = mock_client
+
+ with patch("mcp_agent.cli.commands.install.Path.cwd", return_value=tmp_path):
+ install(📝 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.
| def test_install_vscode(tmp_path): | |
| """Test install to VSCode.""" | |
| vscode_config = tmp_path / ".vscode" / "mcp.json" | |
| with patch("mcp_agent.cli.commands.install.load_api_key_credentials", return_value="test-key"): | |
| with patch("mcp_agent.cli.commands.install.settings") as mock_settings: | |
| mock_settings.API_KEY = "test-key" | |
| mock_settings.API_BASE_URL = "http://test-api" | |
| with patch("mcp_agent.cli.commands.install.Path.cwd", return_value=tmp_path): | |
| install( | |
| server_identifier=MOCK_APP_SERVER_URL, | |
| client="vscode", | |
| name="test-server", | |
| dry_run=False, | |
| force=False, | |
| api_url="http://test-api", | |
| api_key="test-key", | |
| ) | |
| # Verify config file was created | |
| assert vscode_config.exists() | |
| # Verify config contents (VSCode format) | |
| config = json.loads(vscode_config.read_text()) | |
| assert "servers" in config | |
| assert "inputs" in config | |
| assert "test-server" in config["servers"] | |
| server = config["servers"]["test-server"] | |
| assert server["url"] == MOCK_APP_SERVER_URL | |
| assert server["type"] == "sse" | |
| assert server["headers"]["Authorization"] == "Bearer test-key" | |
| def test_install_vscode(tmp_path): | |
| """Test install to VSCode.""" | |
| vscode_config = tmp_path / ".vscode" / "mcp.json" | |
| with patch("mcp_agent.cli.commands.install.load_api_key_credentials", return_value="test-key"): | |
| with patch("mcp_agent.cli.commands.install.settings") as mock_settings: | |
| mock_settings.API_KEY = "test-key" | |
| mock_settings.API_BASE_URL = "http://test-api" | |
| with patch("mcp_agent.cli.commands.install.MCPAppClient") as mock_client_class: | |
| mock_client = MagicMock() | |
| mock_client.get_app = AsyncMock(return_value=None) | |
| mock_client_class.return_value = mock_client | |
| with patch("mcp_agent.cli.commands.install.Path.cwd", return_value=tmp_path): | |
| install( | |
| server_identifier=MOCK_APP_SERVER_URL, | |
| client="vscode", | |
| name="test-server", | |
| dry_run=False, | |
| force=False, | |
| api_url="http://test-api", | |
| api_key="test-key", | |
| ) | |
| # Verify config file was created | |
| assert vscode_config.exists() | |
| # Verify config contents (VSCode format) | |
| config = json.loads(vscode_config.read_text()) | |
| assert "servers" in config | |
| assert "inputs" in config | |
| assert "test-server" in config["servers"] | |
| server = config["servers"]["test-server"] | |
| assert server["url"] == MOCK_APP_SERVER_URL | |
| assert server["type"] == "sse" | |
| assert server["headers"]["Authorization"] == "Bearer test-key" |
🤖 Prompt for AI Agents
In tests/cli/commands/test_install.py around lines 274 to 306, the test calls
install without mocking MCPAppClient so it can make real API calls; patch the
MCPAppClient used in mcp_agent.cli.commands.install to return a mock client
whose get_app method returns a predictable value (or raises as appropriate)
before calling install, and ensure the mock is configured in the same context as
the other patches (e.g., using patch(...) as mock_client and setting
mock_client.return_value.get_app.return_value or side_effect), so the install
flow uses the mocked API client and the test remains isolated and deterministic.
| def test_install_cursor_with_existing_config(tmp_path): | ||
| """Test install to Cursor with existing configuration.""" | ||
| cursor_config = tmp_path / ".cursor" / "mcp.json" | ||
| cursor_config.parent.mkdir(parents=True, exist_ok=True) | ||
|
|
||
| existing = { | ||
| "mcpServers": { | ||
| "existing-server": { | ||
| "url": "https://existing.com/mcp", | ||
| "transport": "http", | ||
| } | ||
| } | ||
| } | ||
| cursor_config.write_text(json.dumps(existing, indent=2)) | ||
|
|
||
| with patch("mcp_agent.cli.commands.install.load_api_key_credentials", return_value="test-key"): | ||
| with patch("mcp_agent.cli.commands.install.settings") as mock_settings: | ||
| mock_settings.API_KEY = "test-key" | ||
| mock_settings.API_BASE_URL = "http://test-api" | ||
|
|
||
| with patch("mcp_agent.cli.commands.install.Path.home", return_value=tmp_path): | ||
| install( | ||
| server_identifier=MOCK_APP_SERVER_URL, | ||
| client="cursor", | ||
| name="new-server", | ||
| dry_run=False, | ||
| force=False, | ||
| api_url="http://test-api", | ||
| api_key="test-key", | ||
| ) | ||
|
|
||
| config = json.loads(cursor_config.read_text()) | ||
| assert len(config["mcpServers"]) == 2 | ||
| assert "existing-server" in config["mcpServers"] | ||
| assert "new-server" in config["mcpServers"] | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mock MCPAppClient to avoid real API calls.
Same issue as the VSCode test—add MCPAppClient mock to prevent actual API calls during testing.
| def test_install_duplicate_without_force(tmp_path): | ||
| """Test install fails when server already exists without --force.""" | ||
| vscode_config = tmp_path / ".vscode" / "mcp.json" | ||
| vscode_config.parent.mkdir(parents=True, exist_ok=True) | ||
|
|
||
| existing = { | ||
| "servers": { | ||
| "test-server": { | ||
| "url": "https://old.com/mcp", | ||
| "type": "http", | ||
| } | ||
| }, | ||
| "inputs": [] | ||
| } | ||
| vscode_config.write_text(json.dumps(existing, indent=2)) | ||
|
|
||
| with patch("mcp_agent.cli.commands.install.load_api_key_credentials", return_value="test-key"): | ||
| with patch("mcp_agent.cli.commands.install.settings") as mock_settings: | ||
| mock_settings.API_KEY = "test-key" | ||
| mock_settings.API_BASE_URL = "http://test-api" | ||
|
|
||
| with patch("mcp_agent.cli.commands.install.Path.cwd", return_value=tmp_path): | ||
| with pytest.raises(CLIError, match="already exists"): | ||
| install( | ||
| server_identifier=MOCK_APP_SERVER_URL, | ||
| client="vscode", | ||
| name="test-server", | ||
| dry_run=False, | ||
| force=False, | ||
| api_url="http://test-api", | ||
| api_key="test-key", | ||
| ) | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mock MCPAppClient to avoid real API calls.
Same issue—add MCPAppClient mock to prevent actual API calls during testing.
🤖 Prompt for AI Agents
In tests/cli/commands/test_install.py around lines 345 to 377, the test still
allows real MCP API calls; patch the MCPAppClient used by the install command to
a mock to prevent network access. Add a patch for
"mcp_agent.cli.commands.install.MCPAppClient" (or the exact import path used in
the install module) that returns a simple Mock instance whose methods/attributes
used by install (constructor, any lookup or list calls) return safe dummy
values; wrap this mock patch in the same context managers as the other patches
so the test asserts the CLIError without making real API requests.
| def test_install_duplicate_with_force(tmp_path): | ||
| """Test install overwrites when server exists with --force.""" | ||
| vscode_config = tmp_path / ".vscode" / "mcp.json" | ||
| vscode_config.parent.mkdir(parents=True, exist_ok=True) | ||
|
|
||
| existing = { | ||
| "servers": { | ||
| "test-server": { | ||
| "url": "https://old.com/mcp", | ||
| "type": "http", | ||
| } | ||
| }, | ||
| "inputs": [] | ||
| } | ||
| vscode_config.write_text(json.dumps(existing, indent=2)) | ||
|
|
||
| with patch("mcp_agent.cli.commands.install.load_api_key_credentials", return_value="test-key"): | ||
| with patch("mcp_agent.cli.commands.install.settings") as mock_settings: | ||
| mock_settings.API_KEY = "test-key" | ||
| mock_settings.API_BASE_URL = "http://test-api" | ||
|
|
||
| with patch("mcp_agent.cli.commands.install.Path.cwd", return_value=tmp_path): | ||
| install( | ||
| server_identifier=MOCK_APP_SERVER_URL, | ||
| client="vscode", | ||
| name="test-server", | ||
| dry_run=False, | ||
| force=True, | ||
| api_url="http://test-api", | ||
| api_key="test-key", | ||
| ) | ||
|
|
||
| config = json.loads(vscode_config.read_text()) | ||
| assert config["servers"]["test-server"]["url"] == MOCK_APP_SERVER_URL | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mock MCPAppClient to avoid real API calls.
Same issue—add MCPAppClient mock to prevent actual API calls during testing.
🤖 Prompt for AI Agents
In tests/cli/commands/test_install.py around lines 379 to 413, the test calls
install without mocking MCPAppClient which can trigger real API calls; patch
mcp_agent.cli.commands.install.MCPAppClient to a Mock before invoking install
and configure that mock to provide the methods/return values the install flow
expects (e.g., any create/get methods or attributes used to obtain the server
URL), so the test runs offline and only asserts the config file update.
| def test_install_dry_run(tmp_path, capsys): | ||
| """Test install in dry run mode.""" | ||
| with patch("mcp_agent.cli.commands.install.load_api_key_credentials", return_value="test-key"): | ||
| with patch("mcp_agent.cli.commands.install.settings") as mock_settings: | ||
| mock_settings.API_KEY = "test-key" | ||
| mock_settings.API_BASE_URL = "http://test-api" | ||
|
|
||
| with patch("mcp_agent.cli.commands.install.Path.cwd", return_value=tmp_path): | ||
| install( | ||
| server_identifier=MOCK_APP_SERVER_URL, | ||
| client="vscode", | ||
| name="test-server", | ||
| dry_run=True, | ||
| force=False, | ||
| api_url="http://test-api", | ||
| api_key="test-key", | ||
| ) | ||
|
|
||
| vscode_config = tmp_path / ".vscode" / "mcp.json" | ||
| assert not vscode_config.exists() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mock MCPAppClient to avoid real API calls.
Same issue as other functional tests—add MCPAppClient mock to prevent actual API calls during testing.
🤖 Prompt for AI Agents
In tests/cli/commands/test_install.py around lines 466 to 485, the test calls
install() but does not mock MCPAppClient so the test may perform real API calls;
patch mcp_agent.cli.commands.install.MCPAppClient (e.g. using
unittest.mock.patch or patch.object) to return a mock client instance with the
attributes/methods the install flow expects (such as .get_application or
.register or context-manager behavior) and scope that patch around the install()
invocation so the test uses the fake client and no real network requests occur.
| def test_install_sse_transport_detection(tmp_path): | ||
| """Test that SSE transport is detected from URL.""" | ||
| vscode_config = tmp_path / ".vscode" / "mcp.json" | ||
|
|
||
| with patch("mcp_agent.cli.commands.install.load_api_key_credentials", return_value="test-key"): | ||
| with patch("mcp_agent.cli.commands.install.settings") as mock_settings: | ||
| mock_settings.API_KEY = "test-key" | ||
| mock_settings.API_BASE_URL = "http://test-api" | ||
|
|
||
| with patch("mcp_agent.cli.commands.install.Path.cwd", return_value=tmp_path): | ||
| install( | ||
| server_identifier="https://example.com/sse", | ||
| client="vscode", | ||
| name="test-server", | ||
| dry_run=False, | ||
| force=False, | ||
| api_url="http://test-api", | ||
| api_key="test-key", | ||
| ) | ||
|
|
||
| config = json.loads(vscode_config.read_text()) | ||
| assert config["servers"]["test-server"]["type"] == "sse" | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mock MCPAppClient to avoid real API calls.
Same issue—add MCPAppClient mock to prevent actual API calls during testing.
| def test_install_http_transport_detection(tmp_path): | ||
| """Test that HTTP transport is detected from URL.""" | ||
| vscode_config = tmp_path / ".vscode" / "mcp.json" | ||
|
|
||
| with patch("mcp_agent.cli.commands.install.load_api_key_credentials", return_value="test-key"): | ||
| with patch("mcp_agent.cli.commands.install.settings") as mock_settings: | ||
| mock_settings.API_KEY = "test-key" | ||
| mock_settings.API_BASE_URL = "http://test-api" | ||
|
|
||
| with patch("mcp_agent.cli.commands.install.Path.cwd", return_value=tmp_path): | ||
| install( | ||
| server_identifier="https://example.com/mcp", | ||
| client="vscode", | ||
| name="test-server", | ||
| dry_run=False, | ||
| force=False, | ||
| api_url="http://test-api", | ||
| api_key="test-key", | ||
| ) | ||
|
|
||
| config = json.loads(vscode_config.read_text()) | ||
| assert config["servers"]["test-server"]["type"] == "http" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mock MCPAppClient to avoid real API calls.
Same issue—add MCPAppClient mock to prevent actual API calls during testing.
🤖 Prompt for AI Agents
In tests/cli/commands/test_install.py around lines 512 to 533, the test calls
install without mocking MCPAppClient so it may perform real API calls; patch
mcp_agent.cli.commands.install.MCPAppClient to return a MagicMock before
invoking install, configure that mock (return_value) with any attributes/methods
the install flow expects (e.g., methods that fetch or create servers) to avoid
network calls, and apply the patch context the same way other dependencies are
patched so the install call uses the mocked client.
### TL;DR Added a new `install` command to the MCP Agent CLI for adding MCP servers to client applications. ### What changed? - Added a new `install` command that provides end-to-end installation of MCP servers to client applications - Supports multiple client applications: VSCode, Claude Code, Cursor, Claude Desktop, and ChatGPT - Handles authentication, server configuration, and writing server configuration to client config files - Automatically detects required secrets and configures them - Provides options for customizing server name, using existing secrets files, and forcing overwrites ### How to test? ``` # Install to VSCode mcp-agent install https://api.example.com/servers/my-server/mcp --client vscode # Install to Claude Code with custom name mcp-agent install app-id-123 --client claude_code --name my-server # Install with existing secrets file mcp-agent install my-server --client cursor --secrets-file secrets.yaml # Dry run to validate without making changes mcp-agent install my-server --client claude_desktop --dry-run ``` <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit ## Release Notes - **New Features** - Added `install` CLI command to register MCP servers with supported client applications (Claude Desktop, VSCode, Cursor, ChatGPT, Claude Code) - Supports dry-run preview mode and force overwrite option for existing configurations - **Tests** - Added comprehensive test coverage for install command validation and client-specific configurations <!-- end of auto-generated comment: release notes by coderabbit.ai -->

TL;DR
Added a new
installcommand to the MCP Agent CLI for adding MCP servers to client applications.What changed?
installcommand that provides end-to-end installation of MCP servers to client applicationsHow to test?
Summary by CodeRabbit
installCLI command to add MCP servers to supported clients (Claude Desktop, VSCode, Cursor, ChatGPT, Claude Code).