Add ClientSetupHandler and setup CLI command

Add first implementation: ClaudeCode
This commit is contained in:
Dominik Jain committed 2026-04-07 18:29:44 +02:00
1 parent 25f5f5095f
commit 2c4174f3bd
2 files changed
+73

No files matched your search

+27
View File
@@ -19,6 +19,7 @@ from tqdm import tqdm
from serena import serena_version
from serena.agent import SerenaAgent
from serena.config.client_setup import client_setup_handlers
from serena.config.context_mode import SerenaAgentContext, SerenaAgentMode
from serena.config.serena_config import (
LanguageBackend,
@@ -176,6 +177,32 @@ class TopLevelCommands(AutoRegisteringGroup):
click.echo(f"Language backend: {language_backend}")
click.echo("\nSerena has been initialised successfully.\n")
@staticmethod
@click.command(
"setup",
help="Set up Serena for use with a specific client by registering it as an MCP server.",
context_settings={"max_content_width": _MAX_CONTENT_WIDTH},
)
@click.argument(
"client",
type=click.Choice([h.name for h in client_setup_handlers]),
)
def setup(client: str) -> None:
# find the matching handler
handler = next(h for h in client_setup_handlers if h.name == client)
# check applicability
if not handler.is_applicable():
click.echo(f"\nCannot apply setup for client '{client}' (not found or not functional).\n")
raise SystemExit(1)
# apply the setup
if handler.apply():
click.echo(f"\nSerena has been successfully set up for {client}.\n")
else:
click.echo(f"\nFailed to set up Serena for {client}.\n")
raise SystemExit(1)
@staticmethod
@click.command("start-mcp-server", help="Starts the Serena MCP server.", context_settings={"max_content_width": _MAX_CONTENT_WIDTH})
@click.option("--project", "project", type=PROJECT_TYPE, default=None, help="Path or name of project to activate at startup.")
+46
View File
@@ -0,0 +1,46 @@
from abc import ABC, abstractmethod
from serena.util.shell import execute_shell_command
class ClientSetupHandler(ABC):
def __init__(self, name: str) -> None:
self.name = name
@abstractmethod
def is_applicable(self) -> bool:
"""
:return: whether the client setup can applied (respective client is available)
"""
@abstractmethod
def get_mcp_server_options(self) -> list[str]:
pass
def get_mcp_server_command(self) -> str:
return f"serena start-mcp-server {' '.join(self.get_mcp_server_options())}"
@abstractmethod
def apply(self) -> bool:
"""
Applies the client setup
"""
class ClientSetupHandlerClaudeCode(ClientSetupHandler):
def __init__(self) -> None:
super().__init__("ClaudeCode")
def is_applicable(self) -> bool:
result = execute_shell_command("claude --version")
return result.return_code == 0 and "Claude" in result.stdout
def get_mcp_server_options(self) -> list[str]:
return ["--context=claude-code", "--project-from-cwd"]
def apply(self) -> bool:
result = execute_shell_command(f"claude mcp add --scope user serena -- {self.get_mcp_server_command()}")
return result.return_code == 0
client_setup_handlers = [ClientSetupHandlerClaudeCode()]