AI测试工具开发新姿势MCP Python SDK
简介
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接口编写自动化一样。
参考资料:
https://github.com/modelcontextprotocol/quickstart-resources/tree/main/weather-server-python
所有文章公众号【测试开发刚哥】首发!
版权申明:本文为博主原创文章,转载请保留原文链接及作者。