diff --git a/src/mcpm/clients/managers/claude_desktop.py b/src/mcpm/clients/managers/claude_desktop.py index 77a2dd0d..3cf22859 100644 --- a/src/mcpm/clients/managers/claude_desktop.py +++ b/src/mcpm/clients/managers/claude_desktop.py @@ -7,7 +7,7 @@ from typing import Any, Dict from mcpm.clients.base import JSONClientManager -from mcpm.schemas.server_config import ServerConfig +from mcpm.schemas.server_config import ServerConfig, SSEServerConfig from mcpm.utils.router_server import format_server_url_with_proxy_headers logger = logging.getLogger(__name__) @@ -116,8 +116,8 @@ def is_server_disabled(self, server_name: str) -> bool: def _format_router_server(self, profile_name, base_url) -> ServerConfig: return format_server_url_with_proxy_headers(self.client_key, profile_name, base_url) - # Uses base class implementation of remove_server - - # Uses base class implementation of get_server - - # Uses base class implementation of list_servers + def to_client_format(self, server_config: ServerConfig) -> Dict[str, Any]: + if isinstance(server_config, SSEServerConfig): + # use mcp proxy to convert to stdio as sse is not supported for claude desktop yet + return self.to_client_format(server_config.to_mcp_proxy_stdio()) + return super().to_client_format(server_config) diff --git a/src/mcpm/router/transport.py b/src/mcpm/router/transport.py index d771e2f0..0186657b 100644 --- a/src/mcpm/router/transport.py +++ b/src/mcpm/router/transport.py @@ -32,7 +32,7 @@ def patch_meta_data(body: bytes, **kwargs) -> bytes: data = json.loads(body.decode("utf-8")) for key, value in kwargs.items(): - data["params"]["_meta"][key] = value + data["params"].setdefault("_meta", {})[key] = value return json.dumps(data).encode("utf-8") diff --git a/src/mcpm/schemas/server_config.py b/src/mcpm/schemas/server_config.py index 61e981f8..e96764a3 100644 --- a/src/mcpm/schemas/server_config.py +++ b/src/mcpm/schemas/server_config.py @@ -57,5 +57,22 @@ class SSEServerConfig(BaseServerConfig): url: str headers: Dict[str, Any] = {} + def to_mcp_proxy_stdio(self) -> STDIOServerConfig: + proxy_args = [ + "mcp-proxy", + self.url, + ] + if self.headers: + proxy_args.append("--headers") + for key, value in self.headers.items(): + proxy_args.append(f"{key}") + proxy_args.append(f"{value}") + + return STDIOServerConfig( + name=self.name, + command="uvx", + args=proxy_args, + ) + ServerConfig = Union[STDIOServerConfig, SSEServerConfig] diff --git a/tests/conftest.py b/tests/conftest.py index 829c01b4..ab0ee9f3 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -13,6 +13,7 @@ # Add the src directory to the path for all tests sys.path.insert(0, str(Path(__file__).parent.parent)) +from mcpm.clients.managers.claude_desktop import ClaudeDesktopManager from mcpm.clients.managers.windsurf import WindsurfManager from mcpm.utils.config import ConfigManager @@ -67,3 +68,9 @@ def windsurf_manager(temp_config_file): def empty_windsurf_manager(empty_config_file): """Create a WindsurfManager instance with an empty config""" return WindsurfManager(config_path=empty_config_file) + + +@pytest.fixture +def claude_desktop_manager(temp_config_file): + """Create a ClaudeDesktopManager instance with the temp config""" + return ClaudeDesktopManager(config_path=temp_config_file) diff --git a/tests/test_add.py b/tests/test_add.py index 9c30c170..2c6531e3 100644 --- a/tests/test_add.py +++ b/tests/test_add.py @@ -4,6 +4,7 @@ from mcpm.clients.client_registry import ClientRegistry from mcpm.commands.server_operations.add import add +from mcpm.schemas.server_config import SSEServerConfig from mcpm.utils.repository import RepositoryManager @@ -186,3 +187,22 @@ def test_add_server_with_empty_args(windsurf_manager, monkeypatch): "API_KEY": "test-api-key", "OPTIONAL_ENV": "", # Optional env var should be empty string } + + +def test_add_sse_server_to_claude_desktop(claude_desktop_manager, monkeypatch): + """Test add sse server to claude desktop""" + server_config = SSEServerConfig( + name="test-sse-server", url="http://localhost:8080", headers={"Authorization": "Bearer test-api-key"} + ) + claude_desktop_manager.add_server(server_config) + stored_config = claude_desktop_manager.get_server("test-sse-server") + assert stored_config is not None + assert stored_config.name == "test-sse-server" + assert stored_config.command == "uvx" + assert stored_config.args == [ + "mcp-proxy", + "http://localhost:8080", + "--headers", + "Authorization", + "Bearer test-api-key", + ]