Skip to content

3.4 开发工具配置

🎯 学习目标:配置完整的MCP开发工具链,包括IDE、调试工具、版本控制等
⏱️ 预计时间:35分钟
📊 难度等级:⭐⭐⭐

🛠️ 工具链概览

一个完整的MCP开发环境需要以下工具:

🎨 代码编辑器配置

🏆 VS Code配置(强烈推荐)

VS Code是MCP开发的最佳选择,因为它:

  • 🔌 丰富的扩展生态
  • 🐍 优秀的Python/TypeScript支持
  • 🛠️ 内置调试器
  • 🔄 Git集成
  • 📡 可能的官方MCP支持

📦 必需扩展安装

bash
# 通过命令行安装扩展
code --install-extension ms-python.python
code --install-extension ms-python.vscode-pylance
code --install-extension ms-vscode.vscode-typescript-next
code --install-extension ms-vscode.vscode-json
code --install-extension bradlc.vscode-tailwindcss  # 如果使用Web界面
code --install-extension ms-vscode.vscode-eslint
code --install-extension esbenp.prettier-vscode
code --install-extension ms-python.black-formatter
code --install-extension ms-python.flake8
code --install-extension ms-toolsai.jupyter
code --install-extension GitLab.gitlab-workflow
code --install-extension GitHub.copilot  # AI辅助编程

⚙️ VS Code工作区配置

创建.vscode/settings.json

json
{
    "// 通用设置": "",
    "editor.fontSize": 14,
    "editor.tabSize": 4,
    "editor.insertSpaces": true,
    "editor.renderWhitespace": "boundary",
    "editor.rulers": [80, 120],
    "files.trimTrailingWhitespace": true,
    "files.insertFinalNewline": true,
    
    "// Python设置": "",
    "python.defaultInterpreterPath": "./venv/bin/python",
    "python.formatting.provider": "black",
    "python.formatting.blackArgs": ["--line-length", "88"],
    "python.linting.enabled": true,
    "python.linting.flake8Enabled": true,
    "python.linting.flake8Args": ["--max-line-length", "88"],
    "python.linting.mypyEnabled": true,
    "python.testing.pytestEnabled": true,
    "python.testing.pytestArgs": ["tests", "-v"],
    
    "// TypeScript/JavaScript设置": "",
    "typescript.preferences.importModuleSpecifier": "relative",
    "javascript.preferences.importModuleSpecifier": "relative",
    "eslint.workingDirectories": ["./"],
    "editor.codeActionsOnSave": {
        "source.organizeImports": true,
        "source.fixAll.eslint": true
    },
    
    "// JSON设置": "",
    "json.schemas": [
        {
            "fileMatch": ["**/package.json"],
            "url": "https://json.schemastore.org/package.json"
        },
        {
            "fileMatch": ["**/.vscode/*.json"],
            "url": "https://json.schemastore.org/vscode-task.json"
        }
    ],
    
    "// 文件排除": "",
    "files.exclude": {
        "**/__pycache__": true,
        "**/*.pyc": true,
        "**/node_modules": true,
        "**/.git": true,
        "**/venv": true,
        "**/.env": true
    },
    
    "// 搜索排除": "",
    "search.exclude": {
        "**/node_modules": true,
        "**/venv": true,
        "**/*.min.js": true
    }
}

🚀 任务配置

创建.vscode/tasks.json

