Claude
Skills
Sign in
Back

mcp-builder

Included with Lifetime
$97 forever

Use when the user needs to build MCP (Model Context Protocol) servers — tool definitions, resource management, prompt templates, transport layers, and client integration. Triggers: user says "MCP", "MCP server", "model context protocol", building tools for AI clients, creating AI integrations.

AI Agents

What this skill does


# MCP Builder

## Overview

Build production-quality MCP (Model Context Protocol) servers that expose tools, resources, and prompts to AI clients. This skill covers the full development lifecycle: tool definition, resource management, prompt templates, transport configuration (stdio, SSE), error handling, security hardening, testing, and client integration.

## Phase 1: Design

1. Identify capabilities to expose (tools, resources, prompts)
2. Define tool schemas with Zod/JSON Schema
3. Plan resource URI patterns
4. Design error handling strategy
5. Choose transport layer (stdio for CLI, SSE for web)

**STOP — Present the capability inventory and transport choice to user for approval.**

### Capability Selection Decision Table

| What You Have | MCP Primitive | Example |
|---|---|---|
| Actions that modify state | Tool | `create-issue`, `send-email`, `deploy-app` |
| Actions that read/query | Tool | `search-documents`, `get-status` |
| Data the AI should read | Resource | `config://settings`, `docs://api/endpoints` |
| Reusable prompt patterns | Prompt | `code-review`, `summarize-document` |
| Real-time data feeds | Resource (subscribable) | `metrics://cpu/current` |

### Transport Selection Decision Table

| Context | Transport | Why |
|---|---|---|
| CLI tool, local client (Claude Desktop) | Stdio | Simple, no network overhead |
| Web application, remote clients | SSE | Network-accessible, real-time |
| Both local and remote | Stdio + SSE | Support both use cases |
| High-throughput, bidirectional | WebSocket (custom) | Lower latency than SSE |

## Phase 2: Implementation

1. Set up MCP server project structure
2. Implement tool handlers with input validation
3. Implement resource providers
4. Add prompt templates
5. Configure transport and authentication

**STOP — Run basic smoke tests before moving to hardening.**

### Project Structure

```
src/
  index.ts          # Server entry point
  tools/
    search.ts       # Tool implementations
    create.ts
  resources/
    documents.ts    # Resource providers
    config.ts
  prompts/
    review.ts       # Prompt templates
  lib/
    database.ts     # Shared utilities
    validation.ts
tests/
  tools.test.ts
  resources.test.ts
package.json
tsconfig.json
```

### Tool Definition Pattern

```typescript
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { z } from 'zod';

const server = new McpServer({
  name: 'my-mcp-server',
  version: '1.0.0',
});

server.tool(
  'search-documents',
  'Search documents by query. Returns matching documents with relevance scores.',
  {
    query: z.string().describe('Search query string'),
    limit: z.number().min(1).max(100).default(10).describe('Maximum results to return'),
    filter: z.object({
      type: z.enum(['article', 'page', 'note']).optional(),
      dateAfter: z.string().datetime().optional(),
    }).optional().describe('Optional filters'),
  },
  async ({ query, limit, filter }) => {
    const results = await searchEngine.search(query, { limit, ...filter });
    return {
      content: [{
        type: 'text',
        text: JSON.stringify(results, null, 2),
      }],
    };
  }
);
```

### Tool Design Principles

| Principle | Rule |
|---|---|
| Clear naming | verb-noun format: `search-documents`, `create-issue` |
| Descriptive descriptions | Explain what, when, and return value |
| Validated inputs | Zod schemas with `.describe()` on every field |
| Structured outputs | Well-formatted text or JSON |
| Idempotent when possible | Same input produces same result |
| Actionable errors | Specific error messages with `isError: true` |

### Tool Response Patterns

