from pam_deploy_graph.mcp_client import ( FunctionMcpToolClient, load_mcp_client_config, SessionMcpToolClient, StdioMcpToolClient, normalize_mcp_sdk_result, ) from pam_deploy_graph.mcp_factory import build_mcp_runner_from_config def test_function_mcp_client_wraps_callable(): client = FunctionMcpToolClient(lambda name, args: {"tool": name, "args": args}) assert client.call_tool("pam_get_online_ips", {"airportCode": "HET"})["tool"] == "pam_get_online_ips" def test_normalize_mcp_sdk_result_structured_content(): result = type("Result", (), {"structuredContent": {"ok": True}})() assert normalize_mcp_sdk_result(result) == {"ok": True} def test_session_mcp_client_normalizes_text_json_content(): content = [type("Text", (), {"text": '{"ok": true}'})()] result = type("Result", (), {"content": content})() class Session: def call_tool(self, tool_name, arguments): return result client = SessionMcpToolClient(Session()) assert client.call_tool("tool", {}) == {"ok": True} def test_load_mcp_client_config(tmp_path): path = tmp_path / "mcp.json" path.write_text( ( '{"server_name": "pam-node-prod", "transport": "stdio", ' '"command": "python", "args": ["-m", "server"], ' '"env": {"PAM_ENV": "test"}, "cwd": "/tmp", "timeout_seconds": 3, ' '"tool_names": {"get-online-ips": "custom_ips"}}' ), encoding="utf-8", ) config = load_mcp_client_config(path) assert config.server_name == "pam-node-prod" assert config.transport == "stdio" assert config.command == "python" assert config.args == ["-m", "server"] assert config.env == {"PAM_ENV": "test"} assert config.cwd == "/tmp" assert config.timeout_seconds == 3 assert config.tool_names["get-online-ips"] == "custom_ips" def test_build_mcp_runner_from_stdio_config(tmp_path): path = tmp_path / "mcp.json" path.write_text( '{"transport": "stdio", "command": "python", "tool_names": {"verify-ip": "custom_verify"}}', encoding="utf-8", ) runner = build_mcp_runner_from_config(path) assert isinstance(runner.client, StdioMcpToolClient) assert runner.tool_names["verify-ip"] == "custom_verify"