Spaces:
Paused
Paused
| """End-to-end MCP wire tests over the mounted lipsync endpoint.""" | |
| import pytest | |
| from starlette.testclient import TestClient | |
| from papers_mcp import server | |
| from tests.conftest import CACHE_DIR, LIPSYNC_REPO | |
| MCP_HEADERS = { | |
| "Accept": "application/json, text/event-stream", | |
| "Content-Type": "application/json", | |
| } | |
| def rpc(method: str, params: dict) -> dict: | |
| return {"jsonrpc": "2.0", "id": 1, "method": method, "params": params} | |
| def client(monkeypatch_module, lipsync_corpus) -> TestClient: | |
| monkeypatch_module.setattr(server, "CORPORA", {"lipsync": LIPSYNC_REPO}) | |
| monkeypatch_module.setattr(server, "DATA_DIR", CACHE_DIR) | |
| app = server.create_app() | |
| with TestClient(app) as test_client: # runs lifespan: sync + load + index | |
| yield test_client | |
| def test_tools_are_listed(client: TestClient) -> None: | |
| resp = client.post("/lipsync/mcp", json=rpc("tools/list", {}), headers=MCP_HEADERS) | |
| assert resp.status_code == 200 | |
| tools = {t["name"] for t in resp.json()["result"]["tools"]} | |
| assert tools == {"search_papers", "get_paper", "get_citations", "list_recent"} | |
| def test_search_papers_tool(client: TestClient) -> None: | |
| resp = client.post( | |
| "/lipsync/mcp", | |
| json=rpc( | |
| "tools/call", | |
| {"name": "search_papers", "arguments": {"query": "latent diffusion lip sync SyncNet"}}, | |
| ), | |
| headers=MCP_HEADERS, | |
| ) | |
| text = resp.json()["result"]["content"][0]["text"] | |
| assert "2412.09262" in text | |
| def test_get_paper_tool(client: TestClient) -> None: | |
| resp = client.post( | |
| "/lipsync/mcp", | |
| json=rpc("tools/call", {"name": "get_paper", "arguments": {"paper_id": "2412.09262"}}), | |
| headers=MCP_HEADERS, | |
| ) | |
| text = resp.json()["result"]["content"][0]["text"] | |
| assert "LatentSync" in text and len(text) > 5000 | |
| def test_unknown_paper_id_is_an_error(client: TestClient) -> None: | |
| resp = client.post( | |
| "/lipsync/mcp", | |
| json=rpc("tools/call", {"name": "get_paper", "arguments": {"paper_id": "0000.00000"}}), | |
| headers=MCP_HEADERS, | |
| ) | |
| assert resp.json()["result"]["isError"] is True | |
| def test_blank_query_is_an_error(client: TestClient) -> None: | |
| resp = client.post( | |
| "/lipsync/mcp", | |
| json=rpc("tools/call", {"name": "search_papers", "arguments": {"query": " "}}), | |
| headers=MCP_HEADERS, | |
| ) | |
| assert resp.json()["result"]["isError"] is True | |
| def test_get_citations_tool(client: TestClient) -> None: | |
| resp = client.post( | |
| "/lipsync/mcp", | |
| json=rpc("tools/call", {"name": "get_citations", "arguments": {"paper_id": "2412.09262"}}), | |
| headers=MCP_HEADERS, | |
| ) | |
| text = resp.json()["result"]["content"][0]["text"] | |
| assert "Cites" in text and "Cited by" in text | |
| def test_list_recent_tool(client: TestClient) -> None: | |
| import re | |
| from datetime import date, timedelta | |
| resp = client.post( | |
| "/lipsync/mcp", | |
| json=rpc("tools/call", {"name": "list_recent", "arguments": {"days": 365}}), | |
| headers=MCP_HEADERS, | |
| ) | |
| text = resp.json()["result"]["content"][0]["text"] | |
| dates = re.findall(r", (\d{4}-\d{2}-\d{2})\)", text) | |
| assert len(dates) > 5 | |
| assert dates == sorted(dates, reverse=True) # newest first | |
| assert min(dates) >= (date.today() - timedelta(days=365)).isoformat() | |
| def test_list_recent_days_over_cap_is_an_error(client: TestClient) -> None: | |
| resp = client.post( | |
| "/lipsync/mcp", | |
| json=rpc("tools/call", {"name": "list_recent", "arguments": {"days": 366}}), | |
| headers=MCP_HEADERS, | |
| ) | |
| assert resp.json()["result"]["isError"] is True | |