mcpresso
TypeScript library to simplify Model Context Protocol server implementation
Installation
# npm npm install mcpresso zod # yarn yarn add mcpresso zod # pnpm pnpm add mcpresso zod
š” Requirements: Node.js 18+ and TypeScript 4.5+. Zod is required for schema validation.
Quick Start
Create a functional MCP server in just a few lines:
import { z } from "zod"; import { createResource, createMCPServer } from "mcpresso"; // 1. Define a schema const UserSchema = z.object({ id: z.string(), name: z.string(), email: z.string().email(), }); // Mock data const users = [ { id: "1", name: "Alice Smith", email: "alice@company.com" }, { id: "2", name: "Bob Johnson", email: "bob@company.com" } ]; // 2. Create a resource const userResource = createResource({ name: "user", schema: UserSchema, uri_template: "users/{id}", handlers: { list: async () => users, get: async ({ id }) => users.find(u => u.id === id), }, }); // 3. Start the server const server = createMCPServer({ name: "my_simple_server", resources: [userResource], }); server.listen(3000, () => { console.log("mcpresso server running on http://localhost:3000"); });
ā What does mcpresso generate automatically?
- MCP Tools: list_user, get_user
- Validation: Zod schemas automatically applied
- TypeScript Types: Inferred from schemas
- Error Handling: Standard JSON-RPC responses
- Documentation: Metadata exposed to AI agents
Define Resources
Resources are the heart of mcpresso. They expose your data to AI agents:
const noteResource = createResource({ name: "note", schema: NoteSchema, uri_template: "notes/{id}", description: "User notes with tags and search", // Relations to other resources relations: { authorId: { type: 'user' }, tagIds: { type: 'tag' } }, // CRUD handlers handlers: { list: async () => await db.notes.findMany(), get: async ({ id }) => await db.notes.findUnique({ where: { id } }), create: async (data) => await db.notes.create({ data }), update: async ({ id, ...data }) => { return await db.notes.update({ where: { id }, data }); }, delete: async ({ id }) => await db.notes.delete({ where: { id } }), // Custom handler for search search: async ({ query, authorId, tags }) => { return await db.notes.findMany({ where: { OR: [ { title: { contains: query } }, { content: { contains: query } } ], authorId: authorId || undefined, tags: tags ? { hasSome: tags } : undefined } }); } }, // Method configuration methodConfig: { create: { omit: ['id', 'createdAt', 'updatedAt'] // Auto-generated fields }, update: { pick: ['title', 'content', 'tags'] // Modifiable fields only }, search: { schema: z.object({ query: z.string().describe("Search in title and content"), authorId: z.string().optional().describe("Filter by author"), tags: z.array(z.string()).optional().describe("Filter by tags") }) } } });
š Relations
Define links between resources. mcpresso automatically generates $ref references in JSON schemas.
āļø methodConfig
Fine-grained control over which fields are exposed for each operation (create, update, search).
Advanced Features
š MCPresso OpenAPI Generator
New dedicated package: Generate complete MCPresso servers from OpenAPI 3.x specifications with full type safety.
# Install the generator globally npm install -g mcpresso-openapi-generator # Generate a server from OpenAPI spec mcpresso-generate generate \ --source ./api-spec.json \ --output ./my-server \ --name my-api-server \ --verbose # Initialize a new MCPresso project mcpresso-generate init \ --name my-project \ --output ./projects \ --verbose # Features: # š Automatic generation from any OpenAPI 3.0 spec # š Full TypeScript support with Zod validation # šÆ MCP compliance out of the box # š¦ Complete project structure with dependencies
š Granular Field Control
Control which fields are editable vs read-only using Zod's .readonly()
method:
const UserSchema = z.object({ id: z.string().readonly(), // Auto-generated by server name: z.string(), // Editable email: z.string().email(), // Editable createdAt: z.date().readonly(), // Set by server updatedAt: z.date().readonly(), // Set by server }); // Behavior: // ⢠GET/LIST: All properties (including readonly) returned // ⢠CREATE: Only editable properties accepted // ⢠UPDATE: Only editable properties accepted // ⢠Readonly fields automatically excluded from operations
š Resource Relations
Define relationships between resources with automatic schema linking:
const noteResource = createResource({ name: "note", schema: NoteSchema, uri_template: "notes/{id}", // Define relations relations: { authorId: { type: 'user' }, // one-to-one tagIds: { type: 'tag' }, // one-to-many }, handlers: { /* CRUD handlers */ } }); // Generated schema includes $ref links: // "authorId": { "$ref": "type://my_server/user" } // This helps AI agents understand data structure
š Custom Search Methods
Add sophisticated search capabilities with dedicated input schemas:
const noteResource = createResource({ name: "note", schema: NoteSchema, uri_template: "notes/{id}", methods: { // Dedicated search method search: { description: "Search notes by content, author, and tags", inputSchema: z.object({ query: z.string().describe("Search text in content"), authorId: z.string().optional().describe("Filter by author"), tags: z.array(z.string()).optional().describe("Filter by tags"), dateRange: z.object({ from: z.date().optional(), to: z.date().optional() }).optional() }), handler: async ({ query, authorId, tags, dateRange }) => { return db.notes.findMany({ where: { content: { contains: query }, authorId, tags: tags ? { hasSome: tags } : undefined, createdAt: dateRange ? { gte: dateRange.from, lte: dateRange.to } : undefined } }); } } } });
š Server Metadata Exposure
Automatically expose comprehensive server information to help clients understand capabilities:
const server = createMCPServer({ name: "my_api_server", resources: [userResource, noteResource], // Enable automatic metadata exposure serverMetadata: { name: "My API Server", version: "1.0.0", description: "Comprehensive API with user and note management", url: "https://api.example.com", contact: { name: "API Support Team", email: "support@example.com", url: "https://example.com/support", }, license: { name: "MIT", url: "https://opensource.org/licenses/MIT", }, capabilities: { authentication: true, rateLimiting: true, retries: true, streaming: true, }, }, }); // Automatically exposed at: metadata://my_api_server/server
Custom Business Methods
Add methods specific to your business domain:
const noteResource = createResource({ name: "note", schema: NoteSchema, methods: { // Business method: generate AI summary generate_summary: { description: "Generate AI summary of user's notes for a period", inputSchema: z.object({ userId: z.string(), period: z.enum(['week', 'month', 'quarter']), topics: z.array(z.string()).optional() }), handler: async ({ userId, period, topics }) => { const notes = await getNotesForPeriod(userId, period, topics); const summary = await generateAISummary(notes); return { summary, noteCount: notes.length }; } }, // Business method: archive by date archive_by_date: { description: "Archive notes older than specified days", inputSchema: z.object({ days: z.number().min(1).describe("Number of days"), dryRun: z.boolean().default(false) }), handler: async ({ days, dryRun }) => { const cutoffDate = new Date(Date.now() - days * 24 * 60 * 60 * 1000); if (dryRun) { const count = await db.notes.count({ where: { createdAt: { lt: cutoffDate } } }); return { message: `Would archive ${count} notes`, count }; } const result = await db.notes.updateMany({ where: { createdAt: { lt: cutoffDate } }, data: { archived: true } }); return { message: `Archived ${result.count} notes`, count: result.count }; } } }, handlers: { /* standard CRUD handlers */ } });
Type Exposure
mcpresso can automatically expose your types to AI models:
const server = createMCPServer({ name: "my_server", resources: [userResource, noteResource], // Enable type exposure exposeTypes: true }); // AI agents can now access: // - type://my_server/user // - type://my_server/note // // With complete JSON schemas including relations
Production Configuration
const server = createMCPServer({ name: "production_server", resources: [userResource, noteResource], // OAuth 2.1 authentication auth: { issuer: process.env.OAUTH_ISSUER!, audience: process.env.OAUTH_AUDIENCE!, algorithms: ['RS256'] }, // Rate limiting to prevent abuse rateLimit: { windowMs: 15 * 60 * 1000, // 15 minutes limit: process.env.NODE_ENV === 'production' ? 50 : 100, message: 'Too many requests, please try again later', standardHeaders: true, legacyHeaders: false }, // Automatic retry with exponential backoff retry: { retries: 3, factor: 2, minTimeout: 1000, maxTimeout: 10000, randomize: true }, // Logs for monitoring onRequest: (req, info) => { logger.info('MCP Request', { method: req.method, resource: info.resource, userId: req.auth?.sub, timestamp: new Date().toISOString(), userAgent: req.headers['user-agent'] }); }, onError: (error, req) => { logger.error('MCP Error', { error: error.message, stack: error.stack, method: req.method, userId: req.auth?.sub }); }, // Strict validation validateRequests: true, sanitizeOutputs: true, // CORS for web apps cors: { origin: process.env.ALLOWED_ORIGINS?.split(',') || [], credentials: true } });
š Production Security Checklist
- ā HTTPS mandatory (valid SSL certificate)
- ā Environment variables for secrets
- ā Rate limiting configured for your load
- ā Monitoring and alerts in place
- ā Structured logs for audit
- ā Critical data backup
- ā Load testing before production
Deployment
mcpresso is compatible with all modern deployment platforms:
š Vercel
Serverless with Edge Functions
vercel deploy
āļø AWS Lambda
Serverless with API Gateway
serverless deploy
š„ Cloudflare Workers
Global edge computing
wrangler deploy
š Detailed guides: Check our deployment documentation for step-by-step instructions for each platform.
Examples & Use Cases
mcpresso includes comprehensive examples for every feature. Find them in the GitHub repository examples folder.
Complete Full-Featured Server
// Full example available at: examples/mcpresso.ts import { z } from "zod"; import { createResource, createMCPServer } from "mcpresso"; // User schema with readonly fields const UserSchema = z.object({ id: z.string().readonly(), name: z.string(), email: z.string().email(), role: z.enum(['admin', 'user', 'guest']), createdAt: z.date().readonly(), updatedAt: z.date().readonly(), }); // Note schema with relations const NoteSchema = z.object({ id: z.string().readonly(), title: z.string(), content: z.string(), authorId: z.string(), tagIds: z.array(z.string()), featured: z.boolean().default(false), createdAt: z.date().readonly(), }); // User resource with search const userResource = createResource({ name: "user", schema: UserSchema, uri_template: "users/{id}", methods: { search: { description: "Search users by name, email, or role", inputSchema: z.object({ query: z.string().optional(), role: z.enum(['admin', 'user', 'guest']).optional(), limit: z.number().max(100).default(10) }), handler: async ({ query, role, limit }) => { return await db.users.findMany({ where: { OR: query ? [ { name: { contains: query } }, { email: { contains: query } } ] : undefined, role }, take: limit }); } } }, handlers: { list: async () => await db.users.findMany(), get: async ({ id }) => await db.users.findUnique({ where: { id } }), create: async (data) => await db.users.create({ data }), update: async ({ id, ...data }) => await db.users.update({ where: { id }, data }), delete: async ({ id }) => await db.users.delete({ where: { id } }) } }); // Note resource with relations and custom methods const noteResource = createResource({ name: "note", schema: NoteSchema, uri_template: "notes/{id}", // Define relationships relations: { authorId: { type: 'user' }, tagIds: { type: 'tag' } }, methods: { // Advanced search search: { description: "Search notes with full-text and filters", inputSchema: z.object({ query: z.string().optional(), authorId: z.string().optional(), featured: z.boolean().optional(), tags: z.array(z.string()).optional() }), handler: async (params) => { /* implementation */ } }, // Business logic generate_summary: { description: "AI-powered note summarization", inputSchema: z.object({ userId: z.string(), period: z.enum(['week', 'month', 'quarter']) }), handler: async ({ userId, period }) => { const notes = await getNotesForPeriod(userId, period); return await generateAISummary(notes); } } }, handlers: { /* CRUD implementations */ } }); // Production server with all features const server = createMCPServer({ name: "enterprise_mcp_server", resources: [userResource, noteResource], // Security auth: { issuer: process.env.OAUTH_ISSUER!, audience: process.env.OAUTH_AUDIENCE! }, // Protection rateLimit: { windowMs: 15 * 60 * 1000, limit: 100 }, // Resilience retry: { retries: 5, factor: 2, minTimeout: 1000, maxTimeout: 60000 }, // Metadata serverMetadata: { name: "Enterprise MCP Server", version: "1.0.0", description: "Full-featured MCP server with users and notes", capabilities: { authentication: true, rateLimiting: true, retries: true, streaming: true } }, // Type exposure exposeTypes: true }); server.listen(3000);
š Available Examples in GitHub
- mcpresso.ts - Complete server with all features
- retry.ts - Automatic retry with failing handlers
- rate-limit.ts - Rate limiting configuration
- server-metadata.ts - Metadata exposure example
- openapi-integration.ts - OpenAPI generator usage
- custom-search.ts - Advanced search methods
- relations.ts - Resource relationships
OpenAPI Generator Workflow
# 1. Install the generator npm install -g mcpresso-openapi-generator # 2. Generate from existing API spec mcpresso-generate generate \ --source https://petstore.swagger.io/v2/swagger.json \ --output ./petstore-mcp \ --name petstore-server \ --verbose # 3. Generated structure: petstore-mcp/ āāā src/ ā āāā resources/ # Generated resources with schemas ā āāā handlers/ # CRUD implementations ā āāā server.ts # Complete MCP server ā āāā types.ts # TypeScript types āāā package.json # Dependencies included āāā tsconfig.json # TypeScript config āāā README.md # Usage instructions # 4. Run immediately cd petstore-mcp npm install npm start # 5. Your OpenAPI spec is now a compliant MCP server!
Real-World Use Cases
š¢ Enterprise CRM
- User management with roles
- Customer data with relations
- Advanced search capabilities
- OAuth 2.1 security
- Rate limiting protection
š Knowledge Base
- Article management
- Full-text search
- Category relationships
- AI-powered summaries
- Metadata exposure
š E-commerce API
- Product catalogs
- Inventory management
- Order processing
- Customer analytics
- OpenAPI integration
Ready to revolutionize your AI operations?
Get early access to build and deploy production-ready AI agents with enterprise-grade security and governance