Skip to content

Commit 169fca4

Browse files
committed
test: add output schema test
1 parent 0e89cdb commit 169fca4

File tree

6 files changed

+70
-9
lines changed

6 files changed

+70
-9
lines changed

tests/strands/tools/mcp/test_mcp_agent_tool.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ def test_tool_spec_with_description(mcp_agent_tool, mock_mcp_tool):
4848
assert tool_spec["name"] == "test_tool"
4949
assert tool_spec["description"] == "A test tool"
5050
assert tool_spec["inputSchema"]["json"] == {"type": "object", "properties": {}}
51+
assert "outputSchema" not in tool_spec
5152

5253

5354
def test_tool_spec_without_description(mock_mcp_tool, mock_mcp_client):
@@ -69,6 +70,15 @@ def test_tool_spec_with_output_schema(mock_mcp_tool, mock_mcp_client):
6970
assert tool_spec["outputSchema"]["json"] == {"type": "object", "properties": {"result": {"type": "string"}}}
7071

7172

73+
def test_tool_spec_without_output_schema(mock_mcp_tool, mock_mcp_client):
74+
mock_mcp_tool.outputSchema = None
75+
76+
agent_tool = MCPAgentTool(mock_mcp_tool, mock_mcp_client)
77+
tool_spec = agent_tool.tool_spec
78+
79+
assert "outputSchema" not in tool_spec
80+
81+
7282
@pytest.mark.asyncio
7383
async def test_stream(mcp_agent_tool, mock_mcp_client, alist):
7484
tool_use = {"toolUseId": "test-123", "name": "test_tool", "input": {"param": "value"}}

tests_integ/mcp/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
"""MCP integration tests package."""

tests_integ/echo_server.py renamed to tests_integ/mcp/echo_server.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,15 @@
1515
$ python echo_server.py
1616
"""
1717

18-
from typing import Any, Dict
19-
2018
from mcp.server import FastMCP
19+
from pydantic import BaseModel
20+
21+
22+
class EchoResponse(BaseModel):
23+
"""Response model for echo with structured content."""
24+
25+
echoed: str
26+
message_length: int
2127

2228

2329
def start_echo_server():
@@ -37,8 +43,8 @@ def echo(to_echo: str) -> str:
3743

3844
# FastMCP automatically constructs structured output schema from method signature
3945
@mcp.tool(description="Echos response back with structured content", structured_output=True)
40-
def echo_with_structured_content(to_echo: str) -> Dict[str, Any]:
41-
return {"echoed": to_echo}
46+
def echo_with_structured_content(to_echo: str) -> EchoResponse:
47+
return EchoResponse(echoed=to_echo, message_length=len(to_echo))
4248

4349
mcp.run(transport="stdio")
4450

tests_integ/test_mcp_client.py renamed to tests_integ/mcp/test_mcp_client.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ def test_mcp_client():
7575

7676
sse_mcp_client = MCPClient(lambda: sse_client("http://127.0.0.1:8000/sse"))
7777
stdio_mcp_client = MCPClient(
78-
lambda: stdio_client(StdioServerParameters(command="python", args=["tests_integ/echo_server.py"]))
78+
lambda: stdio_client(StdioServerParameters(command="python", args=["tests_integ/mcp/echo_server.py"]))
7979
)
8080

8181
with sse_mcp_client, stdio_mcp_client:
@@ -161,7 +161,7 @@ def test_mcp_client():
161161

162162
def test_can_reuse_mcp_client():
163163
stdio_mcp_client = MCPClient(
164-
lambda: stdio_client(StdioServerParameters(command="python", args=["tests_integ/echo_server.py"]))
164+
lambda: stdio_client(StdioServerParameters(command="python", args=["tests_integ/mcp/echo_server.py"]))
165165
)
166166
with stdio_mcp_client:
167167
stdio_mcp_client.list_tools_sync()
@@ -184,7 +184,7 @@ async def test_mcp_client_async_structured_content():
184184
that appears in structuredContent field.
185185
"""
186186
stdio_mcp_client = MCPClient(
187-
lambda: stdio_client(StdioServerParameters(command="python", args=["tests_integ/echo_server.py"]))
187+
lambda: stdio_client(StdioServerParameters(command="python", args=["tests_integ/mcp/echo_server.py"]))
188188
)
189189

190190
with stdio_mcp_client:
@@ -212,7 +212,7 @@ async def test_mcp_client_async_structured_content():
212212
def test_mcp_client_without_structured_content():
213213
"""Test that MCP client works correctly when tools don't return structured content."""
214214
stdio_mcp_client = MCPClient(
215-
lambda: stdio_client(StdioServerParameters(command="python", args=["tests_integ/echo_server.py"]))
215+
lambda: stdio_client(StdioServerParameters(command="python", args=["tests_integ/mcp/echo_server.py"]))
216216
)
217217

218218
with stdio_mcp_client:

tests_integ/test_mcp_client_structured_content_with_hooks.py renamed to tests_integ/mcp/test_mcp_client_structured_content_with_hooks.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ def test_mcp_client_hooks_structured_content():
3737

3838
# Set up MCP client for echo server
3939
stdio_mcp_client = MCPClient(
40-
lambda: stdio_client(StdioServerParameters(command="python", args=["tests_integ/echo_server.py"]))
40+
lambda: stdio_client(StdioServerParameters(command="python", args=["tests_integ/mcp/echo_server.py"]))
4141
)
4242

4343
with stdio_mcp_client:
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
"""Integration test for MCP tools with output schema."""
2+
3+
from mcp import StdioServerParameters, stdio_client
4+
5+
from strands.tools.mcp.mcp_client import MCPClient
6+
7+
from .echo_server import EchoResponse
8+
9+
10+
def test_mcp_tool_output_schema():
11+
"""Test that MCP tools with output schema include it in tool spec."""
12+
stdio_mcp_client = MCPClient(
13+
lambda: stdio_client(StdioServerParameters(command="python", args=["tests_integ/mcp/echo_server.py"]))
14+
)
15+
16+
with stdio_mcp_client:
17+
tools = stdio_mcp_client.list_tools_sync()
18+
19+
# Find tools with and without output schema
20+
echo_tool = next(tool for tool in tools if tool.tool_name == "echo")
21+
structured_tool = next(tool for tool in tools if tool.tool_name == "echo_with_structured_content")
22+
23+
# Verify echo tool has no output schema
24+
echo_spec = echo_tool.tool_spec
25+
assert "outputSchema" not in echo_spec
26+
27+
# Verify structured tool has output schema
28+
structured_spec = structured_tool.tool_spec
29+
assert "outputSchema" in structured_spec
30+
31+
# Validate output schema matches expected structure
32+
expected_schema = {
33+
"description": "Response model for echo with structured content.",
34+
"properties": {
35+
"echoed": {"title": "Echoed", "type": "string"},
36+
"message_length": {"title": "Message Length", "type": "integer"},
37+
},
38+
"required": ["echoed", "message_length"],
39+
"title": "EchoResponse",
40+
"type": "object",
41+
}
42+
43+
assert structured_spec["outputSchema"]["json"] == expected_schema
44+
assert structured_spec["outputSchema"]["json"] == EchoResponse.model_json_schema()

0 commit comments

Comments
 (0)