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')

完整代码链接:https://github.com/modelcontextprotocol/quickstart-resources/blob/main/weather-server-python/weather.py

使用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
    """

具体流程如下:

  1. 客户端把问题发给大模型

  2. 大模型分析可用工具并决定调用哪些工具

  3. 客户端通过MCP服务器执行工具

  4. 执行结果回传大模型

  5. 大模型根据结果组织自然语言

  6. 将响应返给客户端进行展示

总结,MCP是应用与大模型之间交互的桥梁,想要自动生成测试用例,可以创建MCP Server,提供需求和代码给大模型进行分析,并要求它按照固定格式输出测试用例。当然前提是要有1个懂业务懂代码的大模型支持。随着AI技术发展,大模型迭代创新,想象中的大模型终有一天会照进现实。彼时我们编写测试工具,可能就是通过MCP来实现了,就像现在通过HTTP接口编写自动化一样。

参考资料:

https://pypi.org/project/mcp/

https://github.com/modelcontextprotocol/quickstart-resources/tree/main/weather-server-python

posted @ 2025-06-15 14:13  测试开发刚哥  阅读(200)  评论(0)    收藏  举报