json
{
    "version": "2.0.0",
    "tasks": [
        {
            "label": "MCP Server - Python",
            "type": "shell",
            "command": "${workspaceFolder}/venv/bin/python",
            "args": ["src/server.py"],
            "group": {
                "kind": "build",
                "isDefault": true
            },
            "presentation": {
                "echo": true,
                "reveal": "always",
                "focus": false,
                "panel": "new"
            },
            "options": {
                "cwd": "${workspaceFolder}"
            },
            "problemMatcher": []
        },
        {
            "label": "MCP Server - Node.js",
            "type": "shell",
            "command": "npm",
            "args": ["run", "dev"],
            "group": "build",
            "presentation": {
                "echo": true,
                "reveal": "always",
                "focus": false,
                "panel": "new"
            },
            "options": {
                "cwd": "${workspaceFolder}"
            },
            "problemMatcher": ["$tsc"]
        },
        {
            "label": "Run Tests - Python",
            "type": "shell",
            "command": "${workspaceFolder}/venv/bin/python",
            "args": ["-m", "pytest", "tests/", "-v"],
            "group": "test",
            "presentation": {
                "echo": true,
                "reveal": "always",
                "focus": false,
                "panel": "new"
            }
        },
        {
            "label": "Run Tests - Node.js",
            "type": "shell",
            "command": "npm",
            "args": ["test"],
            "group": "test",
            "presentation": {
                "echo": true,
                "reveal": "always",
                "focus": false,
                "panel": "new"
            }
        },
        {
            "label": "Format Code - Python",
            "type": "shell",
            "command": "${workspaceFolder}/venv/bin/python",
            "args": ["-m", "black", "src/", "tests/"],
            "group": "build",
            "presentation": {
                "echo": true,
                "reveal": "silent"
            }
        },
        {
            "label": "Format Code - TypeScript",
            "type": "shell",
            "command": "npx",
            "args": ["prettier", "--write", "src/**/*.ts"],
            "group": "build",
            "presentation": {
                "echo": true,
                "reveal": "silent"
            }
        }
    ]
}

🐛 调试配置

创建.vscode/launch.json

json
{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Debug MCP Server (Python)",
            "type": "python",
            "request": "launch",
            "program": "${workspaceFolder}/src/server.py",
            "args": [],
            "console": "integratedTerminal",
            "cwd": "${workspaceFolder}",
            "env": {
                "PYTHONPATH": "${workspaceFolder}/src"
            },
            "envFile": "${workspaceFolder}/.env"
        },
        {
            "name": "Debug MCP Server (Node.js)",
            "type": "node",
            "request": "launch",
            "program": "${workspaceFolder}/src/server.ts",
            "outFiles": ["${workspaceFolder}/dist/**/*.js"],
            "runtimeArgs": ["-r", "ts-node/register"],
            "env": {
                "NODE_ENV": "development"
            },
            "envFile": "${workspaceFolder}/.env"
        },
        {
            "name": "Debug Tests (Python)",
            "type": "python",
            "request": "launch",
            "module": "pytest",
            "args": ["tests/", "-v", "-s"],
            "cwd": "${workspaceFolder}",
            "console": "integratedTerminal"
        },
        {
            "name": "Attach to MCP Server",
            "type": "node",
            "request": "attach",
            "port": 9229,
            "restart": true,
            "localRoot": "${workspaceFolder}",
            "remoteRoot": "/app"
        }
    ]
}

🧠 其他优秀IDE配置

WebStorm/PyCharm配置

优点

  • 🔍 强大的代码分析
  • 🛠️ 内置重构工具
  • 📊 优秀的调试体验
  • 🔄 Git集成

基础配置

1. 配置Python解释器
   Settings → Project → Python Interpreter → 选择虚拟环境

2. 配置Node.js
   Settings → Languages & Frameworks → Node.js → 设置Node.js路径

3. 配置代码风格
   Settings → Editor → Code Style → 选择项目风格

4. 配置调试器
   Run/Debug Configurations → 添加Python/Node.js配置

Vim/Neovim配置

适合:命令行工作者、远程开发

vim
" ~/.vimrc 或 ~/.config/nvim/init.vim
" 基础配置
set number
set relativenumber
set tabstop=4
set shiftwidth=4
set expandtab
set autoindent

" 插件管理(使用vim-plug)
call plug#begin('~/.vim/plugged')

" 语言支持
Plug 'neoclide/coc.nvim', {'branch': 'release'}  " LSP支持
Plug 'psf/black', {'for': 'python'}              " Python格式化
Plug 'prettier/vim-prettier'                     " JS/TS格式化

" 文件管理
Plug 'preservim/nerdtree'
Plug 'junegunn/fzf.vim'

" Git集成
Plug 'tpope/vim-fugitive'

call plug#end()

" 快捷键配置
nnoremap <leader>t :NERDTreeToggle<CR>
nnoremap <leader>f :Files<CR>
nnoremap <leader>g :Rg<CR>

🔍 专业调试工具

🐛 MCP协议调试器

创建MCP协议调试工具:

python
#!/usr/bin/env python3
"""
mcp_debugger.py - MCP协议调试工具
"""

import json
import asyncio
import websockets
import argparse
from datetime import datetime
from typing import Dict, Any
import colorama
from colorama import Fore, Style

colorama.init()

