mirror of
https://github.com/hanzoai/python-sdk.git
synced 2026-10-23 20:23:00 +00:00
645 lines
25 KiB
Python
645 lines
25 KiB
Python
"""Tests for the CLI module."""
|
|
|
|
import os
|
|
import sys
|
|
from pathlib import Path
|
|
from typing import Callable
|
|
from unittest.mock import MagicMock, patch
|
|
|
|
import pytest
|
|
|
|
from hanzo_mcp.cli import install_claude_desktop_config, main
|
|
|
|
|
|
class TestCLI:
|
|
"""Test the CLI module."""
|
|
|
|
def test_main_server_run(self) -> None:
|
|
"""Test the main function running the server."""
|
|
with (
|
|
patch("argparse.ArgumentParser.parse_args") as mock_parse_args,
|
|
patch("hanzo_mcp.server.HanzoMCPServer") as mock_server_class,
|
|
):
|
|
# Mock parsed arguments
|
|
mock_args = MagicMock()
|
|
mock_args.name = "test-server"
|
|
mock_args.transport = "stdio"
|
|
mock_args.allowed_paths = ["/test/path"]
|
|
mock_args.project_dir = "/test/project"
|
|
mock_args.install = False
|
|
mock_args.agent_model = "anthropic/claude-3-sonnet"
|
|
mock_args.agent_max_tokens = 2000
|
|
mock_args.agent_api_key = "test_api_key"
|
|
mock_args.agent_base_url = None
|
|
mock_args.agent_max_iterations = 10
|
|
mock_args.agent_max_tool_uses = 30
|
|
mock_args.enable_agent_tool = False
|
|
mock_args.disable_write_tools = False
|
|
mock_args.disable_search_tools = False
|
|
mock_args.log_level = "INFO"
|
|
mock_args.host = "127.0.0.1"
|
|
mock_args.port = 3000
|
|
mock_args.project_paths = None
|
|
mock_args.command_timeout = "120s"
|
|
mock_args.dev = False
|
|
mock_args.force_shell = None
|
|
mock_args.daemon = False
|
|
mock_args.socket_path = "/tmp/hanzo-mcp.sock"
|
|
mock_args.max_connections = 100
|
|
mock_args.tool_timeout = None
|
|
mock_args.search_timeout = None
|
|
mock_args.find_timeout = None
|
|
mock_args.ast_timeout = None
|
|
mock_parse_args.return_value = mock_args
|
|
|
|
# Mock server instance
|
|
mock_server = MagicMock()
|
|
mock_server_class.return_value = mock_server
|
|
|
|
# Call main
|
|
main()
|
|
|
|
# Verify server was created with correct arguments
|
|
# Project dir should be added to allowed paths and project_paths
|
|
expected_paths = ["/test/path", "/test/project"]
|
|
mock_server_class.assert_called_once_with(
|
|
name="test-server",
|
|
allowed_paths=expected_paths,
|
|
project_paths=["/test/project"],
|
|
project_dir="/test/project",
|
|
agent_model="anthropic/claude-3-sonnet",
|
|
agent_max_tokens=2000,
|
|
agent_api_key="test_api_key",
|
|
agent_base_url=mock_args.agent_base_url,
|
|
agent_max_iterations=10,
|
|
agent_max_tool_uses=30,
|
|
enable_agent_tool=False,
|
|
command_timeout=120.0,
|
|
disable_write_tools=False,
|
|
disable_search_tools=False,
|
|
host=mock_args.host,
|
|
port=mock_args.port,
|
|
)
|
|
mock_server.run.assert_called_once_with(transport="stdio")
|
|
|
|
def test_main_with_install(self) -> None:
|
|
"""Test the main function with install option."""
|
|
with (
|
|
patch("argparse.ArgumentParser.parse_args") as mock_parse_args,
|
|
patch("hanzo_mcp.cli.install_claude_desktop_config") as mock_install,
|
|
):
|
|
# Mock parsed arguments
|
|
mock_args = MagicMock()
|
|
mock_args.name = "test-server"
|
|
mock_args.install = True
|
|
mock_args.allowed_paths = ["/test/path"]
|
|
mock_args.project_dir = None
|
|
mock_args.disable_write_tools = False
|
|
mock_args.disable_search_tools = False
|
|
mock_args.log_level = "INFO"
|
|
mock_args.host = "127.0.0.1"
|
|
mock_args.port = 3000
|
|
mock_args.command_timeout = "120s"
|
|
mock_args.dev = False
|
|
mock_args.force_shell = None
|
|
mock_args.daemon = False
|
|
mock_args.socket_path = "/tmp/hanzo-mcp.sock"
|
|
mock_args.max_connections = 100
|
|
mock_args.tool_timeout = None
|
|
mock_args.search_timeout = None
|
|
mock_args.find_timeout = None
|
|
mock_args.ast_timeout = None
|
|
mock_parse_args.return_value = mock_args
|
|
|
|
# Call main
|
|
main()
|
|
|
|
# Verify install function was called
|
|
mock_install.assert_called_once_with(
|
|
"test-server",
|
|
["/test/path"],
|
|
mock_args.disable_write_tools,
|
|
mock_args.disable_search_tools,
|
|
mock_args.host,
|
|
mock_args.port,
|
|
)
|
|
|
|
def test_main_without_allowed_paths(self) -> None:
|
|
"""Test the main function without specified allowed paths."""
|
|
with (
|
|
patch("argparse.ArgumentParser.parse_args") as mock_parse_args,
|
|
patch("hanzo_mcp.server.HanzoMCPServer") as mock_server_class,
|
|
patch("os.path.expanduser", return_value="/home/testuser"),
|
|
):
|
|
# Mock parsed arguments
|
|
mock_args = MagicMock()
|
|
mock_args.name = "test-server"
|
|
mock_args.transport = "stdio"
|
|
mock_args.allowed_paths = None
|
|
mock_args.project_dir = None
|
|
mock_args.install = False
|
|
mock_args.agent_model = None
|
|
mock_args.agent_max_tokens = None
|
|
mock_args.agent_api_key = None
|
|
mock_args.agent_base_url = None
|
|
mock_args.agent_max_iterations = 10
|
|
mock_args.agent_max_tool_uses = 30
|
|
mock_args.enable_agent_tool = False
|
|
mock_args.disable_write_tools = False
|
|
mock_args.disable_search_tools = False
|
|
mock_args.log_level = "INFO"
|
|
mock_args.host = "127.0.0.1"
|
|
mock_args.port = 3000
|
|
mock_args.project_paths = None
|
|
mock_args.command_timeout = "120s"
|
|
mock_args.dev = False
|
|
mock_args.force_shell = None
|
|
mock_args.daemon = False
|
|
mock_args.socket_path = "/tmp/hanzo-mcp.sock"
|
|
mock_args.max_connections = 100
|
|
mock_args.tool_timeout = None
|
|
mock_args.search_timeout = None
|
|
mock_args.find_timeout = None
|
|
mock_args.ast_timeout = None
|
|
mock_parse_args.return_value = mock_args
|
|
|
|
# Mock server instance
|
|
mock_server = MagicMock()
|
|
mock_server_class.return_value = mock_server
|
|
|
|
# Call main
|
|
main()
|
|
|
|
# Verify server was created with home directory as allowed path
|
|
mock_server_class.assert_called_once_with(
|
|
name="test-server",
|
|
allowed_paths=["/home/testuser"],
|
|
project_paths=[],
|
|
project_dir=None,
|
|
agent_model=None,
|
|
agent_max_tokens=None,
|
|
agent_api_key=None,
|
|
agent_base_url=None,
|
|
agent_max_iterations=10,
|
|
agent_max_tool_uses=30,
|
|
enable_agent_tool=False,
|
|
command_timeout=120.0,
|
|
disable_write_tools=False,
|
|
disable_search_tools=False,
|
|
host=mock_args.host,
|
|
port=mock_args.port,
|
|
)
|
|
mock_server.run.assert_called_once_with(transport="stdio")
|
|
|
|
def test_main_with_disable_write_tools(self) -> None:
|
|
"""Test the main function with disable_write_tools=True."""
|
|
with (
|
|
patch("argparse.ArgumentParser.parse_args") as mock_parse_args,
|
|
patch("hanzo_mcp.server.HanzoMCPServer") as mock_server_class,
|
|
):
|
|
# Mock parsed arguments
|
|
mock_args = MagicMock()
|
|
mock_args.name = "test-server"
|
|
mock_args.transport = "stdio"
|
|
mock_args.allowed_paths = ["/test/path"]
|
|
mock_args.project_dir = "/test/project"
|
|
mock_args.install = False
|
|
mock_args.agent_model = None
|
|
mock_args.agent_max_tokens = None
|
|
mock_args.agent_api_key = None
|
|
mock_args.agent_base_url = None
|
|
mock_args.agent_max_iterations = 10
|
|
mock_args.agent_max_tool_uses = 30
|
|
mock_args.enable_agent_tool = False
|
|
mock_args.disable_write_tools = True
|
|
mock_args.disable_search_tools = False
|
|
mock_args.log_level = "INFO"
|
|
mock_args.host = "127.0.0.1"
|
|
mock_args.port = 3000
|
|
mock_args.project_paths = None
|
|
mock_args.command_timeout = "120s"
|
|
mock_args.dev = False
|
|
mock_args.force_shell = None
|
|
mock_args.daemon = False
|
|
mock_args.socket_path = "/tmp/hanzo-mcp.sock"
|
|
mock_args.max_connections = 100
|
|
mock_args.tool_timeout = None
|
|
mock_args.search_timeout = None
|
|
mock_args.find_timeout = None
|
|
mock_args.ast_timeout = None
|
|
mock_parse_args.return_value = mock_args
|
|
|
|
# Mock server instance
|
|
mock_server = MagicMock()
|
|
mock_server_class.return_value = mock_server
|
|
|
|
# Call main
|
|
main()
|
|
|
|
# Verify server was created with disable_write_tools=True
|
|
expected_paths = ["/test/path", "/test/project"]
|
|
mock_server_class.assert_called_once_with(
|
|
name="test-server",
|
|
allowed_paths=expected_paths,
|
|
project_paths=["/test/project"],
|
|
project_dir="/test/project",
|
|
agent_model=None,
|
|
agent_max_tokens=None,
|
|
agent_api_key=None,
|
|
agent_base_url=None,
|
|
agent_max_iterations=10,
|
|
agent_max_tool_uses=30,
|
|
enable_agent_tool=False,
|
|
command_timeout=120.0,
|
|
disable_write_tools=True,
|
|
disable_search_tools=False,
|
|
host=mock_args.host,
|
|
port=mock_args.port,
|
|
)
|
|
mock_server.run.assert_called_once_with(transport="stdio")
|
|
|
|
def test_main_with_disable_search_tools(self) -> None:
|
|
"""Test the main function with disable_search_tools=True."""
|
|
with (
|
|
patch("argparse.ArgumentParser.parse_args") as mock_parse_args,
|
|
patch("hanzo_mcp.server.HanzoMCPServer") as mock_server_class,
|
|
):
|
|
# Mock parsed arguments
|
|
mock_args = MagicMock()
|
|
mock_args.name = "test-server"
|
|
mock_args.transport = "stdio"
|
|
mock_args.allowed_paths = ["/test/path"]
|
|
mock_args.project_dir = "/test/project"
|
|
mock_args.install = False
|
|
mock_args.agent_model = None
|
|
mock_args.agent_max_tokens = None
|
|
mock_args.agent_api_key = None
|
|
mock_args.agent_base_url = None
|
|
mock_args.agent_max_iterations = 10
|
|
mock_args.agent_max_tool_uses = 30
|
|
mock_args.enable_agent_tool = False
|
|
mock_args.disable_write_tools = False
|
|
mock_args.disable_search_tools = True
|
|
mock_args.log_level = "INFO"
|
|
mock_args.host = "127.0.0.1"
|
|
mock_args.port = 3000
|
|
mock_args.project_paths = None
|
|
mock_args.command_timeout = "120s"
|
|
mock_args.dev = False
|
|
mock_args.force_shell = None
|
|
mock_args.daemon = False
|
|
mock_args.socket_path = "/tmp/hanzo-mcp.sock"
|
|
mock_args.max_connections = 100
|
|
mock_args.tool_timeout = None
|
|
mock_args.search_timeout = None
|
|
mock_args.find_timeout = None
|
|
mock_args.ast_timeout = None
|
|
mock_parse_args.return_value = mock_args
|
|
|
|
# Mock server instance
|
|
mock_server = MagicMock()
|
|
mock_server_class.return_value = mock_server
|
|
|
|
# Call main
|
|
main()
|
|
|
|
# Verify server was created with disable_search_tools=True
|
|
expected_paths = ["/test/path", "/test/project"]
|
|
mock_server_class.assert_called_once_with(
|
|
name="test-server",
|
|
allowed_paths=expected_paths,
|
|
project_paths=["/test/project"],
|
|
project_dir="/test/project",
|
|
agent_model=None,
|
|
agent_max_tokens=None,
|
|
agent_api_key=None,
|
|
agent_base_url=None,
|
|
agent_max_iterations=10,
|
|
agent_max_tool_uses=30,
|
|
enable_agent_tool=False,
|
|
command_timeout=120.0,
|
|
disable_write_tools=False,
|
|
disable_search_tools=True,
|
|
host=mock_args.host,
|
|
port=mock_args.port,
|
|
)
|
|
mock_server.run.assert_called_once_with(transport="stdio")
|
|
|
|
|
|
class TestInstallClaudeDesktopConfig:
|
|
"""Test the install_claude_desktop_config function."""
|
|
|
|
@pytest.fixture
|
|
def mock_platform(self, monkeypatch) -> Callable[[str], str]:
|
|
"""Mock the sys.platform value."""
|
|
original_platform = sys.platform
|
|
|
|
def _set_platform(plat):
|
|
monkeypatch.setattr(sys, "platform", plat)
|
|
return plat
|
|
|
|
yield _set_platform
|
|
|
|
# Restore original platform
|
|
monkeypatch.setattr(sys, "platform", original_platform)
|
|
|
|
def test_install_config_macos(
|
|
self, mock_platform: Callable[[str], str], tmp_path: Path
|
|
) -> None:
|
|
"""Test installing config on macOS."""
|
|
# Set platform to macOS
|
|
mock_platform("darwin")
|
|
|
|
# Mock home directory and config path
|
|
with (
|
|
patch("pathlib.Path.home", return_value=Path(tmp_path)),
|
|
patch("sys.executable", "/usr/bin/python3"),
|
|
patch("json.dump") as mock_json_dump,
|
|
patch("builtins.open", create=True) as mock_open,
|
|
patch("pathlib.Path.exists", return_value=False),
|
|
patch("pathlib.Path.mkdir") as mock_mkdir,
|
|
):
|
|
# Construct expected config path
|
|
config_dir = tmp_path / "Library" / "Application Support" / "Claude"
|
|
config_file = config_dir / "claude_desktop_config.json"
|
|
|
|
# Mock file opening
|
|
mock_file = MagicMock()
|
|
mock_open.return_value.__enter__.return_value = mock_file
|
|
|
|
# Call the install function
|
|
install_claude_desktop_config("test-server", allowed_paths=["/test/path"])
|
|
|
|
# Verify config directory was created
|
|
mock_mkdir.assert_called_once_with(parents=True, exist_ok=True)
|
|
|
|
# Verify file was opened correctly
|
|
mock_open.assert_called_once()
|
|
args, kwargs = mock_open.call_args
|
|
assert str(config_file) in str(args[0])
|
|
assert kwargs.get("mode") == "w"
|
|
# Note: The mode parameter is set via a positional argument, not a keyword
|
|
# so we're not checking it here
|
|
|
|
# Verify correct config was written
|
|
mock_json_dump.assert_called_once()
|
|
config_data = mock_json_dump.call_args[0][0]
|
|
assert "mcpServers" in config_data
|
|
assert "test-server" in config_data["mcpServers"]
|
|
assert (
|
|
"/usr/bin/python3"
|
|
in config_data["mcpServers"]["test-server"]["command"]
|
|
)
|
|
assert "--allow-path" in str(
|
|
config_data["mcpServers"]["test-server"]["args"]
|
|
)
|
|
assert "/test/path" in str(config_data["mcpServers"]["test-server"]["args"])
|
|
|
|
def test_install_config_windows(
|
|
self, mock_platform: Callable[[str], str], tmp_path: Path
|
|
) -> None:
|
|
"""Test installing config on Windows."""
|
|
# Set platform to Windows
|
|
mock_platform("win32")
|
|
|
|
# Mock environment variable
|
|
with (
|
|
patch.dict(os.environ, {"APPDATA": str(tmp_path)}),
|
|
patch("sys.executable", "C:\\Python\\python.exe"),
|
|
patch("json.dump") as mock_json_dump,
|
|
patch("builtins.open", create=True) as mock_open,
|
|
patch("pathlib.Path.exists", return_value=False),
|
|
patch("pathlib.Path.mkdir") as mock_mkdir,
|
|
):
|
|
# Construct expected config path
|
|
config_dir = Path(tmp_path) / "Claude"
|
|
config_file = config_dir / "claude_desktop_config.json"
|
|
|
|
# Mock file opening
|
|
mock_file = MagicMock()
|
|
mock_open.return_value.__enter__.return_value = mock_file
|
|
|
|
# Call the install function
|
|
install_claude_desktop_config("test-server")
|
|
|
|
# Verify config directory was created
|
|
mock_mkdir.assert_called_once_with(parents=True, exist_ok=True)
|
|
|
|
# Verify file was opened correctly
|
|
mock_open.assert_called_once()
|
|
args, kwargs = mock_open.call_args
|
|
assert str(config_file) in str(args[0])
|
|
|
|
# Verify correct config was written
|
|
mock_json_dump.assert_called_once()
|
|
config_data = mock_json_dump.call_args[0][0]
|
|
assert "mcpServers" in config_data
|
|
assert "test-server" in config_data["mcpServers"]
|
|
|
|
def test_install_config_merge_existing(
|
|
self, mock_platform: Callable[[str], str], tmp_path: Path
|
|
) -> None:
|
|
"""Test merging with existing config file."""
|
|
# Set platform to Linux
|
|
mock_platform("linux")
|
|
|
|
# Create a mock existing config
|
|
existing_config = {
|
|
"mcpServers": {
|
|
"existing-server": {
|
|
"command": "/usr/bin/python3",
|
|
"args": ["-m", "existing_module"],
|
|
}
|
|
},
|
|
"otherSetting": "value",
|
|
}
|
|
|
|
# Mock home directory and config path
|
|
with (
|
|
patch("pathlib.Path.home", return_value=Path(tmp_path)),
|
|
patch("sys.executable", "/usr/bin/python3"),
|
|
patch("json.dump") as mock_json_dump,
|
|
patch("json.load", return_value=existing_config),
|
|
patch("builtins.open", create=True) as mock_open,
|
|
patch("pathlib.Path.exists", return_value=True),
|
|
patch("pathlib.Path.mkdir") as mock_mkdir,
|
|
):
|
|
# Construct expected config path
|
|
config_dir = tmp_path / ".config" / "claude"
|
|
config_dir / "claude_desktop_config.json"
|
|
|
|
# Mock file opening
|
|
mock_file = MagicMock()
|
|
mock_open.return_value.__enter__.return_value = mock_file
|
|
|
|
# Call the install function
|
|
install_claude_desktop_config("test-server")
|
|
|
|
# Verify config directory was created
|
|
mock_mkdir.assert_called_once_with(parents=True, exist_ok=True)
|
|
|
|
# Verify file was opened correctly for reading and writing
|
|
assert mock_open.call_count == 2
|
|
|
|
# Verify correct config was written
|
|
mock_json_dump.assert_called_once()
|
|
config_data = mock_json_dump.call_args[0][0]
|
|
assert "mcpServers" in config_data
|
|
assert "existing-server" in config_data["mcpServers"]
|
|
assert "test-server" in config_data["mcpServers"]
|
|
assert "otherSetting" in config_data
|
|
|
|
def test_install_config_default_paths(
|
|
self, mock_platform: Callable[[str], str], tmp_path: Path
|
|
) -> None:
|
|
"""Test installing config with default allowed paths."""
|
|
# Set platform to macOS
|
|
mock_platform("darwin")
|
|
|
|
# Mock home directory and config path
|
|
with (
|
|
patch("pathlib.Path.home", return_value=Path(tmp_path)),
|
|
patch("sys.executable", "/usr/bin/python3"),
|
|
patch("json.dump") as mock_json_dump,
|
|
patch("builtins.open", create=True) as mock_open,
|
|
patch("pathlib.Path.exists", return_value=False),
|
|
patch("pathlib.Path.mkdir"),
|
|
):
|
|
# Mock file opening
|
|
mock_file = MagicMock()
|
|
mock_open.return_value.__enter__.return_value = mock_file
|
|
|
|
# Call the install function without specifying allowed_paths
|
|
install_claude_desktop_config("test-server")
|
|
|
|
# Verify correct config was written with home directory as allowed path
|
|
mock_json_dump.assert_called_once()
|
|
config_data = mock_json_dump.call_args[0][0]
|
|
server_args = config_data["mcpServers"]["test-server"]["args"]
|
|
|
|
# Verify home directory was added as an allowed path
|
|
assert "--allow-path" in server_args
|
|
home_path_index = server_args.index("--allow-path") + 1
|
|
assert str(tmp_path) in server_args[home_path_index]
|
|
|
|
# Verify --disable-write-tools flag is not present
|
|
assert "--disable-write-tools" not in server_args
|
|
|
|
def test_install_config_with_disable_write_tools(
|
|
self, mock_platform: Callable[[str], str], tmp_path: Path
|
|
) -> None:
|
|
"""Test installing config with disable_write_tools=True."""
|
|
# Set platform to macOS
|
|
mock_platform("darwin")
|
|
|
|
# Mock home directory and config path
|
|
with (
|
|
patch("pathlib.Path.home", return_value=Path(tmp_path)),
|
|
patch("sys.executable", "/usr/bin/python3"),
|
|
patch("json.dump") as mock_json_dump,
|
|
patch("builtins.open", create=True) as mock_open,
|
|
patch("pathlib.Path.exists", return_value=False),
|
|
patch("pathlib.Path.mkdir"),
|
|
):
|
|
# Mock file opening
|
|
mock_file = MagicMock()
|
|
mock_open.return_value.__enter__.return_value = mock_file
|
|
|
|
# Call the install function with disable_write_tools=True
|
|
install_claude_desktop_config(
|
|
"test-server", allowed_paths=["/test/path"], disable_write_tools=True
|
|
)
|
|
|
|
# Verify correct config was written
|
|
mock_json_dump.assert_called_once()
|
|
config_data = mock_json_dump.call_args[0][0]
|
|
server_args = config_data["mcpServers"]["test-server"]["args"]
|
|
|
|
# Verify allowed path was added
|
|
assert "--allow-path" in server_args
|
|
path_index = server_args.index("--allow-path") + 1
|
|
assert "/test/path" in server_args[path_index]
|
|
|
|
# Verify --disable-write-tools flag is present
|
|
assert "--disable-write-tools" in server_args
|
|
|
|
def test_install_config_with_disable_search_tools(
|
|
self, mock_platform: Callable[[str], str], tmp_path: Path
|
|
) -> None:
|
|
"""Test installing config with disable_search_tools=True."""
|
|
# Set platform to macOS
|
|
mock_platform("darwin")
|
|
|
|
# Mock home directory and config path
|
|
with (
|
|
patch("pathlib.Path.home", return_value=Path(tmp_path)),
|
|
patch("sys.executable", "/usr/bin/python3"),
|
|
patch("json.dump") as mock_json_dump,
|
|
patch("builtins.open", create=True) as mock_open,
|
|
patch("pathlib.Path.exists", return_value=False),
|
|
patch("pathlib.Path.mkdir"),
|
|
):
|
|
# Mock file opening
|
|
mock_file = MagicMock()
|
|
mock_open.return_value.__enter__.return_value = mock_file
|
|
|
|
# Call the install function with disable_search_tools=True
|
|
install_claude_desktop_config(
|
|
"test-server", allowed_paths=["/test/path"], disable_search_tools=True
|
|
)
|
|
|
|
# Verify correct config was written
|
|
mock_json_dump.assert_called_once()
|
|
config_data = mock_json_dump.call_args[0][0]
|
|
server_args = config_data["mcpServers"]["test-server"]["args"]
|
|
|
|
# Verify allowed path was added
|
|
assert "--allow-path" in server_args
|
|
path_index = server_args.index("--allow-path") + 1
|
|
assert "/test/path" in server_args[path_index]
|
|
|
|
# Verify --disable-search-tools flag is present
|
|
assert "--disable-search-tools" in server_args
|
|
|
|
def test_install_config_with_both_flags(
|
|
self, mock_platform: Callable[[str], str], tmp_path: Path
|
|
) -> None:
|
|
"""Test installing config with both disable_write_tools and disable_search_tools set to True."""
|
|
# Set platform to macOS
|
|
mock_platform("darwin")
|
|
|
|
# Mock home directory and config path
|
|
with (
|
|
patch("pathlib.Path.home", return_value=Path(tmp_path)),
|
|
patch("sys.executable", "/usr/bin/python3"),
|
|
patch("json.dump") as mock_json_dump,
|
|
patch("builtins.open", create=True) as mock_open,
|
|
patch("pathlib.Path.exists", return_value=False),
|
|
patch("pathlib.Path.mkdir"),
|
|
):
|
|
# Mock file opening
|
|
mock_file = MagicMock()
|
|
mock_open.return_value.__enter__.return_value = mock_file
|
|
|
|
# Call the install function with both flags set to True
|
|
install_claude_desktop_config(
|
|
"test-server",
|
|
allowed_paths=["/test/path"],
|
|
disable_write_tools=True,
|
|
disable_search_tools=True,
|
|
)
|
|
|
|
# Verify correct config was written
|
|
mock_json_dump.assert_called_once()
|
|
config_data = mock_json_dump.call_args[0][0]
|
|
server_args = config_data["mcpServers"]["test-server"]["args"]
|
|
|
|
# Verify allowed path was added
|
|
assert "--allow-path" in server_args
|
|
path_index = server_args.index("--allow-path") + 1
|
|
assert "/test/path" in server_args[path_index]
|
|
|
|
# Verify both flags are present
|
|
assert "--disable-write-tools" in server_args
|
|
assert "--disable-search-tools" in server_args
|