[具身智能-348]:MCP Client代码示例
·
为了让你直观地理解 MCP Client 是如何作为“桥梁”工作的,我为你准备了两个不同维度的代码示例。
第一个示例使用 Python 的 mcp 官方库,展示了 Client 如何“发现能力”和“调用工具”(即标准的请求-响应流程);
第二个示例则展示了 Client 如何处理“服务端推送”(即监听 Server 主动发出的日志通知),这能很好地体现 Client 的异步事件处理能力。
🛠️ 示例一:核心功能实现(Python)
这个脚本模拟了一个 MCP Client 的生命周期:启动 Server -> 握手 -> 获取工具列表 -> 调用工具 -> 关闭。
python
import asyncio
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client
# 1. 定义 Server 的启动参数
# 这里我们假设有一个名为 "mcp-server-time" 的工具,用于获取时间
server_params = StdioServerParameters(
command="python",
args=["-m", "mcp_server_time"],
env=None
)
async def run():
# 2. 建立连接 (Stdio 模式)
# stdio_client 会启动子进程,并接管其 stdin/stdout
async with stdio_client(server_params) as (read, write):
# 3. 创建会话并初始化
# 这里会自动发送 "initialize" 消息并等待 Server 响应
async with ClientSession(read, write) as session:
# 4. 【桥梁作用:能力发现】
# Client 询问 Server:"你都会什么?" (对应 tools/list)
tools = await session.list_tools()
print(f"🔍 发现可用工具: {[tool.name for tool in tools.tools]}")
# 5. 【桥梁作用:指令路由】
# 假设我们要调用名为 "get_current_time" 的工具
# Client 将参数封装为 JSON-RPC 请求发送给 Server
try:
result = await session.call_tool("get_current_time", arguments={"timezone": "Asia/Shanghai"})
# 6. 【桥梁作用:结果回传】
# 接收 Server 的 JSON 响应,并提取内容
print(f"✅ 工具执行结果: {result.content[0].text}")
except Exception as e:
print(f"❌ 调用失败: {e}")
if __name__ == "__main__":
# 运行异步主程序
asyncio.run(run())
代码解析
stdio_client:这是 Client 的传输层,负责启动 Server 进程并建立管道。ClientSession:这是 Client 的协议层,负责处理握手(initialize)和会话管理。list_tools():对应“侦察兵”机制,获取 JSON Schema 定义。call_tool():对应“执行器”机制,发送tools/call请求。
📡 示例二:处理服务端推送(监听日志)
MCP 允许 Server 主动向 Client 发送通知(例如日志或进度更新)。Client 需要注册回调函数来监听这些事件,这体现了 Client 的事件驱动特性。
python
import asyncio
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client
from mcp.types import ServerNotification
# 假设这是一个会打印日志的 Server
server_params = StdioServerParameters(command="python", args=["my_logging_server.py"])
async def handle_notification(notification: ServerNotification):
"""
当 Server 主动推送消息时,Client 会触发此回调
"""
print(f"🔔 收到 Server 推送通知: {notification.method}")
if notification.method == "notifications/message":
print(f" 日志内容: {notification.params.data}")
async def run_with_events():
async with stdio_client(server_params) as (read, write):
async with ClientSession(read, write) as session:
# 【桥梁作用:事件监听】
# Client 注册一个钩子,专门监听 Server 的日志通知
session.set_notification_handler(handle_notification)
# 调用一个会触发日志的工具
print("正在调用工具,等待 Server 推送日志...")
await session.call_tool("start_long_task", arguments={})
# 保持运行一段时间以接收推送
await asyncio.sleep(2)
if __name__ == "__main__":
asyncio.run(run_with_events())
📌 总结
通过这两个示例,你可以清晰地看到 MCP Client 的代码结构是如何对应其架构角色的:
- 传输层:
stdio_client或sse_client负责底层的字节流读写。 - 会话层:
ClientSession负责维护状态和协议握手。 - 业务层:
list_tools、call_tool以及set_notification_handler负责具体的业务交互。
这就是 MCP Client 如何通过几十行代码,就构建起连接大模型与外部世界的桥梁。
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐

所有评论(0)