mcp
SKILL.md
MCP
Build MCP servers that give Claude access to external tools and data.
What is MCP?
Model Context Protocol lets you create servers that Claude can call:
- Query databases
- Call APIs
- Access file systems
- Run custom tools
When to Build an MCP Server
- You want Claude to access live data (not just files)
- You're repeating the same API calls manually
- You want Claude to take actions (create records, trigger workflows)
Project Setup
mkdir my-mcp-server && cd my-mcp-server
pnpm init
pnpm add @modelcontextprotocol/sdk zod
pnpm add -D typescript @types/node tsx
// package.json
{
"type": "module",
"scripts": {
"dev": "tsx watch src/index.ts",
"build": "tsc",
"start": "node dist/index.js"
}
}
// tsconfig.json
{
"compilerOptions": {
"target": "ES2022",
"module": "NodeNext",
"moduleResolution": "NodeNext",
"outDir": "dist",
"strict": true,
"esModuleInterop": true
},
"include": ["src"]
}
Basic Server Template
// src/index.ts
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-server',
version: '1.0.0',
})
// Define a tool
server.tool(
'hello',
'Say hello to someone',
{ name: z.string().describe('Name to greet') },
async ({ name }) => ({
content: [{ type: 'text', text: `Hello, ${name}!` }],
})
)
// Start server
const transport = new StdioServerTransport()
await server.connect(transport)
Common Patterns
Database Access (Postgres)
import pg from 'pg'
const pool = new pg.Pool({
connectionString: process.env.DATABASE_URL,
})
server.tool(
'query',
'Run a read-only SQL query',
{ sql: z.string().describe('SELECT query to run') },
async ({ sql }) => {
if (!sql.trim().toLowerCase().startsWith('select')) {
return { content: [{ type: 'text', text: 'Only SELECT queries allowed' }] }
}
const result = await pool.query(sql)
return { content: [{ type: 'text', text: JSON.stringify(result.rows, null, 2) }] }
}
)
API Wrapper
server.tool(
'get_weather',
'Get current weather for a city',
{ city: z.string() },
async ({ city }) => {
const res = await fetch(`https://api.weather.com/current?city=${city}`)
const data = await res.json()
return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] }
}
)
File System Access
import { readdir, readFile } from 'fs/promises'
server.tool(
'list_projects',
'List projects in studio-manager',
{},
async () => {
const dirs = await readdir('/Users/brew/studio-manager', { withFileTypes: true })
const projects = dirs.filter(d => d.isDirectory()).map(d => d.name)
return { content: [{ type: 'text', text: projects.join('\n') }] }
}
)
Claude Desktop Config
Add to ~/Library/Application Support/Claude/claude_desktop_config.json:
{
"mcpServers": {
"my-server": {
"command": "node",
"args": ["/path/to/my-mcp-server/dist/index.js"],
"env": {
"DATABASE_URL": "postgres://..."
}
}
}
}
Restart Claude Desktop after changes.
Testing
# Run server directly to test
echo '{"jsonrpc":"2.0","id":1,"method":"tools/list"}' | pnpm start
Security Notes
- Validate all inputs with Zod
- Limit database access to SELECT only (unless intentional)
- Don't expose secrets in tool responses
- Consider rate limiting for external APIs
Reference
- MCP Docs: https://modelcontextprotocol.io/docs
- MCP SDK: https://github.com/modelcontextprotocol/sdk
- Anthropic's mcp-builder: https://github.com/anthropics/skills/tree/main/skills/mcp-builder
Weekly Installs
8
Repository
cerico/macfairFirst Seen
Feb 24, 2026
Security Audits
Installed on
trae8
claude-code8
github-copilot8
codex8
windsurf8
kiro-cli8