MCP Builder Skill
Version: 1.2.0 Category: Development Last Updated: 2026-01-02
Overview
This skill teaches how to build high-quality MCP servers that allow large language models to interact with external services through well-designed tools.
Quick Start
# Create and setup MCP server project mkdir my-mcp-server && cd my-mcp-server npm init -y npm install @modelcontextprotocol/sdk zod npm install -D typescript @types/node # Create source directory mkdir src
// src/index.ts - Minimal MCP Server
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { CallToolRequestSchema, ListToolsRequestSchema } from "@modelcontextprotocol/sdk/types.js";
const server = new Server(
{ name: "my-server", version: "1.0.0" },
{ capabilities: { tools: {} } }
);
server.setRequestHandler(ListToolsRequestSchema, async () => ({
tools: [{
name: "hello_world",
description: "Returns a greeting message",
inputSchema: { type: "object", properties: { name: { type: "string" } }, required: ["name"] }
}]
}));
server.setRequestHandler(CallToolRequestSchema, async (request) => {
if (request.params.name === "hello_world") {
return { content: [{ type: "text", text: `Hello, ${request.params.arguments?.name}!` }] };
}
throw new Error(`Unknown tool: ${request.params.name}`);
});
const transport = new StdioServerTransport();
await server.connect(transport);
When to Use
- •Creating integrations for Claude Code with external APIs
- •Building custom tooling for AI-assisted workflows
- •Extending Claude's capabilities with domain-specific tools
- •Automating interactions with third-party services
- •Building reusable MCP servers for team sharing
Four-Phase Development Process
Phase 1: Deep Research and Planning
Study MCP Design Principles:
- •Balance "API coverage vs. workflow tools"
- •Review MCP protocol at modelcontextprotocol.io
- •Learn framework specifics (TypeScript recommended)
- •Analyze target API endpoints
Key Questions:
- •What actions does the user want to perform?
- •What API endpoints are available?
- •Which operations are read-only vs destructive?
- •How should errors be handled?
Phase 2: Implementation
Project Setup (TypeScript):
mkdir my-mcp-server cd my-mcp-server npm init -y npm install @modelcontextprotocol/sdk zod npm install -D typescript @types/node
tsconfig.json:
{
"compilerOptions": {
"target": "ES2020",
"module": "NodeNext",
"moduleResolution": "NodeNext",
"outDir": "./dist",
"strict": true,
"esModuleInterop": true
},
"include": ["src/**/*"]
}
Basic Server Structure:
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import {
CallToolRequestSchema,
ListToolsRequestSchema,
} from "@modelcontextprotocol/sdk/types.js";
const server = new Server(
{ name: "my-server", version: "1.0.0" },
{ capabilities: { tools: {} } }
);
// List available tools
server.setRequestHandler(ListToolsRequestSchema, async () => ({
tools: [
{
name: "my_tool",
description: "Description of what this tool does",
inputSchema: {
type: "object",
properties: {
param1: { type: "string", description: "First parameter" },
param2: { type: "number", description: "Second parameter" }
},
required: ["param1"]
}
}
]
}));
// Handle tool calls
server.setRequestHandler(CallToolRequestSchema, async (request) => {
const { name, arguments: args } = request.params;
if (name === "my_tool") {
// Tool implementation
return {
content: [{ type: "text", text: "Result" }]
};
}
throw new Error(`Unknown tool: ${name}`);
});
// Start server
const transport = new StdioServerTransport();
await server.connect(transport);
Phase 3: Review and Test
Code Quality Checklist:
- • No code duplication
- • Full type coverage
- • Proper error handling
- • Input validation
- • Rate limiting (if needed)
Testing with MCP Inspector:
npx @modelcontextprotocol/inspector node dist/index.js
Phase 4: Create Evaluations
Generate 10 complex, realistic test questions:
- •Independent (no dependencies between questions)
- •Read-only (don't modify external state)
- •Verifiable (clear expected answers)
Key Recommendations
Language Choice
TypeScript preferred for:
- •High-quality SDK support
- •Good compatibility
- •Strong typing
Transport Selection
- •Streamable HTTP: Remote servers
- •stdio: Local servers
Tool Naming
Use consistent, action-oriented prefixes:
github_create_issue github_list_repos slack_send_message slack_list_channels
Error Messages
Provide actionable messages with specific next steps:
throw new Error(
`Failed to fetch repository: ${error.message}. ` +
`Check that the repository exists and you have access.`
);
Tool Annotations
{
name: "delete_file",
description: "Permanently delete a file",
inputSchema: { /* ... */ },
annotations: {
destructiveHint: true,
readOnlyHint: false,
confirmationHint: "Are you sure you want to delete this file?"
}
}
Advanced Patterns
Pagination
async function listAllItems(apiClient: Client): Promise<Item[]> {
const items: Item[] = [];
let cursor: string | undefined;
do {
const response = await apiClient.list({ cursor, limit: 100 });
items.push(...response.items);
cursor = response.nextCursor;
} while (cursor);
return items;
}
Rate Limiting
import Bottleneck from "bottleneck";
const limiter = new Bottleneck({
maxConcurrent: 1,
minTime: 100 // 10 requests per second
});
const rateLimitedFetch = limiter.wrap(fetch);
Authentication
const API_KEY = process.env.MY_API_KEY;
if (!API_KEY) {
throw new Error(
"MY_API_KEY environment variable is required. " +
"Get your API key from https://example.com/settings"
);
}
Integration with Claude Code
Add to claude_desktop_config.json:
{
"mcpServers": {
"my-server": {
"command": "node",
"args": ["/path/to/dist/index.js"],
"env": {
"MY_API_KEY": "your-api-key"
}
}
}
}
Project Configuration (New in 2025)
.mcp.json for Team Sharing
Commit MCP server configs to your repository:
// .mcp.json (project root)
{
"mcpServers": {
"project-db": {
"command": "node",
"args": ["./tools/mcp-server/dist/index.js"],
"env": {
"DB_PATH": "./data/project.db"
}
}
}
}
Scope changes (2025):
- •
projectscope -> Now calledlocal(per-project) - •
globalscope -> Now calleduser(user-wide) - •New: Checked-in
.mcp.jsonfiles for team sharing
Permission Wildcards
Use wildcard syntax for server permissions:
# Allow all tools from a server
mcp__my-server__*
# In settings.json allowlist
{
"permissions": {
"allow": ["mcp__database__*", "mcp__github__*"]
}
}
Timeout Configuration
# Set MCP server startup timeout (default: 30s) export MCP_TIMEOUT=60000 # 60 seconds # Debug mode for troubleshooting claude --mcp-debug
Usage Examples
Example 1: Database Query Tool
server.setRequestHandler(CallToolRequestSchema, async (request) => {
if (request.params.name === "query_database") {
const { sql, params } = request.params.arguments;
const result = await db.query(sql, params);
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
}
});
Example 2: API Integration
server.setRequestHandler(CallToolRequestSchema, async (request) => {
if (request.params.name === "fetch_weather") {
const { city } = request.params.arguments;
const response = await fetch(`https://api.weather.com/v1/${city}`);
const data = await response.json();
return { content: [{ type: "text", text: `Temperature: ${data.temp}F` }] };
}
});
Best Practices
Do
- •Use TypeScript for type safety
- •Validate all inputs with Zod
- •Provide clear, actionable error messages
- •Use environment variables for secrets
- •Implement rate limiting for external APIs
- •Add tool annotations for destructive operations
Don't
- •Hardcode API keys or secrets
- •Skip input validation
- •Return raw error stack traces
- •Create overly complex tool schemas
- •Ignore rate limits on external services
Error Handling
Common Errors
| Error | Cause | Solution |
|---|---|---|
ECONNREFUSED | Server not running | Start the MCP server process |
Tool not found | Incorrect tool name | Check ListToolsRequestSchema handler |
Invalid arguments | Schema mismatch | Validate against inputSchema |
Authentication failed | Missing/invalid API key | Set environment variable correctly |
Timeout | Slow response | Increase MCP_TIMEOUT or optimize handler |
Error Template
try {
const result = await operation();
return { content: [{ type: "text", text: JSON.stringify(result) }] };
} catch (error) {
throw new Error(
`Operation failed: ${error.message}. ` +
`Please check your configuration and try again.`
);
}
Execution Checklist
- • Project initialized with TypeScript and MCP SDK
- • tsconfig.json configured for ES2020/NodeNext
- • Server implements ListToolsRequestSchema handler
- • Server implements CallToolRequestSchema handler
- • Input validation with Zod schemas
- • Error handling with actionable messages
- • Environment variables for sensitive config
- • Tested with MCP Inspector
- • Added to claude_desktop_config.json or .mcp.json
- • Documentation complete
Metrics
| Metric | Target | Description |
|---|---|---|
| Response Time | <500ms | Tool execution latency |
| Error Rate | <1% | Percentage of failed tool calls |
| Type Coverage | 100% | TypeScript strict mode compliance |
| Test Coverage | >80% | Unit test coverage |
Security Best Practices
- •Use trusted servers - Only from official/verified sources
- •Least privilege - Grant minimal required permissions
- •Audit logs - Maintain comprehensive access logs
- •Environment isolation - Use containers for high-risk automation
- •No hardcoded secrets - Always use environment variables
Resources
- •MCP Documentation: https://modelcontextprotocol.io
- •MCP TypeScript SDK: https://github.com/modelcontextprotocol/typescript-sdk
- •MCP Inspector: https://github.com/modelcontextprotocol/inspector
- •Top MCP Servers: https://mcpcat.io/guides/best-mcp-servers-for-claude-code/
Related Skills
- •yaml-workflow-executor - Workflow automation
- •webapp-testing - Testing web integrations
- •git-worktree-workflow - Parallel development
Version History
- •1.2.0 (2026-01-02): Upgraded to SKILL_TEMPLATE_v2 format with Quick Start, Error Handling, Metrics, Execution Checklist
- •1.1.0 (2025-12-30): Added .mcp.json project config, permission wildcards, MCP_TIMEOUT, security best practices
- •1.0.0 (2025-10-15): Initial release with four-phase development process