MCP Framework
Un marco de trabajo en TypeScript para construir servidores del Protocolo de Contexto de Modelo (MCP).
Documentación
MCP Framework
MCP-Framework es un framework para construir servidores del Protocolo de Contexto de Modelos (MCP) de manera elegante en TypeScript.
MCP-Framework te brinda una arquitectura lista para usar, con descubrimiento automático basado en directorios para herramientas, recursos y prompts. Utiliza nuestras potentes abstracciones de MCP para definir herramientas, recursos o prompts de manera elegante. Nuestra CLI facilita comenzar con tu propio servidor MCP.
Características
- 🛠️ Descubrimiento y carga automática de herramientas, recursos y prompts
- Soporte de múltiples transportes (stdio, SSE, HTTP Stream)
- Desarrollo centrado en TypeScript con seguridad de tipos completa
- Construido sobre el SDK oficial de MCP
- Clases base fáciles de usar para herramientas, prompts y recursos
- Autenticación lista para usar para endpoints SSE (OAuth 2.1, JWT, API Key)
Proyectos construidos con MCP Framework
Los siguientes proyectos y servicios están construidos con MCP Framework:
Un servicio de propinas criptográficas que permite a los asistentes de IA ayudar a los usuarios a enviar propinas en criptomonedas a creadores de contenido directamente desde su interfaz de chat. El servicio MCP permite:
- Verificar los tipos de billetera de los usuarios
- Preparar propinas criptográficas para que los usuarios/agentes las completen Las instrucciones de configuración para varios clientes (Cursor, Sage, Claude Desktop) están disponibles en su documentación del servidor MCP.
Apoya nuestro trabajo
Lee la documentación completa aquí
Crear un repositorio con mcp-framework
Usando la CLI (Recomendado)
# Install the framework globally
npm install -g mcp-framework
# Create a new MCP server project
mcp create my-mcp-server
# Navigate to your project
cd my-mcp-server
# Your server is ready to use!
Uso de la CLI
El framework proporciona una potente CLI para gestionar tus proyectos de servidor MCP:
Creación de proyectos
# Create a new project
mcp create <your project name here>
# Create a new project with the new EXPERIMENTAL HTTP transport
Heads up: This will set cors allowed origin to "*", modify it in the index if you wish
mcp create <your project name here> --http --port 1337 --cors
Opciones:
--http: Usar transporte HTTP en lugar del stdio predeterminado
--port : Especificar el puerto HTTP (predeterminado: 8080)
--cors: Habilitar CORS con acceso comodín (*)
Agregar una herramienta
# Add a new tool
mcp add tool price-fetcher
Compilación y validación
El framework proporciona una validación integral para garantizar que tus herramientas estén correctamente documentadas y sean funcionales:
# Build with automatic validation (recommended)
npm run build
# Build with custom validation settings
MCP_SKIP_TOOL_VALIDATION=false npm run build # Force validation (default)
MCP_SKIP_TOOL_VALIDATION=true npm run build # Skip validation (not recommended)
Validación de herramientas
# Validate all tools have proper descriptions (for Zod schemas)
mcp validate
Este comando verifica que todas las herramientas que usan esquemas Zod tengan descripciones para cada campo. La validación se ejecuta automáticamente durante la compilación, pero también puedes ejecutarla de forma independiente:
- ✅ Durante la compilación:
npm run buildvalida automáticamente las herramientas - ✅ Independiente:
mcp validatepara validación manual - ✅ Desarrollo: Usa el helper
defineSchema()para retroalimentación inmediata - ✅ Tiempo de ejecución: El servidor valida las herramientas al iniciar
Ejemplo de error de validación:
❌ Tool validation failed:
❌ PriceFetcher.js: Missing descriptions for fields in price_fetcher: symbol, currency.
All fields must have descriptions when using Zod object schemas.
Use .describe() on each field, e.g., z.string().describe("Field description")
Integración de validación en CI/CD:
{
"scripts": {
"build": "tsc && mcp-build",
"test": "jest && mcp validate",
"prepack": "npm run build && mcp validate"
}
}
Agregar un prompt
# Add a new prompt
mcp add prompt price-analysis
Agregar un recurso
# Add a new resource
mcp add resource market-data
Flujo de trabajo de desarrollo
-
Crea tu proyecto:
mcp create my-mcp-server cd my-mcp-server -
Agrega herramientas:
mcp add tool data-fetcher mcp add tool data-processor mcp add tool report-generator -
Define tus esquemas de herramientas con validación automática:
// tools/DataFetcher.ts import { MCPTool, MCPInput as AddToolInput } from "mcp-framework";
import { z } from "zod";
const AddToolSchema = z.object({ a: z.number().describe("First number to add"), b: z.number().describe("Second number to add"), });
class AddTool extends MCPTool { name = "add"; description = "Add tool description"; schema = AddToolSchema;
async execute(input: AddToolInput) {
const result = input.a + input.b;
return Result: ${result};
}
}
export default AddTool;
4. **Compila con validación automática:**
```bash
npm run build # Automatically validates schemas and compiles
-
Opcional: Ejecuta validación independiente:
mcp validate # Check all tools independently -
Prueba tu servidor:
node dist/index.js # Server validates tools on startup -
Agrega al cliente MCP (consulta el ejemplo de Claude Desktop a continuación)
Consejos profesionales:
- Usa
defineSchema()durante el desarrollo para retroalimentación inmediata - El proceso de compilación detecta automáticamente descripciones faltantes
- El inicio del servidor valida todas las herramientas antes de aceptar conexiones
- Usa el autocompletado de TypeScript con
MCPInput<this>para una mejor experiencia de desarrollo
Uso con Claude Desktop
Desarrollo local
Agrega esta configuración al archivo de configuración de Claude Desktop:
MacOS: ~/Library/Application Support/Claude/claude_desktop_config.json
Windows: %APPDATA%/Claude/claude_desktop_config.json
{
"mcpServers": {
"${projectName}": {
"command": "node",
"args":["/absolute/path/to/${projectName}/dist/index.js"]
}
}
}
Después de publicar
Agrega esta configuración al archivo de configuración de Claude Desktop:
MacOS: ~/Library/Application Support/Claude/claude_desktop_config.json
Windows: %APPDATA%/Claude/claude_desktop_config.json
{
"mcpServers": {
"${projectName}": {
"command": "npx",
"args": ["${projectName}"]
}
}
}
Compilación y pruebas
- Realiza cambios en tus herramientas
- Ejecuta
npm run buildpara compilar - El servidor cargará automáticamente tus herramientas al iniciar
Variables de entorno
El framework admite las siguientes variables de entorno para configuración:
| Variable | Descripción | Predeterminado |
|---|---|---|
| MCP_ENABLE_FILE_LOGGING | Habilitar registro en archivos (true/false) | false |
| MCP_LOG_DIRECTORY | Directorio donde se almacenarán los archivos de registro | logs |
| MCP_DEBUG_CONSOLE | Mostrar mensajes de nivel de depuración en consola (true/false) | false |
Ejemplo de uso:
# Enable file logging
MCP_ENABLE_FILE_LOGGING=true node dist/index.js
# Specify a custom log directory
MCP_ENABLE_FILE_LOGGING=true MCP_LOG_DIRECTORY=my-logs node dist/index.js
# Enable debug messages in console
MCP_DEBUG_CONSOLE=true node dist/index.js
Inicio rápido
Definición de herramientas
MCP Framework utiliza esquemas Zod para definir entradas de herramientas, proporcionando seguridad de tipos, validación y documentación automática:
import { MCPTool, MCPInput } from "mcp-framework";
import { z } from "zod";
const AddToolSchema = z.object({
a: z.number().describe("First number to add"),
b: z.number().describe("Second number to add"),
});
class AddTool extends MCPTool {
name = "add";
description = "Add tool description";
schema = AddToolSchema;
async execute(input: MCPInput<this>) {
const result = input.a + input.b;
return `Result: ${result}`;
}
}
export default AddTool;
Beneficios clave:
- ✅ Fuente única de verdad - Define tipos y validación en un solo lugar
- ✅ Inferencia de tipos automática - Los tipos de TypeScript se infieren de tu esquema
- ✅ Validación enriquecida - Aprovecha las potentes funciones de validación de Zod
- ✅ Descripciones requeridas - El framework exige documentación
- ✅ Mejor soporte de IDE - Autocompletado completo y verificación de tipos
- ✅ Código más limpio - Sin definiciones de tipos duplicadas
Funciones avanzadas de esquemas Zod
El framework admite todas las funciones de Zod:
import { MCPTool, MCPInput } from "mcp-framework";
import { z } from "zod";
const AdvancedSchema = z.object({
// String constraints and formats
email: z.string().email().describe("User email address"),
name: z.string().min(2).max(50).describe("User name"),
website: z.string().url().optional().describe("Optional website URL"),
// Number constraints
age: z.number().int().positive().max(120).describe("User age"),
rating: z.number().min(1).max(5).describe("Rating from 1 to 5"),
// Arrays and objects
tags: z.array(z.string()).describe("List of tags"),
metadata: z.object({
priority: z.enum(['low', 'medium', 'high']).describe("Task priority"),
dueDate: z.string().optional().describe("Due date in ISO format")
}).describe("Additional metadata"),
// Default values
status: z.string().default('pending').describe("Current status"),
// Unions and enums
category: z.union([
z.literal('personal'),
z.literal('work'),
z.literal('other')
]).describe("Category type")
});
class AdvancedTool extends MCPTool {
name = "advanced_tool";
description = "Tool demonstrating advanced Zod features";
schema = AdvancedSchema;
async execute(input: MCPInput<this>) {
// TypeScript automatically knows all the types!
const { email, name, website, age, rating, tags, metadata, status, category } = input;
console.log(input.name.toUpperCase()); // ✅ TypeScript knows this is valid
console.log(input.age.toFixed(2)); // ✅ Number methods available
console.log(input.tags.length); // ✅ Array methods available
console.log(input.website?.includes("https")); // ✅ Optional handling
return `Processed user: ${name}`;
}
}
Inferencia de tipos automática
El tipo MCPInput<this> infiere automáticamente el tipo de entrada correcto de tu esquema, eliminando la necesidad de definiciones de tipos manuales:
class MyTool extends MCPTool {
schema = z.object({
name: z.string().describe("User name"),
age: z.number().optional().describe("User age"),
tags: z.array(z.string()).describe("User tags")
});
async execute(input: MCPInput<this>) {
// TypeScript automatically knows:
// input.name is string
// input.age is number | undefined
// input.tags is string[]
console.log(input.name.toUpperCase()); // ✅ TypeScript knows this is valid
console.log(input.age?.toFixed(2)); // ✅ Handles optional correctly
console.log(input.tags.length); // ✅ Array methods available
}
}
¡No más interfaces duplicadas ni parámetros de tipo genéricos necesarios!
Validación de esquemas y descripciones
Todos los campos del esquema deben tener descripciones. Esto garantiza que tus herramientas estén bien documentadas y proporciona una mejor experiencia de usuario en los clientes MCP.
El framework valida las descripciones en múltiples niveles:
1. Validación en tiempo de compilación (Recomendado)
npm run build # Automatically validates during compilation
2. Validación en tiempo de desarrollo
Usa el helper defineSchema para retroalimentación inmediata:
import { defineSchema } from "mcp-framework";
// This will throw an error immediately if descriptions are missing
const MySchema = defineSchema({
name: z.string(), // ❌ Error: Missing description
age: z.number().describe("User age") // ✅ Good
});
3. Validación independiente
mcp validate # Check all tools for proper descriptions
4. Validación en tiempo de ejecución
El servidor valida automáticamente las herramientas al iniciar.
Para omitir la validación (no recomendado):
# Skip during build
MCP_SKIP_TOOL_VALIDATION=true npm run build
# Skip during development
NODE_ENV=production npm run dev
Configuración del servidor
import { MCPServer } from "mcp-framework";
const server = new MCPServer();
// OR (mutually exclusive!) with SSE transport
const server = new MCPServer({
transport: {
type: "sse",
options: {
port: 8080 // Optional (default: 8080)
}
}
});
// Start the server
await server.start();
Configuración de transporte
Transporte stdio (Predeterminado)
El transporte stdio se usa por defecto si no se proporciona configuración de transporte:
const server = new MCPServer();
// or explicitly:
const server = new MCPServer({
transport: { type: "stdio" }
});
Transporte SSE
Para usar el transporte de Eventos Enviados por el Servidor (SSE):
const server = new MCPServer({
transport: {
type: "sse",
options: {
port: 8080, // Optional (default: 8080)
endpoint: "/sse", // Optional (default: "/sse")
messageEndpoint: "/messages", // Optional (default: "/messages")
cors: {
allowOrigin: "*", // Optional (default: "*")
allowMethods: "GET, POST, OPTIONS", // Optional (default: "GET, POST, OPTIONS")
allowHeaders: "Content-Type, Authorization, x-api-key", // Optional (default: "Content-Type, Authorization, x-api-key")
exposeHeaders: "Content-Type, Authorization, x-api-key", // Optional (default: "Content-Type, Authorization, x-api-key")
maxAge: "86400" // Optional (default: "86400")
}
}
}
});
Transporte HTTP Stream
Para usar el transporte HTTP Stream:
const server = new MCPServer({
transport: {
type: "http-stream",
options: {
port: 8080, // Optional (default: 8080)
endpoint: "/mcp", // Optional (default: "/mcp")
responseMode: "batch", // Optional (default: "batch"), can be "batch" or "stream"
batchTimeout: 30000, // Optional (default: 30000ms) - timeout for batch responses
maxMessageSize: "4mb", // Optional (default: "4mb") - maximum message size
// Session configuration
session: {
enabled: true, // Optional (default: true)
headerName: "Mcp-Session-Id", // Optional (default: "Mcp-Session-Id")
allowClientTermination: true, // Optional (default: true)
},
// Stream resumability (for missed messages)
resumability: {
enabled: false, // Optional (default: false)
historyDuration: 300000, // Optional (default: 300000ms = 5min) - how long to keep message history
},
// CORS configuration
cors: {
allowOrigin: "*" // Other CORS options use defaults
}
}
}
});
Modos de respuesta
El transporte HTTP Stream admite dos modos de respuesta:
-
Modo por lotes (Predeterminado): Las respuestas se recopilan y se envían como una única respuesta JSON-RPC. Esto es adecuado para patrones típicos de solicitud-respuesta y es más eficiente para la mayoría de los casos de uso.
-
Modo de transmisión: Todas las respuestas se envían a través de una conexión SSE persistente abierta para cada solicitud. Esto es ideal para operaciones de larga duración o cuando el servidor necesita enviar múltiples mensajes en respuesta a una sola solicitud.
Puedes configurar el modo de respuesta según tus necesidades específicas:
// For batch mode (default):
const server = new MCPServer({
transport: {
type: "http-stream",
options: {
responseMode: "batch"
}
}
});
// For stream mode:
const server = new MCPServer({
transport: {
type: "http-stream",
options: {
responseMode: "stream"
}
}
});
Características del transporte HTTP Stream
- Gestión de sesiones: Seguimiento y gestión automática de sesiones
- Reanudabilidad de transmisión: Soporte opcional para reanudar transmisiones después de una pérdida de conexión
- Procesamiento por lotes: Soporte para solicitudes/respuestas por lotes JSON-RPC
- Manejo integral de errores: Respuestas de error detalladas con códigos de error JSON-RPC
Autenticación
MCP Framework proporciona autenticación opcional para endpoints SSE. Puedes elegir entre autenticación JWT, API Key, OAuth 2.1, o implementar tu propio proveedor de autenticación personalizado.
Autenticación JWT
import { MCPServer, JWTAuthProvider } from "mcp-framework";
import { Algorithm } from "jsonwebtoken";
const server = new MCPServer({
transport: {
type: "sse",
options: {
auth: {
provider: new JWTAuthProvider({
secret: process.env.JWT_SECRET,
algorithms: ["HS256" as Algorithm], // Optional (default: ["HS256"])
headerName: "Authorization" // Optional (default: "Authorization")
}),
endpoints: {
sse: true, // Protect SSE endpoint (default: false)
messages: true // Protect message endpoint (default: true)
}
}
}
}
});
Los clientes deben incluir un token JWT válido en el encabezado Authorization:
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
Autenticación con API Key
import { MCPServer, APIKeyAuthProvider } from "mcp-framework";
const server = new MCPServer({
transport: {
type: "sse",
options: {
auth: {
provider: new APIKeyAuthProvider({
keys: [process.env.API_KEY],
headerName: "X-API-Key" // Optional (default: "X-API-Key")
})
}
}
}
});
Los clientes deben incluir una clave API válida en el encabezado X-API-Key:
X-API-Key: your-api-key
Autenticación OAuth 2.1
MCP Framework admite autenticación OAuth 2.1 según la especificación MCP (2025-06-18), incluidos los Metadatos de Recursos Protegidos (RFC 9728) y la validación adecuada de tokens con soporte JWKS.
La autenticación OAuth funciona con transportes SSE y HTTP Stream y admite dos estrategias de validación:
Validación JWT (Recomendada para rendimiento)
La validación JWT obtiene claves públicas del endpoint JWKS de tu servidor de autorización y valida tokens localmente. Esta es la opción más rápida, ya que no requiere un viaje de ida y vuelta al servidor de autenticación para cada solicitud.
import { MCPServer, OAuthAuthProvider } from "mcp-framework";
const server = new MCPServer({
transport: {
type: "http-stream",
options: {
port: 8080,
auth: {
provider: new OAuthAuthProvider({
authorizationServers: [
process.env.OAUTH_AUTHORIZATION_SERVER
],
resource: process.env.OAUTH_RESOURCE,
validation: {
type: 'jwt',
jwksUri: process.env.OAUTH_JWKS_URI,
audience: process.env.OAUTH_AUDIENCE,
issuer: process.env.OAUTH_ISSUER,
algorithms: ['RS256', 'ES256'] // Optional (default: ['RS256', 'ES256'])
}
}),
endpoints: {
initialize: true, // Protect session initialization
messages: true // Protect MCP messages
}
}
}
}
});
Variables de entorno:
OAUTH_AUTHORIZATION_SERVER=https://auth.example.com
OAUTH_RESOURCE=https://mcp.example.com
OAUTH_JWKS_URI=https://auth.example.com/.well-known/jwks.json
OAUTH_AUDIENCE=https://mcp.example.com
OAUTH_ISSUER=https://auth.example.com
Introspección de tokens (Recomendada para control centralizado)
La introspección de tokens valida tokens llamando al endpoint de introspección de tu servidor de autorización. Esto proporciona control centralizado y es útil cuando necesitas revocación de tokens en tiempo real.
import { MCPServer, OAuthAuthProvider } from "mcp-framework";
const server = new MCPServer({
transport: {
type: "sse",
options: {
auth: {
provider: new OAuthAuthProvider({
authorizationServers: [
process.env.OAUTH_AUTHORIZATION_SERVER
],
resource: process.env.OAUTH_RESOURCE,
validation: {
type: 'introspection',
audience: process.env.OAUTH_AUDIENCE,
issuer: process.env.OAUTH_ISSUER,
introspection: {
endpoint: process.env.OAUTH_INTROSPECTION_ENDPOINT,
clientId: process.env.OAUTH_CLIENT_ID,
clientSecret: process.env.OAUTH_CLIENT_SECRET
}
}
})
}
}
}
});
Variables de entorno:
OAUTH_AUTHORIZATION_SERVER=https://auth.example.com
OAUTH_RESOURCE=https://mcp.example.com
OAUTH_AUDIENCE=https://mcp.example.com
OAUTH_ISSUER=https://auth.example.com
OAUTH_INTROSPECTION_ENDPOINT=https://auth.example.com/oauth/introspect
OAUTH_CLIENT_ID=mcp-server
OAUTH_CLIENT_SECRET=your-client-secret
Características de OAuth
- Cumplimiento RFC 9728: Endpoint automático de Metadatos de Recursos Protegidos en
/.well-known/oauth-protected-resource - Encabezados WWW-Authenticate RFC 6750: Respuestas de error OAuth adecuadas con encabezados de desafío
- Caché de claves JWKS: Claves públicas almacenadas en caché durante 15 minutos (configurable)
- Caché de introspección de tokens: Resultados de introspección almacenados en caché durante 5 minutos (configurable)
- Seguridad: Los tokens en cadenas de consulta se rechazan automáticamente
- Extracción de claims: Claims de tokens de acceso en tus manejadores de herramientas a través de
AuthResult
Proveedores OAuth populares
El proveedor OAuth funciona con cualquier servidor de autorización OAuth 2.1 compatible con RFC:
- Auth0: Usa el URI JWKS y el emisor del tenant de Auth0
- Okta: Usa la configuración del servidor de autorización de Okta
- AWS Cognito: Usa el endpoint JWKS del grupo de usuarios de Cognito
- Azure AD / Entra ID: Usa los endpoints de Microsoft Entra ID
- Personalizado: Cualquier servidor de autorización compatible con OAuth 2.1
Para guías de configuración detalladas con proveedores específicos, consulta la Guía de configuración de OAuth.
Uso del cliente
Los clientes deben incluir un token de acceso OAuth válido en el encabezado Authorization:
# Make a request with OAuth token
curl -X POST http://localhost:8080/mcp \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..." \
-H "Content-Type: application/json" \
-d '{"jsonrpc": "2.0", "method": "tools/list", "id": 1}'
# Discover OAuth configuration
curl http://localhost:8080/.well-known/oauth-protected-resource
Mejores prácticas de seguridad
- Usa siempre HTTPS en producción - Los tokens OAuth nunca deben transmitirse a través de conexiones no cifradas
- Valida los claims de audiencia - Evita la reutilización de tokens entre diferentes servicios
- Usa tokens de corta duración - Reduce el riesgo si los tokens se ven comprometidos
- Habilita el caché de introspección de tokens - Reduce la carga en el servidor de autorización mientras mantiene la seguridad
- Monitorea errores de tokens - Realiza un seguimiento de los intentos de autenticación fallidos para obtener información de seguridad
Autenticación personalizada
Puedes implementar tu propio proveedor de autenticación implementando la interfaz AuthProvider:
import { AuthProvider, AuthResult } from "mcp-framework";
import { IncomingMessage } from "node:http";
class CustomAuthProvider implements AuthProvider {
async authenticate(req: IncomingMessage): Promise<boolean | AuthResult> {
// Implement your custom authentication logic
return true;
}
getAuthError() {
return {
status: 401,
message: "Authentication failed"
};
}
}
Servidores MCP de documentación (@mcpframework/docs)
Levanta un servidor MCP de documentación desde cualquier sitio Fumadocs o cualquier sitio con llms.txt — los agentes de IA obtienen herramientas para buscar, navegar y recuperar tu documentación.
Inicio rápido (CLI)
# Scaffold a new docs MCP server project
npx create-docs-mcp my-api-docs
cd my-api-docs
# Configure your docs site URL
cp .env.example .env
# Edit .env → set DOCS_BASE_URL=https://docs.myapi.com
# Build and run
npm run build
npm start
Inicio rápido (Programático)
import { DocsServer, FumadocsRemoteSource } from "@mcpframework/docs";
const source = new FumadocsRemoteSource({
baseUrl: "https://docs.myapi.com",
});
const server = new DocsServer({
source,
name: "my-api-docs",
version: "1.0.0",
});
server.start();
Adaptadores de fuente
| Adaptador | Mejor para | Búsqueda |
|---|---|---|
FumadocsRemoteSource | Sitios Fumadocs | Búsqueda nativa Orama con respaldo |
LlmsTxtSource | Cualquier sitio con llms.txt | Coincidencia de texto local |
DocSource personalizado | Cualquier backend de documentación | Tu implementación |
Herramientas MCP integradas
| Herramienta | Descripción |
|---|---|
search_docs | Busca documentación por palabra clave o frase |
get_page | Recupera el contenido completo en markdown de una página |
list_sections | Navega por la estructura del árbol de documentación |
Agrega a tu cliente MCP
# Claude Code
claude mcp add my-api-docs -- node /path/to/my-api-docs/dist/index.js
# Or with environment variable
claude mcp add my-api-docs -e DOCS_BASE_URL=https://docs.myapi.com -- node /path/to/my-api-docs/dist/index.js
Para la configuración de Claude Desktop / Cursor y documentación completa, consulta el README de @mcpframework/docs.
Licencia
MIT