MCP服务器开发框架

提供MCP服务器开发的基础结构、依赖设置、错误处理和性能优化的开发框架,用于实现工具、资源和上下文信息的统一交换协议。

  • by essences
  • JavaScript
  • 本地部署
  • 1 星标
  • 更新于
在 GitHub 查看 essences/mcp-echo-server

使用说明

这个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.安装要点

基本构造

  • 创建服务器实例
  • 功能定义
  • 实现请求处理程序
  • 设置错误处理
  • 启动服务器

重要注意事项

  1. ES模块化

    • package.json单击功能区上"type": "module"的规格化距离的幂函数
    • 在导入路径中.js包括(例如:sdk/server/index.js)
  2. 利用类型定义

    • 模式定义输入验证
    • 正确使用错误类型
  3. 错误处理

    • MCP使用错误类型
    • 正确选择错误代码
    • 提供详细的错误消息
  4. 安全考虑

    • 验证输入值
    • 设置执行权限
    • 适当管理环境变量

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.故障排除

  1. 权限错误

    • 在构建脚本中授予执行权限
    • chmod +x build/index.js执行
  2. 模块解析错误

    • 通过.js包括扩展名
    • moduleResolution正确设置
  3. 环境变量问题

    • 在配置文件中适当定义环境变量
    • 在运行时确认环境变量是否可用
  4. 安全限制

    • alwaysAllow确认的设置
    • 确认是否已授予所需权限

6.最佳实践

  1. 模块化

    • 按功能拆分模块
    • 提取可重用代码
  2. 错误处理

    • 详细的错误信息
    • 错误分层
    • 适当的日志输出
  3. 测试

    • 创建设备测试
    • 实施集成测试
    • 考虑边缘情况
  4. 文档

    • 代码注释增强
    • API制作式样书
    • 提供使用示例

7.常见问题与对策

SDK相关问题

  1. SDK版本不匹配

    • 问题: No matching version found for @modelcontextprotocol/sdk@^x.x.x
    • 原因:package.json中指定的版本不存在
    • 対策:
      • 现有MCP服务器package.json确认
      • 使用已确认动作的版本(当前为^1.5.0)
      • 版本化使用^(小盒)确保兼容性
  2. 模块解决问题

    • 问题: Cannot find module '@modelcontextprotocol/sdk/server/index'
    • 原因:ES模块和CommonJS混合问题
    • 対策:
      • package.json在…之上 "type": "module" 添加
      • 在导入路径中 .js 添加
      • tsconfig.json单击功能区上 "module": "ES2020" 指定

文件系统权限问题

  1. 执行权限错误

    • 问题: Permission denied 不能实行
    • 原因:构建的文件没有执行权限
    • 対策:
      • 在构建脚本中chmod 添加
      "build": "tsc && node -e \"require('fs').chmodSync('build/index.js', '755')\""
      
  2. 文件写入权限

    • 问题: OSError: Read-only file system
    • 原因:进程没有写权限
    • 対策:
      • 使用临时目录
      • 指定具有适当权限的目录
      • 如果需要sudo 按权限运行

配置文件关系

  1. 配置文件识别问题

    • 问题:MCP未检测到服务器
    • 原因:配置文件路径或格式不正确
    • 対策:
      • 使用绝对路径
      • alwaysAllow工具名称
      • 更新两个配置文件
        • 克莱恩: ~/Library/Application Support/Cursor/User/globalStorage/rooveterinaryinc.roo-cline/settings/cline_mcp_settings.json
        • 克劳德: ~/Library/Application Support/Claude/claude_desktop_config.json
  2. 环境变量问题

    • 问题:未识别环境变量
    • 原因:在配置文件中指定环境变量不恰当
    • 対策:
      • MCP在服务器设置的“env”部分中明确指定
      • 机密信息通过环境变量传递
      "env": {
        "API_KEY": "your-api-key"
      }
      

流程管理

  1. 重复启动进程

    • 问题:启动多个相同的服务器
    • 原因:上一个进程未完成
    • 対策:
      • 使用启动脚本退出旧进程
      pkill -f 'node build/index.js' || true
      
      • 考虑使用流程管理工具(例如pm2)
  2. 结束处理问题

    • 问题:进程未成功完成
    • 原因:未实施信号处理
    • 対策:
      • SIGINT等信号处理程序
      process.on('SIGINT', async () => {
        await server.close();
        process.exit(0);
      });
      

