""" Tests for the MCP config writer utility (write_mcp_config). """ import json import os import pytest from config import MCPConfig, MCPServerConfig, write_mcp_config # --------------------------------------------------------------------------- # Fixtures # --------------------------------------------------------------------------- @pytest.fixture def workspace(tmp_path): """Return a temporary workspace directory path.""" return str(tmp_path) @pytest.fixture def sample_mcp_config(): """Return an MCPConfig with one server entry.""" return MCPConfig( servers={ "my-tool": MCPServerConfig( command="npx", args=["-y", "@my/tool"], env={"API_KEY": "test123"}, ) } ) # --------------------------------------------------------------------------- # Tests: write_mcp_config # --------------------------------------------------------------------------- class TestWriteMcpConfig: def test_skips_when_no_servers(self, workspace): """Empty servers dict should not create any file.""" write_mcp_config(MCPConfig(), workspace, use_claude=True) assert not os.path.exists(os.path.join(workspace, ".mcp.json")) assert not os.path.exists(os.path.join(workspace, "opencode.json")) def test_writes_mcp_json_for_claude(self, workspace, sample_mcp_config): """Claude runtime should produce .mcp.json with 'mcpServers' key.""" write_mcp_config(sample_mcp_config, workspace, use_claude=True) path = os.path.join(workspace, ".mcp.json") assert os.path.isfile(path) with open(path, encoding="utf-8") as f: data = json.load(f) assert "mcpServers" in data assert "my-tool" in data["mcpServers"] srv = data["mcpServers"]["my-tool"] assert srv["command"] == "npx" assert srv["args"] == ["-y", "@my/tool"] assert srv["env"] == {"API_KEY": "test123"} def test_writes_opencode_json_for_opencode(self, workspace, sample_mcp_config): """OpenCode runtime should produce opencode.json with 'mcp' key.""" write_mcp_config(sample_mcp_config, workspace, use_claude=False) path = os.path.join(workspace, "opencode.json") assert os.path.isfile(path) with open(path, encoding="utf-8") as f: data = json.load(f) assert "mcp" in data assert "my-tool" in data["mcp"] def test_multiple_servers(self, workspace): """Multiple server entries should all appear in the output.""" cfg = MCPConfig( servers={ "server-a": MCPServerConfig(command="cmd-a", args=["--flag"]), "server-b": MCPServerConfig(command="cmd-b", env={"X": "1"}), } ) write_mcp_config(cfg, workspace, use_claude=True) with open(os.path.join(workspace, ".mcp.json"), encoding="utf-8") as f: data = json.load(f) assert len(data["mcpServers"]) == 2 assert "server-a" in data["mcpServers"] assert "server-b" in data["mcpServers"] def test_creates_parent_directories(self, tmp_path): """Should create intermediate directories if workspace doesn't exist.""" nested = str(tmp_path / "deep" / "nested" / "workspace") cfg = MCPConfig( servers={"s": MCPServerConfig(command="echo")} ) write_mcp_config(cfg, nested, use_claude=True) assert os.path.isfile(os.path.join(nested, ".mcp.json")) def test_produces_valid_json(self, workspace, sample_mcp_config): """Output file must be valid, parseable JSON.""" write_mcp_config(sample_mcp_config, workspace, use_claude=True) path = os.path.join(workspace, ".mcp.json") with open(path, encoding="utf-8") as f: data = json.load(f) # Would raise on invalid JSON assert isinstance(data, dict) def test_overwrites_existing_file(self, workspace): """Writing twice should overwrite the previous config.""" cfg1 = MCPConfig(servers={"old": MCPServerConfig(command="old-cmd")}) cfg2 = MCPConfig(servers={"new": MCPServerConfig(command="new-cmd")}) write_mcp_config(cfg1, workspace, use_claude=True) write_mcp_config(cfg2, workspace, use_claude=True) with open(os.path.join(workspace, ".mcp.json"), encoding="utf-8") as f: data = json.load(f) assert "new" in data["mcpServers"] assert "old" not in data["mcpServers"] def test_tilde_expansion(self, monkeypatch, tmp_path): """Workspace path with ~ should be expanded.""" monkeypatch.setenv("HOME", str(tmp_path)) # Also handle Windows monkeypatch.setattr(os.path, "expanduser", lambda p: p.replace("~", str(tmp_path))) cfg = MCPConfig(servers={"s": MCPServerConfig(command="echo")}) write_mcp_config(cfg, "~/my-workspace", use_claude=False) assert os.path.isfile(os.path.join(str(tmp_path), "my-workspace", "opencode.json"))