M9: MCP Hub locale/correlation propagation, real Hub health check, fix stale test image
Fixed two concrete gaps in the MCP knowledge-search endpoint: no locale field existed at all (now nl-BE/en-GB/fr-BE, wired to the knowledge provider's existing language param), and the correlation ID was always freshly minted, ignoring any inbound X-Correlation-Id header. Added a shared dependency and applied it to all four MCP endpoints so Fleet Ops's own audit log preserves the Hub's real correlation ID end to end. MCP_HUB_BASE_URL/MCP_PROVIDER_ID were declared in .env.example but never read anywhere. Since the Hub's own registration is catalog-driven (it never needs Fleet Ops to push a registration call), wired mcp_hub_base_url for a real Hub reachability health check instead of an unneeded self-registration call. Renamed Fleet Ops's own internal audit tool labels mobilityops_* -> fleet_ops_* (mirrored in contracts/mcp-tools.json with mobilityops_* kept as deprecated aliases); documented that the live Hub connector's own dotted tool namespace is a separate, Hub-owned naming layer, deliberately not touched. Automation page's MCP card now shows real evidence (last tool/client/count/ timestamp, honest no-evidence state) instead of just the registration flag. Also fixed a real methodology gap found mid-session: compose.yaml's api service has no bind mount, so `docker compose run --rm api` silently tests a stale image until rebuilt. Re-ran every local gate after rebuilding; fixed one genuinely stale test assertion and two lint line-length errors surfaced by that rebuild. 176 tests passing, ruff clean, mypy clean (50 files). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
2ae2044e3a
commit
727c19a779
@@ -81,6 +81,48 @@ def test_mcp_tool_requests_are_audited(client, ops_client):
|
||||
assert events[0]["actor_type"] == "service"
|
||||
|
||||
|
||||
def test_search_knowledge_respects_requested_locale(client):
|
||||
response = client.post(
|
||||
"/api/v1/integrations/mcp/search-knowledge",
|
||||
json={
|
||||
"question": "Wat moet ik doen wanneer een voertuig beschadigd terugkomt?",
|
||||
"max_sources": 1,
|
||||
"locale": "nl-BE",
|
||||
},
|
||||
headers=_headers(),
|
||||
)
|
||||
assert response.status_code == 200
|
||||
body = response.json()
|
||||
assert body["evidence_state"] == "grounded"
|
||||
|
||||
|
||||
def test_search_knowledge_preserves_inbound_correlation_id(client, ops_client):
|
||||
inbound = "11111111-1111-1111-1111-111111111111"
|
||||
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(client_id="correlation-probe"), "X-Correlation-Id": inbound},
|
||||
)
|
||||
assert response.status_code == 200
|
||||
assert response.json()["correlation_id"] == inbound
|
||||
|
||||
events = ops_client.get("/api/v1/audit", params={"action": "mcp_tool_request"}).json()
|
||||
matching = [e for e in events if e["correlation_id"] == inbound]
|
||||
assert len(matching) == 1
|
||||
|
||||
|
||||
def test_operations_summary_mints_correlation_id_when_none_supplied(client, ops_client):
|
||||
response = client.get(
|
||||
"/api/v1/integrations/mcp/operations-summary",
|
||||
headers=_headers(client_id="no-correlation-probe"),
|
||||
)
|
||||
assert response.status_code == 200
|
||||
events = ops_client.get("/api/v1/audit", params={"action": "mcp_tool_request"}).json()
|
||||
matching = [e for e in events if e["actor_label"] == "no-correlation-probe"]
|
||||
assert len(matching) >= 1
|
||||
assert matching[0]["correlation_id"] # a fresh UUID was minted, not left empty
|
||||
|
||||
|
||||
def test_no_write_endpoints_exist_under_mcp_namespace(client):
|
||||
for method, path in [
|
||||
("post", "/api/v1/integrations/mcp/vehicles/MO-016"),
|
||||
|
||||
Reference in New Issue
Block a user