Newsletter
Join the Community
Subscribe to our newsletter for the latest news and updates
Cline 官方提供了 MCP 插件开发权威指南,本文系统阐述如何通过模型上下文协议(MCP)为 Cline 构建功能强大的插件生态。作为 Cline 官方核心开发指南,内容涵盖:
以下是对 MCP 插件开发协议的翻译部分,内容比较多,含代码,建议电脑上阅读
本协议旨在规范使用 Cline 构建 MCP 插件的开发流程。
模型上下文协议(MCP)插件通过以下方式扩展 Cline 等 AI 助手的能力:
没有 MCP 的 AI 助手虽然强大但孤立。通过 MCP,它们获得了与几乎所有数字系统交互的能力。
有效的 MCP 插件开发核心在于遵循结构化协议。该协议通过放置在 MCP 工作目录根目录(/Users/your-name/Documents/Cline/MCP)的 .clinerules 文件实现。
.clinerules 是 Cline 在所在目录自动读取的特殊配置文件。这些文件:
# MCP Plugin Development Protocol
⚠️ CRITICAL: DO NOT USE attempt_completion BEFORE TESTING ⚠️
## Step 1: Planning (PLAN MODE)
- What problem does this tool solve?
- What API/service will it use?
- What are the authentication requirements?
□ Standard API key
□ OAuth (requires separate setup script)
□ Other credentials
## Step 2: Implementation (ACT MODE)
1. Bootstrap
- For web services, JavaScript integration, or Node.js environments:
---
npx @modelcontextprotocol/create-server my-server
cd my-server
npm install
---
- For data science, ML workflows, or Python environments:
---
pip install mcp
# Or with uv (recommended)
uv add "mcp[cli]"
---
2. Core Implementation
- Use MCP SDK
- Implement comprehensive logging
- TypeScript (for web/JS projects):
---
console.error('[Setup] Initializing server...');
console.error('[API] Request to endpoint:', endpoint);
console.error('[Error] Failed with:', error);
---
- Python (for data science/ML projects):
---
import logging
logging.error('[Setup] Initializing server...')
logging.error(f'[API] Request to endpoint: {endpoint}')
logging.error(f'[Error] Failed with: {str(error)}')
---
- Add type definitions
- Handle errors with context
- Implement rate limiting if needed
3. Configuration
- Get credentials from user if needed
- Add to MCP settings:
- For TypeScript projects:
---
{
"mcpServers": {
"my-server": {
"command": "node",
"args": ["path/to/build/index.js"],
"env": {
"API_KEY": "key"
},
"disabled": false,
"autoApprove": []
}
}
}
---
- For Python projects:
---
# Directly with command line
mcp install server.py -v API_KEY=key
# Or in settings.json
{
"mcpServers": {
"my-server": {
"command": "python",
"args": ["server.py"],
"env": {
"API_KEY": "key"
},
"disabled": false,
"autoApprove": []
}
}
}
---
## Step 3: Testing (BLOCKER ⛔️)
<thinking>
BEFORE using attempt_completion, I MUST verify:
□ Have I tested EVERY tool?
□ Have I confirmed success from the user for each test?
□ Have I documented the test results?
If ANY answer is "no", I MUST NOT use attempt_completion.
</thinking>
1. Test Each Tool (REQUIRED)
□ Test each tool with valid inputs
□ Verify output format is correct
⚠️ DO NOT PROCEED UNTIL ALL TOOLS TESTED
## Step 4: Completion
❗ STOP AND VERIFY:
□ Every tool has been tested with valid inputs
□ Output format is correct for each tool
Only after ALL tools have been tested can attempt_completion be used.
## Key Requirements
- ✓ Must use MCP SDK
- ✓ Must have comprehensive logging
- ✓ Must test each tool individually
- ✓ Must handle errors gracefully
- ⛔️ NEVER skip testing before completion
当工作目录存在此 .clinerules 文件时,Cline 将:
创建 MCP 插件只需简单几步:
首先按上述协议在 MCP 工作目录创建。clinerules 文件,该文件配置 Cline 在此目录使用 MCP 开发协议。
通过明确描述开始对话:
示例:
I want to build an MCP plugin for the AlphaAdvantage financial API.
It should allow me to get real-time stock data, perform technical
analysis, and retrieve company financial information.
Cline 将自动进入规划模式,指导您:
准备就绪后,可通过聊天底部切换至执行模式开始实现。
4. 提前提供 API 文档
最有效的方式是在开始时分享官方 API 文档:
Here's the API documentation for the service:
[Paste API documentation here]
提供完整 API 细节(端点、认证、数据结构)可显著提升 Cline 的实现能力。
协作设计阶段:
完成规划后进入实现阶段:
演示 AlphaAdvantage MCP 服务开发流程,该服务提供股票数据分析和报告功能。
经过规划阶段,我们将:
定义问题:用户需通过 AI 助手直接获取金融数据和分析
选择 API:AlphaAdvantage 金融数据 API
• 标准 API 密钥认证
• 免费版 5 次/分钟速率限制
• 多种金融数据端点
• 技术分析(RSI、MACD 等指标)
• 基本面分析(财务报表、比率)
• 财报数据
• 新闻与情绪分析
• 整洁的 Markdown 输出
• 结构化数据表格
• 趋势视觉指标(↑/↓)
• 财务数字规范格式
实现
项目初始化:
npx @modelcontextprotocol/create-server alphaadvantage-mcp
cd alphaadvantage-mcp
npm install axios node-cache
项目结构:
src/
├── api/
│ └── alphaAdvantageClient.ts # 含速率限制和缓存的API客户端
├── formatters/
│ └── markdownFormatter.ts # Markdown格式化工具
└── index.ts # 主服务实现
包含:
关键实现细节:
/** 基于免费版实施速率限制 */
private async enforceRateLimit() {
if (this.requestsThisMinute >= 5) {
console.error("[速率限制] 已达限制,等待下一分钟...");
return new Promise<void>((resolve) => {
const remainingMs = 60 * 1000 - (Date.now() % (60 * 1000));
setTimeout(resolve, remainingMs + 100); // 100毫秒缓冲
});
}
this.requestsThisMinute++;
return Promise.resolve();
}
Markdown 格式化
实现美观的财务数据显示:
/** 将公司概览格式化为Markdown */
export function formatStockOverview(overviewData: any, quoteData: any): string {
// 提取数据
const overview = overviewData;
const quote = quoteData["Global Quote"];
// 计算价格变化
const currentPrice = parseFloat(quote["05. price"] || "0");
const priceChange = parseFloat(quote["09. change"] || "0");
const changePercent = parseFloat(quote["10. change percent"]?.replace("%", "") || "0");
// 格式化Markdown
let markdown = `# ${overview.Symbol} (${overview.Name}) - ${formatCurrency(currentPrice)} ${addTrendIndicator(priceChange)}${changePercent > 0 ? '+' : ''}${changePercent.toFixed(2)}%\n\n`;
// 添加更多细节...
return markdown;
}
工具实现
定义五个清晰接口的工具:
server.setRequestHandler(ListToolsRequestSchema, async () => {
console.error("[初始化] 列出可用工具");
return {
tools: [
{
name: "get_stock_overview",
description: "获取股票代码的基本信息和当前报价",
inputSchema: {
type: "object",
properties: {
symbol: {
type: "string",
description: "股票代码(如'AAPL')"
},
market: {
type: "string",
description: "可选市场(如'US')"
},
default: "US"
},
required: ["symbol"]
}
},
// 其他工具定义...
];
};
});
每个工具处理包含:
关键测试流程:
{
"mcpServers": {
"alphaadvantage-mcp": {
"command": "node",
"args": ["/path/to/alphaadvantage-mcp/build/index.js"],
"env": {
"ALPHAVANTAGE_API_KEY": "YOUR_API_KEY"
},
"disabled": false,
"autoApprove": []
}
}
}
# AAPL (Apple Inc) - $241.84 ↑+1.91%
**Sector:** TECHNOLOGY
**Industry:** ELECTRONIC COMPUTERS
**Market Cap:** 3.63T
**P/E Ratio:** 38.26
...
# Technical Analysis: AAPL
## Daily Price Action
Current Price: $241.84 (↑$4.54, +1.91%)
### Recent Daily Prices
| Date | Open | High | Low | Close | Volume |
|------|------|------|-----|-------|--------|
| 2025-02-28 | $236.95 | $242.09 | $230.20 | $241.84 | 56.83M |
...
# Earnings Report: MSFT (Microsoft Corporation)
**Sector:** TECHNOLOGY
**Industry:** SERVICES-PREPACKAGED SOFTWARE
**Current EPS:** $12.43
## Recent Quarterly Earnings
| Quarter | Date | EPS Estimate | EPS Actual | Surprise % |
|---------|------|-------------|------------|------------|
| 2024-12-31 | 2025-01-29 | $3.11 | $3.23 | ↑4.01% |
...
AlphaAdvantage 案例的核心经验:
// 启动日志
console.error('[初始化] 启动AlphaAdvantage MCP服务...');
// API请求日志
console.error(`[API] 获取${symbol}股票概览`);
// 带上下文的错误处理
console.error(`[错误] 工具执行失败: ${error.message}`);
// 缓存操作
console.error(`[缓存] 使用缓存数据: ${cacheKey}`);
export interface AlphaAdvantageConfig {
apiKey: string;
cacheTTL?: Partial<typeof DEFAULT_CACHE_TTL>;
baseURL?: string;
}
/**
* Validate that a stock symbol is provided and looks valid
*/
function validateSymbol(symbol: unknown): asserts symbol is string {
if (typeof symbol !== "string" || symbol.trim() === "") {
throw new McpError(ErrorCode.InvalidParams, "A valid stock symbol is required");
}
// Basic symbol validation (letters, numbers, dots)
const symbolRegex = /^[A-Za-z0-9.]+$/;
if (!symbolRegex.test(symbol)) {
throw new McpError(ErrorCode.InvalidParams, `Invalid stock symbol: ${symbol}`);
}
}
// 默认缓存时间(秒)
const DEFAULT_CACHE_TTL = {
STOCK_OVERVIEW: 3600, // 1小时
TECHNICAL_ANALYSIS: 1800, // 30分钟
FUNDAMENTAL_ANALYSIS: 86400, // 24小时
EARNINGS_REPORT: 86400,
NEWS: 900, // 15分钟
};
// 优先读取缓存
const cachedData = this.cache.get<T>(cacheKey);
if (cachedData) {
console.error(`[缓存] 使用缓存数据: ${cacheKey}`);
return cachedData;
}
// 缓存成功响应
this.cache.set(cacheKey, response.data, cacheTTL);
try {
switch (request.params.name) {
case "get_stock_overview":
// 实现...
break;
// 其他情况...
default:
throw new McpError(ErrorCode.MethodNotFound, `未知工具: ${request.params.name}`);
}
} catch (error) {
console.error(`[错误] 工具执行失败: ${error instanceof Error ? error.message : String(error)}`);
if (error instanceof McpError) {
throw error;
}
return {
content: [{ type: "text", text: `错误: ${error instanceof Error ? error.message : String(error)}` }],
isError: true
};
}
// Authenticate using API key from environment
const API_KEY = process.env.ALPHAVANTAGE_API_KEY;
if (!API_KEY) {
console.error("[Error] Missing ALPHAVANTAGE_API_KEY environment variable");
process.exit(1);
}
// Initialize API client
const apiClient = new AlphaAdvantageClient({
apiKey: API_KEY
});
if (this.requestsThisMinute >= 5) {
console.error("[Rate Limit] Rate limit reached. Waiting for next minute...");
return new Promise<void>((resolve) => {
const remainingMs = 60 * 1000 - (Date.now() % (60 * 1000));
setTimeout(resolve, remainingMs + 100); // Add 100ms buffer
});
}