使用说明
这个MCP的规格
-
仕様:此MCP是输入的内容直接返回的简单的方法。该规格是通过直接返还用户的输入,确认基本动作的原型。
-
役割:本规格为MCP作为服务器的平台提供,作为今后发展和定制的基础。
MCP服务器开发指南
1.项目设置
# 1. プロジェクトディレクトリの作成
mkdir my-mcp-server && cd my-mcp-server
# 2. npmプロジェクトの初期化
npm init -y
# 3. 必要な依存関係のインストール
npm install @modelcontextprotocol/sdk typescript
npm install -D @types/node
# 4. TypeScript設定の初期化
npx tsc --init
2.重要配置文件
package.json
{
"name": "my-mcp-server",
"version": "1.0.0",
"type": "module", // ESモジュールを使用
"main": "build/index.js",
"scripts": {
"build": "tsc && node -e \"require('fs').chmodSync('build/index.js', '755')\"",
"start": "node build/index.js",
"dev": "npm run build && npm start"
}
}
tsconfig.json
{
"compilerOptions": {
"target": "ES2020",
"module": "ES2020",
"moduleResolution": "node",
"outDir": "./build",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true
}
}
3.安装要点
基本构造
- 创建服务器实例
- 功能定义
- 实现请求处理程序
- 设置错误处理
- 启动服务器
重要注意事项
-
ES模块化
- package.json单击功能区上
"type": "module"的规格化距离的幂函数 - 在导入路径中
.js包括(例如:sdk/server/index.js)
- package.json单击功能区上
-
利用类型定义
- 模式定义输入验证
- 正确使用错误类型
-
错误处理
- MCP使用错误类型
- 正确选择错误代码
- 提供详细的错误消息
-
安全考虑
- 验证输入值
- 设置执行权限
- 适当管理环境变量
4.部署过程
Cline (Cursor)配置
// settings/cline_mcp_settings.json
{
"mcpServers": {
"my-server": {
"command": "node",
"args": ["/path/to/my-mcp-server/build/index.js"],
"env": {},
"disabled": false,
"alwaysAllow": ["my_tool"]
}
}
}
Claude Desktop配置
// claude_desktop_config.json
{
"mcpServers": {
"my-server": {
"command": "node",
"args": ["/path/to/my-mcp-server/build/index.js"],
"env": {},
"disabled": false,
"alwaysAllow": ["my_tool"]
}
}
}
5.故障排除
-
权限错误
- 在构建脚本中授予执行权限
chmod +x build/index.js执行
-
模块解析错误
- 通过
.js包括扩展名 moduleResolution正确设置
- 通过
-
环境变量问题
- 在配置文件中适当定义环境变量
- 在运行时确认环境变量是否可用
-
安全限制
alwaysAllow确认的设置- 确认是否已授予所需权限
6.最佳实践
-
模块化
- 按功能拆分模块
- 提取可重用代码
-
错误处理
- 详细的错误信息
- 错误分层
- 适当的日志输出
-
测试
- 创建设备测试
- 实施集成测试
- 考虑边缘情况
-
文档
- 代码注释增强
- API制作式样书
- 提供使用示例
7.常见问题与对策
SDK相关问题
-
SDK版本不匹配
- 问题:
No matching version found for @modelcontextprotocol/sdk@^x.x.x - 原因:package.json中指定的版本不存在
- 対策:
- 现有MCP服务器package.json确认
- 使用已确认动作的版本(当前为^1.5.0)
- 版本化使用^(小盒)确保兼容性
- 问题:
-
模块解决问题
- 问题:
Cannot find module '@modelcontextprotocol/sdk/server/index' - 原因:ES模块和CommonJS混合问题
- 対策:
- package.json在…之上
"type": "module"添加 - 在导入路径中
.js添加 - tsconfig.json单击功能区上
"module": "ES2020"指定
- package.json在…之上
- 问题:
文件系统权限问题
-
执行权限错误
- 问题:
Permission denied不能实行 - 原因:构建的文件没有执行权限
- 対策:
- 在构建脚本中chmod 添加
"build": "tsc && node -e \"require('fs').chmodSync('build/index.js', '755')\""
- 问题:
-
文件写入权限
- 问题:
OSError: Read-only file system - 原因:进程没有写权限
- 対策:
- 使用临时目录
- 指定具有适当权限的目录
- 如果需要sudo 按权限运行
- 问题:
配置文件关系
-
配置文件识别问题
- 问题:MCP未检测到服务器
- 原因:配置文件路径或格式不正确
- 対策:
- 使用绝对路径
- alwaysAllow工具名称
- 更新两个配置文件
- 克莱恩:
~/Library/Application Support/Cursor/User/globalStorage/rooveterinaryinc.roo-cline/settings/cline_mcp_settings.json - 克劳德:
~/Library/Application Support/Claude/claude_desktop_config.json
- 克莱恩:
-
环境变量问题
- 问题:未识别环境变量
- 原因:在配置文件中指定环境变量不恰当
- 対策:
- MCP在服务器设置的“env”部分中明确指定
- 机密信息通过环境变量传递
"env": { "API_KEY": "your-api-key" }
流程管理
-
重复启动进程
- 问题:启动多个相同的服务器
- 原因:上一个进程未完成
- 対策:
- 使用启动脚本退出旧进程
pkill -f 'node build/index.js' || true- 考虑使用流程管理工具(例如pm2)
-
结束处理问题
- 问题:进程未成功完成
- 原因:未实施信号处理
- 対策:
- SIGINT等信号处理程序
process.on('SIGINT', async () => { await server.close(); process.exit(0); });
8.开发核对表
-
项目设置
- []package.jsonの“类型”:“模块”設定
- []适当的SDK指定版本
- [ ] TypeScript确认设置
-
実装
- [ ] ES导入模块格式
- []实施错误处理
- []活用类型定义
-
构建和权限
- []在构建脚本中授予执行权限
- []确认所需目录的访问权限
-
设定
- [ ] Cline更新配置文件
- [ ] Claude Desktop更新配置文件
- []适当设置环境变量
-
测试
- []基本功能的动作确认
- []测试错误案例
- []多个环境中的动作确认
9.其他重要考虑事项
资源管理
- 内存泄漏对策
- 问题:长时间运行,内存使用量逐渐增加
- 原因:
- 取消激活事件侦听器
- 未删除临时文件
- 高速缓存的无限增长
- 対策:
- 定期内存使用监控
- 实施资源清理过程
let cleanupInterval = setInterval(() => { // クリーンアップ処理 // - 古いキャッシュの削除 // - 一時ファイルの削除 // - 未使用のコネクションのクローズ }, 3600000); // 1時間ごと // プロセス終了時にインターバルをクリア process.on('SIGINT', () => { clearInterval(cleanupInterval); process.exit(0); });
错误恢复
-
自动恢复连接中断
- 问题:断开网络时服务器无法恢复
- 対策:
class ConnectionManager { private retryCount = 0; private readonly maxRetries = 5; private readonly retryDelay = 5000; // 5秒 async connect() { try { await this.server.connect(transport); } catch (error) { if (this.retryCount < this.maxRetries) { this.retryCount++; console.error(`接続失敗。${this.retryCount}回目の再試行...`); setTimeout(() => this.connect(), this.retryDelay); } else { console.error('最大再試行回数を超過。サーバーを停止します。'); process.exit(1); } } } }
-
分层和正确处理错误
enum ErrorSeverity { LOW = 'LOW', // 警告のみ MEDIUM = 'MEDIUM', // リトライ可能 HIGH = 'HIGH' // 即時終了必要 } class MCPServerError extends Error { constructor( message: string, public severity: ErrorSeverity, public recoverable: boolean ) { super(message); } } // エラーハンドラーでの使用例 try { // 処理 } catch (error) { if (error instanceof MCPServerError) { switch (error.severity) { case ErrorSeverity.LOW: console.warn(error.message); break; case ErrorSeverity.MEDIUM: if (error.recoverable) { // リトライロジック } break; case ErrorSeverity.HIGH: console.error('致命的エラー。サーバーを終了します。'); process.exit(1); } } }
性能优化
-
大规模数据处理
- 实施流处理
- 内存效率高的缓冲管理
import { Transform } from 'stream'; class DataProcessor extends Transform { constructor(options = {}) { super({ ...options, objectMode: true, highWaterMark: 64 // バッファサイズの制御 }); } _transform(chunk, encoding, callback) { // データの変換処理 callback(null, processedChunk); } } -
缓存策略
class CacheManager { private cache = new Map<string, { data: any, timestamp: number }>(); private readonly maxAge = 3600000; // 1時間 set(key: string, value: any) { this.cache.set(key, { data: value, timestamp: Date.now() }); } get(key: string) { const entry = this.cache.get(key); if (!entry) return null; if (Date.now() - entry.timestamp > this.maxAge) { this.cache.delete(key); return null; } return entry.data; } cleanup() { const now = Date.now(); for (const [key, entry] of this.cache.entries()) { if (now - entry.timestamp > this.maxAge) { this.cache.delete(key); } } } }
安全增强
-
输入验证增强
class InputValidator { static validateToolInput(toolName: string, args: unknown): boolean { // ツール名の形式チェック if (!/^[a-z0-9_]+$/.test(toolName)) { throw new McpError( ErrorCode.InvalidParams, 'Tool name must contain only lowercase letters, numbers, and underscores' ); } // 引数の型チェック if (!args || typeof args !== 'object') { throw new McpError( ErrorCode.InvalidParams, 'Arguments must be an object' ); } // その他のバリデーション return true; } } -
实施速率限制
class RateLimiter { private requests = new Map<string, number[]>(); private readonly windowMs = 60000; // 1分 private readonly maxRequests = 100; // 1分あたり100リクエスト isAllowed(clientId: string): boolean { const now = Date.now(); const windowStart = now - this.windowMs; // 古いリクエストを削除 let requests = this.requests.get(clientId) || []; requests = requests.filter(time => time > windowStart); if (requests.length >= this.maxRequests) { return false; } requests.push(now); this.requests.set(clientId, requests); return true; } }
运用管理
-
记录轮换
import { createWriteStream, rename } from 'fs/promises'; import { format } from 'date-fns'; class LogManager { private currentLogStream: WriteStream; private readonly maxSize = 10 * 1024 * 1024; // 10MB private currentSize = 0; constructor(private readonly logDir: string) { this.rotateIfNeeded(); } async log(message: string) { const entry = `${new Date().toISOString()} ${message}\n`; this.currentSize += Buffer.byteLength(entry); if (this.currentSize >= this.maxSize) { await this.rotateLog(); } this.currentLogStream.write(entry); } private async rotateLog() { const oldLog = `${this.logDir}/mcp-server.${format(new Date(), 'yyyyMMdd-HHmmss')}.log`; await rename(`${this.logDir}/mcp-server.log`, oldLog); this.currentLogStream = createWriteStream(`${this.logDir}/mcp-server.log`); this.currentSize = 0; } } -
健康检查功能
class HealthCheck { private readonly checks = new Map<string, () => Promise<boolean>>(); private status = { healthy: true, lastCheck: Date.now(), details: {} as Record<string, boolean> }; addCheck(name: string, check: () => Promise<boolean>) { this.checks.set(name, check); } async runChecks() { for (const [name, check] of this.checks.entries()) { try { this.status.details[name] = await check(); } catch (error) { this.status.details[name] = false; } } this.status.healthy = Object.values(this.status.details).every(Boolean); this.status.lastCheck = Date.now(); return this.status; } }
编码质量
-
严格使用类型
// 悪い例 type AnyObject = { [key: string]: any }; // 良い例 interface ToolConfig { name: string; version: string; options?: { timeout?: number; retries?: number; }; } -
改进测试覆盖
// テストユーティリティ class TestUtils { static async createMockServer() { const server = new Server({ name: 'test-server', version: '1.0.0' }, { capabilities: { tools: {}, resources: {} } }); // モックトランスポートの設定 const mockTransport = new MockTransport(); await server.connect(mockTransport); return { server, transport: mockTransport }; } static generateTestCases() { return [ // 正常系のテストケース { input: { text: 'test' }, expected: 'test' }, // エラー系のテストケース { input: {}, expectedError: ErrorCode.InvalidParams }, // エッジケース { input: { text: ''.padStart(1000000, 'a') }, expected: 'error' } ]; } }
10.发放核对表
-
编码质量
- []所有测试均通过
- []完成代码审核
- []执行褶皱/成形器
- []类型检查完成
- []删除未使用的代码
-
安全性
- []依赖性漏洞检查
- []机密信息的泄漏检查
- []确认输入验证
- []错误消息中的信息泄漏检查
-
性能
- []检查内存泄漏
- []负荷测试的实施
- []确认资源用量
- []确认缓存策略
-
運用準備
- []确认日志输出
- []监控设置
- []备份策略
- []确认故障恢复步骤
-
文档
- [ ] API更新式样书
- []配置文件的说明
- []故障排除指南
- []记录变更履历
11. MCP规格和开发雏形的作用
-
MCP仕様: MCP (Model Context Protocol) 表示各MCP用于在服务器之间统一交换工具、资源和上下文信息的协议。这有助于在不同的系统之间进行协作,从而实现灵活的扩展。
-
开发雏形的作用:本雏形MCP为服务器开发提供基本结构、相关性设置、方案定义、错误处理、安全性和性能优化的最佳实践。这有助于快速启动项目并实现一致的实施。
-
利用手顺:
- 以雏形内容为基础初始化项目
- 自定义所需的依赖关系和设置
- 按照指定的指导方针进行开发,适用于运用环境
-
注意事项:雏形中记载的设定和代码是基本例子,需要根据实际的运用环境和要求进行定制。请根据各项目的目的适当调整。
