构建 MCP 客户端(核心版)
构建 MCP 客户端(核心版)
本页基于官方教程的核心内容,聚焦最小可用实现(方案A:先核心内容,后完整教程),示例与代码均来自官方文档源,便于快速上手与后续扩展。
建议先阅读:/docs/quickstart/server/(了解客户端与服务器的通信模型)
系统要求(Python)
- macOS 或 Windows
- 最新 Python 版本
- 已安装
uv
初始化项目(Python)
# 创建项目目录
uv init mcp-client
cd mcp-client
# 创建虚拟环境
uv venv
# 激活虚拟环境(macOS/Linux)
source .venv/bin/activate
# 安装依赖
uv add mcp anthropic python-dotenv
# 清理样板并新建主文件
rm main.py
touch client.py
Windows PowerShell 等效命令与官方一致,可参考官方教程。
配置 API Key(Anthropic)
echo "ANTHROPIC_API_KEY=<your key here>" > .env
echo ".env" >> .gitignore
客户端骨架代码(来自官方)
import asyncio
from typing import Optional
from contextlib import AsyncExitStack
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client
from anthropic import Anthropic
from dotenv import load_dotenv
load_dotenv() # load environment variables from .env
class MCPClient:
def __init__(self):
# Initialize session and client objects
self.session: Optional[ClientSession] = None
self.exit_stack = AsyncExitStack()
self.anthropic = Anthropic()
# methods will go here
连接 MCP 服务器(官方示例)
async def connect_to_server(self, server_script_path: str):
"""Connect to an MCP server
Args:
server_script_path: Path to the server script (.py or .js)
"""
is_python = server_script_path.endswith('.py')
is_js = server_script_path.endswith('.js')
if not (is_python or is_js):
raise ValueError("Server script must be a .py or .js file")
command = "python" if is_python else "node"
server_params = StdioServerParameters(
command=command,
args=[server_script_path],
env=None
)
stdio_transport = await self.exit_stack.enter_async_context(stdio_client(server_params))
self.stdio, self.write = stdio_transport
self.session = await self.exit_stack.enter_async_context(ClientSession(self.stdio, self.write))
await self.session.initialize()
# List available tools
response = await self.session.list_tools()
tools = response.tools
print("\nConnected to server with tools:", [tool.name for tool in tools])
查询处理主流程(官方示例片段)
async def process_query(self, query: str) -> str:
"""Process a query using Claude and available tools"""
messages = [
{
"role": "user",
"content": query
}
]
response = await self.session.list_tools()
available_tools = [{
"name": tool.name,
"description": tool.description,
"input_schema": tool.inputSchema
} for tool in response.tools]
# Initial Claude API call
response = self.anthropic.messages.create(
model="claude-3-5-sonnet-20241022",
max_tokens=1000,
messages=messages,
tools=available_tools
)
# 后续:解析响应、工具调用编排、聚合最终结果(参见官方教程完整代码)
下一步
- 补充工具调用执行与结果合并逻辑
- 新增 TypeScript 版本(与官方教程保持一致)
- 增加错误处理与重试策略
- 与 /specification/draft/basic/authorization/ 对齐,接入 OAuth 令牌
完整代码与更多语言版本将分步补齐,保持与官方更新同步。