MCP协议实战:从零构建AI助手扩展服务器的完整指南
1. 引言:AI助手扩展能力的痛点与解决方案
在AI助手日益普及的今天,Claude和ChatGPT已经成为开发者日常工作中不可或缺的智能伙伴。然而,许多开发者在使用过程中发现,这些AI助手虽然功能强大,但在特定领域的专业能力仍有局限。比如需要查询实时数据、调用内部API、或者处理特定格式的文件时,往往需要频繁切换工具,效率大打折扣。
这正是MCP(Model Context Protocol)协议要解决的核心问题。MCP允许开发者创建自定义服务器,为AI助手扩展专属能力,让Claude和ChatGPT能够直接调用外部工具和服务。本文将完整演示如何从零开始构建MCP服务器,并成功集成到Claude Desktop和ChatGPT中,实现真正的个性化AI助手。
无论你是想要为团队内部工具添加AI支持,还是希望让AI助手具备处理特定业务数据的能力,本文提供的完整实战方案都能直接复用。我们将从基础概念讲起,逐步深入到代码实现、部署配置和实际应用场景。
2. MCP协议核心概念解析
2.1 什么是MCP协议
MCP(Model Context Protocol)是一个开放协议,旨在标准化AI模型与外部工具和服务之间的交互方式。可以将其理解为AI领域的"驱动程序"标准——就像打印机需要驱动程序才能与电脑通信一样,MCP服务器就是AI助手与外部世界通信的"驱动"。
MCP协议的核心价值在于解耦AI模型与具体工具的实现。通过统一的协议规范,开发者可以编写一次MCP服务器,就能让所有支持该协议的AI模型(如Claude、ChatGPT等)使用这些工具能力。
2.2 MCP协议的核心组件
一个完整的MCP生态系统包含三个关键组件:
MCP客户端:即AI助手本身,如Claude Desktop或ChatGPT。客户端负责发起工具调用请求,并处理服务器返回的结果。
MCP服务器:开发者编写的自定义服务,封装了特定的工具能力。服务器接收客户端的请求,执行相应的操作,并返回结果。
传输层:客户端与服务器之间的通信通道,支持stdio(标准输入输出)和HTTP两种方式。
2.3 MCP与传统插件架构的区别
与传统插件架构相比,MCP具有几个显著优势:
语言无关性:MCP服务器可以用任何编程语言编写,只要遵循协议规范即可。
进程隔离:MCP服务器运行在独立的进程中,即使服务器崩溃也不会影响AI助手主程序。
标准化接口:统一的协议规范意味着更好的兼容性和可维护性。
安全可控:每个工具都需要显式授权,用户对AI助手的权限有完全的控制权。
3. 环境准备与开发工具选择
3.1 基础环境要求
在开始MCP服务器开发前,需要确保本地环境满足以下要求:
操作系统:Windows 10/11、macOS 10.15+ 或 Linux Ubuntu 18.04+Node.js:版本18.0.0或更高(推荐使用LTS版本)Python:版本3.8或更高(可选,用于某些特定的工具实现)Git:用于版本控制和示例代码下载
3.2 开发工具推荐
代码编辑器:Visual Studio Code(推荐)或WebStormMCP SDK:使用官方提供的TypeScript/JavaScript SDK调试工具:VS Code内置调试器、Chrome DevToolsAPI测试工具:Postman或curl(用于HTTP传输层测试)
3.3 Claude Desktop安装与配置
由于Claude Desktop是目前对MCP支持最完善的客户端,我们以其为例进行演示:
- 访问Anthropic官网下载Claude Desktop
- 安装完成后启动程序
- 在设置中启用"开发者模式"
- 确认MCP配置目录位置(通常位于用户主目录下的.claude/mcp-servers)
3.4 项目结构规划
在开始编码前,我们先规划标准的MCP项目结构:
my-mcp-server/ ├── src/ │ ├── tools/ # 工具实现 │ ├── resources/ # 资源管理 │ ├── types/ # 类型定义 │ └── index.ts # 入口文件 ├── package.json # 项目配置 ├── tsconfig.json # TypeScript配置 ├── claude.json # Claude配置文件 └── README.md # 项目说明4. 创建第一个MCP服务器:天气查询示例
4.1 初始化项目
首先创建项目目录并初始化npm包:
# 创建项目目录 mkdir weather-mcp-server cd weather-mcp-server # 初始化npm项目 npm init -y # 安装MCP SDK和TypeScript npm install @modelcontextprotocol/sdk typescript @types/node ts-node # 创建TypeScript配置 npx tsc --init修改tsconfig.json文件,确保包含以下关键配置:
{ "compilerOptions": { "target": "ES2020", "module": "CommonJS", "outDir": "./dist", "rootDir": "./src", "strict": true, "esModuleInterop": true, "skipLibCheck": true, "forceConsistentCasingInFileNames": true }, "include": ["src/**/*"], "exclude": ["node_modules", "dist"] }4.2 定义工具接口
创建src/types/weather.ts文件,定义天气查询的数据结构:
export interface WeatherRequest { city: string; country?: string; units?: 'metric' | 'imperial'; } export interface WeatherResponse { city: string; country: string; temperature: number; description: string; humidity: number; windSpeed: number; timestamp: string; } export interface WeatherError { error: string; message: string; }4.3 实现天气查询工具
创建src/tools/weatherTool.ts文件,实现核心的天气查询逻辑:
import { Tool } from '@modelcontextprotocol/sdk'; import { WeatherRequest, WeatherResponse, WeatherError } from '../types/weather'; export class WeatherTool { private readonly apiKey: string; private readonly baseUrl: string = 'http://api.openweathermap.org/data/2.5'; constructor(apiKey: string) { this.apiKey = apiKey; } // 定义工具元数据 getToolDefinition(): Tool { return { name: 'get_weather', description: '获取指定城市的当前天气信息', inputSchema: { type: 'object', properties: { city: { type: 'string', description: '城市名称(英文或拼音)' }, country: { type: 'string', description: '国家代码(可选),如CN、US' }, units: { type: 'string', enum: ['metric', 'imperial'], description: '温度单位:metric为摄氏度,imperial为华氏度' } }, required: ['city'] } }; } // 执行天气查询 async execute(input: WeatherRequest): Promise<WeatherResponse | WeatherError> { try { const query = input.country ? `${input.city},${input.country}` : input.city; const response = await fetch( `${this.baseUrl}/weather?q=${encodeURIComponent(query)}&units=${input.units || 'metric'}&appid=${this.apiKey}` ); if (!response.ok) { return { error: 'API_ERROR', message: `天气API请求失败: ${response.statusText}` }; } const data = await response.json(); return { city: data.name, country: data.sys.country, temperature: Math.round(data.main.temp), description: data.weather[0].description, humidity: data.main.humidity, windSpeed: data.wind.speed, timestamp: new Date().toISOString() }; } catch (error) { return { error: 'NETWORK_ERROR', message: `网络请求失败: ${error instanceof Error ? error.message : '未知错误'}` }; } } }4.4 创建MCP服务器主程序
创建src/index.ts文件,实现MCP服务器的主逻辑:
import { Server } from '@modelcontextprotocol/sdk/server/index.js'; import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; import { CallToolRequest, ListToolsRequest, ListToolsRequestSchema, CallToolRequestSchema, } from '@modelcontextprotocol/sdk/types.js'; import { WeatherTool } from './tools/weatherTool.js'; class WeatherMCPServer { private server: Server; private weatherTool: WeatherTool; constructor() { this.server = new Server( { name: 'weather-mcp-server', version: '1.0.0', }, { capabilities: { tools: {}, }, } ); // 初始化天气工具(在实际使用中应从环境变量获取API密钥) this.weatherTool = new WeatherTool(process.env.WEATHER_API_KEY || 'your-api-key-here'); this.setupToolHandlers(); this.setupErrorHandlers(); } private setupToolHandlers() { // 处理工具列表请求 this.server.setRequestHandler(ListToolsRequestSchema, async (): Promise<any> => { return { tools: [this.weatherTool.getToolDefinition()], }; }); // 处理工具调用请求 this.server.setRequestHandler(CallToolRequestSchema, async (request: CallToolRequest): Promise<any> => { if (request.params.name === 'get_weather') { const result = await this.weatherTool.execute(request.params.arguments as any); return { content: [ { type: 'text', text: JSON.stringify(result, null, 2), }, ], }; } throw new Error(`未知的工具: ${request.params.name}`); }); } private setupErrorHandlers() { this.server.onerror = (error) => { console.error('服务器错误:', error); }; process.on('SIGINT', async () => { await this.server.close(); process.exit(0); }); } async run() { const transport = new StdioServerTransport(); await this.server.connect(transport); console.error('Weather MCP服务器已启动,正在等待连接...'); } } // 启动服务器 const server = new WeatherMCPServer(); server.run().catch(console.error);4.5 配置Claude Desktop集成
创建claude.json配置文件,告诉Claude如何连接我们的MCP服务器:
{ "mcpServers": { "weather-server": { "command": "node", "args": [ "/absolute/path/to/your/weather-mcp-server/dist/index.js" ], "env": { "WEATHER_API_KEY": "your-actual-api-key" } } } }4.6 编译和测试
添加构建脚本到package.json:
{ "scripts": { "build": "tsc", "start": "node dist/index.js", "dev": "ts-node src/index.ts" } }执行构建和测试:
# 编译TypeScript代码 npm run build # 测试服务器 npm start5. 高级MCP服务器功能实现
5.1 多工具集成服务器
在实际项目中,我们通常需要集成多个相关工具。下面演示如何创建一个包含多个功能的MCP服务器:
创建src/tools/index.ts整合多个工具:
import { Tool } from '@modelcontextprotocol/sdk'; import { WeatherTool } from './weatherTool'; import { TimeZoneTool } from './timezoneTool'; import { CurrencyTool } from './currencyTool'; export class MultiToolServer { private tools: Map<string, any> = new Map(); constructor() { this.tools.set('weather', new WeatherTool(process.env.WEATHER_API_KEY!)); this.tools.set('timezone', new TimeZoneTool()); this.tools.set('currency', new CurrencyTool(process.env.CURRENCY_API_KEY!)); } getToolDefinitions(): Tool[] { return Array.from(this.tools.values()).map(tool => tool.getToolDefinition() ); } async executeTool(name: string, input: any): Promise<any> { const tool = this.tools.get(name); if (!tool) { throw new Error(`工具未找到: ${name}`); } return await tool.execute(input); } getAvailableTools(): string[] { return Array.from(this.tools.keys()); } }5.2 资源管理功能
MCP协议不仅支持工具调用,还支持资源管理。下面实现一个文件资源管理器:
创建src/resources/fileResource.ts:
import { ResourceTemplate } from '@modelcontextprotocol/sdk'; import { readFile, writeFile, readdir, stat } from 'fs/promises'; import { join } from 'path'; export class FileResourceManager { getResourceTemplates(): ResourceTemplate[] { return [ { uri: 'file:///{path}', name: '文件资源', description: '访问本地文件系统', mimeType: 'text/plain', schema: { type: 'object', properties: { path: { type: 'string', description: '文件路径' } }, required: ['path'] } } ]; } async readFileResource(uri: string): Promise<string> { const path = uri.replace('file:///', ''); return await readFile(path, 'utf-8'); } async listDirectory(path: string): Promise<any[]> { const files = await readdir(path); const result = []; for (const file of files) { const filePath = join(path, file); const stats = await stat(filePath); result.push({ name: file, path: filePath, type: stats.isDirectory() ? 'directory' : 'file', size: stats.size, modified: stats.mtime }); } return result; } }5.3 错误处理与日志记录
健壮的MCP服务器需要完善的错误处理机制:
创建src/utils/logger.ts:
export class Logger { private readonly logLevel: string; constructor(level: string = 'info') { this.logLevel = level; } error(message: string, error?: any) { console.error(`[ERROR] ${message}`, error || ''); } warn(message: string) { if (this.logLevel === 'error') return; console.warn(`[WARN] ${message}`); } info(message: string) { if (this.logLevel === 'error' || this.logLevel === 'warn') return; console.log(`[INFO] ${message}`); } debug(message: string) { if (this.logLevel !== 'debug') return; console.debug(`[DEBUG] ${message}`); } }增强的错误处理中间件:
import { Logger } from '../utils/logger'; export class ErrorHandler { private logger: Logger; constructor() { this.logger = new Logger(process.env.LOG_LEVEL || 'info'); } handleToolError(error: any, toolName: string, input: any) { this.logger.error(`工具执行失败: ${toolName}`, { error: error.message, input, timestamp: new Date().toISOString() }); return { error: 'EXECUTION_ERROR', message: `工具 ${toolName} 执行失败: ${error.message}`, timestamp: new Date().toISOString() }; } validateToolInput(schema: any, input: any): string[] { const errors: string[] = []; // 检查必需字段 if (schema.required) { for (const field of schema.required) { if (input[field] === undefined || input[field] === null) { errors.push(`缺少必需字段: ${field}`); } } } // 检查字段类型 if (schema.properties) { for (const [field, definition] of Object.entries(schema.properties) as [string, any][]) { if (input[field] !== undefined) { if (definition.type && typeof input[field] !== definition.type) { errors.push(`字段 ${field} 类型错误,期望 ${definition.type}`); } } } } return errors; } }6. Claude Desktop集成配置详解
6.1 配置文件详解
Claude Desktop通过JSON配置文件管理MCP服务器集成。以下是完整的配置示例:
创建~/.claude/mcp-servers/weather-server.json:
{ "command": "/usr/local/bin/node", "args": [ "/Users/yourusername/projects/weather-mcp-server/dist/index.js" ], "env": { "WEATHER_API_KEY": "your-openweathermap-api-key", "LOG_LEVEL": "info", "NODE_ENV": "production" }, "timeout": 30000, "cwd": "/Users/yourusername/projects/weather-mcp-server", "disabled": false }6.2 环境变量安全管理
敏感信息如API密钥应该通过环境变量管理:
创建.env文件(不要提交到版本控制):
WEATHER_API_KEY=your_actual_api_key_here CURRENCY_API_KEY=your_currency_api_key LOG_LEVEL=info使用dotenv加载配置:
import { config } from 'dotenv'; config(); // 验证必需的环境变量 const requiredEnvVars = ['WEATHER_API_KEY']; for (const envVar of requiredEnvVars) { if (!process.env[envVar]) { throw new Error(`缺少必需的环境变量: ${envVar}`); } }6.3 调试配置
创建VS Code调试配置文件.vscode/launch.json:
{ "version": "0.2.0", "configurations": [ { "name": "调试MCP服务器", "type": "node", "request": "launch", "program": "${workspaceFolder}/src/index.ts", "outFiles": ["${workspaceFolder}/dist/**/*.js"], "runtimeArgs": ["-r", "ts-node/register"], "env": { "WEATHER_API_KEY": "test-key", "LOG_LEVEL": "debug" }, "console": "integratedTerminal" } ] }7. ChatGPT自定义GPT集成方案
7.1 创建自定义GPT动作
虽然ChatGPT目前对MCP的原生支持不如Claude完善,但我们可以通过自定义GPT的Actions功能实现类似效果:
创建openapi.yaml文件定义API接口:
openapi: 3.1.0 info: title: Weather MCP Server API description: 为ChatGPT提供天气查询功能的MCP兼容接口 version: 1.0.0 servers: - url: https://your-api-domain.com description: 生产环境服务器 paths: /weather: post: operationId: getWeather summary: 获取城市天气信息 description: 查询指定城市的当前天气状况 requestBody: required: true content: application/json: schema: type: object properties: city: type: string description: 城市名称 country: type: string description: 国家代码(可选) units: type: string enum: [metric, imperial] description: 温度单位 required: - city responses: '200': description: 成功返回天气信息 content: application/json: schema: type: object properties: city: type: string temperature: type: number description: type: string humidity: type: number windSpeed: type: number7.2 实现HTTP MCP服务器
创建基于HTTP的MCP服务器适配器:
import express from 'express'; import { WeatherTool } from './tools/weatherTool'; class HTTPMCPServer { private app: express.Application; private weatherTool: WeatherTool; constructor() { this.app = express(); this.weatherTool = new WeatherTool(process.env.WEATHER_API_KEY!); this.setupMiddleware(); this.setupRoutes(); } private setupMiddleware() { this.app.use(express.json()); this.app.use((req, res, next) => { res.header('Access-Control-Allow-Origin', '*'); res.header('Access-Control-Allow-Headers', 'Content-Type'); next(); }); } private setupRoutes() { // MCP协议兼容端点 this.app.post('/mcp/tools/list', (req, res) => { res.json({ tools: [this.weatherTool.getToolDefinition()] }); }); this.app.post('/mcp/tools/call', async (req, res) => { try { const { name, arguments: args } = req.body; if (name === 'get_weather') { const result = await this.weatherTool.execute(args); res.json({ content: [{ type: 'text', text: JSON.stringify(result) }] }); } else { res.status(404).json({ error: '工具未找到' }); } } catch (error) { res.status(500).json({ error: '执行失败', message: error instanceof Error ? error.message : '未知错误' }); } }); // ChatGPT Actions兼容端点 this.app.post('/chatgpt/weather', async (req, res) => { try { const { city, country, units } = req.body; const result = await this.weatherTool.execute({ city, country, units }); res.json(result); } catch (error) { res.status(500).json({ error: '天气查询失败', details: error instanceof Error ? error.message : '未知错误' }); } }); } start(port: number = 3000) { this.app.listen(port, () => { console.log(`HTTP MCP服务器运行在端口 ${port}`); }); } } const server = new HTTPMCPServer(); server.start();8. 常见问题与解决方案
8.1 连接与配置问题
问题1:Claude Desktop无法识别MCP服务器
现象:启动Claude后看不到自定义工具排查步骤:
- 检查配置文件路径是否正确:
~/.claude/mcp-servers/ - 确认JSON配置文件格式正确
- 查看Claude Desktop日志(帮助 → 查看日志)
- 验证node路径和脚本路径是否正确
解决方案:
# 检查node路径 which node # 测试直接运行MCP服务器 node /path/to/your/mcp-server/dist/index.js问题2:权限错误或文件不存在
现象:服务器启动失败,提示权限不足解决方案:
# 给脚本添加执行权限 chmod +x /path/to/your/script.js # 检查文件路径是否存在 ls -la /path/to/your/mcp-server/8.2 工具执行问题
问题3:工具调用超时
现象:AI助手显示工具执行超时可能原因:
- 网络连接缓慢
- API响应时间过长
- 服务器处理逻辑复杂
优化方案:
// 添加超时控制 async executeWithTimeout(input: any, timeoutMs: number = 10000) { const timeoutPromise = new Promise((_, reject) => setTimeout(() => reject(new Error('执行超时')), timeoutMs) ); const executionPromise = this.execute(input); return Promise.race([executionPromise, timeoutPromise]); }问题4:API密钥错误或配额不足
现象:工具返回认证错误解决方案:
// 实现API密钥轮换 class APIKeyManager { private keys: string[]; private currentIndex: number = 0; constructor(keys: string[]) { this.keys = keys; } getCurrentKey(): string { return this.keys[this.currentIndex]; } rotateKey(): void { this.currentIndex = (this.currentIndex + 1) % this.keys.length; } handleAuthError(): void { this.rotateKey(); } }8.3 性能优化问题
问题5:服务器响应缓慢
优化策略:
- 实现结果缓存
- 使用连接池
- 优化数据库查询
- 启用压缩
// 简单的内存缓存实现 class CacheManager { private cache: Map<string, { data: any; expiry: number }> = new Map(); private defaultTTL: number = 300000; // 5分钟 get(key: string): any { const item = this.cache.get(key); if (!item || Date.now() > item.expiry) { this.cache.delete(key); return null; } return item.data; } set(key: string, data: any, ttl?: number): void { this.cache.set(key, { data, expiry: Date.now() + (ttl || this.defaultTTL) }); } }9. 安全最佳实践
9.1 输入验证与消毒
所有用户输入都必须经过严格验证:
export class SecurityValidator { static validateCityName(city: string): boolean { // 只允许字母、空格、连字符和基本标点 const validPattern = /^[a-zA-Z\s\-',\.]+$/; return validPattern.test(city) && city.length <= 100; } static sanitizeInput(input: string): string { // 移除潜在的恶意字符 return input .replace(/[<>]/g, '') .replace(/javascript:/gi, '') .replace(/on\w+=/gi, '') .trim(); } static validateAPIInput(schema: any, input: any): { isValid: boolean; errors: string[] } { const errors: string[] = []; for (const [key, value] of Object.entries(input)) { // 检查未知字段 if (!schema.properties[key]) { errors.push(`未知字段: ${key}`); continue; } // 类型检查 const fieldSchema = schema.properties[key]; if (fieldSchema.type && typeof value !== fieldSchema.type) { errors.push(`字段 ${key} 类型错误`); } // 枚举值检查 if (fieldSchema.enum && !fieldSchema.enum.includes(value)) { errors.push(`字段 ${key} 值不在允许范围内`); } } return { isValid: errors.length === 0, errors }; } }9.2 权限控制与访问限制
实现基于上下文的权限控制:
class PermissionManager { private allowedTools: Map<string, string[]> = new Map(); constructor() { // 定义工具访问权限 this.allowedTools.set('weather', ['public']); this.allowedTools.set('file_read', ['authenticated']); this.allowedTools.set('admin_tools', ['admin']); } canAccessTool(toolName: string, userContext: any): boolean { const requiredRoles = this.allowedTools.get(toolName); if (!requiredRoles) return false; return requiredRoles.some(role => userContext.roles?.includes(role) || role === 'public' ); } auditToolUsage(toolName: string, input: any, userContext: any): void { console.log(`[AUDIT] 工具使用记录`, { tool: toolName, user: userContext.userId, input: this.sanitizeForLogging(input), timestamp: new Date().toISOString(), ip: userContext.ipAddress }); } private sanitizeForLogging(input: any): any { const sanitized = { ...input }; // 移除敏感信息 if (sanitized.password) delete sanitized.password; if (sanitized.apiKey) delete sanitized.apiKey; return sanitized; } }9.3 错误信息处理
避免在错误响应中泄露敏感信息:
export class SafeErrorHandler { static sanitizeError(error: any): { message: string; code: string } { // 生产环境中隐藏详细错误信息 if (process.env.NODE_ENV === 'production') { if (error instanceof DatabaseError) { return { message: '数据库操作失败', code: 'DB_ERROR' }; } if (error instanceof NetworkError) { return { message: '网络连接失败', code: 'NETWORK_ERROR' }; } return { message: '操作失败', code: 'GENERIC_ERROR' }; } // 开发环境显示详细错误 return { message: error.message, code: error.code || 'UNKNOWN_ERROR' }; } }10. 生产环境部署指南
10.1 容器化部署
创建Dockerfile优化生产环境部署:
FROM node:18-alpine WORKDIR /app # 安装依赖 COPY package*.json ./ RUN npm ci --only=production # 复制编译后的代码 COPY dist/ ./dist/ # 创建非root用户 RUN addgroup -g 1001 -S nodejs RUN adduser -S mcp-server -u 1001 USER mcp-server # 健康检查 HEALTHCHECK --interval=30s --timeout=3s \ CMD node -e "require('http').get('http://localhost:3000/health', (res) => { process.exit(res.statusCode === 200 ? 0 : 1) })" EXPOSE 3000 CMD ["node", "dist/index.js"]创建docker-compose.yml简化部署:
version: '3.8' services: mcp-server: build: . ports: - "3000:3000" environment: - NODE_ENV=production - WEATHER_API_KEY=${WEATHER_API_KEY} - LOG_LEVEL=info restart: unless-stopped healthcheck: test: ["CMD", "node", "-e", "require('http').get('http://localhost:3000/health', (res) => { process.exit(res.statusCode === 200 ? 0 : 1) })"] interval: 30s timeout: 10s retries: 310.2 监控与日志
实现完整的监控体系:
import { createLogger, format, transports } from 'winston'; export const logger = createLogger({ level: process.env.LOG_LEVEL || 'info', format: format.combine( format.timestamp(), format.errors({ stack: true }), format.json() ), transports: [ new transports.File({ filename: 'error.log', level: 'error' }), new transports.File({ filename: 'combined.log' }), new transports.Console({ format: format.simple() }) ] }); // 性能监控 export class PerformanceMonitor { private metrics: Map<string, number[]> = new Map(); startTimer(operation: string): () => number { const start = Date.now(); return () => { const duration = Date.now() - start; this.recordMetric(operation, duration); return duration; }; } private recordMetric(operation: string, duration: number): void { if (!this.metrics.has(operation)) { this.metrics.set(operation, []); } this.metrics.get(operation)!.push(duration); // 定期清理旧数据 if (this.metrics.get(operation)!.length > 1000) { this.metrics.set(operation, this.metrics.get(operation)!.slice(-500)); } } getMetrics(): any { const result: any = {}; for (const [operation, durations] of this.metrics) { result[operation] = { count: durations.length, average: durations.reduce((a, b) => a + b, 0) / durations.length, p95: this.percentile(durations, 95), max: Math.max(...durations) }; } return result; } private percentile(arr: number[], p: number): number { const sorted = [...arr].sort((a, b) => a - b); const index = Math.ceil((p / 100) * sorted.length) - 1; return sorted[index]; } }通过本文的完整指南,你应该已经掌握了MCP服务器的核心概念、开发流程和部署实践。从简单的天气查询工具到复杂的企业级集成,MCP协议为AI助手的能力扩展提供了标准化且强大的解决方案。
在实际项目中,建议先从简单的工具开始,逐步扩展到复杂的业务场景。记得始终遵循安全最佳实践,特别是在处理敏感数据和外部API集成时。随着MCP生态的不断发展,这项技术将为AI应用开发带来更多可能性。