class MCPDebugger:
    def __init__(self, host: str = "localhost", port: int = 8080):
        self.host = host
        self.port = port
        self.message_id = 1
        
    def log_message(self, direction: str, message: Dict[str, Any]):
        """记录消息"""
        timestamp = datetime.now().strftime("%H:%M:%S.%f")[:-3]
        color = Fore.GREEN if direction == "SEND" else Fore.BLUE
        
        print(f"{color}[{timestamp}] {direction}{Style.RESET_ALL}")
        print(f"  {json.dumps(message, indent=2, ensure_ascii=False)}")
        print()
    
    async def send_request(self, websocket, method: str, params: Dict[str, Any] = None):
        """发送MCP请求"""
        request = {
            "jsonrpc": "2.0",
            "id": self.message_id,
            "method": method,
            "params": params or {}
        }
        
        self.message_id += 1
        self.log_message("SEND", request)
        
        await websocket.send(json.dumps(request))
        
        response = await websocket.recv()
        response_data = json.loads(response)
        self.log_message("RECV", response_data)
        
        return response_data
    
    async def interactive_session(self):
        """交互式调试会话"""
        uri = f"ws://{self.host}:{self.port}"
        
        try:
            async with websockets.connect(uri) as websocket:
                print(f"{Fore.YELLOW}🔗 已连接到 {uri}{Style.RESET_ALL}")
                print("📝 可用命令: list_tools, call_tool <name>, initialize, quit")
                print()
                
                # 初始化连接
                await self.send_request(websocket, "initialize", {
                    "protocolVersion": "2024-11-05",
                    "capabilities": {
                        "sampling": {}
                    },
                    "clientInfo": {
                        "name": "MCP Debugger",
                        "version": "1.0.0"
                    }
                })
                
                while True:
                    try:
                        command = input(f"{Fore.CYAN}mcp> {Style.RESET_ALL}").strip()
                        
                        if command == "quit":
                            break
                        elif command == "list_tools":
                            await self.send_request(websocket, "tools/list")
                        elif command.startswith("call_tool "):
                            tool_name = command.split(" ", 1)[1]
                            await self.send_request(websocket, "tools/call", {
                                "name": tool_name,
                                "arguments": {}
                            })
                        elif command == "initialize":
                            await self.send_request(websocket, "initialize", {
                                "protocolVersion": "2024-11-05",
                                "capabilities": {"sampling": {}},
                                "clientInfo": {"name": "MCP Debugger", "version": "1.0.0"}
                            })
                        else:
                            print(f"{Fore.RED}未知命令: {command}{Style.RESET_ALL}")
                    
                    except KeyboardInterrupt:
                        break
                    except Exception as e:
                        print(f"{Fore.RED}错误: {e}{Style.RESET_ALL}")
        
        except Exception as e:
            print(f"{Fore.RED}连接失败: {e}{Style.RESET_ALL}")

def main():
    parser = argparse.ArgumentParser(description="MCP协议调试工具")
    parser.add_argument("--host", default="localhost", help="MCP服务器主机")
    parser.add_argument("--port", type=int, default=8080, help="MCP服务器端口")
    
    args = parser.parse_args()
    
    debugger = MCPDebugger(args.host, args.port)
    asyncio.run(debugger.interactive_session())

if __name__ == "__main__":
    main()

🌐 HTTP调试工具

创建HTTP MCP调试器:

javascript
// mcp-http-debugger.js - HTTP版本的MCP调试器
const express = require('express');
const axios = require('axios');
const chalk = require('chalk');

class MCPHTTPDebugger {
    constructor(targetUrl = 'http://localhost:3000') {
        this.targetUrl = targetUrl;
        this.messageId = 1;
        this.app = express();
        this.setupRoutes();
    }
    
