Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 11 additions & 3 deletions src/claude_code_sdk/_internal/transport/subprocess_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,9 +130,17 @@ def _build_command(self) -> list[str]:
cmd.extend(["--add-dir", str(directory)])

if self._options.mcp_servers:
cmd.extend(
["--mcp-config", json.dumps({"mcpServers": self._options.mcp_servers})]
)
if isinstance(self._options.mcp_servers, dict):
# Dict format: serialize to JSON
cmd.extend(
[
"--mcp-config",
json.dumps({"mcpServers": self._options.mcp_servers}),
]
)
else:
# String or Path format: pass directly as file path or JSON string
cmd.extend(["--mcp-config", str(self._options.mcp_servers)])

# Add extra args for future CLI flags
for flag, value in self._options.extra_args.items():
Expand Down
2 changes: 1 addition & 1 deletion src/claude_code_sdk/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ class ClaudeCodeOptions:
max_thinking_tokens: int = 8000
system_prompt: str | None = None
append_system_prompt: str | None = None
mcp_servers: dict[str, McpServerConfig] = field(default_factory=dict)
mcp_servers: dict[str, McpServerConfig] | str | Path = field(default_factory=dict)
permission_mode: PermissionMode | None = None
continue_conversation: bool = False
resume: str | None = None
Expand Down
72 changes: 72 additions & 0 deletions tests/test_transport.py
Original file line number Diff line number Diff line change
Expand Up @@ -227,3 +227,75 @@ def test_build_command_with_extra_args(self):
boolean_idx = cmd.index("--boolean-flag")
# Either it's the last element or the next element is another flag
assert boolean_idx == len(cmd) - 1 or cmd[boolean_idx + 1].startswith("--")

def test_build_command_with_mcp_servers(self):
"""Test building CLI command with mcp_servers option."""
import json

mcp_servers = {
"test-server": {
"type": "stdio",
"command": "/path/to/server",
"args": ["--option", "value"],
}
}

transport = SubprocessCLITransport(
prompt="test",
options=ClaudeCodeOptions(mcp_servers=mcp_servers),
cli_path="/usr/bin/claude",
)

cmd = transport._build_command()

# Find the --mcp-config flag and its value
assert "--mcp-config" in cmd
mcp_idx = cmd.index("--mcp-config")
mcp_config_value = cmd[mcp_idx + 1]

# Parse the JSON and verify structure
config = json.loads(mcp_config_value)
assert "mcpServers" in config
assert config["mcpServers"] == mcp_servers

def test_build_command_with_mcp_servers_as_file_path(self):
"""Test building CLI command with mcp_servers as file path."""
from pathlib import Path

# Test with string path
transport = SubprocessCLITransport(
prompt="test",
options=ClaudeCodeOptions(mcp_servers="/path/to/mcp-config.json"),
cli_path="/usr/bin/claude",
)

cmd = transport._build_command()
assert "--mcp-config" in cmd
mcp_idx = cmd.index("--mcp-config")
assert cmd[mcp_idx + 1] == "/path/to/mcp-config.json"

# Test with Path object
transport = SubprocessCLITransport(
prompt="test",
options=ClaudeCodeOptions(mcp_servers=Path("/path/to/mcp-config.json")),
cli_path="/usr/bin/claude",
)

cmd = transport._build_command()
assert "--mcp-config" in cmd
mcp_idx = cmd.index("--mcp-config")
assert cmd[mcp_idx + 1] == "/path/to/mcp-config.json"

def test_build_command_with_mcp_servers_as_json_string(self):
"""Test building CLI command with mcp_servers as JSON string."""
json_config = '{"mcpServers": {"server": {"type": "stdio", "command": "test"}}}'
transport = SubprocessCLITransport(
prompt="test",
options=ClaudeCodeOptions(mcp_servers=json_config),
cli_path="/usr/bin/claude",
)

cmd = transport._build_command()
assert "--mcp-config" in cmd
mcp_idx = cmd.index("--mcp-config")
assert cmd[mcp_idx + 1] == json_config