# MCP Server Development Protocol

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? <a href="#what-are-mcp-servers" id="what-are-mcp-servers"></a>

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 <a href="#the-development-protocol" id="the-development-protocol"></a>

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:

Copy

````
# 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 <a href="#getting-started" id="getting-started"></a>

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:

Copy

```
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:

Copy

```
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 <a href="#understanding-the-two-modes" id="understanding-the-two-modes"></a>

**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 <a href="#case-study-alphaadvantage-stock-analysis-server" id="case-study-alphaadvantage-stock-analysis-server"></a>

Let's walk through the development process of our AlphaAdvantage MCP server, which provides stock data analysis and reporting capabilities.

**Planning Phase**

![](https://docs.cline.bot/~gitbook/image?url=https%3A%2F%2F3321249260-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252Ff8Oh1Lcy6yWYq1caYESV%252Fuploads%252FD8titDIv3ttw3PzMIR8P%252Fplanning-phase.gif%3Falt%3Dmedia%26token%3D8bc8ae34-f922-4c07-82ad-82e5eb3a3979\&width=768\&dpr=4\&quality=100\&sign=f5f2bae8\&sv=2)

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**

![](https://docs.cline.bot/~gitbook/image?url=https%3A%2F%2F3321249260-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252Ff8Oh1Lcy6yWYq1caYESV%252Fuploads%252FZMEeCFXac5ijuBz5WhQE%252Fbuilding-mcp-plugin.gif%3Falt%3Dmedia%26token%3Ddb8410da-7af1-4201-b97e-418b617e7c1c\&width=768\&dpr=4\&quality=100\&sign=909d5f98\&sv=2)

We began by bootstrapping the project:

Copy

```
npx @modelcontextprotocol/create-server alphaadvantage-mcp
cd alphaadvantage-mcp
npm install axios node-cache
```

Next, we structured our project with:

Copy

```
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:

Copy

```
/**
 * 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:

Copy

```
/**
 * 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:

Copy

```
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:

Copy

```
{
  "mcpServers": {
    "alphaadvantage-mcp": {
      "command": "node",
      "args": [
        "/path/to/alphaadvantage-mcp/build/index.js"
      ],
      "env": {
        "ALPHAVANTAGE_API_KEY": "YOUR_API_KEY"
      },
      "disabled": false,
      "autoApprove": []
    }
  }
}
```

1. Then we tested each tool individually:

* **get\_stock\_overview**: Retrieved AAPL stock overview information

  Copy

  ```
  # 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

  Copy

  ```
  # 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

  Copy

  ```
  # 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 <a href="#core-implementation-best-practices" id="core-implementation-best-practices"></a>

**Comprehensive Logging**

Effective logging is essential for debugging MCP servers:

Copy

```
// 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:

Copy

```
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:

Copy

```
// 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:

Copy

```
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 <a href="#mcp-resources" id="mcp-resources"></a>

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:

Copy

```
server.setRequestHandler(ListResourcesRequestSchema, async () => {
  return {
    resources: [
      {
        uri: "file:///project/readme.md",
        name: "Project README",
        mimeType: "text/markdown"
      }
    ]
  };
});
```

1. **Implement read handlers** to deliver the content:

Copy

```
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 <a href="#common-challenges-and-solutions" id="common-challenges-and-solutions"></a>

**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

Copy

```
// 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

Copy

```
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 <a href="#additional-resources" id="additional-resources"></a>

* [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)

[PreviousMCP Transport Mechanisms](https://docs.cline.bot/mcp-servers/mcp-transport-mechanisms)[<br>](https://docs.cline.bot/custom-model-configs/aws-bedrock)
