人工智能开发工具MCP服务器
教育参考实现,演示如何将MCP服务器构建为现有REST API的桥梁。
这个MCP服务器展示了如何通过模型上下文协议(MCP),通过将REST API与会话接口封装在一起,来展示人工智能开发工具的智能。它是为那些想了解MCP-as-API-桥接模式的开发人员设计的学习资源。
](https://github.com/modelcontextprotocol)  ](https://nodejs.org)
______________________________________________________________________
架构:MCP作为API桥梁
该项目展示了 推荐模式 对于MCP服务器:包装现有的RESTneneneba API以提供会话访问,而不是从头开始构建所有内容。
模式
graph TB
subgraph " "
DB[(Database
PostgreSQL)]
API[REST API
Business Logic
Auth • Rate Limiting • Caching]
DB --> API
end
API --> |JSON| DEV[Direct API Access]
API --> |Bridge| MCP[MCP Server
~200 lines
Format JSON → NL]
DEV --> DEVS[👨💻 Developers
Programmatic Access]
MCP --> USERS[💬 Users + Claude
Conversational Access]
style DB fill:#e8f5e9,stroke:#43a047
style API fill:#e3f2fd,stroke:#1976d2,stroke-width:3px
style DEV fill:#fff3e0,stroke:#f57c00
style MCP fill:#f3e5f5,stroke:#7b1fa2,stroke-width:2px
style DEVS fill:#fff3e0,stroke:#f57c00
style USERS fill:#f3e5f5,stroke:#7b1fa2为什么是这种架构?
单一事实来源
- 所有业务逻辑都存在于REST API中
- 身份验证、速率限制、缓存发生一次
- API更改自动流向MCP
双重访问模式
- 开发人员直接使用API进行编程访问
- 非技术用户通过Claude获得对话访问权限
- 相同的数据,不同的接口,满足不同的需求
薄包装
- MCP服务器包含约200行格式化代码
- 调用现有的API终结点
- 转换JSON响应→ 自然语言
- 易于维护和扩展
它的作用
此MCP服务器通过与Claude的自然对话使AI开发工具智能变得可访问。您可以问:
查询示例:
- *“比较OpenAI SDK与Anthropic SDK的采用情况”*
- *“本月增长最快的AI编码工具是什么?”*
- *“向我展示Cursor在过去6个月的增长历史”*
- *“查找下载量超过500万的所有LLM API框架”*
Claude使用公开的工具获取数据,并以自然语言呈现见解,包括增长趋势、社区指标和比较分析。
哪些数据被泄露:
- NPM下载统计(每周/每月)
- GitHub存储库指标(星级、活动)
- 社区参与(Stack Overflow问题,Reddit提到)
- 历史增长趋势
- 工具元数据(描述、类别、包名称)
______________________________________________________________________
代码结构
ai-developer-tools-mcp/
├── src/
│ ├── index.js # MCP server entry point
│ ├── tools/ # MCP tool definitions
│ │ ├── compare.js # Compare multiple tools
│ │ ├── trending.js # Get trending tools
│ │ ├── history.js # Historical data
│ │ └── search.js # Search/filter tools
│ ├── api/ # API client layer (THE BRIDGE)
│ │ └── client.js # Simulates REST API calls
│ ├── data/ # Mock data (simulates database)
│ │ └── mock-data.js # Sample data
│ └── utils/ # Formatters
│ └── formatters.js # JSON → Natural language
├── test/
│ └── test-tools.js # Test suite
├── .env.example
├── package.json
└── README.md关键层
1.MCP工具(src/tools/)
- 定义克劳德可以称之为什么
- 从Claude接收结构化参数
- 调用API客户端
- 返回格式化的响应
2.API客户(src/api/client.js) ⭐ 桥
- 在此演示中模拟REST API调用
- 在生产环境中:发出真正的HTTP请求
- 处理身份验证、错误和超时
- 返回JSON响应
3.格式化程序(src/utils/formatters.js)
- 转换JSON→ 自然语言
- 添加见解和背景
- 使数据对话
- 这就是MCP增值的地方
4.模拟数据(src/data/mock-data.js)
- 模拟数据库响应
- 代表性样本数据
- 生产中:被真实数据库取代
______________________________________________________________________
生产vs演示
演示(此Repo)
API客户端(src/api/client.js):
async getToolMetrics(toolId) {
// Simulate network delay
await this._simulateNetworkDelay();
// Return mock data
const data = mockData.getCurrentMetrics(toolId);
return this._successResponse(data);
}它展示了什么:
- MCP工具→ API客户端→ 数据源模式
- 请求/响应流程
- 错误处理
- 响应格式
生产(vibe data.com)
API客户:
async getToolMetrics(toolId) {
// Make real HTTP request
const response = await fetch(
`${this.baseURL}/tools/${toolId}/metrics`,
{
headers: {
'Authorization': `Bearer ${this.apiKey}`,
'Content-Type': 'application/json'
},
timeout: this.timeout
}
);
if (!response.ok) {
throw new Error(`API error: ${response.status}`);
}
return await response.json();
}什么变化:
fetch()而不是模拟数据- 真实身份验证标头
- 实际超时处理
- 生产错误处理
- 速率限制
- 重试逻辑
其他一切都保持不变:
- MCP工具定义✓
- 响应格式化程序✓
- 工具参数模式✓
- MCP服务器设置✓
______________________________________________________________________
快速开始
先决条件
- Node.js 18或更高版本
- Claude Desktop应用程序(或任何兼容MCP的客户端)
安装
# Clone the repository
git clone https://github.com/grzetich/ai-developer-tools-mcp.git
cd ai-developer-tools-mcp
# Install dependencies
npm install
# (Optional) Copy and configure environment variables
cp .env.example .env运行服务器
选项1:独立测试
# Run the server in stdio mode
npm start
# Or run tests to verify all tools work
npm test选项2:连接到克劳德桌面
将此配置添加到您的Claude Desktop配置文件中:
macOS: ~/Library/Application Support/Claude/claude_desktop_config.json 窗户: %APPDATA%\Claude\claude_desktop_config.json
{
"mcpServers": {
"ai-developer-tools": {
"command": "node",
"args": ["/absolute/path/to/ai-developer-tools-mcp/src/index.js"]
}
}
}重新启动克劳德桌面。您应该看到MCP部分中列出的服务器。
测试它是否有效
问克劳德:
*“目前最流行的AI编码工具是什么?”*
克劳德将使用 get_trending_tools 该工具用于获取当前数据并将其呈现给您。
______________________________________________________________________
桥梁模式是如何工作的
请求流
sequenceDiagram
participant User
participant Claude
participant MCP as MCP Server
(This Code)
participant API as REST API
(Mock/Real)
participant DB as Database
(Mock Data)
User->>Claude: "What's Cursor's growth trend?"
Claude->>MCP: Call get_tool_history(tool: "cursor")
MCP->>API: GET /tools/cursor/history
API->>DB: Query historical data
DB-->>API: Return data rows
API-->>MCP: JSON response
Note over MCP: Format JSON → Natural language
MCP-->>Claude: "Cursor grew 55% to 8.1M downloads..."
Claude-->>User: Present formatted answer代码示例
用户询问: “Cursor的采用趋势是什么?”
1.克劳德决定调用该工具:
{
"tool": "get_tool_history",
"arguments": {
"tool": "cursor",
"months": 6
}
}2.MCP工具收到呼叫:
// src/tools/history.js
async execute(args) {
const { tool, months } = args;
// Call API client
const response = await apiClient.getToolHistory(tool, months);
// Format JSON → Natural language
return formatHistory(response.data, tool, months);
}3、API客户端请求:
// src/api/client.js
async getToolHistory(toolId, months) {
// In demo: return mock data
// In production: fetch(`${baseURL}/tools/${toolId}/history?months=${months}`)
const data = mockData.getHistoricalData(toolId, months);
return this._successResponse({ tool_id: toolId, data });
}4.格式化程序转换响应:
// src/utils/formatters.js
export function formatHistory(apiResponse, toolId, months) {
const { data } = apiResponse;
let output = `📈 ${toolId.toUpperCase()} - ${months} Month History\n\n`;
data.forEach(point => {
output += `${point.month}: ${formatNumber(point.downloads)} downloads\n`;
});
const growth = calculateGrowth(data);
output += `\n**Growth:** ${growth}% over ${months} months\n`;
return output;
}5.克劳德向用户展示: “根据数据,Cursor在过去6个月里表现出强劲的增长,下载量从520万增加到810万(增长55.8%)……”
______________________________________________________________________
可用工具
1. compare_tools
比较2-3个AI开发工具的采用指标
参数:
{
"tools": ["openai", "anthropic"],
"time_range": "30d"
}退货: 与增长指标和关键见解进行并排比较
______________________________________________________________________
2. get_trending_tools
获取增长最快的AI开发工具
参数:
{
"time_range": "30d",
"limit": 5,
"category": "llm-api"
}退货: 根据当前指标按增长百分比排名
______________________________________________________________________
3. get_tool_history
获取特定工具的历史采用数据
参数:
{
"tool": "cursor",
"months": 6
}退货: 月度时间表及增长分析
______________________________________________________________________
4. search_tools
按条件搜索和筛选工具
参数:
{
"category": "llm-api",
"min_downloads": 10000000,
"sort_by": "downloads"
}退货: 包含完整详细信息和摘要统计信息的筛选列表
______________________________________________________________________
迁移到生产
步骤1:更新API客户端
用真实的HTTP请求替换模拟调用:
// src/api/client.js
class ApiClient {
constructor(baseURL, options = {}) {
this.baseURL = baseURL;
this.apiKey = options.apiKey;
this.timeout = options.timeout || 5000;
}
async getToolMetrics(toolId) {
try {
const response = await fetch(
`${this.baseURL}/tools/${toolId}/metrics`,
{
headers: {
'Authorization': `Bearer ${this.apiKey}`,
'Content-Type': 'application/json'
},
signal: AbortSignal.timeout(this.timeout)
}
);
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
const data = await response.json();
return this._successResponse(data);
} catch (error) {
if (error.name === 'AbortError') {
return this._errorResponse(408, 'Request timeout');
}
return this._errorResponse(500, error.message);
}
}
// ... implement other methods similarly
}
// Configure with environment variables
export const apiClient = new ApiClient(
process.env.API_BASE_URL || 'https://api.vibe-data.com',
{
apiKey: process.env.API_KEY,
timeout: parseInt(process.env.API_TIMEOUT) || 5000
}
);步骤2:添加身份验证
// .env
API_BASE_URL=https://api.vibe-data.com
API_KEY=your_api_key_here
API_TIMEOUT=5000步骤3:添加速率限制
// src/api/client.js
class ApiClient {
constructor(baseURL, options = {}) {
this.baseURL = baseURL;
this.apiKey = options.apiKey;
this.rateLimiter = new RateLimiter(options.rateLimit || 100); // 100 requests/min
}
async getToolMetrics(toolId) {
// Wait for rate limit
await this.rateLimiter.wait();
// Make request...
}
}步骤4:添加重试逻辑
async getToolMetrics(toolId, retries = 3) {
for (let i = 0; i setTimeout(resolve, delay));
}第五步:测试
其他一切(工具、格式化程序、MCP服务器)保持不变。
______________________________________________________________________
设计决策
为什么要包装API而不是直接数据库访问?
关注点分离:
- API处理业务逻辑、授权、速率限制
- MCP服务器专注于会话格式化
- 不要在这两个地方重复逻辑
安全:
- API是您的安全边界
- MCP服务器不需要数据库凭据
- 相同的安全规则适用于所有客户端
可维护性:
- 一个用于业务逻辑的代码库
- API自动更改流程
- MCP层薄而简单
为什么要将响应格式化为文本?
克劳德擅长语言:
- 语言模型最适合文本,而不是JSON
- 无需解析-Claude可以直接引用或总结
- 更灵活-克劳德可以根据上下文调整演示文稿
更好的用户体验:
- 用户看到的是洞察,而不是数据结构
- 自然对话流
- 背景和解释包括
例子:
JSON响应:
{"downloads": 8100000, "growth_pct": 55.8}格式化文本:
Cursor grew 55% over the quarter, reaching 8.1M monthly
downloads, indicating strong developer adoption.同样的数据,但一个是机器数据,一个是人类数据。
为什么每个功能都有一个工具?
克劳德表现更好:
- Claude更容易选择清晰、专注的工具
- 更简单的参数模式
- 更可预测的行为
更易于维护:
- 每个工具都有一个责任
- 独立测试
- 清晰的文件
可组合:
- Claude可以链接多个工具调用
- “比较前三大趋势工具”=
get_trending+compare_tools
______________________________________________________________________
真实世界用例
此模式适用于任何具有可查询数据的产品:
B2B SaaS
- API 分析平台、客户仪表板
- MCP: *“我们的MRR趋势如何?”* *“哪些客户流失了?”*
电子商务
- API 库存系统、订单管理
- MCP: *“哪些产品库存低?”* *“显示本周的退货”*
内部工具
- API 自动化报告、集成
- MCP: *“查找待处理的发票”* *“比较第三季度与第四季度的销售额”*
______________________________________________________________________
贡献
欢迎投稿!这是一个教育项目,所以质量重于数量。
良好贡献:
- 具有明确用例的附加工具
- 更好的模拟数据演示边缘情况
- 文档改进
- 生产实施示例
- 测试改进
请先打开一个问题 讨论:
- 主要建筑变化
- 新的依赖关系
- 打破工具界面的更改
______________________________________________________________________
许可证
MIT许可证-请参阅 许可证 文件以获取详细信息。
______________________________________________________________________
致谢
______________________________________________________________________
了解更多
______________________________________________________________________
问题?问题?思想? 打开一个问题 或伸出手来!
