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/编辑器配置完成
- [ ] 调试器可以正常工作
- [ ] 测试框架安装并配置
- [ ] 版本控制工具可用
- [ ] 文档生成工具就绪
开发工具配置完成!接下来进行最终的环境验证。 ✅