Mcp Builder Expert
Comprehensive skill designed for guide, creating, high, quality. Includes structured workflows, validation checks, and reusable patterns for development.
MCP Server Builder Skill
A Claude Code skill for building production-quality Model Context Protocol (MCP) servers — covering tool design, resource exposure, transport configuration, authentication, error handling, and deployment.
When to Use This Skill
Choose this skill when:
- Building a new MCP server to expose tools and data to LLMs
- Designing tool interfaces for Claude Code integration
- Implementing resource endpoints for data access
- Adding authentication and authorization to MCP servers
- Deploying MCP servers to production environments
- Testing and debugging MCP server implementations
Consider alternatives when:
- You need to use existing MCP tools, not build them (use MCP client)
- You need a REST/GraphQL API without MCP (use a web framework)
- You need to modify Claude Code's built-in tools (not possible via MCP)
Quick Start
# TypeScript MCP Server npm init -y npm install @modelcontextprotocol/sdk zod
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; import { z } from 'zod'; const server = new McpServer({ name: 'my-data-server', version: '1.0.0', }); // Define a tool server.tool( 'query_database', 'Execute a read-only SQL query against the analytics database', { sql: z.string().describe('SQL query to execute (SELECT only)'), limit: z.number().default(100).describe('Maximum rows to return'), }, async ({ sql, limit }) => { if (!sql.trim().toUpperCase().startsWith('SELECT')) { return { content: [{ type: 'text', text: 'Error: Only SELECT queries allowed' }] }; } const results = await db.query(sql, { limit }); return { content: [{ type: 'text', text: JSON.stringify(results, null, 2) }] }; } ); // Define a resource server.resource('schema://tables', 'Database schema information', async () => ({ contents: [{ uri: 'schema://tables', text: JSON.stringify(await db.getSchema()) }] })); // Start server const transport = new StdioServerTransport(); await server.connect(transport);
Core Concepts
MCP Components
| Component | Purpose | Example |
|---|---|---|
| Tools | Functions the LLM can call | query_database, send_email, create_ticket |
| Resources | Read-only data endpoints | schema://tables, config://app, docs://api |
| Prompts | Reusable prompt templates | summarize_data, explain_error |
Tool Design Patterns
// Pattern: Tool with validation and structured response server.tool( 'create_ticket', 'Create a support ticket in the ticketing system', { title: z.string().min(5).max(200).describe('Ticket title'), description: z.string().describe('Detailed description of the issue'), priority: z.enum(['low', 'medium', 'high', 'critical']).describe('Ticket priority'), assignee: z.string().optional().describe('Team member to assign'), }, async ({ title, description, priority, assignee }) => { const ticket = await ticketService.create({ title, description, priority, assignee }); return { content: [{ type: 'text', text: `Created ticket #${ticket.id}: ${ticket.title}\nStatus: ${ticket.status}\nPriority: ${ticket.priority}` }] }; } ); // Pattern: Tool with error handling server.tool('fetch_metrics', 'Get application metrics for a time range', { metric: z.string().describe('Metric name (e.g., cpu_usage, memory, requests)'), period: z.enum(['1h', '24h', '7d', '30d']).describe('Time period'), }, async ({ metric, period }) => { try { const data = await metricsService.query(metric, period); return { content: [{ type: 'text', text: formatMetrics(data) }] }; } catch (error) { return { content: [{ type: 'text', text: `Error fetching ${metric}: ${error.message}` }], isError: true }; } });
Configuration
| Parameter | Type | Default | Description |
|---|---|---|---|
name | string | — | Server name (required) |
version | string | "1.0.0" | Server version |
transport | string | "stdio" | Transport: stdio, sse, streamable-http |
auth | string | "none" | Authentication: none, token, oauth |
max_concurrent | number | 10 | Maximum concurrent tool calls |
timeout | number | 30000 | Tool execution timeout (ms) |
log_level | string | "info" | Logging: debug, info, warn, error |
Best Practices
-
Write detailed tool descriptions — the LLM decides when and how to call tools based on descriptions; include when to use the tool, what it returns, and any important constraints.
-
Use Zod schemas with
.describe()on every parameter — parameter descriptions help the LLM provide correct inputs; without them, the LLM guesses at parameter meanings. -
Return structured data, not formatted text — return JSON or structured strings so the LLM can interpret and present the data appropriately for the user's question.
-
Handle errors gracefully with
isError: true— return error messages as content with the error flag instead of throwing exceptions; this gives the LLM information to respond helpfully. -
Make tools idempotent when possible — tools that can be safely called multiple times with the same input simplify error recovery; the LLM may retry failed tool calls.
Common Issues
LLM calls the wrong tool — Tool descriptions are too similar. Differentiate descriptions clearly and include "Use this when..." guidance. Avoid generic names like getData — be specific like get_user_profile.
Tool timeout on long operations — Increase the timeout for specific tools or use progress reporting. Consider breaking long operations into multiple smaller tools that can be called sequentially.
Server crashes on malformed input — Even with Zod validation, edge cases can cause issues. Wrap tool handlers in try-catch and return error content instead of crashing the server.
Reviews
No reviews yet. Be the first to review this template!
Similar Templates
Full-Stack Code Reviewer
Comprehensive code review skill that checks for security vulnerabilities, performance issues, accessibility, and best practices across frontend and backend code.
Test Suite Generator
Generates comprehensive test suites with unit tests, integration tests, and edge cases. Supports Jest, Vitest, Pytest, and Go testing.
Pro Architecture Workspace
Battle-tested skill for architectural, decision, making, framework. Includes structured workflows, validation checks, and reusable patterns for development.