from app.core.config import get_settings def _headers(token: str | None = None, client_id: str = "test-mcp-client"): settings = get_settings() return { "X-Service-Token": token if token is not None else settings.mcp_hub_service_token, "X-Client-Id": client_id, } def test_operations_summary_requires_service_token(client): response = client.get( "/api/v1/integrations/mcp/operations-summary", headers=_headers(token="wrong") ) assert response.status_code == 401 def test_operations_summary_returns_metrics(client): response = client.get("/api/v1/integrations/mcp/operations-summary", headers=_headers()) assert response.status_code == 200 body = response.json() assert "metrics" in body assert body["metrics"]["available"] >= 0 def test_attention_vehicles_filters_by_severity(client): response = client.get( "/api/v1/integrations/mcp/attention-vehicles", params={"minimum_severity": "high", "limit": 50}, headers=_headers(), ) assert response.status_code == 200 rows = response.json() assert all(r["severity"] == "high" for r in rows) def test_attention_vehicles_respects_limit(client): response = client.get( "/api/v1/integrations/mcp/attention-vehicles", params={"minimum_severity": "low", "limit": 2}, headers=_headers(), ) assert response.status_code == 200 assert len(response.json()) <= 2 def test_vehicle_details_known_ref(client): response = client.get( "/api/v1/integrations/mcp/vehicles/MO-016", headers=_headers() ) assert response.status_code == 200 body = response.json() assert body["public_ref"] == "MO-016" assert "registration_number" not in body # narrow read-only view, not the full record def test_vehicle_details_unknown_ref_is_404(client): response = client.get( "/api/v1/integrations/mcp/vehicles/MO-999", headers=_headers() ) assert response.status_code == 404 def test_search_knowledge_grounded_and_respects_max_sources(client): response = client.post( "/api/v1/integrations/mcp/search-knowledge", json={"question": "What must I do when a vehicle returns with damage?", "max_sources": 1}, headers=_headers(), ) assert response.status_code == 200 body = response.json() assert body["evidence_state"] == "grounded" assert len(body["sources"]) == 1 def test_mcp_tool_requests_are_audited(client, ops_client): client.get("/api/v1/integrations/mcp/operations-summary", headers=_headers(client_id="probe-1")) events = ops_client.get("/api/v1/audit", params={"action": "mcp_tool_request"}).json() assert len(events) >= 1 assert events[0]["actor_type"] == "service" def test_no_write_endpoints_exist_under_mcp_namespace(client): for method, path in [ ("post", "/api/v1/integrations/mcp/vehicles/MO-016"), ("put", "/api/v1/integrations/mcp/vehicles/MO-016"), ("delete", "/api/v1/integrations/mcp/vehicles/MO-016"), ]: response = getattr(client, method)(path, headers=_headers()) assert response.status_code in (404, 405)