Overview
TypeScript framework for rapidly building MCP servers with declarative API.
Setup
Run with npx:
npm install @modelcontextprotocol/sdkConfiguration
Define tools with decorators, run with mcp.run()Documentation
FastMCP
Overview
FastMCP is a TypeScript framework for rapidly building MCP (Model Context Protocol) servers. It provides a high-level, intuitive API that abstracts away the complexity of the MCP protocol while maintaining full compliance. FastMCP is designed for developers who want to create MCP servers quickly without dealing with low-level protocol details.
FastMCP draws inspiration from FastAPI, offering a similar developer experience with type-safe tool definitions, automatic schema generation, and built-in validation. It's particularly well-suited for TypeScript/JavaScript developers who want to extend AI models with custom tools and data sources.
Features
- Declarative API: Define tools and resources with simple decorators
- Type Safety: Full TypeScript support with automatic schema generation
- Built-in Validation: Request validation using Zod schemas
- Automatic Documentation: Auto-generated API documentation
- Streaming Support: Native support for streaming tool outputs
- Error Handling: Comprehensive error handling and recovery
- Testing Utilities: Built-in tools for testing MCP servers
- Hot Reload: Development mode with automatic restart
Installation
npm install @modelcontextprotocol/sdk
Quick Start
Hello World MCP Server
import { FastMCP } from "@modelcontextprotocol/sdk/fastmcp";
const mcp = new FastMCP({
name: "hello-server",
version: "1.0.0"
});
// Define a simple tool
mcp.tool("hello", {
description: "Say hello to someone",
parameters: {
name: { type: "string", description: "Name to greet" }
}
}, async ({ name }) => {
return `Hello, ${name}!`;
});
// Start the server
mcp.run();
Run the Server
node hello-server.js
Connect from Claude
{
"mcpServers": {
"hello": {
"command": "node",
"args": ["/path/to/hello-server.js"]
}
}
}
Core Concepts
Tools
Tools are the primary way MCP servers expose functionality:
mcp.tool("calculate", {
description: "Perform mathematical calculations",
parameters: {
expression: { type: "string", description: "Math expression" }
}
}, async ({ expression }) => {
// Safe evaluation
const result = eval(expression);
return `Result: ${result}`;
});
Resources
Resources provide read-only data access:
mcp.resource("config://settings", {
description: "Application configuration",
mimeType: "application/json"
}, async () => {
return JSON.stringify({ theme: "dark", language: "en" });
});
Prompts
Prompts are reusable prompt templates:
mcp.prompt("code-review", {
description: "Code review template",
arguments: {
code: { description: "Code to review", required: true },
language: { description: "Programming language" }
}
}, async ({ code, language }) => {
return {
messages: [{
role: "user",
content: {
type: "text",
text: `Please review this ${language || "code"}:\n\n${code}`
}
}]
};
});
Advanced Features
Input Validation with Zod
import { z } from "zod";
mcp.tool("search", {
description: "Search for items",
parameters: z.object({
query: z.string().min(1).max(100),
limit: z.number().int().positive().max(100).default(10),
filters: z.object({
category: z.string().optional(),
dateFrom: z.string().datetime().optional()
}).optional()
})
}, async ({ query, limit, filters }) => {
// Type-safe parameters
const results = await db.search(query, { limit, filters });
return results;
});
Streaming Outputs
mcp.tool("streaming-task", {
description: "A task that streams progress"
}, async function* () {
yield { progress: 0, message: "Starting..." };
await sleep(1000);
yield { progress: 50, message: "Processing..." };
await sleep(1000);
yield { progress: 100, message: "Complete!" };
});
Multiple Tools with Class
class CalculatorServer extends FastMCP {
constructor() {
super({ name: "calculator", version: "1.0.0" });
this.setupTools();
}
private setupTools() {
this.tool("add", { parameters: { a: "number", b: "number" } }, ({ a, b }) => a + b);
this.tool("subtract", { parameters: { a: "number", b: "number" } }, ({ a, b }) => a - b);
this.tool("multiply", { parameters: { a: "number", b: "number" } }, ({ a, b }) => a * b);
this.tool("divide", { parameters: { a: "number", b: "number" } }, ({ a, b }) => {
if (b === 0) throw new Error("Division by zero");
return a / b;
});
}
}
Resources with Templates
mcp.resource("user://{userId}/profile", {
description: "User profile information"
}, async ({ userId }) => {
const user = await db.getUser(userId);
return JSON.stringify(user, null, 2);
});
// Access: user://123/profile
Examples
GitHub Integration
import { FastMCP } from "@modelcontextprotocol/sdk/fastmcp";
import { Octokit } from "@octokit/rest";
const mcp = new FastMCP({ name: "github-tools", version: "1.0.0" });
const octokit = new Octokit({ auth: process.env.GITHUB_TOKEN });
mcp.tool("list-repos", {
description: "List repositories for the authenticated user",
parameters: {
visibility: { type: "string", enum: ["all", "public", "private"] }
}
}, async ({ visibility }) => {
const { data } = await octokit.repos.listForAuthenticatedUser({ visibility });
return data.map(r => ({ name: r.name, url: r.html_url }));
});
mcp.tool("create-issue", {
description: "Create a new issue",
parameters: {
owner: { type: "string" },
repo: { type: "string" },
title: { type: "string" },
body: { type: "string" }
}
}, async ({ owner, repo, title, body }) => {
const { data } = await octokit.issues.create({ owner, repo, title, body });
return { html_url: data.html_url, number: data.number };
});
mcp.run();
Database Server
import { FastMCP } from "@modelcontextprotocol/sdk/fastmcp";
import { Pool } from "pg";
const mcp = new FastMCP({ name: "postgres-server", version: "1.0.0" });
const pool = new Pool({ connectionString: process.env.DATABASE_URL });
mcp.tool("query", {
description: "Execute a SQL query",
parameters: {
sql: { type: "string" },
params: { type: "array", items: { type: "string" } }
}
}, async ({ sql, params }) => {
const result = await pool.query(sql, params);
return result.rows;
});
mcp.resource("schema://tables", {
description: "List all tables in the database"
}, async () => {
const { rows } = await pool.query(`
SELECT table_name FROM information_schema.tables
WHERE table_schema = 'public'
`);
return rows.map(r => r.table_name);
});
mcp.run();
Pros
- ✅ Extremely fast development with declarative API
- ✅ Full TypeScript type safety
- ✅ Automatic JSON Schema generation
- ✅ Built-in validation with Zod
- ✅ Streaming support out of the box
- ✅ Excellent developer experience
- ✅ Well-documented with many examples
- ✅ Active community and maintenance
Cons
- ❌ TypeScript-only (no Python version)
- ❌ Requires Node.js runtime
- ❌ Less control than raw MCP SDK
- ❌ Newer project with smaller ecosystem
- ❌ Some advanced features need raw SDK
When to Use
- Rapid MCP server development — Fastest way to build servers
- TypeScript/JavaScript projects — Native language support
- Prototyping MCP integrations — Quick iteration and testing
- Team with TS expertise — Leverage existing skills
- Production MCP servers — Battle-tested framework
