MCP服务开发及测试(Python)

前言

这个示例,目标是带你从零完成下面几件事:

  • 用 uv 管理 Python 依赖和虚拟环境
  • 使用 FastMCP 编写一个最小的 MCP 服务(SSE 传输)
  • 实现一个简单工具:根据科目获取知识点列表
  • 用官方 mcp SDK 写一个最小客户端脚本,通过 SSE 调用这个工具

看完本教程,你应该能够:

  • 理解一个最小 MCP 服务端的代码结构;
  • 知道如何启动 SSE 模式的 MCP 服务;
  • 知道如何在客户端侧通过 SSE 调用 MCP 工具;
  • 在此基础上,自行增加更多科目或更多工具函数。

项目结构

项目主要由三部分组成:

  • 项目配置与依赖pyproject.toml
  • MCP 服务端代码ques_mcp/server.py
  • MCP 客户端测试代码test_client.py

你可以把它理解为:

  • pyproject.toml:告诉 uv 要装哪些包;
  • ques_mcp/server.py:真正对外提供 MCP 能力的“服务器”;
  • test_client.py:一个最小的“学生端”,用来验证服务器是否工作正常。

项目配置

示例使用 uv 管理依赖和虚拟环境,核心配置位于 pyproject.toml,关键内容示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[project]
name = "ques-mcp"
version = "0.1.0"
description = "基于 FastMCP 的试题知识点列表 MCP SSE 服务"
requires-python = ">=3.10"

dependencies = [
"fastmcp>=0.4.0",
]

[project.optional-dependencies]
dev = [
"ruff>=0.6.0",
]

[tool.uv]
preview = true

实际文件中还包含作者、license 等信息,这里只展示与运行相关的关键字段。

这里最重要的是两点:

  • dependencies 里声明了 fastmcp,说明本示例需要这个包来实现 MCP 服务;
  • [tool.uv] 表明我们打算用 uv 来管理整个项目。

服务端代码

服务端使用 FastMCP 实现,只提供一个工具:根据科目获取知识点列表,保持尽可能简单,方便教学和调试。

完整核心代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
from typing import Dict, List

from fastmcp import FastMCP


mcp = FastMCP("simple-subject-knowledge")


_SUBJECT_KNOWLEDGE: Dict[str, List[str]] = {
"数学": [
"一元一次方程",
"函数与图像",
],
"物理": [
"牛顿第二定律",
"功与能",
],
}


@mcp.tool()
def get_knowledge_points_by_subject(subject: str) -> List[str]:
"""
根据科目名称获取该科目的知识点列表。

示例科目:
- 数学
- 物理
"""
return _SUBJECT_KNOWLEDGE.get(subject, [])


def main() -> None:
mcp.run(transport="sse")


if __name__ == "__main__":
main()

要点说明(建议逐条对照代码理解):

  • 服务器实例mcp = FastMCP("simple-subject-knowledge")
    给你的 MCP 服务起了一个名字,客户端可以据此识别。
  • 演示数据_SUBJECT_KNOWLEDGE
    • 键是科目(例如 "数学""物理");
    • 值是知识点名称列表(字符串数组)。
      在真实项目中,你可以把这里替换为数据库、API 调用等。
  • 工具定义@mcp.tool()
    • 装饰器会把 get_knowledge_points_by_subject 暴露为 MCP 工具;
    • 入参是 subject: str,返回 List[str]
    • 未命中时返回空列表 [],避免抛异常。
  • 以 SSE 方式运行mcp.run(transport="sse")
    • 表示通过 SSE(Server‑Sent Events) 对外提供 MCP 服务;
  • FastMCP 会在本地起一个 HTTP 服务,并暴露一个 SSE 端点,后面客户端会连这个端点。

环境准备

如果你已经完成过一次 uv 初始化和依赖安装,可以直接跳到「启动服务端」。

在项目根目录 d:\Project\ai\ques_mcp 下执行:

1
2
3
uv venv          # 如已创建虚拟环境可跳过
uv sync # 安装 pyproject.toml 中声明的依赖(含 fastmcp)
uv add mcp # 安装官方 MCP Python SDK,用于测试脚本

说明:

  • fastmcp:实现 MCP 服务器。
  • mcp:官方 MCP Python SDK,用来写客户端测试脚本。

启动服务端

在项目根目录下运行:

1
uv run python -m app.server

效果(大致会看到类似输出):

  • 启动一个基于 FastMCP 的 MCP 服务器;
  • 使用 SSE 传输transport="sse");
  • 默认监听地址类似:http://127.0.0.1:8000/sse(实际端口以启动日志为准)。

教学提示:此时你可以把这个终端理解为「后端服务器窗口」,后面的客户端脚本需要保持它处于运行状态。

MCP服务测试

示例代码目录下已提供 test_client.py,使用官方 mcp SDK 通过 SSE 调用工具。
我们假设服务端仍在上一节的终端窗口中保持运行。

另一个 终端窗口中执行:

1
2
cd d:\Project\ai\ques_mcp
uv run python test_client.py

代码解析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import asyncio

from mcp import ClientSession
from mcp.client.sse import sse_client


SERVER_URL = "http://127.0.0.1:8000/sse"


async def main() -> None:
async with sse_client(url=SERVER_URL) as (read_stream, write_stream):
async with ClientSession(read_stream, write_stream) as session:
await session.initialize()

subject = "数学"
print(f"调用 get_knowledge_points_by_subject,subject = {subject!r}")

result = await session.call_tool(
name="get_knowledge_points_by_subject",
arguments={"subject": subject},
)

print("调用结果:")
for item in result.content:
print(item)


if __name__ == "__main__":
asyncio.run(main())

行为概览:

  • 使用 sse_client 连接 SERVER_URL(即服务端的 SSE 地址);
  • 使用 ClientSession 封装这条连接,并调用 initialize() 完成 MCP 协议初始化;
  • 调用 MCP 工具 get_knowledge_points_by_subject,传入参数 subject="数学"
  • 将工具返回的内容逐条打印到终端。

运行效果

依然在 客户端终端 中执行:

1
2
cd d:\Project\ai\ques_mcp
uv run python test_client.py

你应该能看到类似输出:

  • 一行表示正在调用工具(包含 subject = '数学');
  • 随后打印知识点列表(例如:一元一次方程函数与图像 等)。

若想测试不同科目,可修改 test_client.py 中的:

1
subject = "数学"

为其它键值(例如 "物理"),对应数据在 ques_mcp/server.py_SUBJECT_KNOWLEDGE 中定义。

小练习:尝试在 _SUBJECT_KNOWLEDGE 里增加一个新科目(例如「化学」),然后在客户端请求这个新科目,确认服务端和客户端都工作正常。

在桌面客户端中使用

下载 Cherry Studio - 多平台 AI 客户端

当你确认本教程中的「服务端 + 测试客户端」都在本地正常工作后,可以进一步在支持 MCP 的桌面客户端(如 Cherry Studio 等)中配置:

  • 新增一个 SSE 类型 的 MCP 服务器;
  • URL 填写服务启动后输出的 SSE 地址(通常是 http://127.0.0.1:8000/sse);
  • 重启或刷新桌面客户端后,就可以在其中直接调用 get_knowledge_points_by_subject 工具。

添加MCP服务

image-20260305120714132

助手中开启

助手右边的三个点,选择编辑助手

image-20260305120809570

询问

1
获取数学的知识点列表

调用效果如下

image-20260305120355234