📑 目录导航
快速索引
- 一、核心使用流程
- 步骤 1: 环境准备
- 步骤 2: 创建 MCP 服务器
- 步骤 3: 客户端集成
- 步骤 4: 验证运行
- 二、场景化配置模板
- 场景 1: 数据库连接 (PostgreSQL)
- 场景 2: API 集成
- 场景 3: 本地工具链集成
- 场景 4: 文件系统访问
- 三、部署与运维
- 1. 本地开发环境
- 2. 生产环境部署 (Docker/K8s)
- 3. 监控与日志
- 四、最佳实践指南
- 1. 安全性最佳实践
- 2. 性能优化建议
- 3. 错误处理模式
- 五、配套流程图
- 1. 配置加载流程图
- 2. 工具调用时序图
- 3. 多场景部署拓扑图
- 4. 错误排查决策树
- 六、故障排查手册
- 常见问题速查表
- 配置验证脚本
一、核心使用流程
步骤 1: 环境准备
系统要求
- Node.js >= 18.0.0
- Python >= 3.9 (可选,用于Python MCP服务器)
- 操作系统: Linux / macOS / Windows
安装 MCP SDK
# Node.js 环境
npm install @modelcontextprotocol/sdk
# Python 环境
pip install mcp
# 验证安装
npm list @modelcontextprotocol/sdk
python -c "import mcp; print(mcp.__version__)"
💡 提示: 建议使用 nvm 或 pyenv 管理多版本环境
基础服务器模板 (Node.js)
// server.js
const { MCPServer } = require('@modelcontextprotocol/sdk');
const server = new MCPServer({
name: 'my-mcp-server',
version: '1.0.0'
});
// 注册工具
server.tool('get_weather', {
description: '获取城市天气信息',
parameters: {
city: { type: 'string', required: true }
}
}, async ({ city }) => {
return { temperature: 25, condition: 'sunny' };
});
// 启动服务器
server.listen(3000);
步骤 2: 创建 MCP 服务器
配置文件示例
{
"mcpServers": {
"weather-service": {
"command": "node",
"args": ["server.js"],
"env": {
"API_KEY": "your-api-key"
}
}
}
}
步骤 3: 客户端集成
const { MCPClient } = require('@modelcontextprotocol/sdk');
const client = new MCPClient();
// 连接到服务器
await client.connect('stdio', {
command: 'node',
args: ['server.js']
});
// 调用工具
const result = await client.callTool('get_weather', {
city: 'Beijing'
});
console.log(result); // { temperature: 25, condition: 'sunny' }
步骤 4: 验证运行
测试命令
# 启动服务器
node server.js
# 测试工具调用
curl -X POST http://localhost:3000/tools/get_weather \
-H "Content-Type: application/json" \
-d '{"city": "Beijing"}'
# 查看日志
tail -f logs/mcp-server.log
📝 成功标志:
- 服务器启动无错误
- 工具调用返回预期结果
- 日志显示正常连接信息
二、场景化配置模板
场景 1: 数据库连接
PostgreSQL 配置示例
最小配置{
"mcpServers": {
"postgres-db": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-postgres"],
"env": {
"POSTGRES_URL": "postgresql://user:pass@localhost:5432/db"
}
}
}
}
{
"mcpServers": {
"postgres-db": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-postgres"],
"env": {
"POSTGRES_URL": "postgresql://user:pass@localhost:5432/db",
"MAX_CONNECTIONS": "20",
"CONNECTION_TIMEOUT": "5000",
"QUERY_TIMEOUT": "30000",
"SSL_MODE": "require"
}
}
}
}
工具调用示例
// 查询数据
const result = await client.callTool('query', {
sql: 'SELECT * FROM users WHERE age > $1',
params: [18]
});
// 错误处理
try {
await client.callTool('query', { sql: 'INVALID SQL' });
} catch (error) {
console.error('Query failed:', error.message);
}
调试命令
# 测试数据库连接
psql $POSTGRES_URL -c "SELECT 1"
# 查看活动连接
psql $POSTGRES_URL -c "SELECT * FROM pg_stat_activity"
场景 2: API 集成
第三方 API 配置
最小配置{
"mcpServers": {
"weather-api": {
"command": "node",
"args": ["api-server.js"],
"env": {
"API_KEY": "your-key",
"API_URL": "https://api.weather.com"
}
}
}
}
{
"mcpServers": {
"weather-api": {
"command": "node",
"args": ["api-server.js"],
"env": {
"API_KEY": "your-key",
"API_URL": "https://api.weather.com",
"RATE_LIMIT": "100",
"RATE_WINDOW": "60000",
"RETRY_ATTEMPTS": "3",
"RETRY_DELAY": "1000",
"TIMEOUT": "5000",
"CACHE_TTL": "300"
}
}
}
}
请求封装示例
server.tool('fetch_weather', {
description: '获取天气数据',
parameters: {
city: { type: 'string', required: true }
}
}, async ({ city }) => {
const response = await fetch(`${process.env.API_URL}/weather`, {
method: 'GET',
headers: {
'Authorization': `Bearer ${process.env.API_KEY}`,
'Content-Type': 'application/json'
},
params: { city }
});
return await response.json();
});
速率限制与重试
const rateLimit = require('express-rate-limit');
const limiter = rateLimit({
windowMs: parseInt(process.env.RATE_WINDOW),
max: parseInt(process.env.RATE_LIMIT)
});
// 重试机制
async function retryRequest(fn, attempts = 3) {
for (let i = 0; i < attempts; i++) {
try {
return await fn();
} catch (error) {
if (i === attempts - 1) throw error;
await new Promise(r => setTimeout(r, 1000 * (i + 1)));
}
}
}
场景 3: 本地工具链集成
文件系统操作配置
基础配置{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem"],
"env": {
"ALLOWED_PATHS": "/home/user/documents,/tmp",
"MAX_FILE_SIZE": "10485760",
"ALLOWED_EXTENSIONS": ".txt,.md,.json"
}
}
}
}
工具调用示例
// 读取文件
const content = await client.callTool('read_file', {
path: '/home/user/documents/data.json'
});
// 写入文件
await client.callTool('write_file', {
path: '/home/user/documents/output.txt',
content: 'Hello, MCP!'
});
// 列出目录
const files = await client.callTool('list_directory', {
path: '/home/user/documents'
});
Shell 命令暴露
server.tool('execute_command', {
description: '执行系统命令',
parameters: {
command: { type: 'string', required: true }
}
}, async ({ command }) => {
// 安全检查
const allowedCommands = ['ls', 'cat', 'grep'];
const cmd = command.split(' ')[0];
if (!allowedCommands.includes(cmd)) {
throw new Error('Command not allowed');
}
const { exec } = require('child_process');
return new Promise((resolve, reject) => {
exec(command, (error, stdout, stderr) => {
if (error) reject(error);
else resolve({ stdout, stderr });
});
});
});
⚠️ 安全提示: 始终验证和限制可执行的命令,避免命令注入攻击
场景 4: Claude Desktop 集成
配置文件路径
# macOS
~/Library/Application Support/Claude/claude_desktop_config.json
# Windows
%APPDATA%\Claude\claude_desktop_config.json
# Linux
~/.config/Claude/claude_desktop_config.json
配置示例
{
"mcpServers": {
"mytools": {
"command": "node",
"args": ["/path/to/server.js"],
"env": {
"API_KEY": "your-key"
}
},
"database": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-postgres"],
"env": {
"POSTGRES_URL": "postgresql://localhost:5432/mydb"
}
}
}
}
💡 提示: 配置后需要重启 Claude Desktop 才能生效
三、部署与运维
1. 本地开发环境
环境变量配置清单
# .env 文件
NODE_ENV=development
MCP_PORT=3000
LOG_LEVEL=debug
DB_URL=postgresql://localhost:5432/dev
API_KEY=dev-key-123
CACHE_ENABLED=false
端口与网络设置
| 参数 | 默认值 | 说明 |
|---|---|---|
| MCP_PORT | 3000 | 服务监听端口 |
| MCP_HOST | 127.0.0.1 | 绑定地址 |
| CORS_ORIGIN | * | 允许的跨域来源 |
日志配置
const winston = require('winston');
const logger = winston.createLogger({
level: process.env.LOG_LEVEL || 'info',
format: winston.format.json(),
transports: [
new winston.transports.File({ filename: 'error.log', level: 'error' }),
new winston.transports.File({ filename: 'combined.log' })
]
});
2. 生产环境部署
环境变量配置清单
# .env.production
NODE_ENV=production
MCP_PORT=3000
LOG_LEVEL=warn
DB_URL=postgresql://prod-host:5432/prod
API_KEY=prod-key-secure
CACHE_ENABLED=true
REDIS_URL=redis://redis:6379
MAX_CONNECTIONS=100
REQUEST_TIMEOUT=30000
Docker 容器化配置
DockerfileFROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
EXPOSE 3000
HEALTHCHECK --interval=30s --timeout=3s \
CMD node healthcheck.js
CMD ["node", "server.js"]
version: '3.8'
services:
mcp-server:
build: .
ports:
- "3000:3000"
environment:
- NODE_ENV=production
- DB_URL=postgresql://db:5432/prod
restart: unless-stopped
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
健康检查端点
// healthcheck.js
const http = require('http');
const options = {
host: 'localhost',
port: 3000,
path: '/health',
timeout: 2000
};
const request = http.request(options, (res) => {
if (res.statusCode === 200) {
process.exit(0);
} else {
process.exit(1);
}
});
request.on('error', () => process.exit(1));
request.end();
性能调优参数
| 参数 | 推荐值 | 说明 |
|---|---|---|
| NODE_OPTIONS | --max-old-space-size=4096 | 最大堆内存 |
| UV_THREADPOOL_SIZE | 128 | 线程池大小 |
| MAX_CONNECTIONS | 100 | 最大并发连接 |
3. 监控与日志
日志聚合配置
const winston = require('winston');
const { ElasticsearchTransport } = require('winston-elasticsearch');
const logger = winston.createLogger({
level: process.env.LOG_LEVEL || 'info',
format: winston.format.combine(
winston.format.timestamp(),
winston.format.json()
),
transports: [
// 文件日志
new winston.transports.File({
filename: 'error.log',
level: 'error'
}),
new winston.transports.File({
filename: 'combined.log'
}),
// Elasticsearch (可选)
new ElasticsearchTransport({
level: 'info',
clientOpts: { node: 'http://elasticsearch:9200' }
})
]
});
健康监控指标
server.tool('health', {
description: '健康检查端点'
}, async () => {
return {
status: 'healthy',
uptime: process.uptime(),
memory: process.memoryUsage(),
timestamp: Date.now(),
version: '1.0.0'
};
});
// Prometheus 指标暴露
const client = require('prom-client');
const register = new client.Registry();
const httpRequestDuration = new client.Histogram({
name: 'mcp_request_duration_seconds',
help: 'Duration of MCP requests in seconds',
labelNames: ['tool', 'status']
});
register.registerMetric(httpRequestDuration);
四、最佳实践指南
1. 安全性最佳实践
环境变量管理
// ❌ 错误: 硬编码敏感信息
const apiKey = 'sk-1234567890abcdef';
// ✅ 正确: 使用环境变量
const apiKey = process.env.API_KEY;
if (!apiKey) {
throw new Error('API_KEY environment variable is required');
}
输入验证
server.tool('query_user', {
description: '查询用户信息',
parameters: {
userId: {
type: 'string',
required: true,
pattern: '^[0-9a-f]{24}$' // MongoDB ObjectId 格式
}
}
}, async ({ userId }) => {
// 参数清理
const sanitizedId = userId.trim();
// 二次验证
if (!/^[0-9a-f]{24}$/.test(sanitizedId)) {
throw new Error('Invalid user ID format');
}
return await db.users.findById(sanitizedId);
});
权限控制
const permissions = {
'read': ['read_file', 'list_directory'],
'write': ['write_file', 'delete_file'],
'admin': ['execute_command', 'system_info']
};
function checkPermission(toolName, userRole) {
const allowedTools = permissions[userRole] || [];
if (!allowedTools.includes(toolName)) {
throw new Error(`Permission denied for tool: ${toolName}`);
}
}
2. 性能优化建议
连接池配置
const { Pool } = require('pg');
const pool = new Pool({
host: process.env.DB_HOST,
port: 5432,
database: process.env.DB_NAME,
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
// 连接池配置
min: 5, // 最小连接数
max: 20, // 最大连接数
idleTimeoutMillis: 30000, // 空闲超时
connectionTimeoutMillis: 2000
});
缓存策略
const Redis = require('ioredis');
const redis = new Redis(process.env.REDIS_URL);
server.tool('get_user', {
description: '获取用户信息 (带缓存)'
}, async ({ userId }) => {
// 尝试从缓存获取
const cacheKey = `user:${userId}`;
const cached = await redis.get(cacheKey);
if (cached) {
return JSON.parse(cached);
}
// 从数据库查询
const user = await db.users.findById(userId);
// 写入缓存 (5分钟过期)
await redis.setex(cacheKey, 300, JSON.stringify(user));
return user;
});
批量操作优化
// ❌ 低效: 循环查询
for (const id of userIds) {
const user = await db.users.findById(id);
results.push(user);
}
// ✅ 高效: 批量查询
const users = await db.users.find({
_id: { $in: userIds }
});
3. 错误处理模式
统一错误处理
class MCPError extends Error {
constructor(code, message, details = {}) {
super(message);
this.code = code;
this.details = details;
}
}
server.tool('risky_operation', {
description: '可能失败的操作'
}, async (params) => {
try {
return await performOperation(params);
} catch (error) {
// 分类错误
if (error.code === 'ECONNREFUSED') {
throw new MCPError(
'CONNECTION_ERROR',
'Unable to connect to backend service',
{ originalError: error.message }
);
}
if (error.name === 'ValidationError') {
throw new MCPError(
'INVALID_INPUT',
'Input validation failed',
{ fields: error.errors }
);
}
// 未知错误
throw new MCPError(
'INTERNAL_ERROR',
'An unexpected error occurred',
{ originalError: error.message }
);
}
});
重试机制
async function withRetry(fn, options = {}) {
const {
maxAttempts = 3,
delayMs = 1000,
backoffMultiplier = 2,
retryableErrors = ['ETIMEDOUT', 'ECONNRESET']
} = options;
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
try {
return await fn();
} catch (error) {
// 判断是否可重试
const isRetryable = retryableErrors.includes(error.code);
const isLastAttempt = attempt === maxAttempts;
if (!isRetryable || isLastAttempt) {
throw error;
}
// 指数退避
const delay = delayMs * Math.pow(backoffMultiplier, attempt - 1);
await new Promise(resolve => setTimeout(resolve, delay));
}
}
}
// 使用示例
const result = await withRetry(
() => client.callTool('unstable_api', params),
{ maxAttempts: 3, delayMs: 1000 }
);
优雅降级
server.tool('get_recommendations', {
description: '获取推荐 (带降级)'
}, async ({ userId }) => {
try {
// 尝试使用 AI 推荐
return await aiService.getRecommendations(userId);
} catch (error) {
logger.warn('AI service unavailable, falling back to rules-based');
// 降级到规则引擎
return await rulesEngine.getRecommendations(userId);
}
});
五、配套流程图
1. 配置加载流程图
2. 工具调用时序图
3. 多场景部署拓扑图
4. 错误排查决策树
六、故障排查手册
常见问题速查表
问题 1: 服务器无法启动
| 错误信息 | 可能原因 | 解决方案 |
|---|---|---|
| EADDRINUSE | 端口已被占用 | 修改端口或关闭占用进程: lsof -i :3000 |
| MODULE_NOT_FOUND | 依赖未安装 | 运行 npm install |
| EACCES | 权限不足 | 检查文件权限或使用正确的用户运行 |
| Invalid JSON | 配置文件格式错误 | 使用 JSON 校验工具检查语法 |
问题 2: 工具调用失败
# 检查服务器日志
tail -f logs/mcp-server.log
# 测试工具是否注册
curl http://localhost:3000/tools
# 使用调试模式启动
LOG_LEVEL=debug node server.js
问题 3: 性能问题
- 响应慢: 检查数据库连接池配置,启用缓存
- 内存泄漏: 使用
node --inspect server.js进行内存分析 - 高 CPU: 优化查询语句,减少计算密集型操作
问题 4: Claude Desktop 未识别服务器
检查清单:
- ✓ 配置文件路径是否正确
- ✓ JSON 格式是否有效 (使用
jq . config.json验证) - ✓ 命令路径是否为绝对路径
- ✓ 是否重启了 Claude Desktop
- ✓ 查看 Claude 日志:
~/Library/Logs/Claude/
调试技巧
启用详细日志
# 设置环境变量
export DEBUG=mcp:*
export LOG_LEVEL=debug
# 启动服务器
node server.js 2>&1 | tee server.log
使用 MCP Inspector 工具
# 安装 inspector
npm install -g @modelcontextprotocol/inspector
# 启动 inspector
mcp-inspector node server.js
# 在浏览器打开
# http://localhost:5173
配置验证脚本
// validate-config.js
const fs = require('fs');
function validateConfig(configPath) {
try {
const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
// 检查必需字段
if (!config.mcpServers) {
throw new Error('Missing mcpServers field');
}
// 验证每个服务器配置
for (const [name, server] of Object.entries(config.mcpServers)) {
if (!server.command) {
throw new Error(`Server ${name}: missing command`);
}
if (!Array.isArray(server.args)) {
throw new Error(`Server ${name}: args must be an array`);
}
console.log(`✓ Server ${name} configuration valid`);
}
console.log('\n✓ All configurations valid!');
return true;
} catch (error) {
console.error(`✗ Validation failed: ${error.message}`);
return false;
}
}
// 使用示例
validateConfig('./mcp-config.json');
运行验证
node validate-config.js
# 输出示例:
# ✓ Server postgres-db configuration valid
# ✓ Server weather-api configuration valid
# ✓ All configurations valid!