    setupRoutes() {
        this.app.use(express.json());
        this.app.use(express.static('public'));
        
        // 代理所有MCP请求
        this.app.post('/mcp/*', async (req, res) => {
            const method = req.path.replace('/mcp/', '');
            const mcpRequest = {
                jsonrpc: '2.0',
                id: this.messageId++,
                method: method,
                params: req.body
            };
            
            this.logMessage('SEND', mcpRequest);
            
            try {
                const response = await axios.post(this.targetUrl, mcpRequest, {
                    headers: { 'Content-Type': 'application/json' }
                });
                
                this.logMessage('RECV', response.data);
                res.json(response.data);
            } catch (error) {
                console.error(chalk.red('请求失败:'), error.message);
                res.status(500).json({
                    jsonrpc: '2.0',
                    id: mcpRequest.id,
                    error: {
                        code: -32603,
                        message: 'Internal error',
                        data: error.message
                    }
                });
            }
        });
        
        // 调试界面
        this.app.get('/', (req, res) => {
            res.send(`
                <html>
                <head><title>MCP HTTP Debugger</title></head>
                <body>
                    <h1>MCP HTTP Debugger</h1>
                    <div>
                        <h2>发送请求</h2>
                        <select id="method">
                            <option value="initialize">initialize</option>
                            <option value="tools/list">tools/list</option>
                            <option value="tools/call">tools/call</option>
                        </select>
                        <br><br>
                        <textarea id="params" rows="10" cols="50">{}</textarea>
                        <br><br>
                        <button onclick="sendRequest()">发送</button>
                    </div>
                    <div id="response"></div>
                    
                    <script>
                        async function sendRequest() {
                            const method = document.getElementById('method').value;
                            const params = JSON.parse(document.getElementById('params').value || '{}');
                            
                            const response = await fetch('/mcp/' + method, {
                                method: 'POST',
                                headers: {'Content-Type': 'application/json'},
                                body: JSON.stringify(params)
                            });
                            
                            const result = await response.json();
                            document.getElementById('response').innerHTML = 
                                '<pre>' + JSON.stringify(result, null, 2) + '</pre>';
                        }
                    </script>
                </body>
                </html>
            `);
        });
    }
    
    logMessage(direction, message) {
        const timestamp = new Date().toISOString().split('T')[1].slice(0, -1);
        const color = direction === 'SEND' ? chalk.green : chalk.blue;
        
        console.log(color(`[${timestamp}] ${direction}`));
        console.log('  ' + JSON.stringify(message, null, 2));
        console.log();
    }
    
    start(port = 3001) {
        this.app.listen(port, () => {
            console.log(chalk.yellow(`🔗 MCP HTTP调试器启动: http://localhost:${port}`));
            console.log(chalk.yellow(`📡 目标MCP服务器: ${this.targetUrl}`));
        });
    }
}

// 使用方式
const debugger = new MCPHTTPDebugger(process.argv[2] || 'http://localhost:3000');
debugger.start(3001);

🧪 测试工具配置

🐍 Python测试环境

创建pytest.ini

ini
[tool:pytest]
testpaths = tests
python_files = test_*.py *_test.py
python_classes = Test*
python_functions = test_*
addopts = 
    -v
    --tb=short
    --strict-markers
    --strict-config
    --color=yes
    --durations=10
markers =
    unit: 单元测试
    integration: 集成测试
    slow: 慢速测试
    mcp: MCP相关测试

安装测试依赖:

bash
# 在虚拟环境中
pip install pytest pytest-asyncio pytest-cov pytest-mock
pip install httpx  # 用于HTTP测试
pip install websockets  # 用于WebSocket测试

创建测试示例:

python
# tests/test_mcp_server.py
import pytest
import asyncio
import json
from unittest.mock import Mock, patch

class TestMCPServer:
    @pytest.fixture
    def mcp_server(self):
        """MCP服务器fixture"""
        from src.server import MCPServer
        return MCPServer()
    
    @pytest.mark.asyncio
    async def test_initialize(self, mcp_server):
        """测试初始化"""
        request = {
            "jsonrpc": "2.0",
            "id": 1,
            "method": "initialize",
            "params": {
                "protocolVersion": "2024-11-05",
                "capabilities": {"sampling": {}},
                "clientInfo": {"name": "test", "version": "1.0"}
            }
        }
        
        response = await mcp_server.handle_request(request)
        
        assert response["jsonrpc"] == "2.0"
        assert response["id"] == 1
        assert "result" in response
    
    @pytest.mark.asyncio
    async def test_list_tools(self, mcp_server):
        """测试工具列表"""
        request = {
            "jsonrpc": "2.0",
            "id": 2,
            "method": "tools/list",
            "params": {}
        }
        
        response = await mcp_server.handle_request(request)
        
        assert response["jsonrpc"] == "2.0"
        assert "result" in response
        assert "tools" in response["result"]
    
    @pytest.mark.mcp
    @pytest.mark.integration
    async def test_tool_call_integration(self, mcp_server):
        """集成测试:工具调用"""
        # 先获取工具列表
        list_request = {
            "jsonrpc": "2.0",
            "id": 1,
            "method": "tools/list"
        }
        
        list_response = await mcp_server.handle_request(list_request)
        tools = list_response["result"]["tools"]
        
        if tools:
            # 调用第一个工具
            call_request = {
                "jsonrpc": "2.0",
                "id": 2,
                "method": "tools/call",
                "params": {
                    "name": tools[0]["name"],
                    "arguments": {}
                }
            }
            
            call_response = await mcp_server.handle_request(call_request)
            assert "result" in call_response or "error" in call_response

