Python 客户端连接服务器

服务器写好后,还得有"客户端"去消费它的工具。官方 Python SDK(包名 mcp)同时提供 FastMCP(写服务器)和一套异步客户端:本地用 stdio 传输,远程用 Streamable HTTP。本章给出两端都能跑通的最小示例。

安装官方 SDK

pip install "mcp[cli]"      # 官方 Python SDK;[cli] 额外带上 mcp 命令行工具

客户端 API 随 SDK 版本快速演进,写法如有出入,一律以 modelcontextprotocol.io 的官方 SDK 文档为准。

准备一个测试服务器

先写一个极简单的 stdio 服务器,后面所有客户端都连它:

# server_echo.py:一个只提供 add 工具的 FastMCP 服务器
from mcp.server.fastmcp import FastMCP

mcp = FastMCP("echo")

@mcp.tool()
def add(a: int, b: int) -> int:
    """两数相加"""
    return a + b

if __name__ == "__main__":
    mcp.run()       # FastMCP 默认以 stdio 方式运行

用 stdio_client 连接本地服务器

stdio 客户端把"命令行 + 参数"描述进 StdioServerParameters,SDK 负责拉起子进程并与之双向通信:

# client_stdio.py:完整可运行的 stdio 客户端
import asyncio
import sys
from mcp import ClientSession
from mcp.client.stdio import StdioServerParameters, stdio_client

async def main():
    params = StdioServerParameters(
        command=sys.executable,   # 用当前 Python 解释器去启动服务器
        args=["server_echo.py"],  # 服务器脚本路径(与本文件同目录)
    )
    async with stdio_client(params) as (read, write):    # 建立两条传输流
        async with ClientSession(read, write) as session:
            await session.initialize()            # ① 握手初始化(必须先做)
            tools = await session.list_tools()    # ② 列出服务器声明的工具
            print(f"可用工具:{[t.name for t in tools.tools]}")
            # 输出:可用工具:['add']
            result = await session.call_tool(     # ③ 调用工具,实参按 JSON Schema 传
                "add", {"a": 2, "b": 3}
            )
            print(f"返回:{result.content[0].text}")   # 输出:返回:5

asyncio.run(main())

要点:stdio_client 负责进程生命周期,ClientSession 负责协议;list_tools 返回工具清单(含名称、描述、inputSchema),call_tool 的第一个参数是工具名、第二个是参数字典,结果内容在 result.content 的 TextContent 块里。

连接远程 Streamable HTTP 服务器

服务器通过 HTTP 部署后(见第 15 章),客户端换成 streamablehttp_client,其余流程一致。官方已弃用旧的 SSE 传输,新项目一律用 Streamable HTTP:

# client_http.py:连接远程 Streamable HTTP 服务器
import asyncio
from mcp import ClientSession
from mcp.client.streamable_http import streamablehttp_client

URL = "http://127.0.0.1:8000/mcp"    # 远程服务地址,需先按第 15 章部署

async def main():
    async with streamablehttp_client(URL) as (read, write, _get_session_id):
        async with ClientSession(read, write) as session:
            await session.initialize()
            result = await session.call_tool("add", {"a": 10, "b": 5})
            print(f"远程返回:{result.content[0].text}")   # 输出:远程返回:15

asyncio.run(main())

两点提示:个别 SDK 版本的 streamablehttp_client 只返回 (read, write) 两条流,按你安装的版本解包即可;需要带鉴权头时给 streamablehttp_client 传 headers 参数,字段名以官方文档为准。 小结:客户端三板斧是 stdio_client(或 streamablehttp_client)→ ClientSession → initialize,之后 list_tools 看工具、call_tool 调工具;stdio 连本机子进程、Streamable HTTP 连远程服务,SSE 传输已弃用。

笔记加载中…