AI测试工具开发新姿势MCP Python SDK¶

PythonSDK¶

简介¶
MCP是什么?通俗易懂地讲,在互联网时代,应用程序是通过HTTP来交互的,而来到AI时代,大模型可以通过MCP来进行交互。MCP是Model Context Protocol缩写,专为大模型(LLM,Large Language Model)设计的大模型上下文协议。
MCP Server是什么?MCP Server就像网关之于应用程序,数据库连接池之于数据库,位于中间位置,接收请求,调用大模型。可以调用Server进行业务开发,也可以自建Server实现特定功能。
MCP Python SDK是什么?MCP的Python实现,它包含以下功能(官方原文):
Build MCP clients that can connect to any MCP server
Create MCP servers that expose resources, prompts and tools
Use standard transports like stdio, SSE, and Streamable HTTP
Handle all MCP protocol messages and lifecycle events
安装¶
推荐使用uv工具来管理Python项目。
安装3.10以上版本Python:
uv python install 3.10
创建示例项目:
uv init mcp-server-demo
cd mcp-server-demo
创建虚拟环境:
uv venv
### 如果当前不是默认Python3.10,需指定版本
uv venv --python 3.10
执行后会提示:
Creating virtual environment at: .venv
Activate with: source .venv/bin/activate
激活:
source .venv/bin/activate
安装MCP Python SDK:
uv add "mcp[cli]"
快速入门¶
### server.py
from mcp.server.fastmcp import FastMCP
### Create an MCP server
mcp = FastMCP("server")
### Add a dynamic greting resource
@mcp.resource("greeting://{name}")
def get_greeting(name: str) -> str:
"""Get a personalized greeting"""
return f"Hello, {name}!"
### Add an addition tool
@mcp.tool()
def add(a: int, b: int) -> int:
"""Add two numbers"""
return a + b
@mcp.prompt()
def review_code(code: str) -> str:
return f"Please review this code:\n\n{code}"
if __name__ == "__main__":
# Initialize and run the server
mcp.run(transport='stdio')
这里创建了1个简单的Mock Server,它定义了3个函数,在进行一些配置后,使用自然语言向大模型提问,大模型就会调用相应的函数获取结果:
@mcp.resource,相当于GET,加载信息到大模型上下文
@mcp.tool,相当于POST,执行某些操作
@mcp.prompt,提示词,大模型交互的模版
如果想要调试,执行命令mcp dev server.py,打开自带Inspector在Web浏览器进行调试。
如果想要大模型响应,需要在大模型的配置文件中配置,配置文件通常为JSON:
{
"mcpServers": {
"server": {
"command": "uv",
"args": [
"--directory",
"/ABSOLUTE/PATH/TO/PARENT/FOLDER/weather",
"run",
"server.py"
]
}
}
}
配置好以后,给大模型提问,比如:“使用server打个招呼吧,我的名字是Gang”。大模型的回答是:
用户要求使用MCP服务器"server"来打招呼,名字是"Gang"
查看已连接的MCP服务器,发现"server"服务器提供了一个"greeting"资源模板
需要获取这个资源并传入用户名参数
使用get_mcp_resource工具,指定server_name为"server",uri为"greeting://Gang"
想要在 server MCP 服务器上访问一个资源:
greeting://Gang
get_greeting: Get a personalized greeting
返回值 未知类型
响应
Hello, Gang!
已使用server MCP服务器完成打招呼任务,返回的问候语是:"Hello, Gang!"
这个回答有点啰嗦,继续对话:“不要中间这些描述,直接返回结果”
Hello, Gang!
在实际应用时,也是需要优化对话来让大模型按照我们预期输出结果。
示例¶
基于MCP Server实现天气服务器:
### weather.py
from typing import Any
import httpx
from mcp.server.fastmcp import FastMCP
### Initialize FastMCP server
mcp = FastMCP("weather")
### Constants
NWS_API_BASE = "https://api.weather.gov"
USER_AGENT = "weather-app/1.0"
从国家气象局获取天气数据并格式化:
async def make_nws_request(url: str) -> dict[str, Any] | None:
"""Make a request to the NWS API with proper error handling."""
headers = {
"User-Agent": USER_AGENT,
"Accept": "application/geo+json"
}
async with httpx.AsyncClient() as client:
try:
response = await client.get(url, headers=headers, timeout=30.0)
response.raise_for_status()
return response.json()
except Exception:
return None
def format_alert(feature: dict) -> str:
"""Format an alert feature into a readable string."""
props = feature["properties"]
return f"""
Event: {props.get('event', 'Unknown')}
Area: {props.get('areaDesc', 'Unknown')}
Severity: {props.get('severity', 'Unknown')}
Description: {props.get('description', 'No description available')}
Instructions: {props.get('instruction', 'No specific instructions provided')}
"""
实现工具:
@mcp.tool()
async def get_alerts(state: str) -> str:
"""Get weather alerts for a US state.
Args:
state: Two-letter US state code (e.g. CA, NY)
"""
url = f"{NWS_API_BASE}/alerts/active/area/{state}"
data = await make_nws_request(url)
if not data or "features" not in data:
return "Unable to fetch alerts or no alerts found."
if not data["features"]:
return "No active alerts for this state."
alerts = [format_alert(feature) for feature in data["features"]]
return "\n---\n".join(alerts)
@mcp.tool()
async def get_forecast(latitude: float, longitude: float) -> str:
"""Get weather forecast for a location.
Args:
latitude: Latitude of the location
longitude: Longitude of the location
"""
# First get the forecast grid endpoint
points_url = f"{NWS_API_BASE}/points/{latitude},{longitude}"
points_data = await make_nws_request(points_url)
if not points_data:
return "Unable to fetch forecast data for this location."
# Get the forecast URL from the points response
forecast_url = points_data["properties"]["forecast"]
forecast_data = await make_nws_request(forecast_url)
if not forecast_data:
return "Unable to fetch detailed forecast."
# Format the periods into a readable forecast
periods = forecast_data["properties"]["periods"]
forecasts = []
for period in periods[:5]: # Only show next 5 periods
forecast = f"""
{period['name']}:
Temperature: {period['temperature']}°{period['temperatureUnit']}
Wind: {period['windSpeed']} {period['windDirection']}
Forecast: {period['detailedForecast']}
"""
forecasts.append(forecast)
return "\n---\n".join(forecasts)
编写启动服务代码:
if __name__ == "__main__":
# Initialize and run the server
mcp.run(transport='stdio')
使用uv run weather.py运行,此时看不到任何效果,没有报错即可。
接下来需要找个大模型,比如Claude桌面版,在配置文件中添加:
~/Library/Application Support/Claude/claude_desktop_config.json
{
"mcpServers": {
"weather": {
"command": "uv",
"args": [
"--directory",
"/ABSOLUTE/PATH/TO/PARENT/FOLDER/weather",
"run",
"weather.py"
]
}
}
}
FastMCP能通过Python类型注解(Type Hints)和文档字符串(Docstrings)自动生成工具定义,所以向大模型提问:What’s the weather in New York tomorrow?(因为这个示例对接的是美国国家气象局服务,只能问美国天气),它就能知道你想问天气,然后根据函数的文档字符串,找到相应的工具:
@mcp.tool()
async def get_alerts(state: str) -> str:
"""Get weather alerts for a US state.
Args:
state: Two-letter US state code (e.g. CA, NY)
"""
@mcp.tool()
async def get_forecast(latitude: float, longitude: float) -> str:
"""Get weather forecast for a location.
Args:
latitude: Latitude of the location
longitude: Longitude of the location
"""
具体流程如下:
客户端把问题发给大模型
大模型分析可用工具并决定调用哪些工具
客户端通过MCP服务器执行工具
执行结果回传大模型
大模型根据结果组织自然语言
将响应返给客户端进行展示
总结,MCP是应用与大模型之间交互的桥梁,想要自动生成测试用例,可以创建MCP Server,提供需求和代码给大模型进行分析,并要求它按照固定格式输出测试用例。当然前提是要有1个懂业务懂代码的大模型支持。随着AI技术发展,大模型迭代创新,想象中的大模型终有一天会照进现实。彼时我们编写测试工具,可能就是通过MCP来实现了,就像现在通过HTTP接口编写自动化一样。