Skip to main content
Glama
test_output_schema.py7.38 kB
""" 测试 outputSchema 功能 验证所有工具是否正确支持 outputSchema 和结构化输出。 """ import pytest import asyncio import json from mcp import ClientSession from mcp.client.stdio import stdio_client, StdioServerParameters from pathlib import Path @pytest.fixture async def mcp_client(): """创建 MCP 客户端用于测试""" server_script = Path(__file__).parent.parent / "run.py" server_params = StdioServerParameters( command="python", args=[str(server_script)], ) async with stdio_client(server_params) as (read, write): async with ClientSession(read, write) as session: await session.initialize() yield session @pytest.mark.asyncio async def test_tools_have_output_schema(mcp_client): """测试工具是否包含 outputSchema""" tools_response = await mcp_client.list_tools() # 查找几个关键工具 tool_names = [tool.name for tool in tools_response.tools] # 验证关键工具存在 assert "add" in tool_names assert "calculate_bmi" in tool_names assert "count_words" in tool_names assert "list_directory" in tool_names # 验证工具包含 outputSchema for tool in tools_response.tools: if tool.name in ["add", "calculate_bmi", "count_words", "list_directory"]: assert hasattr(tool, 'outputSchema'), f"Tool {tool.name} should have outputSchema" assert tool.outputSchema is not None, f"Tool {tool.name} outputSchema should not be None" assert tool.outputSchema.get("type") == "object", f"Tool {tool.name} outputSchema should be object type" @pytest.mark.asyncio async def test_calculator_output_schema(mcp_client): """测试计算器工具的 outputSchema""" tools_response = await mcp_client.list_tools() # 测试 add 工具 add_tool = next((t for t in tools_response.tools if t.name == "add"), None) assert add_tool is not None assert add_tool.outputSchema is not None # 验证 outputSchema 结构 schema = add_tool.outputSchema assert schema["type"] == "object" properties = schema.get("properties", {}) # 验证必需字段 assert "success" in properties assert "timestamp" in properties assert "result" in properties assert "expression" in properties assert "operation" in properties @pytest.mark.asyncio async def test_bmi_output_schema(mcp_client): """测试 BMI 工具的 outputSchema""" tools_response = await mcp_client.list_tools() bmi_tool = next((t for t in tools_response.tools if t.name == "calculate_bmi"), None) assert bmi_tool is not None assert bmi_tool.outputSchema is not None # 验证 outputSchema 结构 schema = bmi_tool.outputSchema properties = schema.get("properties", {}) # 验证 BMI 特定字段 assert "bmi" in properties assert "category" in properties assert "weight_kg" in properties assert "height_m" in properties @pytest.mark.asyncio async def test_text_analysis_output_schema(mcp_client): """测试文本分析工具的 outputSchema""" tools_response = await mcp_client.list_tools() count_words_tool = next((t for t in tools_response.tools if t.name == "count_words"), None) assert count_words_tool is not None assert count_words_tool.outputSchema is not None # 验证 outputSchema 结构 schema = count_words_tool.outputSchema properties = schema.get("properties", {}) # 验证文本分析字段 assert "words" in properties assert "characters" in properties assert "characters_no_spaces" in properties assert "lines" in properties @pytest.mark.asyncio async def test_structured_output_response(mcp_client): """测试工具调用返回结构化输出""" # 测试计算器工具 result = await mcp_client.call_tool("add", {"a": 5, "b": 3}) # 验证返回结果包含结构化内容 assert hasattr(result, 'content'), "Result should have content" assert len(result.content) > 0, "Result should have content items" # 如果支持结构化内容,验证其存在 if hasattr(result, 'structuredContent'): structured = result.structuredContent assert structured["success"] is True assert structured["result"] == 8.0 assert "expression" in structured assert "operation" in structured @pytest.mark.asyncio async def test_bmi_structured_output(mcp_client): """测试 BMI 工具的结构化输出""" result = await mcp_client.call_tool("calculate_bmi", { "weight_kg": 70, "height_m": 1.75 }) # 验证返回结果 assert hasattr(result, 'content') assert len(result.content) > 0 # 验证结构化内容(如果支持) if hasattr(result, 'structuredContent'): structured = result.structuredContent assert structured["success"] is True assert "bmi" in structured assert "category" in structured assert structured["weight_kg"] == 70 assert structured["height_m"] == 1.75 # 验证 BMI 计算正确 expected_bmi = 70 / (1.75 ** 2) assert abs(structured["bmi"] - round(expected_bmi, 2)) < 0.01 @pytest.mark.asyncio async def test_text_analysis_structured_output(mcp_client): """测试文本分析的结构化输出""" test_text = "Hello world!\nThis is a test." result = await mcp_client.call_tool("count_words", {"text": test_text}) # 验证返回结果 assert hasattr(result, 'content') # 验证结构化内容(如果支持) if hasattr(result, 'structuredContent'): structured = result.structuredContent assert structured["success"] is True assert structured["words"] == 5 # "Hello", "world!", "This", "is", "a", "test." assert structured["characters"] == len(test_text) assert structured["lines"] == 2 @pytest.mark.asyncio async def test_error_handling_with_structured_output(mcp_client): """测试错误处理是否保持结构化输出兼容""" try: # 测试除零错误 result = await mcp_client.call_tool("divide", {"a": 5, "b": 0}) # 如果没有抛出异常,检查错误是否在结果中 if hasattr(result, 'isError'): assert result.isError is True except Exception as e: # 验证错误被正确抛出 assert "Cannot divide by zero" in str(e) @pytest.mark.asyncio async def test_backward_compatibility(mcp_client): """测试向后兼容性 - 确保现有客户端仍能正常工作""" # 调用工具并验证基本响应格式 result = await mcp_client.call_tool("add", {"a": 10, "b": 20}) # 验证基本响应结构(向后兼容) assert hasattr(result, 'content') assert len(result.content) > 0 # 验证 content 包含文本表示 content_text = result.content[0].text if hasattr(result.content[0], 'text') else str(result.content[0]) assert content_text is not None assert len(content_text) > 0 if __name__ == "__main__": # 运行简单的同步测试 print("Running outputSchema tests...") # 这里可以添加一些简单的验证逻辑 print("✅ Test file created successfully") print("Run with: pytest tests/test_output_schema.py -v")

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/WW-AI-Lab/Awesome-MCP-Scaffold'

If you have feedback or need assistance with the MCP directory API, please join our Discord server