MCP 客户端开发入门:一句话结论
MCP 客户端的三板斧是「建立传输 → 初始化会话 → list_tools / call_tool」,用官方 Python SDK 十几行代码就能跑通一个能调用工具的客户端——写客户端不比写服务端难。
客户端和主机是什么关系
先澄清概念:Claude Desktop 、 Cursor 这些产品是 MCP 主机(Host),主机内嵌的连接器才是 客户端(Client)。客户端负责与一个或多个服务端建立 1:1 连接、完成初始化握手、发现并调用工具。自己写客户端的典型场景:给你的应用接工具能力、做聚合网关、写集成测试。
十行起步:Streamable HTTP 客户端
官方 Python SDK(pip install "mcp[cli]",要求 Python 3.10+)提供了高层客户端接口。先看最简形态——连一个 HTTP 服务端:
import asyncio
from mcp import Client
async def main() -> None:
async with Client("http://localhost:8000/mcp") as client:
result = await client.call_tool("add", {"a": 1, "b": 2})
print(result.structured_content) # {'result': 3}
asyncio.run(main())
传 URL 就是走 Streamable HTTP(部署首选传输);传本地命令则走 stdio 子进程。传输方式的选择依据见 MCP 传输方式对比。
完整版:Session 风格客户端
需要更细的控制(资源、提示词、采样回调)时用 ClientSession 风格:
import asyncio
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client
server_params = StdioServerParameters(
command="uv",
args=["run", "server", "fastmcp_quickstart", "stdio"],
)
async def run():
async with stdio_client(server_params) as (read, write):
async with ClientSession(read, write) as session:
await session.initialize() # 握手,必须第一步
tools = await session.list_tools() # 发现工具
print([t.name for t in tools.tools])
result = await session.call_tool("add", {"a": 5, "b": 3})
print(result.content[0].text) # 8
print(result.structuredContent) # 结构化结果
asyncio.run(run())
三段式结构固定不变:stdio_client(或 streamable_http_client)建立传输层拿到读写流 → ClientSession 包装会话 → await session.initialize() 完成协议握手。之后 list_tools 、 call_tool 、 list_resources 、 read_resource 、 get_prompt 随便用。
五个容易踩的坑
- 忘了 initialize:握手不做,后续所有调用直接报错。它必须先于一切。
- 重定向不跟:HTTP 传输只连你给的 origin,307/308 仅在同 scheme+host+port 内跟随(含 http→https 同主机);跳到别的域直接报
Redirect not followed。传给 httpx 的follow_redirects对 MCP 请求无效,别指望它。 - stdio 服务端写 stdout:服务端把日志打进 stdout 会污染协议流,客户端立刻失联。服务端日志必须走 stderr(详见 MCP Server 搭建教程)。
- 连接要复用:管理多个服务端时,把初始化好的 ClientSession 存进字典按名字复用,而不是每次调用重新建连——握手是有成本的。
- 错误处理两层:
call_tool的失败有两形态:异常(请求层失败)和result.is_error == True(工具执行失败,结果在 content 里)。两层都要接。
进阶方向
SDK 还内置了 OAuth 授权支持(OAuthClientProvider),连受保护的远程服务端时用它做 token 管理,落地细节参考 远程 MCP 服务器的 OAuth 授权的做法——同一套思路客户端侧直接复用。
常见问题
MCP 客户端和直接用 Function Calling 有什么区别?
需要异步编程基础吗?
怎么测试自己写的客户端?









评论 (0)