mcp
This commit is contained in:
12
scripts/mcp-server/tests/conftest.py
Normal file
12
scripts/mcp-server/tests/conftest.py
Normal file
@@ -0,0 +1,12 @@
|
||||
"""Test configuration for MCP server tests."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
PROJECT_ROOT = Path(__file__).resolve().parents[1]
|
||||
SRC = PROJECT_ROOT / "src"
|
||||
for path in (PROJECT_ROOT, SRC):
|
||||
if str(path) not in sys.path:
|
||||
sys.path.insert(0, str(path))
|
||||
13
scripts/mcp-server/tests/test_docs_sync.py
Normal file
13
scripts/mcp-server/tests/test_docs_sync.py
Normal file
@@ -0,0 +1,13 @@
|
||||
"""Docs sync tests."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from mcp_server.docs_sync import check_catalog_parity
|
||||
|
||||
|
||||
def test_docs_sync_runs() -> None:
|
||||
"""Docs sync returns structured result."""
|
||||
result = check_catalog_parity()
|
||||
assert "status" in result
|
||||
assert "missingInDocs" in result
|
||||
assert isinstance(result["missingInDocs"], list)
|
||||
25
scripts/mcp-server/tests/test_performance.py
Normal file
25
scripts/mcp-server/tests/test_performance.py
Normal file
@@ -0,0 +1,25 @@
|
||||
"""Performance tests for MCP server handlers."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import time
|
||||
|
||||
from mcp_server.server import handle_request
|
||||
|
||||
MAX_LATENCY_SECONDS = 2
|
||||
|
||||
|
||||
def test_list_tools_is_fast() -> None:
|
||||
"""ListTools responds under the latency target."""
|
||||
start = time.perf_counter()
|
||||
handle_request({"method": "listTools", "params": {}})
|
||||
duration = time.perf_counter() - start
|
||||
assert duration < MAX_LATENCY_SECONDS
|
||||
|
||||
|
||||
def test_invoke_tool_is_fast() -> None:
|
||||
"""InvokeTool responds under the latency target."""
|
||||
start = time.perf_counter()
|
||||
handle_request({"method": "invokeTool", "params": {"name": "show-constitution", "args": {}}})
|
||||
duration = time.perf_counter() - start
|
||||
assert duration < MAX_LATENCY_SECONDS
|
||||
56
scripts/mcp-server/tests/test_server.py
Normal file
56
scripts/mcp-server/tests/test_server.py
Normal file
@@ -0,0 +1,56 @@
|
||||
"""Server dispatch tests."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from mcp_server import server as server_module
|
||||
from mcp_server.server import handle_request
|
||||
|
||||
METHOD_NOT_FOUND = -32601
|
||||
|
||||
|
||||
def test_list_tools_round_trip() -> None:
|
||||
"""ListTools returns catalog entries."""
|
||||
response = handle_request({"method": "listTools", "params": {}})
|
||||
tools = response["result"]["tools"]
|
||||
assert isinstance(tools, list)
|
||||
assert any(entry["name"] == "show-constitution" for entry in tools)
|
||||
|
||||
|
||||
def test_invoke_tool_round_trip() -> None:
|
||||
"""InvokeTool returns standard shape."""
|
||||
response = handle_request(
|
||||
{"method": "invokeTool", "params": {"name": "show-constitution", "args": {}}}
|
||||
)
|
||||
result = response["result"]
|
||||
assert result["status"] in {"ok", "unsupported", "invalid_input"}
|
||||
assert "output" in result
|
||||
|
||||
|
||||
def test_sync_docs_response_shape() -> None:
|
||||
"""SyncDocs returns expected fields."""
|
||||
response = handle_request({"method": "syncDocs", "params": {}})
|
||||
result = response["result"]
|
||||
assert "status" in result
|
||||
assert "missingInDocs" in result
|
||||
|
||||
|
||||
def test_invalid_method() -> None:
|
||||
"""Unknown method yields error."""
|
||||
response = handle_request({"method": "unknown", "params": {}})
|
||||
assert "error" in response
|
||||
assert response["error"]["code"] == METHOD_NOT_FOUND
|
||||
|
||||
|
||||
def test_unavailable_service_returns_actions(monkeypatch) -> None:
|
||||
"""Invoke tool failure returns guidance."""
|
||||
|
||||
def boom(*_: object, **__: object) -> dict:
|
||||
raise RuntimeError("boom")
|
||||
|
||||
monkeypatch.setattr(server_module, "invoke_tool", boom)
|
||||
response = handle_request(
|
||||
{"method": "invokeTool", "params": {"name": "list-mcp-tasks", "args": {}}}
|
||||
)
|
||||
assert "result" in response
|
||||
assert response["result"]["status"] == "failed"
|
||||
assert "actions" in response["result"]
|
||||
31
scripts/mcp-server/tests/test_tools.py
Normal file
31
scripts/mcp-server/tests/test_tools.py
Normal file
@@ -0,0 +1,31 @@
|
||||
"""Tool registry tests."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from mcp_server import tools
|
||||
|
||||
MIN_TOOLS = 5
|
||||
|
||||
|
||||
def test_tool_catalog_has_minimum_tools() -> None:
|
||||
"""Catalog includes baseline tools."""
|
||||
catalog = tools.tool_catalog()
|
||||
assert len(catalog) >= MIN_TOOLS
|
||||
names = {tool.name for tool in catalog}
|
||||
assert "show-constitution" in names
|
||||
assert "list-playbooks" in names
|
||||
assert "show-reference" in names
|
||||
|
||||
|
||||
def test_invoke_tool_handles_unknown() -> None:
|
||||
"""Unknown tool returns unsupported guidance."""
|
||||
result = tools.invoke_tool("missing-tool", {})
|
||||
assert result["status"] == "unsupported"
|
||||
assert "listTools" in result["actions"][0]
|
||||
|
||||
|
||||
def test_list_tools_payload_shape() -> None:
|
||||
"""Payload includes tools key."""
|
||||
payload = tools.list_tools_payload()
|
||||
assert "tools" in payload
|
||||
assert all("name" in entry for entry in payload["tools"])
|
||||
Reference in New Issue
Block a user