```typescript
// Text response
return { content: [{ type: 'text', text: 'Operation completed successfully' }] };

// Structured data response
return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };

// Multi-part response
return {
  content: [
    { type: 'text', text: `Found ${results.length} results:` },
    { type: 'text', text: results.map(r => `- ${r.title}: ${r.summary}`).join('\n') },
  ],
};

// Image response
return { content: [{ type: 'image', data: base64Data, mimeType: 'image/png' }] };

// Error response
return {
  content: [{ type: 'text', text: `Error: ${error.message}` }],
  isError: true,
};
```

## Resource Management

### Resource Definition

```typescript
// Static resource
server.resource(
  'config',
  'config://app/settings',
  { mimeType: 'application/json' },
  async () => ({
    contents: [{
      uri: 'config://app/settings',
      mimeType: 'application/json',
      text: JSON.stringify(appConfig),
    }],
  })
);

// Dynamic resource with URI template
server.resource(
  'document',
  new ResourceTemplate('docs://{category}/{id}', { list: undefined }),
  { mimeType: 'text/markdown' },
  async (uri, { category, id }) => ({
    contents: [{
      uri: uri.href,
      mimeType: 'text/markdown',
      text: await getDocument(category, id),
    }],
  })
);
```

### Resource URI Conventions

```
file:///path/to/file          — Local files
https://api.example.com/data  — Remote HTTP resources
db://database/table/id        — Database records
config://app/settings         — Configuration
docs://category/slug          — Documentation
```

## Prompt Templates

```typescript
server.prompt(
  'code-review',
  'Generate a code review for the given file',
  {
    filePath: z.string().describe('Path to the file to review'),
    severity: z.enum(['strict', 'normal', 'lenient']).default('normal'),
  },
  async ({ filePath, severity }) => {
    const code = await readFile(filePath, 'utf-8');
    return {
      messages: [{
        role: 'user',
        content: {
          type: 'text',
          text: `Review this code with ${severity} standards:\n\n\`\`\`\n${code}\n\`\`\``,
        },
      }],
    };
  }
);
```

## Transport Layers

### Stdio Transport (CLI tools, local development)

```typescript
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';

const transport = new StdioServerTransport();
await server.connect(transport);
```

### SSE Transport (Web applications, remote servers)

```typescript
import express from 'express';
import { SSEServerTransport } from '@modelcontextprotocol/sdk/server/sse.js';

const app = express();

app.get('/sse', async (req, res) => {
  const transport = new SSEServerTransport('/messages', res);
  await server.connect(transport);
});

app.post('/messages', async (req, res) => {
  // Handle incoming messages
});

app.listen(3001);
```

## Phase 3: Hardening

1. Add comprehensive error handling
2. Implement rate limiting and timeouts
3. Security review (input sanitization, permission checks)
4. Write integration tests
5. Document tools and resources for clients

**STOP — All tests must pass and security review must be complete before deployment.**

### Error Handling

```typescript
server.tool('risky-operation', 'Performs an operation that might fail', {
  input: z.string(),
}, async ({ input }) => {
  try {
    const result = await performOperation(input);
    return { content: [{ type: 'text', text: JSON.stringify(result) }] };
  } catch (error) {
    if (error instanceof ValidationError) {
      return {
        content: [{ type: 'text', text: `Invalid input: ${error.message}` }],
        isError: true,
      };
    }
    if (error instanceof NotFoundError) {
      return {
        content: [{ type: 'text', text: `Resource not found: ${error.message}` }],
        isError: true,
      };
    }
    console.error('Unexpected error:', error);
    return {
      content: [{ type: 'text', text: 'An unexpected error occurred. Please try again.' }],
      isError: true,
    };
  }
});
```

### Error Handling Rules

| Rule | Why |
|---|---|
| Never expose stack traces to clients | Security risk |
| Return `isError: true` for all errors | Client can distinguish success/failure |
| Log unexpected errors server-side | Debugging and monitoring |
| Provide actionable error messages | Client c

Related in AI Agents