mirror of
https://github.com/cline/cline.git
synced 2025-06-03 03:59:07 +00:00

* add cdn image links * changeset --------- Co-authored-by: Elephant Lumps <celestial_vault@Elephants-MacBook-Pro.local>
706 lines
20 KiB
Plaintext
706 lines
20 KiB
Plaintext
---
|
|
title: "MCP Server Development Protocol"
|
|
description: "This protocol is designed to streamline the development process of building MCP servers with Cline."
|
|
---
|
|
|
|
> 🚀 **Build and share your MCP servers with the world.** Once you've created a great MCP server, submit it to the [Cline MCP Marketplace](https://github.com/cline/mcp-marketplace) to make it discoverable and one-click installable by thousands of developers.
|
|
|
|
## What Are MCP Servers?
|
|
|
|
Model Context Protocol (MCP) servers extend AI assistants like Cline by giving them the ability to:
|
|
|
|
- Access external APIs and services
|
|
- Retrieve real-time data
|
|
- Control applications and local systems
|
|
- Perform actions beyond what text prompts alone can achieve
|
|
|
|
Without MCP, AI assistants are powerful but isolated. With MCP, they gain the ability to interact with virtually any digital system.
|
|
|
|
## The Development Protocol
|
|
|
|
The heart of effective MCP server development is following a structured protocol. This protocol is implemented through a `.clinerules` file that lives at the **root** of your MCP working directory (/Users/your-name/Documents/Cline/MCP).
|
|
|
|
### Using `.clinerules` Files
|
|
|
|
A `.clinerules` file is a special configuration that Cline reads automatically when working in the directory where it's placed. These files:
|
|
|
|
- Configure Cline's behavior and enforce best practices
|
|
- Switch Cline into a specialized MCP development mode
|
|
- Provide a step-by-step protocol for building servers
|
|
- Implement safety measures like preventing premature completion
|
|
- Guide you through planning, implementation, and testing phases
|
|
|
|
Here's the complete MCP Server Development Protocol that should be placed in your `.clinerules` file:
|
|
|
|
````markdown
|
|
# MCP Server 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:
|
|
```bash
|
|
npx @modelcontextprotocol/create-server my-server
|
|
cd my-server
|
|
npm install
|
|
```
|
|
- For data science, ML workflows, or Python environments:
|
|
```bash
|
|
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):
|
|
```typescript
|
|
console.error("[Setup] Initializing server...")
|
|
console.error("[API] Request to endpoint:", endpoint)
|
|
console.error("[Error] Failed with:", error)
|
|
```
|
|
- Python (for data science/ML projects):
|
|
```python
|
|
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:
|
|
```json
|
|
{
|
|
"mcpServers": {
|
|
"my-server": {
|
|
"command": "node",
|
|
"args": ["path/to/build/index.js"],
|
|
"env": {
|
|
"API_KEY": "key"
|
|
},
|
|
"disabled": false,
|
|
"autoApprove": []
|
|
}
|
|
}
|
|
}
|
|
```
|
|
- For Python projects:
|
|
|
|
```bash
|
|
# 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
|
|
````
|
|
|
|
When this `.clinerules` file is present in your working directory, Cline will:
|
|
|
|
1. Start in **PLAN MODE** to design your server before implementation
|
|
2. Enforce proper implementation patterns in **ACT MODE**
|
|
3. Require testing of all tools before allowing completion
|
|
4. Guide you through the entire development lifecycle
|
|
|
|
## Getting Started
|
|
|
|
Creating an MCP server requires just a few simple steps to get started:
|
|
|
|
### 1. Create a `.clinerules` file (🚨 IMPORTANT)
|
|
|
|
First, add a `.clinerules` file to the root of your MCP working directory using the protocol above. This file configures Cline to use the MCP development protocol when working in this folder.
|
|
|
|
### 2. Start a Chat with a Clear Description
|
|
|
|
Begin your Cline chat by clearly describing what you want to build. Be specific about:
|
|
|
|
- The purpose of your MCP server
|
|
- Which API or service you want to integrate with
|
|
- Any specific tools or features you need
|
|
|
|
For example:
|
|
|
|
```plaintext
|
|
I want to build an MCP server for the AlphaAdvantage financial API.
|
|
It should allow me to get real-time stock data, perform technical
|
|
analysis, and retrieve company financial information.
|
|
```
|
|
|
|
### 3. Work Through the Protocol
|
|
|
|
Cline will automatically start in PLAN MODE, guiding you through the planning process:
|
|
|
|
- Discussing the problem scope
|
|
- Reviewing API documentation
|
|
- Planning authentication methods
|
|
- Designing tool interfaces
|
|
|
|
When ready, switch to ACT MODE using the toggle at the bottom of the chat to begin implementation.
|
|
|
|
### 4. Provide API Documentation Early
|
|
|
|
One of the most effective ways to help Cline build your MCP server is to share official API documentation right at the start:
|
|
|
|
```plaintext
|
|
Here's the API documentation for the service:
|
|
[Paste API documentation here]
|
|
```
|
|
|
|
Providing comprehensive API details (endpoints, authentication, data structures) significantly improves Cline's ability to implement an effective MCP server.
|
|
|
|
## Understanding the Two Modes
|
|
|
|
### PLAN MODE
|
|
|
|
In this collaborative phase, you work with Cline to design your MCP server:
|
|
|
|
- Define the problem scope
|
|
- Choose appropriate APIs
|
|
- Plan authentication methods
|
|
- Design the tool interfaces
|
|
- Determine data formats
|
|
|
|
### ACT MODE
|
|
|
|
Once planning is complete, Cline helps implement the server:
|
|
|
|
- Set up the project structure
|
|
- Write the implementation code
|
|
- Configure settings
|
|
- Test each component thoroughly
|
|
- Finalize documentation
|
|
|
|
## Case Study: AlphaAdvantage Stock Analysis Server
|
|
|
|
Let's walk through the development process of our AlphaAdvantage MCP server, which provides stock data analysis and reporting capabilities.
|
|
|
|
### Planning Phase
|
|
|
|
<Frame>
|
|
<img
|
|
src="https://storage.googleapis.com/cline_public_images/docs/assets/planning-phase.gif"
|
|
alt="Planning phase demonstration"
|
|
/>
|
|
</Frame>
|
|
|
|
During the planning phase, we:
|
|
|
|
1. **Defined the problem**: Users need access to financial data, stock analysis, and market insights directly through their AI assistant
|
|
2. **Selected the API**: AlphaAdvantage API for financial market data
|
|
- Standard API key authentication
|
|
- Rate limits of 5 requests per minute (free tier)
|
|
- Various endpoints for different financial data types
|
|
3. **Designed the tools needed**:
|
|
- Stock overview information (current price, company details)
|
|
- Technical analysis with indicators (RSI, MACD, etc.)
|
|
- Fundamental analysis (financial statements, ratios)
|
|
- Earnings report data
|
|
- News and sentiment analysis
|
|
4. **Planned data formatting**:
|
|
- Clean, well-formatted markdown output
|
|
- Tables for structured data
|
|
- Visual indicators (↑/↓) for trends
|
|
- Proper formatting of financial numbers
|
|
|
|
### Implementation
|
|
|
|
<Frame>
|
|
<img
|
|
src="https://storage.googleapis.com/cline_public_images/docs/assets/building-mcp-plugin.gif"
|
|
alt="Building MCP plugin demonstration"
|
|
/>
|
|
</Frame>
|
|
|
|
We began by bootstrapping the project:
|
|
|
|
```bash
|
|
npx @modelcontextprotocol/create-server alphaadvantage-mcp
|
|
cd alphaadvantage-mcp
|
|
npm install axios node-cache
|
|
```
|
|
|
|
Next, we structured our project with:
|
|
|
|
```plaintext
|
|
src/
|
|
├── api/
|
|
│ └── alphaAdvantageClient.ts # API client with rate limiting & caching
|
|
├── formatters/
|
|
│ └── markdownFormatter.ts # Output formatters for clean markdown
|
|
└── index.ts # Main MCP server implementation
|
|
```
|
|
|
|
#### API Client Implementation
|
|
|
|
The API client implementation included:
|
|
|
|
- **Rate limiting**: Enforcing the 5 requests per minute limit
|
|
- **Caching**: Reducing API calls with strategic caching
|
|
- **Error handling**: Robust error detection and reporting
|
|
- **Typed interfaces**: Clear TypeScript types for all data
|
|
|
|
Key implementation details:
|
|
|
|
```typescript
|
|
/**
|
|
* Manage rate limiting based on free tier (5 calls per minute)
|
|
*/
|
|
private async enforceRateLimit() {
|
|
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
|
|
});
|
|
}
|
|
|
|
this.requestsThisMinute++;
|
|
return Promise.resolve();
|
|
}
|
|
```
|
|
|
|
#### Markdown Formatting
|
|
|
|
We implemented formatters to display financial data beautifully:
|
|
|
|
```typescript
|
|
/**
|
|
* Format company overview into markdown
|
|
*/
|
|
export function formatStockOverview(overviewData: any, quoteData: any): string {
|
|
// Extract data
|
|
const overview = overviewData
|
|
const quote = quoteData["Global Quote"]
|
|
|
|
// Calculate price change
|
|
const currentPrice = parseFloat(quote["05. price"] || "0")
|
|
const priceChange = parseFloat(quote["09. change"] || "0")
|
|
const changePercent = parseFloat(quote["10. change percent"]?.replace("%", "") || "0")
|
|
|
|
// Format markdown
|
|
let markdown = `# ${overview.Symbol} (${overview.Name}) - ${formatCurrency(currentPrice)} ${addTrendIndicator(priceChange)}${changePercent > 0 ? "+" : ""}${changePercent.toFixed(2)}%\n\n`
|
|
|
|
// Add more details...
|
|
|
|
return markdown
|
|
}
|
|
```
|
|
|
|
#### Tool Implementation
|
|
|
|
We defined five tools with clear interfaces:
|
|
|
|
```typescript
|
|
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
console.error("[Setup] Listing available tools")
|
|
|
|
return {
|
|
tools: [
|
|
{
|
|
name: "get_stock_overview",
|
|
description: "Get basic company info and current quote for a stock symbol",
|
|
inputSchema: {
|
|
type: "object",
|
|
properties: {
|
|
symbol: {
|
|
type: "string",
|
|
description: "Stock symbol (e.g., 'AAPL')",
|
|
},
|
|
market: {
|
|
type: "string",
|
|
description: "Optional market (e.g., 'US')",
|
|
default: "US",
|
|
},
|
|
},
|
|
required: ["symbol"],
|
|
},
|
|
},
|
|
// Additional tools defined here...
|
|
],
|
|
}
|
|
})
|
|
```
|
|
|
|
Each tool's handler included:
|
|
|
|
- Input validation
|
|
- API client calls with error handling
|
|
- Markdown formatting of responses
|
|
- Comprehensive logging
|
|
|
|
### Testing Phase
|
|
|
|
This critical phase involved systematically testing each tool:
|
|
|
|
1. First, we configured the MCP server in the settings:
|
|
|
|
```json
|
|
{
|
|
"mcpServers": {
|
|
"alphaadvantage-mcp": {
|
|
"command": "node",
|
|
"args": ["/path/to/alphaadvantage-mcp/build/index.js"],
|
|
"env": {
|
|
"ALPHAVANTAGE_API_KEY": "YOUR_API_KEY"
|
|
},
|
|
"disabled": false,
|
|
"autoApprove": []
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
2. Then we tested each tool individually:
|
|
|
|
- **get_stock_overview**: Retrieved AAPL stock overview information
|
|
|
|
```markdown
|
|
# AAPL (Apple Inc) - $241.84 ↑+1.91%
|
|
|
|
**Sector:** TECHNOLOGY
|
|
**Industry:** ELECTRONIC COMPUTERS
|
|
**Market Cap:** 3.63T
|
|
**P/E Ratio:** 38.26
|
|
...
|
|
```
|
|
|
|
- **get_technical_analysis**: Obtained price action and RSI data
|
|
|
|
```markdown
|
|
# 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 |
|
|
|
|
...
|
|
```
|
|
|
|
- **get_earnings_report**: Retrieved MSFT earnings history and formatted report
|
|
|
|
```markdown
|
|
# 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% |
|
|
|
|
...
|
|
```
|
|
|
|
### Challenges and Solutions
|
|
|
|
During development, we encountered several challenges:
|
|
|
|
1. **API Rate Limiting**:
|
|
- **Challenge**: Free tier limited to 5 calls per minute
|
|
- **Solution**: Implemented queuing, enforced rate limits, and added comprehensive caching
|
|
2. **Data Formatting**:
|
|
- **Challenge**: Raw API data not user-friendly
|
|
- **Solution**: Created formatting utilities for consistent display of financial data
|
|
3. **Timeout Issues**:
|
|
- **Challenge**: Complex tools making multiple API calls could timeout
|
|
- **Solution**: Suggested breaking complex tools into smaller pieces, optimizing caching
|
|
|
|
### Lessons Learned
|
|
|
|
Our AlphaAdvantage implementation taught us several key lessons:
|
|
|
|
1. **Plan for API Limits**: Understand and design around API rate limits from the beginning
|
|
2. **Cache Strategically**: Identify high-value caching opportunities to improve performance
|
|
3. **Format for Readability**: Invest in good data formatting for improved user experience
|
|
4. **Test Every Path**: Test all tools individually before completion
|
|
5. **Handle API Complexity**: For APIs requiring multiple calls, design tools with simpler scopes
|
|
|
|
## Core Implementation Best Practices
|
|
|
|
### Comprehensive Logging
|
|
|
|
Effective logging is essential for debugging MCP servers:
|
|
|
|
```typescript
|
|
// Start-up logging
|
|
console.error("[Setup] Initializing AlphaAdvantage MCP server...")
|
|
|
|
// API request logging
|
|
console.error(`[API] Getting stock overview for ${symbol}`)
|
|
|
|
// Error handling with context
|
|
console.error(`[Error] Tool execution failed: ${error.message}`)
|
|
|
|
// Cache operations
|
|
console.error(`[Cache] Using cached data for: ${cacheKey}`)
|
|
```
|
|
|
|
### Strong Typing
|
|
|
|
Type definitions prevent errors and improve maintainability:
|
|
|
|
```typescript
|
|
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}`)
|
|
}
|
|
}
|
|
```
|
|
|
|
### Intelligent Caching
|
|
|
|
Reduce API calls and improve performance:
|
|
|
|
```typescript
|
|
// Default cache TTL in seconds
|
|
const DEFAULT_CACHE_TTL = {
|
|
STOCK_OVERVIEW: 60 * 60, // 1 hour
|
|
TECHNICAL_ANALYSIS: 60 * 30, // 30 minutes
|
|
FUNDAMENTAL_ANALYSIS: 60 * 60 * 24, // 24 hours
|
|
EARNINGS_REPORT: 60 * 60 * 24, // 24 hours
|
|
NEWS: 60 * 15, // 15 minutes
|
|
}
|
|
|
|
// Check cache first
|
|
const cachedData = this.cache.get<T>(cacheKey)
|
|
if (cachedData) {
|
|
console.error(`[Cache] Using cached data for: ${cacheKey}`)
|
|
return cachedData
|
|
}
|
|
|
|
// Cache successful responses
|
|
this.cache.set(cacheKey, response.data, cacheTTL)
|
|
```
|
|
|
|
### Graceful Error Handling
|
|
|
|
Implement robust error handling that maintains a good user experience:
|
|
|
|
```typescript
|
|
try {
|
|
switch (request.params.name) {
|
|
case "get_stock_overview": {
|
|
// Implementation...
|
|
}
|
|
|
|
// Other cases...
|
|
|
|
default:
|
|
throw new McpError(ErrorCode.MethodNotFound, `Unknown tool: ${request.params.name}`)
|
|
}
|
|
} catch (error) {
|
|
console.error(`[Error] Tool execution failed: ${error instanceof Error ? error.message : String(error)}`)
|
|
|
|
if (error instanceof McpError) {
|
|
throw error
|
|
}
|
|
|
|
return {
|
|
content: [
|
|
{
|
|
type: "text",
|
|
text: `Error: ${error instanceof Error ? error.message : String(error)}`,
|
|
},
|
|
],
|
|
isError: true,
|
|
}
|
|
}
|
|
```
|
|
|
|
## MCP Resources
|
|
|
|
Resources let your MCP servers expose data to Cline without executing code. They're perfect for providing context like files, API responses, or database records that Cline can reference during conversations.
|
|
|
|
### Adding Resources to Your MCP Server
|
|
|
|
1. **Define the resources** your server will expose:
|
|
|
|
```typescript
|
|
server.setRequestHandler(ListResourcesRequestSchema, async () => {
|
|
return {
|
|
resources: [
|
|
{
|
|
uri: "file:///project/readme.md",
|
|
name: "Project README",
|
|
mimeType: "text/markdown",
|
|
},
|
|
],
|
|
}
|
|
})
|
|
```
|
|
|
|
2. **Implement read handlers** to deliver the content:
|
|
|
|
```typescript
|
|
server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
|
|
if (request.params.uri === "file:///project/readme.md") {
|
|
const content = await fs.promises.readFile("/path/to/readme.md", "utf-8")
|
|
return {
|
|
contents: [
|
|
{
|
|
uri: request.params.uri,
|
|
mimeType: "text/markdown",
|
|
text: content,
|
|
},
|
|
],
|
|
}
|
|
}
|
|
|
|
throw new Error("Resource not found")
|
|
})
|
|
```
|
|
|
|
Resources make your MCP servers more context-aware, allowing Cline to access specific information without requiring you to copy/paste. For more information, refer to the [official documentation](https://modelcontextprotocol.io/docs/concepts/resources).
|
|
|
|
## Common Challenges and Solutions
|
|
|
|
### API Authentication Complexities
|
|
|
|
**Challenge**: APIs often have different authentication methods.
|
|
|
|
**Solution**:
|
|
|
|
- For API keys, use environment variables in the MCP configuration
|
|
- For OAuth, create a separate script to obtain refresh tokens
|
|
- Store sensitive tokens securely
|
|
|
|
```typescript
|
|
// 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,
|
|
})
|
|
```
|
|
|
|
### Missing or Limited API Features
|
|
|
|
**Challenge**: APIs may not provide all the functionality you need.
|
|
|
|
**Solution**:
|
|
|
|
- Implement fallbacks using available endpoints
|
|
- Create simulated functionality where necessary
|
|
- Transform API data to match your needs
|
|
|
|
### API Rate Limiting
|
|
|
|
**Challenge**: Most APIs have rate limits that can cause failures.
|
|
|
|
**Solution**:
|
|
|
|
- Implement proper rate limiting
|
|
- Add intelligent caching
|
|
- Provide graceful degradation
|
|
- Add transparent errors about rate limits
|
|
|
|
```typescript
|
|
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
|
|
})
|
|
}
|
|
```
|
|
|
|
## Additional Resources
|
|
|
|
- [MCP Protocol Documentation](https://github.com/modelcontextprotocol/mcp)
|
|
- [MCP SDK Documentation](https://github.com/modelcontextprotocol/sdk-js)
|
|
- [MCP Server Examples](https://github.com/modelcontextprotocol/servers)
|