diff --git a/agents/tools/opax_mcp_client.py b/agents/tools/opax_mcp_client.py index 550eae8..48955a6 100644 --- a/agents/tools/opax_mcp_client.py +++ b/agents/tools/opax_mcp_client.py @@ -14,7 +14,7 @@ import httpx import google.auth import google.auth.transport.requests -OPAX_MCP_URL = os.environ.get("MCP_SERVER_URL", "https://opax-mcp-zjbqp3prqq-uc.a.run.app") +OPAX_MCP_URL = os.environ.get("MCP_SERVER_URL", "https://opax-mcp-357036551735.us-central1.run.app") MCP_SECRET = os.environ.get("MCP_SECRET", "") @@ -44,22 +44,71 @@ def _headers() -> dict: def call_tool(tool: str, params: dict = None) -> dict: - """Kall eit opax-mcp tool. Returnerer {tool, result}.""" - resp = httpx.post( - f"{OPAX_MCP_URL}/tools/call", - headers=_headers(), - json={"tool": tool, "params": params or {}}, - timeout=30, - ) + """Kall eit tool på OPAX JSON-RPC MCP endepunktet.""" + endpoint = OPAX_MCP_URL.rstrip("/") + "/" + payload = { + "jsonrpc": "2.0", + "id": "opax-client-tools-call", + "method": "tools/call", + "params": { + "name": tool, + "arguments": params or {}, + }, + } + resp = httpx.post(endpoint, headers=_headers(), json=payload, timeout=30) resp.raise_for_status() - return resp.json() + json_resp = resp.json() + + if not isinstance(json_resp, dict): + raise RuntimeError("JSON-RPC response must be an object.") + + error = json_resp.get("error") + if error: + if isinstance(error, dict): + raise RuntimeError( + f"JSON-RPC error {error.get('code')}: {error.get('message')}" + ) + raise RuntimeError("JSON-RPC response contains an invalid error object.") + + if "result" not in json_resp: + raise RuntimeError("JSON-RPC response missing 'result' field.") + + return json_resp["result"] def list_tools() -> list: - """List alle tilgjengelige tools i opax-mcp.""" - resp = httpx.get(f"{OPAX_MCP_URL}/tools", headers=_headers(), timeout=10) + """List alle tilgjengelige tools frå OPAX JSON-RPC MCP endepunktet.""" + endpoint = OPAX_MCP_URL.rstrip("/") + "/" + payload = { + "jsonrpc": "2.0", + "id": "opax-client-tools-list", + "method": "tools/list", + "params": {}, + } + resp = httpx.post(endpoint, headers=_headers(), json=payload, timeout=10) resp.raise_for_status() - return resp.json().get("tools", []) + json_resp = resp.json() + + if not isinstance(json_resp, dict): + raise RuntimeError("JSON-RPC response must be an object.") + + error = json_resp.get("error") + if error: + if isinstance(error, dict): + raise RuntimeError( + f"JSON-RPC error {error.get('code')}: {error.get('message')}" + ) + raise RuntimeError("JSON-RPC response contains an invalid error object.") + + result = json_resp.get("result") + if not isinstance(result, dict): + raise RuntimeError("JSON-RPC response missing object 'result' field.") + + tools = result.get("tools") + if not isinstance(tools, list): + raise RuntimeError("JSON-RPC response missing 'result.tools' list.") + + return tools # --------------------------------------------------------------------------- diff --git a/opax-mcp/server.py b/opax-mcp/server.py index 559275d..30db979 100644 --- a/opax-mcp/server.py +++ b/opax-mcp/server.py @@ -91,7 +91,7 @@ WORKSPACE_ADMIN_USER = "chris.christiansen@vauco.no" # Emma-vm Ollama — direkte tilkobling OLLAMA_BASE_URL = os.environ.get("OLLAMA_BASE_URL", "http://34.13.238.133:11434") -EMMA_MODEL = os.environ.get("EMMA_MODEL", "gemma3:27b") +EMMA_MODEL = os.environ.get("EMMA_MODEL", "qwen2.5:7b") EMMA_FAST_MODEL = os.environ.get("EMMA_FAST_MODEL", "gemma3:4b") EMMA_LIGHT_MODEL = os.environ.get("EMMA_LIGHT_MODEL", "qwen2.5:3b") @@ -775,7 +775,7 @@ TOOLS = { ), # AI Agents "run_jason": (run_jason, "Kjør Jason-agenten med en prompt", {"type":"object","properties":{"prompt":{"type":"string"},"mode":{"type":"string"}},"required":["prompt"]}), - "run_emma": (run_emma, "Emma Vauger (gemma3:27b) — primær lokal AI", {"type":"object","properties":{"prompt":{"type":"string"}}}), + "run_emma": (run_emma, "Emma Vauger (qwen2.5:7b) — primær lokal AI", {"type":"object","properties":{"prompt":{"type":"string"}}}), # Local models — read-only discovery "list_emma_models": (