2.2 Host、Client、Server详解
🎯 学习目标:深入理解MCP三大核心组件的职责、关系和实现方式
⏱️ 预计时间:45分钟
📊 难度等级:⭐⭐
🎭 三大角色的戏剧比喻
在深入技术细节之前,让我们用一个戏剧比喻来理解MCP的三大核心组件:
🎪 MCP剧场演出
────────────────────────────────
🎭 导演 (Host) - 总体协调,决定剧情走向
🎤 翻译 (Client) - 负责演员间的沟通翻译
🎨 演员 (Server) - 各自表演专业技能
在这个比喻中:
- 导演(Host):理解观众需求,指导整场演出
- 翻译(Client):确保导演和演员能够有效沟通
- 演员(Server):各有专长,负责具体的表演
🏠 Host(宿主):MCP生态的大脑
🧠 Host的核心职责
Host是MCP生态系统的控制中心,就像一个智能指挥官:
📋 Host的详细职责
职责 | 说明 | 举例 |
---|---|---|
用户交互 | 提供友好的用户界面 | Web界面、CLI、语音交互 |
意图理解 | 解析用户需求和意图 | "发邮件" → 需要邮件工具 |
任务规划 | 制定执行计划和步骤 | 先查联系人,再发送邮件 |
工具编排 | 协调多个工具协作 | 组合查询、计算、通知等工具 |
结果整合 | 整合多个工具的输出 | 合并数据,格式化展示 |
错误处理 | 处理异常和容错恢复 | 工具失败时的备用方案 |
💻 Host的技术实现
基础Host架构
javascript
class MCPHost {
constructor() {
this.aiModel = new AIModel();
this.mcpClients = new Map(); // 管理多个MCP客户端
this.taskPlanner = new TaskPlanner();
this.resultProcessor = new ResultProcessor();
}
async processUserRequest(userInput) {
try {
// 1. 理解用户意图
const intent = await this.aiModel.parseIntent(userInput);
console.log('用户意图:', intent);
// 2. 制定执行计划
const plan = await this.taskPlanner.createPlan(intent);
console.log('执行计划:', plan);
// 3. 执行计划中的每个步骤
const results = [];
for (const step of plan.steps) {
const result = await this.executeStep(step);
results.push(result);
}
// 4. 整合结果
const finalResult = await this.resultProcessor.integrate(results);
// 5. 生成用户友好的回复
return await this.aiModel.generateResponse(finalResult);
} catch (error) {
return this.handleError(error);
}
}
async executeStep(step) {
const client = this.mcpClients.get(step.serverId);
if (!client) {
throw new Error(`找不到服务器: ${step.serverId}`);
}
return await client.callTool(step.toolName, step.parameters);
}
}
高级Host功能
javascript
class AdvancedMCPHost extends MCPHost {
constructor() {
super();
this.conversationContext = new ConversationContext();
this.preferenceManager = new UserPreferenceManager();
this.securityManager = new SecurityManager();
}
// 上下文感知的请求处理
async processWithContext(userInput, conversationId) {
// 获取对话上下文
const context = await this.conversationContext.get(conversationId);
// 结合上下文理解意图
const intent = await this.aiModel.parseIntentWithContext(
userInput,
context
);
// 个性化任务规划
const userPrefs = await this.preferenceManager.getPreferences(
context.userId
);
const plan = await this.taskPlanner.createPersonalizedPlan(
intent,
userPrefs
);
// 安全检查
await this.securityManager.validatePlan(plan, context.userId);
// 执行并更新上下文
const result = await this.executePlan(plan);
await this.conversationContext.update(conversationId, {
intent,
plan,
result
});
return result;
}
}
🎯 Host的实际应用
VS Code中的MCP Host
typescript
// VS Code扩展中的MCP Host实现
export class VSCodeMCPHost {
private clients: Map<string, MCPClient> = new Map();
private outputChannel: vscode.OutputChannel;
constructor() {
this.outputChannel = vscode.window.createOutputChannel('MCP Host');
}
// 处理编辑器命令
async handleEditorCommand(command: string, editor: vscode.TextEditor) {
const intent = this.parseEditorIntent(command, editor);
switch (intent.type) {
case 'code_analysis':
return await this.analyzeCode(editor);
case 'code_generation':
return await this.generateCode(intent.requirements);
case 'refactor':
return await this.refactorCode(editor, intent.target);
default:
throw new Error(`未知命令: ${command}`);
}
}
private async analyzeCode(editor: vscode.TextEditor) {
const codeAnalysisClient = this.clients.get('code-analysis');
const result = await codeAnalysisClient.callTool('analyze', {
code: editor.document.getText(),
language: editor.document.languageId
});
// 在VS Code中显示分析结果
this.showAnalysisResults(result);
return result;
}
}
🤖 Client(客户端):MCP协议的执行者
🔗 Client的核心职责
Client是MCP协议的具体实现者,负责与Server的所有通信:
📋 Client的详细功能
功能模块 | 职责 | 技术要点 |
---|---|---|
连接管理 | 建立和维护与Server的连接 | 连接池、重连机制、健康检查 |
协议处理 | 实现MCP协议规范 | 消息序列化、协议版本协商 |
能力发现 | 发现和缓存Server能力 | 能力查询、缓存更新、版本管理 |
消息路由 | 将请求路由到正确的Server | 负载均衡、故障转移、超时处理 |
结果处理 | 处理Server响应 | 结果解析、错误处理、数据转换 |
安全控制 | 认证和权限验证 | 身份认证、访问控制、数据加密 |
💻 Client的技术实现
基础Client实现
javascript
class MCPClient {
constructor() {
this.connections = new Map();
this.capabilities = new Map();
this.eventEmitter = new EventEmitter();
}
// 连接到MCP服务器
async connect(serverInfo) {
try {
// 建立底层连接(WebSocket、HTTP、进程通信等)
const transport = await this.createTransport(serverInfo);
// 创建MCP连接
const connection = new MCPConnection(transport);
// 协议握手
await this.performHandshake(connection, serverInfo);
// 发现服务器能力
const capabilities = await this.discoverCapabilities(connection);
// 缓存连接和能力
this.connections.set(serverInfo.id, connection);
this.capabilities.set(serverInfo.id, capabilities);
// 监听连接事件
this.setupConnectionListeners(connection, serverInfo.id);
this.eventEmitter.emit('connected', serverInfo.id);
return connection;
} catch (error) {
console.error(`连接服务器失败: ${serverInfo.id}`, error);
throw error;
}
}
// 调用工具
async callTool(serverId, toolName, parameters) {
const connection = this.connections.get(serverId);
if (!connection) {
throw new Error(`未连接到服务器: ${serverId}`);
}
// 验证工具存在
const capabilities = this.capabilities.get(serverId);
const tool = capabilities.tools.find(t => t.name === toolName);
if (!tool) {
throw new Error(`工具不存在: ${toolName}`);
}
// 验证参数
this.validateParameters(parameters, tool.inputSchema);
// 构造MCP消息
const message = {
jsonrpc: '2.0',
id: this.generateRequestId(),
method: 'tools/call',
params: {
name: toolName,
arguments: parameters
}
};
// 发送请求并等待响应
const response = await connection.request(message);
if (response.error) {
throw new MCPError(response.error.message, response.error.code);
}
return response.result;
}
// 协议握手
async performHandshake(connection, serverInfo) {
const handshakeMessage = {
jsonrpc: '2.0',
id: 1,
method: 'initialize',
params: {
protocolVersion: '2025-01-07',
capabilities: {
roots: {
listChanged: true
},
sampling: {}
},
clientInfo: {
name: 'MCP Client',
version: '1.0.0'
}
}
};
const response = await connection.request(handshakeMessage);
if (response.error) {
throw new Error(`握手失败: ${response.error.message}`);
}
// 发送初始化完成通知
await connection.notify({
jsonrpc: '2.0',
method: 'notifications/initialized'
});
return response.result;
}
}
高级Client功能
javascript
class AdvancedMCPClient extends MCPClient {
constructor() {
super();
this.connectionPool = new ConnectionPool();
this.circuitBreaker = new CircuitBreaker();
this.metricsCollector = new MetricsCollector();
}
// 带重试的工具调用
async callToolWithRetry(serverId, toolName, parameters, options = {}) {
const maxRetries = options.maxRetries || 3;
const retryDelay = options.retryDelay || 1000;
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
// 检查熔断器状态
if (this.circuitBreaker.isOpen(serverId)) {
throw new Error(`服务器 ${serverId} 熔断中`);
}
const startTime = Date.now();
const result = await this.callTool(serverId, toolName, parameters);
// 记录成功指标
this.metricsCollector.recordSuccess(serverId, Date.now() - startTime);
this.circuitBreaker.recordSuccess(serverId);
return result;
} catch (error) {
console.warn(`工具调用失败 (尝试 ${attempt}/${maxRetries}):`, error);
// 记录失败指标
this.metricsCollector.recordFailure(serverId, error);
this.circuitBreaker.recordFailure(serverId);
if (attempt === maxRetries) {
throw error;
}
// 等待重试
await this.sleep(retryDelay * attempt);
}
}
}
// 批量工具调用
async callToolsBatch(requests) {
const promises = requests.map(async (request) => {
try {
const result = await this.callTool(
request.serverId,
request.toolName,
request.parameters
);
return { success: true, result, request };
} catch (error) {
return { success: false, error, request };
}
});
return await Promise.all(promises);
}
}
🏪 Server(服务器):MCP工具的提供者
🛠️ Server的核心职责
Server是MCP生态中的工具提供者,每个Server专注于特定领域的功能:
📋 Server的功能模块
模块 | 职责 | 实现要点 |
---|---|---|
工具管理 | 注册和管理提供的工具 | 工具注册、元数据管理、版本控制 |
资源管理 | 管理可访问的资源 | 资源抽象、访问控制、生命周期管理 |
协议实现 | 实现MCP服务器端协议 | 消息处理、错误响应、状态管理 |
执行引擎 | 执行具体的工具逻辑 | 参数验证、业务逻辑、结果封装 |
安全机制 | 认证授权和安全控制 | 身份验证、权限检查、数据保护 |
💻 Server的技术实现
基础Server框架
javascript
class MCPServer {
constructor(name) {
this.name = name;
this.tools = new Map();
this.resources = new Map();
this.prompts = new Map();
this.requestHandlers = new Map();
// 注册核心处理器
this.setupCoreHandlers();
}
// 注册工具
registerTool(name, handler, schema) {
this.tools.set(name, {
name,
description: schema.description,
inputSchema: schema.inputSchema,
handler: this.wrapToolHandler(handler)
});
console.log(`工具已注册: ${name}`);
}
// 包装工具处理器,添加验证和错误处理
wrapToolHandler(handler) {
return async (parameters) => {
try {
// 执行工具逻辑
const result = await handler(parameters);
// 标准化返回格式
return {
content: [
{
type: 'text',
text: typeof result === 'string' ? result : JSON.stringify(result)
}
]
};
} catch (error) {
console.error('工具执行错误:', error);
throw new MCPError(
`工具执行失败: ${error.message}`,
'TOOL_EXECUTION_ERROR'
);
}
};
}
// 处理MCP请求
async handleRequest(request) {
const { method, params, id } = request;
try {
const handler = this.requestHandlers.get(method);
if (!handler) {
throw new MCPError(
`不支持的方法: ${method}`,
'METHOD_NOT_FOUND'
);
}
const result = await handler(params);
return {
jsonrpc: '2.0',
id,
result
};
} catch (error) {
return {
jsonrpc: '2.0',
id,
error: {
code: error.code || 'INTERNAL_ERROR',
message: error.message
}
};
}
}
// 设置核心处理器
setupCoreHandlers() {
// 初始化处理器
this.requestHandlers.set('initialize', async (params) => {
return {
protocolVersion: '2025-01-07',
capabilities: {
tools: {
listChanged: true
},
resources: {
subscribe: true,
listChanged: true
}
},
serverInfo: {
name: this.name,
version: '1.0.0'
}
};
});
// 工具列表处理器
this.requestHandlers.set('tools/list', async () => {
return {
tools: Array.from(this.tools.values()).map(tool => ({
name: tool.name,
description: tool.description,
inputSchema: tool.inputSchema
}))
};
});
// 工具调用处理器
this.requestHandlers.set('tools/call', async (params) => {
const { name, arguments: args } = params;
const tool = this.tools.get(name);
if (!tool) {
throw new MCPError(`工具不存在: ${name}`, 'TOOL_NOT_FOUND');
}
return await tool.handler(args);
});
}
}
专业化Server示例
javascript
// 数学计算Server
class MathCalculatorServer extends MCPServer {
constructor() {
super('math-calculator');
this.registerMathTools();
}
registerMathTools() {
// 基础计算工具
this.registerTool('add',
(params) => params.a + params.b,
{
description: '两数相加',
inputSchema: {
type: 'object',
properties: {
a: { type: 'number', description: '第一个数' },
b: { type: 'number', description: '第二个数' }
},
required: ['a', 'b']
}
}
);
// 高级计算工具
this.registerTool('solve_equation',
async (params) => {
const { equation, variable } = params;
// 这里可以集成数学求解库
return `方程 ${equation} 关于 ${variable} 的解`;
},
{
description: '求解数学方程',
inputSchema: {
type: 'object',
properties: {
equation: { type: 'string', description: '数学方程' },
variable: { type: 'string', description: '未知变量' }
},
required: ['equation', 'variable']
}
}
);
// 统计分析工具
this.registerTool('statistics',
(params) => {
const { numbers } = params;
const sum = numbers.reduce((a, b) => a + b, 0);
const mean = sum / numbers.length;
const variance = numbers.reduce((acc, num) => acc + Math.pow(num - mean, 2), 0) / numbers.length;
return {
count: numbers.length,
sum,
mean,
variance,
stddev: Math.sqrt(variance)
};
},
{
description: '数组统计分析',
inputSchema: {
type: 'object',
properties: {
numbers: {
type: 'array',
items: { type: 'number' },
description: '数字数组'
}
},
required: ['numbers']
}
}
);
}
}
🔄 三者协作的完整流程
📊 详细的交互时序图
🎯 协作关系总结
组件 | 主要职责 | 与其他组件的关系 |
---|---|---|
Host | 用户交互、任务编排 | 通过Client调用Server,向用户展示结果 |
Client | 协议实现、连接管理 | 接收Host指令,与Server通信 |
Server | 工具实现、资源提供 | 响应Client请求,执行具体功能 |
🎯 本节小结
通过这一小节,你应该已经深入理解了:
✅ Host的职责:用户交互、意图理解、任务规划、工具编排、结果整合
✅ Client的职责:连接管理、协议处理、能力发现、消息路由、结果处理
✅ Server的职责:工具注册、资源管理、协议实现、执行引擎、安全控制
✅ 协作关系:三者如何配合完成完整的AI工具调用流程
✅ 技术实现:每个组件的核心代码结构和实现要点
🤔 深入思考
- 💭 在你的项目中,你会如何设计Host的用户交互界面?
- 🔍 Client的连接管理需要考虑哪些异常情况?
- 🛠️ 你想开发什么类型的MCP Server?
理解了三大组件的职责,是不是想知道它们之间具体是如何通信的?