🟨 JavaScript/TypeScript测试环境

安装测试依赖:

bash
npm install --save-dev jest @types/jest ts-jest
npm install --save-dev supertest  # HTTP测试
npm install --save-dev ws @types/ws  # WebSocket测试

创建jest.config.js

javascript
module.exports = {
    preset: 'ts-jest',
    testEnvironment: 'node',
    roots: ['<rootDir>/src', '<rootDir>/tests'],
    testMatch: [
        '**/__tests__/**/*.ts',
        '**/?(*.)+(spec|test).ts'
    ],
    transform: {
        '^.+\\.ts$': 'ts-jest'
    },
    collectCoverageFrom: [
        'src/**/*.ts',
        '!src/**/*.d.ts'
    ],
    coverageDirectory: 'coverage',
    coverageReporters: ['text', 'lcov', 'html'],
    setupFilesAfterEnv: ['<rootDir>/tests/setup.ts']
};

创建测试示例:

typescript
// tests/mcp-server.test.ts
import { MCPServer } from '../src/server';
import WebSocket from 'ws';

describe('MCP Server', () => {
    let server: MCPServer;
    
    beforeEach(() => {
        server = new MCPServer();
    });
    
    afterEach(async () => {
        await server.close();
    });
    
    test('should initialize correctly', async () => {
        const request = {
            jsonrpc: '2.0',
            id: 1,
            method: 'initialize',
            params: {
                protocolVersion: '2024-11-05',
                capabilities: { sampling: {} },
                clientInfo: { name: 'test', version: '1.0' }
            }
        };
        
        const response = await server.handleRequest(request);
        
        expect(response.jsonrpc).toBe('2.0');
        expect(response.id).toBe(1);
        expect(response.result).toBeDefined();
    });
    
    test('should list tools', async () => {
        const request = {
            jsonrpc: '2.0',
            id: 2,
            method: 'tools/list',
            params: {}
        };
        
        const response = await server.handleRequest(request);
        
        expect(response.result).toHaveProperty('tools');
        expect(Array.isArray(response.result.tools)).toBe(true);
    });
});

📚 文档工具配置

📖 API文档生成

Python - Sphinx配置

bash
# 安装Sphinx
pip install sphinx sphinx-rtd-theme sphinx-autodoc-typehints

# 初始化文档
sphinx-quickstart docs

# 配置 docs/conf.py
extensions = [
    'sphinx.ext.autodoc',
    'sphinx.ext.viewcode',
    'sphinx.ext.napoleon',
    'sphinx_rtd_theme'
]

html_theme = 'sphinx_rtd_theme'

TypeScript - TypeDoc配置

bash
# 安装TypeDoc
npm install --save-dev typedoc

# 配置 typedoc.json
{
    "entryPoints": ["src/index.ts"],
    "out": "docs",
    "theme": "default",
    "includeVersion": true,
    "exclude": ["**/*.test.ts", "**/*.spec.ts"]
}

🎯 本节小结

通过这一小节,你应该已经掌握了:

完整工具链:了解MCP开发所需的各种工具
IDE配置:配置VS Code等开发环境
调试工具:MCP协议专用调试器的使用
测试环境:Python和TypeScript测试框架配置
文档工具:API文档生成工具的使用

🔗 配置检查清单

在进入下一小节之前,请确认:

  • [ ] IDE/编辑器配置完成
  • [ ] 调试器可以正常工作
  • [ ] 测试框架安装并配置
  • [ ] 版本控制工具可用
  • [ ] 文档生成工具就绪

开发工具配置完成!接下来进行最终的环境验证。


👉 下一小节:3.5 环境验证