"""Smoke tests du serveur MCP (sans transport réseau). On vérifie que : - build_server() ne lève pas - tous les outils LangChain sont bien enregistrés côté MCP - un call_tool fonctionne et renvoie le contenu structuré attendu """ from __future__ import annotations import asyncio import httpx import pytest import respx from jdm_agent.client import JDMClient from jdm_agent.client.cache import DiskJSONCache from jdm_agent.tools.jdm_tools import ALL_TOOLS, set_default_client BASE = "https://jdm-api.demo.lirmm.fr" @pytest.fixture def mcp_with_mocks(tmp_path): """Construit le serveur MCP avec un JDMClient mocké.""" pytest.importorskip("fastmcp") from jdm_agent.mcp.server import build_server client = JDMClient(base_url=BASE, cache=DiskJSONCache(cache_dir=tmp_path / "cache")) set_default_client(client) server = build_server(client=client) return server def test_build_server_registers_all_tools(mcp_with_mocks): server = mcp_with_mocks tools = asyncio.run(server.list_tools()) names = {t.name for t in tools} expected = {t.name for t in ALL_TOOLS} assert expected.issubset(names), f"manquants: {expected - names}" def test_mcp_call_tool_returns_triplets(mcp_with_mocks): """call_tool('get_synonyms') exécute la vraie fonction et renvoie ses résultats.""" server = mcp_with_mocks with respx.mock(base_url=BASE) as mock: mock.get("/v0/relations_types").mock(return_value=httpx.Response(200, json=[ {"id": 5, "name": "r_syn", "help": "synonymes"}, ])) mock.get("/v0/nodes_types").mock(return_value=httpx.Response(200, json=[ {"id": 1, "name": "n_generic", "help": ""}, ])) mock.get("/v0/relations/from/chat").mock(return_value=httpx.Response(200, json={ "nodes": [ {"id": 150, "name": "chat", "type": 1, "w": 7967}, {"id": 999, "name": "matou", "type": 1, "w": 100}, ], "relations": [{"id": 1, "node1": 150, "node2": 999, "type": 5, "w": 80.0}], })) result = asyncio.run(server.call_tool( "get_synonyms", {"term": "chat", "min_weight": 0, "limit": 5} )) payload = result.structured_content["result"] assert any(t["target"] == "matou" and t["relation"] == "r_syn" for t in payload)