Building Your First MCP Server: A Complete Guide for Claude Code
The Model Context Protocol (MCP) is how Claude Code extends its capabilities — from file systems to databases to real-time APIs. Building your own MCP server unlocks unlimited tool integrations.
What Is an MCP Server?
An MCP server exposes tools, resources, and prompts to Claude Code. When Claude runs inside your editor, it discovers connected MCP servers and can call their tools mid-conversation.
Claude Code
│
├── MCP Server A (filesystem)
├── MCP Server B (database)
└── MCP Server C (your custom server)
Setting Up the Project
npm init -y
npm install @modelcontextprotocol/sdk
Your First 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-mcp-server', version: '1.0.0' },
{ capabilities: { tools: {} } }
);
server.setRequestHandler(ListToolsRequestSchema, async () => ({
tools: [{
name: 'get_weather',
description: 'Get current weather for a city',
inputSchema: {
type: 'object',
properties: {
city: { type: 'string', description: 'City name' }
},
required: ['city']
}
}]
}));
server.setRequestHandler(CallToolRequestSchema, async (request) => {
if (request.params.name === 'get_weather') {
const { city } = request.params.arguments as { city: string };
// Call your weather API here
return { content: [{ type: 'text', text: `Weather in ${city}: 72°F, sunny` }] };
}
throw new Error(`Unknown tool: ${request.params.name}`);
});
const transport = new StdioServerTransport();
await server.connect(transport);
Connecting to Claude Code
Add your server to ~/.claude/config.json:
{
"mcpServers": {
"my-server": {
"command": "node",
"args": ["/path/to/your/server/index.js"]
}
}
}
Security Considerations
MCP servers run with your full system permissions. Before deploying:
- Validate all inputs before executing commands
- Never expose credentials through tool outputs
- Sanitize file paths to prevent traversal attacks
- Rate-limit expensive operations
The MCP Security Scanner Pro audits MCP servers against 22 vulnerability rules — critical before running third-party servers in your Claude session ($29 one-time).
Adding Resources
Resources let Claude read structured data from your server:
import { ListResourcesRequestSchema, ReadResourceRequestSchema } from '@modelcontextprotocol/sdk/types.js';
server.setRequestHandler(ListResourcesRequestSchema, async () => ({
resources: [{
uri: 'config://app',
name: 'Application Config',
mimeType: 'application/json'
}]
}));
server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
if (request.params.uri === 'config://app') {
return { contents: [{ uri: 'config://app', mimeType: 'application/json', text: JSON.stringify(appConfig) }] };
}
throw new Error('Resource not found');
});
Testing Your Server
Use the MCP inspector for local testing:
npx @modelcontextprotocol/inspector node index.js
This opens a browser UI where you can call tools and inspect responses without needing a full Claude Code session.
Production Checklist
Before publishing your MCP server:
- [ ] Input validation on all tool arguments
- [ ] Error handling that returns meaningful messages
- [ ] No hardcoded credentials (use environment variables)
- [ ] Rate limiting for external API calls
- [ ] Security audit with MCP Security Scanner
Built 6 production MCP servers at whoffagents.com — each security-audited before release.
Top comments (0)