mirror of
https://github.com/open-jarvis/OpenJarvis.git
synced 2026-07-30 02:42:16 +00:00
83 lines
3.1 KiB
Python
83 lines
3.1 KiB
Python
"""Matrix tests — verify every built-in tool is discoverable and callable via MCP."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import pytest
|
|
|
|
from openjarvis.mcp.client import MCPClient
|
|
from openjarvis.mcp.server import MCPServer
|
|
from openjarvis.mcp.transport import InProcessTransport
|
|
from openjarvis.tools.calculator import CalculatorTool
|
|
from openjarvis.tools.think import ThinkTool
|
|
|
|
# Tool configs: (tool_class, call_arguments, expected_substring)
|
|
_TOOL_CONFIGS = {
|
|
"calculator": (CalculatorTool, {"expression": "2+2"}, "4"),
|
|
"think": (ThinkTool, {"thought": "test thought"}, "test thought"),
|
|
}
|
|
|
|
|
|
def _make_client(tool_classes):
|
|
"""Create an MCP client with the given tool instances."""
|
|
tools = [cls() for cls in tool_classes]
|
|
server = MCPServer(tools)
|
|
transport = InProcessTransport(server)
|
|
return MCPClient(transport)
|
|
|
|
|
|
@pytest.mark.parametrize("tool_name", ["calculator", "think"])
|
|
class TestMCPToolsMatrix:
|
|
def test_tool_discoverable_via_mcp(self, tool_name):
|
|
tool_cls, _, _ = _TOOL_CONFIGS[tool_name]
|
|
client = _make_client([tool_cls])
|
|
tools = client.list_tools()
|
|
names = [t.name for t in tools]
|
|
assert tool_name in names
|
|
|
|
def test_tool_callable_via_mcp(self, tool_name):
|
|
tool_cls, arguments, expected = _TOOL_CONFIGS[tool_name]
|
|
client = _make_client([tool_cls])
|
|
result = client.call_tool(tool_name, arguments)
|
|
assert result["isError"] is False
|
|
assert expected in result["content"][0]["text"]
|
|
|
|
def test_tool_has_description(self, tool_name):
|
|
tool_cls, _, _ = _TOOL_CONFIGS[tool_name]
|
|
client = _make_client([tool_cls])
|
|
tools = client.list_tools()
|
|
tool_spec = next(t for t in tools if t.name == tool_name)
|
|
assert tool_spec.description # non-empty
|
|
|
|
def test_tool_has_input_schema(self, tool_name):
|
|
tool_cls, _, _ = _TOOL_CONFIGS[tool_name]
|
|
client = _make_client([tool_cls])
|
|
tools = client.list_tools()
|
|
tool_spec = next(t for t in tools if t.name == tool_name)
|
|
assert "properties" in tool_spec.parameters
|
|
|
|
def test_tool_result_format(self, tool_name):
|
|
tool_cls, arguments, _ = _TOOL_CONFIGS[tool_name]
|
|
client = _make_client([tool_cls])
|
|
result = client.call_tool(tool_name, arguments)
|
|
assert "content" in result
|
|
assert "isError" in result
|
|
assert isinstance(result["content"], list)
|
|
assert result["content"][0]["type"] == "text"
|
|
|
|
def test_tool_error_handling(self, tool_name):
|
|
"""Calling with bad args should not crash the server."""
|
|
tool_cls, _, _ = _TOOL_CONFIGS[tool_name]
|
|
client = _make_client([tool_cls])
|
|
# Call with empty arguments
|
|
result = client.call_tool(tool_name, {})
|
|
# Should return a response (not crash)
|
|
assert "content" in result
|
|
|
|
def test_tool_in_full_server(self, tool_name):
|
|
"""Tool should be discoverable when all tools are registered."""
|
|
all_classes = [cls for cls, _, _ in _TOOL_CONFIGS.values()]
|
|
client = _make_client(all_classes)
|
|
tools = client.list_tools()
|
|
names = [t.name for t in tools]
|
|
assert tool_name in names
|