Best MCP Server Boilerplates 2026
·StarterPick Team
mcpai-agentsclaudetypescriptboilerplate2026
TL;DR
MCP (Model Context Protocol) is the emerging standard for AI tool integrations in 2026 — but boilerplate tooling is still young. The official @modelcontextprotocol/create-server CLI is the fastest starting point. For TypeScript MCP servers that integrate with databases and external APIs, the FastMCP framework (Python) or the official TypeScript SDK with custom structure is the production pattern. Claude Code, Cursor, and Windsurf all support MCP natively.
Key Takeaways
- MCP standard: Anthropic's open protocol for giving AI assistants tools, resources, and prompts
- Official CLI:
npx @modelcontextprotocol/create-server— zero-config TypeScript starter - FastMCP: Python framework with decorator-based tool/resource definitions
- Transport options: stdio (local), SSE (remote server), HTTP Streamable
- AI host support: Claude Desktop, Claude Code, Cursor, Windsurf, Continue.dev
- 2026 status: Protocol stabilized; tooling still maturing
The MCP Architecture
AI Host (Claude, Cursor)
↕ MCP Protocol (stdio or SSE)
MCP Server (your code)
↕ Any API/DB/Service
External Systems (GitHub, databases, APIs)
MCP Server provides three primitives:
→ Tools: Functions the AI can call (read file, run query, API call)
→ Resources: Data the AI can read (file contents, DB records, docs)
→ Prompts: Reusable prompt templates with parameters
Official TypeScript Starter
npx @modelcontextprotocol/create-server my-mcp-server
cd my-mcp-server && npm install
Generated structure:
my-mcp-server/
src/
index.ts ← Main server entry
package.json
tsconfig.json
README.md
// src/index.ts — official starter pattern:
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import {
CallToolRequestSchema,
ListToolsRequestSchema,
ListResourcesRequestSchema,
ReadResourceRequestSchema,
} from '@modelcontextprotocol/sdk/types.js';
const server = new Server(
{
name: 'my-mcp-server',
version: '1.0.0',
},
{
capabilities: {
tools: {},
resources: {},
},
}
);
// Register available 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' },
units: {
type: 'string',
enum: ['celsius', 'fahrenheit'],
default: 'celsius'
},
},
required: ['city'],
},
},
],
}));
// Handle tool calls:
server.setRequestHandler(CallToolRequestSchema, async (request) => {
const { name, arguments: args } = request.params;
if (name === 'get_weather') {
const { city, units = 'celsius' } = args as { city: string; units?: string };
const response = await fetch(
`https://api.openweathermap.org/data/2.5/weather?q=${city}&units=${units === 'celsius' ? 'metric' : 'imperial'}&appid=${process.env.OPENWEATHER_API_KEY}`
);
const data = await response.json();
return {
content: [
{
type: 'text',
text: `Weather in ${city}: ${data.main.temp}°${units === 'celsius' ? 'C' : 'F'}, ${data.weather[0].description}`,
},
],
};
}
throw new Error(`Unknown tool: ${name}`);
});
// Start with stdio transport (for Claude Desktop, Claude Code):
const transport = new StdioServerTransport();
await server.connect(transport);
Production Pattern: TypeScript MCP + Database
// Full MCP server with Postgres tools (production pattern):
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import { drizzle } from 'drizzle-orm/postgres-js';
import postgres from 'postgres';
import * as schema from './schema.js';
const client = postgres(process.env.DATABASE_URL!);
const db = drizzle(client, { schema });
const server = new Server(
{ name: 'db-mcp-server', version: '1.0.0' },
{ capabilities: { tools: {}, resources: {} } }
);
server.setRequestHandler(ListToolsRequestSchema, async () => ({
tools: [
{
name: 'query_users',
description: 'Query users from the database',
inputSchema: {
type: 'object',
properties: {
limit: { type: 'number', default: 10 },
plan: { type: 'string', enum: ['free', 'pro', 'enterprise'] },
search: { type: 'string', description: 'Search by email or name' },
},
},
},
{
name: 'get_metrics',
description: 'Get aggregated business metrics',
inputSchema: {
type: 'object',
properties: {
period: { type: 'string', enum: ['today', '7d', '30d', '90d'] },
},
required: ['period'],
},
},
],
}));
server.setRequestHandler(CallToolRequestSchema, async (request) => {
const { name, arguments: args } = request.params;
if (name === 'query_users') {
const { limit = 10, plan, search } = args as any;
let query = db.select().from(schema.users).limit(limit);
if (plan) query = query.where(eq(schema.users.plan, plan));
const users = await query;
return {
content: [{
type: 'text',
text: JSON.stringify(users, null, 2),
}],
};
}
if (name === 'get_metrics') {
const { period } = args as any;
const days = { today: 1, '7d': 7, '30d': 30, '90d': 90 }[period];
const metrics = await db.execute(sql`
SELECT
COUNT(*) as total_users,
COUNT(CASE WHEN plan = 'pro' THEN 1 END) as pro_users,
SUM(mrr) as total_mrr
FROM users
WHERE created_at > NOW() - INTERVAL '${days} days'
`);
return {
content: [{
type: 'text',
text: JSON.stringify(metrics.rows[0], null, 2),
}],
};
}
throw new Error(`Unknown tool: ${name}`);
});
await server.connect(new StdioServerTransport());
FastMCP: Python Decorator Pattern
# pip install fastmcp
# The cleanest MCP server DX:
from fastmcp import FastMCP
import httpx
mcp = FastMCP("weather-server")
@mcp.tool()
async def get_weather(city: str, units: str = "celsius") -> str:
"""Get current weather for a city."""
async with httpx.AsyncClient() as client:
response = await client.get(
f"https://api.openweathermap.org/data/2.5/weather",
params={"q": city, "units": "metric" if units == "celsius" else "imperial",
"appid": os.environ["OPENWEATHER_API_KEY"]}
)
data = response.json()
return f"Weather in {city}: {data['main']['temp']}°, {data['weather'][0]['description']}"
@mcp.resource("config://app-settings")
def get_config() -> str:
"""Get application configuration."""
return json.dumps({"environment": "production", "version": "1.2.3"})
@mcp.prompt()
def analyze_data(dataset_name: str) -> str:
"""Generate a prompt for data analysis."""
return f"Analyze the {dataset_name} dataset and identify key trends, outliers, and actionable insights."
if __name__ == "__main__":
mcp.run() # stdio transport by default
Claude Desktop Configuration
// ~/Library/Application Support/Claude/claude_desktop_config.json
{
"mcpServers": {
"my-weather-server": {
"command": "node",
"args": ["/path/to/my-mcp-server/dist/index.js"],
"env": {
"OPENWEATHER_API_KEY": "your-api-key"
}
},
"my-db-server": {
"command": "node",
"args": ["/path/to/db-mcp-server/dist/index.js"],
"env": {
"DATABASE_URL": "postgresql://..."
}
}
}
}
// Claude Code (.claude/mcp.json in project):
{
"mcpServers": {
"project-db": {
"command": "node",
"args": ["./mcp-server/dist/index.js"],
"env": {
"DATABASE_URL": "${DATABASE_URL}"
}
}
}
}
Remote MCP Server (SSE Transport)
// For remote deployment — SSE transport:
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { SSEServerTransport } from '@modelcontextprotocol/sdk/server/sse.js';
import express from 'express';
const app = express();
const server = new Server(
{ name: 'remote-mcp', version: '1.0.0' },
{ capabilities: { tools: {} } }
);
// Register tools (same as stdio version)...
const transport = new SSEServerTransport('/messages', res);
app.get('/sse', async (req, res) => {
await server.connect(transport);
});
app.post('/messages', async (req, res) => {
await transport.handlePostMessage(req, res);
});
app.listen(3001);
Boilerplate Comparison
| Official TS Starter | FastMCP (Python) | Custom Express+SSE | |
|---|---|---|---|
| Language | TypeScript | Python | TypeScript |
| Transport | stdio | stdio | SSE (remote) |
| DX | Verbose | ✅ Decorator-based | Medium |
| Type safety | ✅ | Partial | Manual |
| Remote hosting | Needs adaptation | ✅ Built-in | ✅ |
| Production ready | ✅ | ✅ | ✅ |
Quick Start Recommendations
Building a local AI tool (Claude Desktop/Code):
→ TypeScript: npx @modelcontextprotocol/create-server
→ Python: pip install fastmcp && fastmcp new my-server
Building a hosted MCP service:
→ TypeScript + Express + SSE transport
→ Deploy to Railway, Fly.io, or any Node.js host
Building an MCP server for a SaaS product:
→ OAuth authentication layer on top of SSE transport
→ Rate limiting per user
→ Tool access based on subscription plan
Find more AI infrastructure boilerplates at StarterPick.