|
5 | 5 | well-typed, validated data that clients can easily process. |
6 | 6 | """ |
7 | 7 |
|
| 8 | +import asyncio |
| 9 | +import json |
| 10 | +import sys |
8 | 11 | from dataclasses import dataclass |
9 | 12 | from datetime import datetime |
10 | 13 | from typing import TypedDict |
11 | 14 |
|
12 | 15 | from pydantic import BaseModel, Field |
13 | 16 |
|
14 | 17 | from mcp.server.fastmcp import FastMCP |
| 18 | +from mcp.shared.memory import create_connected_server_and_client_session as client_session |
15 | 19 |
|
16 | 20 | # Create server |
17 | 21 | mcp = FastMCP("Weather Service") |
@@ -147,27 +151,75 @@ def get_weather_stats(city: str, days: int = 7) -> WeatherStats: |
147 | 151 |
|
148 | 152 |
|
149 | 153 | if __name__ == "__main__": |
150 | | - # For testing individual tools |
151 | | - import asyncio |
152 | 154 |
|
153 | | - async def test(): |
154 | | - # Test the tools |
155 | | - weather = get_weather("London") |
156 | | - print(f"Weather in London: {weather.model_dump_json(indent=2)}") |
157 | | - |
158 | | - summary = get_weather_summary("Paris") |
159 | | - print(f"\nWeather summary for Paris: {summary}") |
160 | | - |
161 | | - metrics = get_weather_metrics(["Tokyo", "Sydney", "Mumbai"]) |
162 | | - print(f"\nWeather metrics: {metrics}") |
163 | | - |
164 | | - alerts = get_weather_alerts("California") |
165 | | - print(f"\nWeather alerts: {len(alerts)} alerts found") |
166 | | - |
167 | | - temp = get_temperature("Berlin", "fahrenheit") |
168 | | - print(f"\nTemperature in Berlin: {temp}°F") |
169 | | - |
170 | | - stats = get_weather_stats("Seattle", 30) |
171 | | - print(f"\nWeather stats for Seattle: {stats.model_dump_json(indent=2)}") |
172 | | - |
173 | | - asyncio.run(test()) |
| 155 | + async def test() -> None: |
| 156 | + """Test the tools by calling them through the server as a client would""" |
| 157 | + print("Testing Weather Service Tools (via MCP protocol)\n") |
| 158 | + print("=" * 80) |
| 159 | + |
| 160 | + async with client_session(mcp._mcp_server) as client: |
| 161 | + # Test get_weather |
| 162 | + result = await client.call_tool("get_weather", {"city": "London"}) |
| 163 | + print("\nWeather in London:") |
| 164 | + print(json.dumps(result.structuredContent, indent=2)) |
| 165 | + |
| 166 | + # Test get_weather_summary |
| 167 | + result = await client.call_tool("get_weather_summary", {"city": "Paris"}) |
| 168 | + print("\nWeather summary for Paris:") |
| 169 | + print(json.dumps(result.structuredContent, indent=2)) |
| 170 | + |
| 171 | + # Test get_weather_metrics |
| 172 | + result = await client.call_tool("get_weather_metrics", {"cities": ["Tokyo", "Sydney", "Mumbai"]}) |
| 173 | + print("\nWeather metrics:") |
| 174 | + print(json.dumps(result.structuredContent, indent=2)) |
| 175 | + |
| 176 | + # Test get_weather_alerts |
| 177 | + result = await client.call_tool("get_weather_alerts", {"region": "California"}) |
| 178 | + print("\nWeather alerts for California:") |
| 179 | + print(json.dumps(result.structuredContent, indent=2)) |
| 180 | + |
| 181 | + # Test get_temperature |
| 182 | + result = await client.call_tool("get_temperature", {"city": "Berlin", "unit": "fahrenheit"}) |
| 183 | + print("\nTemperature in Berlin:") |
| 184 | + print(json.dumps(result.structuredContent, indent=2)) |
| 185 | + |
| 186 | + # Test get_weather_stats |
| 187 | + result = await client.call_tool("get_weather_stats", {"city": "Seattle", "days": 30}) |
| 188 | + print("\nWeather stats for Seattle (30 days):") |
| 189 | + print(json.dumps(result.structuredContent, indent=2)) |
| 190 | + |
| 191 | + # Also show the text content for comparison |
| 192 | + print("\nText content for last result:") |
| 193 | + for content in result.content: |
| 194 | + if content.type == "text": |
| 195 | + print(content.text) |
| 196 | + |
| 197 | + async def print_schemas() -> None: |
| 198 | + """Print all tool schemas""" |
| 199 | + print("Tool Schemas for Weather Service\n") |
| 200 | + print("=" * 80) |
| 201 | + |
| 202 | + tools = await mcp.list_tools() |
| 203 | + for tool in tools: |
| 204 | + print(f"\nTool: {tool.name}") |
| 205 | + print(f"Description: {tool.description}") |
| 206 | + print("Input Schema:") |
| 207 | + print(json.dumps(tool.inputSchema, indent=2)) |
| 208 | + |
| 209 | + if tool.outputSchema: |
| 210 | + print("Output Schema:") |
| 211 | + print(json.dumps(tool.outputSchema, indent=2)) |
| 212 | + else: |
| 213 | + print("Output Schema: None (returns unstructured content)") |
| 214 | + |
| 215 | + print("-" * 80) |
| 216 | + |
| 217 | + # Check command line arguments |
| 218 | + if len(sys.argv) > 1 and sys.argv[1] == "--schemas": |
| 219 | + asyncio.run(print_schemas()) |
| 220 | + else: |
| 221 | + print("Usage:") |
| 222 | + print(" python weather_structured.py # Run tool tests") |
| 223 | + print(" python weather_structured.py --schemas # Print tool schemas") |
| 224 | + print() |
| 225 | + asyncio.run(test()) |
0 commit comments