8.开发核对表

  1. 项目设置

    • []package.jsonの“类型”:“模块”設定
    • []适当的SDK指定版本
    • [ ] TypeScript确认设置
  2. 実装

    • [ ] ES导入模块格式
    • []实施错误处理
    • []活用类型定义
  3. 构建和权限

    • []在构建脚本中授予执行权限
    • []确认所需目录的访问权限
  4. 设定

    • [ ] Cline更新配置文件
    • [ ] Claude Desktop更新配置文件
    • []适当设置环境变量
  5. 测试

    • []基本功能的动作确认
    • []测试错误案例
    • []多个环境中的动作确认

9.其他重要考虑事项

资源管理

  1. 内存泄漏对策
    • 问题:长时间运行,内存使用量逐渐增加
    • 原因:
      • 取消激活事件侦听器
      • 未删除临时文件
      • 高速缓存的无限增长
    • 対策:
      • 定期内存使用监控
      • 实施资源清理过程
      let cleanupInterval = setInterval(() => {
        // クリーンアップ処理
        // - 古いキャッシュの削除
        // - 一時ファイルの削除
        // - 未使用のコネクションのクローズ
      }, 3600000); // 1時間ごと
      
      // プロセス終了時にインターバルをクリア
      process.on('SIGINT', () => {
        clearInterval(cleanupInterval);
        process.exit(0);
      });
      

错误恢复

  1. 自动恢复连接中断

    • 问题:断开网络时服务器无法恢复
    • 対策:
      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);
            }
          }
        }
      }
      
  2. 分层和正确处理错误

    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);
        }
      }
    }
    

性能优化

  1. 大规模数据处理

    • 实施流处理
    • 内存效率高的缓冲管理
    import { Transform } from 'stream';
    
    class DataProcessor extends Transform {
      constructor(options = {}) {
        super({
          ...options,
          objectMode: true,
          highWaterMark: 64 // バッファサイズの制御
        });
      }
    
      _transform(chunk, encoding, callback) {
        // データの変換処理
        callback(null, processedChunk);
      }
    }
    
  2. 缓存策略

    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);
          }
        }
      }
    }
    

安全增强

  1. 输入验证增强

    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;
      }
    }
    
  2. 实施速率限制

    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;
      }
    }
    

运用管理

  1. 记录轮换

    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;
      }
    }
    
  2. 健康检查功能

    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;
      }
    }
    

编码质量

  1. 严格使用类型

    // 悪い例
    type AnyObject = { [key: string]: any };
    
    // 良い例
    interface ToolConfig {
      name: string;
      version: string;
      options?: {
        timeout?: number;
        retries?: number;
      };
    }
    
  2. 改进测试覆盖

    // テストユーティリティ
    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.发放核对表

  1. 编码质量

    • []所有测试均通过
    • []完成代码审核
    • []执行褶皱/成形器
    • []类型检查完成
    • []删除未使用的代码
  2. 安全性

    • []依赖性漏洞检查
    • []机密信息的泄漏检查
    • []确认输入验证
    • []错误消息中的信息泄漏检查
  3. 性能

    • []检查内存泄漏
    • []负荷测试的实施
    • []确认资源用量
    • []确认缓存策略
  4. 運用準備

    • []确认日志输出
    • []监控设置
    • []备份策略
    • []确认故障恢复步骤
  5. 文档

    • [ ] API更新式样书
    • []配置文件的说明
    • []故障排除指南
    • []记录变更履历

11. MCP规格和开发雏形的作用

  • MCP仕様: MCP (Model Context Protocol) 表示各MCP用于在服务器之间统一交换工具、资源和上下文信息的协议。这有助于在不同的系统之间进行协作,从而实现灵活的扩展。

  • 开发雏形的作用:本雏形MCP为服务器开发提供基本结构、相关性设置、方案定义、错误处理、安全性和性能优化的最佳实践。这有助于快速启动项目并实现一致的实施。

  • 利用手顺:

    1. 以雏形内容为基础初始化项目
    2. 自定义所需的依赖关系和设置
    3. 按照指定的指导方针进行开发,适用于运用环境
  • 注意事项:雏形中记载的设定和代码是基本例子,需要根据实际的运用环境和要求进行定制。请根据各项目的目的适当调整。