From d41faf6b3072d4f8bdb2adc896125c7fd0d6117d Mon Sep 17 00:00:00 2001 From: Mathieu Virbel Date: Sat, 12 Jul 2025 18:59:52 -0600 Subject: [PATCH] feat: add --mcp-type option for remote MCP servers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Auto-detects connection type from URL (/sse -> sse, /mcp -> streamable_http) or allows manual specification. Updates goose plugin to use actual MCP type instead of hardcoded sse. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- cubbi/cli.py | 23 ++++++++++++++++++++++- cubbi/container.py | 2 +- cubbi/images/goose/goose_plugin.py | 4 ++-- cubbi/mcp.py | 2 ++ cubbi/models.py | 1 + 5 files changed, 28 insertions(+), 4 deletions(-) diff --git a/cubbi/cli.py b/cubbi/cli.py index ce4f159..615d6c2 100644 --- a/cubbi/cli.py +++ b/cubbi/cli.py @@ -1573,6 +1573,11 @@ def add_mcp( def add_remote_mcp( name: str = typer.Argument(..., help="MCP server name"), url: str = typer.Argument(..., help="URL of the remote MCP server"), + mcp_type: str = typer.Option( + "auto", + "--mcp-type", + help="MCP connection type: sse, streamable_http, stdio, or auto (default: auto)", + ), header: List[str] = typer.Option( [], "--header", "-H", help="HTTP headers (format: KEY=VALUE)" ), @@ -1581,6 +1586,22 @@ def add_remote_mcp( ), ) -> None: """Add a remote MCP server""" + if mcp_type == "auto": + if url.endswith("/sse"): + mcp_type = "sse" + elif url.endswith("/mcp"): + mcp_type = "streamable_http" + else: + console.print( + f"[red]Cannot auto-detect MCP type from URL '{url}'. Please specify --mcp-type (sse, streamable_http, or stdio)[/red]" + ) + return + elif mcp_type not in ["sse", "streamable_http", "stdio"]: + console.print( + f"[red]Invalid MCP type '{mcp_type}'. Must be: sse, streamable_http, stdio, or auto[/red]" + ) + return + # Parse headers headers = {} for h in header: @@ -1595,7 +1616,7 @@ def add_remote_mcp( try: with console.status(f"Adding remote MCP server '{name}'..."): mcp_manager.add_remote_mcp( - name, url, headers, add_as_default=not no_default + name, url, headers, mcp_type=mcp_type, add_as_default=not no_default ) console.print(f"[green]Added remote MCP server '{name}'[/green]") diff --git a/cubbi/container.py b/cubbi/container.py index 37bf60f..cbfe22d 100644 --- a/cubbi/container.py +++ b/cubbi/container.py @@ -443,7 +443,7 @@ class ContainerManager: ) # Set type-specific information - env_vars[f"MCP_{idx}_TYPE"] = "remote" + env_vars[f"MCP_{idx}_TYPE"] = mcp_config.get("mcp_type", "sse") env_vars[f"MCP_{idx}_NAME"] = mcp_name # Set environment variables for MCP count if we have any diff --git a/cubbi/images/goose/goose_plugin.py b/cubbi/images/goose/goose_plugin.py index d30671f..b92894f 100644 --- a/cubbi/images/goose/goose_plugin.py +++ b/cubbi/images/goose/goose_plugin.py @@ -171,7 +171,7 @@ class GoosePlugin(ToolPlugin): "enabled": True, "name": server_name, "timeout": 60, - "type": "sse", + "type": server.get("type", "sse"), "uri": mcp_url, "envs": {}, } @@ -184,7 +184,7 @@ class GoosePlugin(ToolPlugin): "enabled": True, "name": server_name, "timeout": 60, - "type": "sse", + "type": server.get("type", "sse"), "uri": server_url, "envs": {}, } diff --git a/cubbi/mcp.py b/cubbi/mcp.py index 3526811..674e1a7 100644 --- a/cubbi/mcp.py +++ b/cubbi/mcp.py @@ -79,6 +79,7 @@ class MCPManager: name: str, url: str, headers: Dict[str, str] = None, + mcp_type: Optional[str] = None, add_as_default: bool = True, ) -> Dict[str, Any]: """Add a remote MCP server. @@ -97,6 +98,7 @@ class MCPManager: name=name, url=url, headers=headers or {}, + mcp_type=mcp_type, ) # Add to the configuration diff --git a/cubbi/models.py b/cubbi/models.py index 8b310be..f9dc3ba 100644 --- a/cubbi/models.py +++ b/cubbi/models.py @@ -61,6 +61,7 @@ class RemoteMCP(BaseModel): type: str = "remote" url: str headers: Dict[str, str] = Field(default_factory=dict) + mcp_type: Optional[str] = None class DockerMCP(BaseModel):