Python MCP实战:构建 FastAPI 服务端与客户端示例&MCP客户端调用

引言

在现代微服务架构中,服务间的通信协议选择至关重要。除了常见的 RESTful API、gRPC 等,MCP(Message-oriented Communication Protocol)作为一种面向消息的通信协议,也逐渐在特定场景中展现出其优势。本文将通过一个具体的 Python 示例,演示如何基于 fastapi-mcpmcp 库,构建一个 MCP 服务端和客户端,并实现工具(Tool)的远程调用。

服务端将使用 FastAPI 框架,通过 fastapi-mcp 库将一个 API endpoint 暴露为 MCP 工具。客户端则会演示如何连接到 MCP 服务,列出可用的工具,并远程调用它。

核心组件:

  • 服务端 (main.py): 一个基于 FastAPI 的 Web 应用,提供 MCP 服务。
  • 客户端 (test/mcp_client.py): 一个 Python 脚本,用于连接 MCP 服务并与之交互。

服务端实现 (main.py)

我们的服务端基于 FastAPI 构建。核心是利用 fastapi-mcp 库将指定的 FastAPI 路由转换成 MCP 可以识别和调用的"工具"。

1. 定义 FastAPI 路由

首先,我们定义一个标准的 FastAPI 路由,这个路由将是我们要通过 MCP 暴露的功能。在这个例子中,我们创建了一个名为 get_gStore_date 的异步函数,它接收 questiontype 两个参数,并返回一个答案。

python 复制代码
# main.py

from fastapi import FastAPI
from fastapi_mcp import FastApiMCP
import uvicorn

# 创建FastAPI应用
app = FastAPI(
    title="GRAPH RAG API",
    description="高效的web数据管理接口",
    version="0.1.0",
)

# ... (其他FastAPI配置,如CORS、异常处理等)

@app.get("/answer", operation_id="get_data", tags=["mcp"], summary="根据问题获取答案")
async def get_gStore_date(question: str, type: str):
    # 在实际应用中,这里会调用服务层处理业务逻辑
    # chat_service = get_chat_service()
    # answer = await chat_service.get_answer_mcp(question,type)
    print(f"收到问题: {question}, 类型: {type}")
    return f"这是关于 '{question}' 的答案。"

# ...

关键点:

  • operation_id="get_data": 这个 ID 将作为 MCP 工具的名称。
  • tags=["mcp"]: 我们通过标签(tag)来筛选哪些路由需要被 MCP 服务暴露。

2. 集成 FastApiMCP

接下来,我们实例化 FastApiMCP 并将其挂载到 FastAPI 应用上。

python 复制代码
# main.py (续)

# 创建 FastApiMCP 实例并挂载
mcp = FastApiMCP(
    app,
    name="问题检索mcp", 
    description="测试描述",
    include_tags=["mcp"]  # 只暴露包含 "mcp" 标签的路由
)
mcp.mount_sse(mount_path="/sse")

if __name__ == "__main__":
    uvicorn.run(app, host="0.0.0.0", port=8000)

关键点:

  • include_tags=["mcp"]: 告诉 FastApiMCP 只扫描并注册那些 tags 列表中包含 "mcp" 的路由。
  • mcp.mount_sse(mount_path="/sse"): 在指定的路径 (/sse) 上启用基于 SSE (Server-Sent Events) 的 MCP 通信端点。客户端将通过这个端点进行连接。

客户端实现 (test/mcp_client.py)

客户端使用 mcp 库来连接服务端,并执行工具调用。

1. 连接和初始化

客户端代码的核心是使用 sse_client 创建一个到服务器 /sse 端点的连接,并初始化一个 ClientSession

python 复制代码
# test/mcp_client.py

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

async def simple_client():
    """使用 mcp 库的简化客户端"""
    url = "http://127.0.0.1:8000/sse"  # 指向 SSE 挂载点
    
    try:
        async with sse_client(url) as (read, write):
            async with ClientSession(read, write) as session:
                # 1. 初始化会话(MCP 握手)
                await session.initialize()
                print("✅ MCP 会话初始化成功")
                
                # ... 后续操作
                
    except Exception as e:
        print(f"❌ 客户端连接失败: {e}")

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

关键点:

  • sse_client(url): 创建一个异步上下文管理器,处理与 SSE 端点的连接。
  • session.initialize(): 执行 MCP 握手,确保客户端和服务端可以正常通信。

2. 列出和调用工具

初始化成功后,我们就可以与服务端交互了,例如列出所有可用的工具,或者调用某个特定的工具。

python 复制代码
# test/mcp_client.py (续, 在 session 上下文内)

# 2. 列出可用工具
tools_result = await session.list_tools()
print("🛠️ 可用的工具:")
for tool in tools_result.tools:
    print(f"  - {tool.name}: {tool.description}")

# 3. 调用工具
call_result = await session.call_tool(
    "get_data",
    arguments={
        "question": "测试问题",
        "type": "test"
    }
)

if call_result.content:
    print(f"📝 调用结果: {call_result.content[0].text}")

关键点:

  • session.list_tools(): 从服务端获取所有已注册工具的列表。
  • session.call_tool("get_data", ...): 远程调用名为 get_data 的工具。
  • arguments: 一个字典,包含了调用工具时需要传递的参数,这些参数对应于 main.pyget_date 函数的参数。

如何运行

1. 启动服务端

在项目根目录下,运行 main.py

bash 复制代码
python main.py

你应该会看到 Uvicorn 启动服务的日志,表明服务正在 http://0.0.0.0:8000 上运行。

2. 运行客户端

打开另一个终端,运行 test/mcp_client.py

bash 复制代码
python test/mcp_client.py

预期输出

如果一切顺利,你将在客户端的终端看到类似以下的输出:

复制代码
✅ MCP 会话初始化成功
🛠️ 可用的工具:
  - get_data: 根据问题获取回复
📝 调用结果: 这是关于 '测试问题' 的答案。

同时,在服务端 的终端,你会看到 get_date 函数被触发时打印的信息:

复制代码
收到问题: 测试问题, 类型: test

结论

本文通过一个简单的示例,展示了如何使用 fastapi-mcpmcp 库在 Python 中构建 MCP 服务端和客户端。这种模式非常适合于需要将现有 Web API(特别是 FastAPI)快速封装成可远程调用的"工具集"的场景,为服务间通信提供了一种灵活且强大的替代方案。通过 operation_idtags 的智能映射,集成过程变得非常直观和高效。

相关推荐
zzzzls~8 小时前
Python 工程化: 用 Copier 打造“自我进化“的项目脚手架
开发语言·python·copier
韶博雅8 小时前
emcc24ai
开发语言·数据库·python
yongui478349 小时前
C# 与三菱PLC通讯解决方案
开发语言·c#
2501_933329559 小时前
技术架构深度解析:Infoseek舆情监测系统的全链路设计与GEO时代的技术实践
开发语言·人工智能·分布式·架构
Tong Z9 小时前
常见的限流算法和实现原理
java·开发语言
凭君语未可9 小时前
Java 中的实现类是什么
java·开发语言
He少年9 小时前
【基础知识、Skill、Rules和MCP案例介绍】
java·前端·python
wearegogog1239 小时前
离散系统参数辨识与广义预测控制MATLAB实现
开发语言·matlab
史迪仔01129 小时前
[QML] QML IMage图像处理
开发语言·前端·javascript·c++·qt
AI_Claude_code9 小时前
ZLibrary访问困境方案四:利用Cloudflare Workers等边缘计算实现访问
javascript·人工智能·爬虫·python·网络爬虫·边缘计算·爬山算法