Source code for ralph.mcp.transport.claude
"""Claude-specific MCP transport helpers."""
from __future__ import annotations
import json
from pathlib import Path
from ralph.mcp.tools.names import RALPH_MCP_SERVER_NAME
from ralph.mcp.transport.common import _load_mcpservers_from_paths, merge_existing_upstreams
from ralph.mcp.upstream.config import UpstreamMcpServer, normalize_upstream_mcp_servers
[docs]
def claude_mcp_config(
endpoint: str,
*,
workspace_path: Path | None = None,
unsafe_mode: bool = False,
) -> str:
"""Return the Claude MCP JSON config string pointing to the given endpoint."""
ralph_entry = {
RALPH_MCP_SERVER_NAME: {
"type": "http",
"url": endpoint,
}
}
current_config: dict[str, object] = {"mcpServers": dict(ralph_entry)}
if workspace_path is not None:
current_config["workspace_path"] = workspace_path
merged_config = merge_existing_upstreams(
"claude", current_config, unsafe_mode=unsafe_mode, workspace_path=workspace_path
)
config_payload = merged_config
return json.dumps(config_payload, separators=(",", ":"))
[docs]
def load_existing_claude_upstream_servers(
workspace_path: Path | None = None,
) -> tuple[UpstreamMcpServer, ...]:
"""Read Claude's MCP config files and return any upstream MCP servers found."""
servers = _load_mcpservers_from_paths(_claude_mcp_config_paths(workspace_path))
return normalize_upstream_mcp_servers(servers)
def _claude_mcp_config_paths(workspace_path: Path | None) -> tuple[Path, ...]:
workspace_paths: tuple[Path, ...] = ()
if workspace_path is not None:
workspace_paths = (
workspace_path / ".mcp.json",
workspace_path / ".claude.json",
)
return (
Path.home() / ".claude.json",
*workspace_paths,
)
__all__ = [
"claude_mcp_config",
"load_existing_claude_upstream_servers",
]