apprecio-mcp-base
v2.3.10
Published
Base package for creating Apprecio MCP servers with consistency
Maintainers
Readme
apprecio-mcp-base
Base package para crear servidores MCP (Model Context Protocol) de Apprecio con consistencia y reutilización de código.
🚀 Características
- Servidor Base Abstracto: Clase
McpBaseServerque encapsula toda la lógica común - Sistema de Features: Arquitectura modular con
FeatureModule - Configuración Centralizada: Sistema de configuración con validación Zod
- Logger Unificado: Winston logger con niveles configurables y rotación de archivos
- Middlewares Reutilizables: Autenticación Bearer Token, Rate Limiting, CORS, Helmet
- Conectores Database: MongoDB y Redis pre-configurados
- Port Management: Búsqueda automática de puertos disponibles
- Graceful Shutdown: Manejo automático de señales SIGINT/SIGTERM
- TypeScript First: Completamente tipado con soporte para path aliases
- CLI Generator: Generador de proyectos y features automático
📦 Instalación
npm install apprecio-mcp-base
# o
pnpm add apprecio-mcp-base🎯 Quick Start
Opción 1: Usar el CLI (Recomendado)
# 1. Setup global link (una vez)
cd apprecio-mcp-base
npm run build
npm link
# 2. Generar nuevo proyecto
mcp-generate init
# Responder wizard:
# - Nombre del proyecto
# - Ruta
# - Usar MongoDB (sí/no)
# - Base URL de tu API
# ¿Instalar dependencias? Yes
# ¿Linkear apprecio-mcp-base? Yes
# 3. Ejecutar
cd my-project
npm run devOpción 2: Manual
import {
McpBaseServer,
createServer,
findAvailablePort,
createMongoDBConnector,
logger,
type MongoDBConnector
} from 'apprecio-mcp-base';
class MyMcpServer extends McpBaseServer {
private dbConnector?: MongoDBConnector;
protected async registerFeatures(): Promise<void> {
// Registrar tus features
this.registerFeature('users', usersFeature);
}
protected async onBeforeStart(): Promise<void> {
const mongoUri = this.config.mongodbUri;
if (mongoUri) {
this.dbConnector = createMongoDBConnector(mongoUri);
await this.dbConnector.connect();
}
}
protected async onBeforeShutdown(): Promise<void> {
if (this.dbConnector) {
await this.dbConnector.disconnect();
}
}
}
async function main() {
const server = new MyMcpServer({
name: 'my-mcp-server',
version: '1.0.0',
});
const port = await findAvailablePort(server.getConfig().ssePort);
const { httpServer, transport } = await createServer(port);
await server.start(httpServer, transport, port);
}
main();🔧 CLI Generator
El paquete incluye un CLI para generar proyectos y features automáticamente.
Comandos Disponibles
# Generar nuevo proyecto
mcp-generate init
# Generar nueva feature
mcp-generate feature
# Help
mcp-generate --helpGenerar Proyecto
mcp-generate init
# Wizard interactivo:
? Nombre del proyecto: my-awesome-mcp
? Ruta: ./my-awesome-mcp
? Descripción: My awesome MCP server
? Autor: Apprecio
? ¿Usar MongoDB? Yes
? ¿Usar Redis? Yes
? ¿Instalar dependencias? Yes
? ¿Linkear apprecio-mcp-base? Yes
# Genera:
# ✅ Estructura completa del proyecto
# ✅ Archivos base incluyendo Redis y MongoDB setup
# ✅ Scripts de setup (post-install.sh, check-permissions.sh)
# ✅ Configuración (.env, tsconfig.json, package.json)
# ✅ README.md completoGenerar Feature
cd my-project
npm run generate
# Wizard interactivo:
? Nombre de la feature: users
? Descripción: Manage users
? ¿Necesita service? Yes
? ¿Qué orígenes de datos utilizará esta feature? (Selecciona con Espacio):
[x] MongoDB (Mongoose)
[x] Redis
[ ] API HTTP Externa
? Tools: [x] list, [x] get, [x] create, [x] update
? Nombre de la entidad: user
? ¿Auto-registrar en main.ts? Yes
# Genera:
# ✅ users.feature.ts - Feature module con tools
# ✅ users.service.ts - Service inteligente que combina:
# - Modelos de Mongoose
# - Repositorio de Redis (con singleton compartido)
# - Cliente HTTP (si se selecciona)
# ✅ users.validation.ts - Zod schemas
# ✅ users.model.ts (si se selecciona MongoDB)
# ✅ Actualiza main.ts automáticamente📚 Sistema de Features
Crear un Feature Module
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { logger, type FeatureModule } from 'apprecio-mcp-base';
export const usersFeature: FeatureModule = {
name: 'users',
register(mcpServer: McpServer): void {
// Registrar tool
mcpServer.tool(
'list_users',
'List all users',
{
page: { type: 'number', description: 'Page number' },
limit: { type: 'number', description: 'Items per page' }
},
async (args, extra) => {
// Extraer token de auth
const req = extra as any;
const token = req?.requestInfo?.headers?.authorization;
// Tu lógica aquí
const users = await userService.list(args);
return {
content: [{
type: 'text',
text: JSON.stringify(users)
}]
};
}
);
logger.info('Users feature registered');
},
async initialize(): Promise<void> {
logger.info('Users feature initialized');
},
async cleanup(): Promise<void> {
logger.info('Users feature cleaned up');
}
};Registrar Features
class MyMcpServer extends McpBaseServer {
protected async registerFeatures(): Promise<void> {
this.registerFeature('users', usersFeature);
this.registerFeature('products', productsFeature);
this.registerFeature('orders', ordersFeature);
logger.info('All features registered');
}
}🔐 Autenticación
Middleware de Autenticación
import { createAuthMiddleware } from 'apprecio-mcp-base';
// Crear middleware
const auth = createAuthMiddleware({
apiKey: process.env.API_KEY,
enabled: process.env.AUTH_ENABLED !== 'false'
});
// Usar en Express
app.get('/health', handler); // Público
app.use('/sse', auth); // Protegido
app.post('/sse', handler);Usar Token en Features
mcpServer.tool('secure_action', schema, async (args, extra) => {
// Extraer token
const req = extra as any;
const token = req?.requestInfo?.headers?.authorization;
if (!token) {
throw new Error('Unauthorized');
}
// Validar y usar token
const isValid = await validateToken(token);
if (!isValid) {
throw new Error('Invalid token');
}
// Procesar acción
return { content: [{ type: 'text', text: 'Success' }] };
});📝 Configuración
Variables de Entorno
# Authentication
API_KEY=your-secret-key-here
AUTH_ENABLED=false
# Database (opcional)
MONGODB_URI=mongodb://localhost:27017/mydb
# Server
MCP_SSE_PORT=3200
# Timeouts (ms)
MCP_TIMEOUT=180000
SSE_TIMEOUT=1800000
# Logging
LOG_LEVEL=info
# CORS
CORS_ALLOW_ORIGIN=*
# Rate Limiting
RATE_LIMIT_WINDOW_MS=900000
RATE_LIMIT_MAX_REQUESTS=100Acceder a Configuración
class MyMcpServer extends McpBaseServer {
protected async registerFeatures(): Promise<void> {
// Acceder a config
const config = this.config;
logger.info(`Server port: ${config.ssePort}`);
logger.info(`MongoDB URI: ${config.mongodbUri}`);
logger.info(`Log level: ${config.logLevel}`);
}
}🗄️ Database Connectors
MongoDB
import { createMongoDBConnector } from 'apprecio-mcp-base';
// Crear conector
const db = createMongoDBConnector('mongodb://localhost:27017/db');
// Conectar
await db.connect();
// Usar mongoose
const connection = db.getConnection();
const User = connection.model('User', userSchema);
// Desconectar
await db.disconnect();Redis
El proyecto generado incluye un patrón de Singleton y Repositorio para Redis.
En main.ts (Setup):
import { createRedisConnector } from 'apprecio-mcp-base';
import { setRedisClient } from './db/redis/client.js'; // Store generado
// Inicialización
const redis = createRedisConnector(process.env.REDIS_URL);
await redis.connect();
// Compartir instancia globalmente
setRedisClient(redis.getClient());En tus Servicios (Uso):
import { getRedisClient } from '../../db/redis/client.js';
import { createRedisRepository } from '../../db/redis/redis.js';
class UserService {
// Crea un repositorio "scopeado" a una entidad (usa prefijos ej: 'user:')
private redis = createRedisRepository(getRedisClient(), 'user');
async cacheUser(user: any) {
// Métodos helper: save, find, findAll, clear, etc.
await this.redis.save(user.id, JSON.stringify(user));
}
}📊 Logger
import { logger, createChildLogger, setLogLevel } from 'apprecio-mcp-base';
// Uso básico
logger.info('Server started');
logger.error('Error occurred', error);
logger.debug('Debug info', { metadata });
logger.warn('Warning message');
// Logger con contexto
const featureLogger = createChildLogger('UsersFeature');
featureLogger.info('User created', { userId: 123 });
// Cambiar nivel dinámicamente
setLogLevel('debug');🛠️ Desarrollo
Estructura del Proyecto
apprecio-mcp-base/
├── cli/ # CLI generator
│ ├── generators/
│ │ ├── init-generator.ts # Generador de proyectos
│ │ ├── feature-generator.ts # Generador de features
│ │ ├── service-generator.ts # Generador de services
│ │ ├── router-generator.ts # Generador de routers
│ │ └── main-updater.ts # Actualizador de main.ts
│ ├── templates/
│ │ ├── post-install.sh
│ │ └── check-permissions.sh
│ └── generate-feature.ts # Entry point del CLI
├── src/
│ ├── core/ # Núcleo del framework
│ │ ├── McpBaseServer.ts # Clase base
│ │ ├── config.ts # Sistema de configuración
│ │ ├── logger.ts # Logger centralizado
│ │ └── types.ts # Tipos compartidos
│ ├── middleware/ # Middlewares Express
│ │ ├── auth.ts # Autenticación Bearer
│ │ ├── rate-limit.ts # Rate limiting
│ │ └── cors.ts # CORS config
│ ├── database/ # Conectores DB
│ │ ├── mongodb.ts
│ │ └── redis.ts
│ ├── server/ # Server builders
│ │ └── express.ts
│ ├── utils/ # Utilidades
│ │ ├── port.ts # Port finder
│ │ └── shutdown.ts # Graceful shutdown
│ └── index.ts # Exports principales
├── examples/ # Ejemplos de uso
├── package.json
├── tsconfig.json
└── README.mdScripts Disponibles
# Build del paquete
npm run build
# Build con watch
npm run build:watch
# Build CLI
npm run build:cli
# Build todo
npm run build:all
# Link global
npm link
# Generate feature (si estás en un proyecto)
npm run generateDesarrollo del CLI
# Build CLI
npm run build:cli
# Link globalmente
npm link
# Usar en cualquier lugar
mcp-generate init🚀 Setup para Desarrollo
1. Setup Inicial
# Clone repo
git clone https://github.com/apprecio/apprecio-mcp-base.git
cd apprecio-mcp-base
# Instalar dependencias
npm install
# Build
npm run build
# Link global
npm link2. Crear Proyecto de Prueba
# Generar proyecto
mcp-generate init
# Configurar
cd my-test-project
npm install
npm link apprecio-mcp-base
# Ejecutar
npm run dev3. Desarrollo Iterativo
# Terminal 1: Watch mode en apprecio-mcp-base
cd apprecio-mcp-base
npm run build:watch
# Terminal 2: Tu proyecto
cd my-test-project
npm run dev
# Los cambios en apprecio-mcp-base se reflejan automáticamente📚 API Reference
McpBaseServer
abstract class McpBaseServer {
constructor(options: ServerOptions)
// Métodos abstractos
protected abstract registerFeatures(): Promise<void>
// Hooks opcionales
protected async onBeforeStart?(): Promise<void>
protected async onBeforeShutdown?(): Promise<void>
// Métodos públicos
getMcpServer(): McpServer
getConfig(): BaseConfig
getFeatures(): Map<string, FeatureModule>
// Lifecycle
async start(httpServer: HttpServer, transport: Transport, port: number): Promise<void>
}FeatureModule
interface FeatureModule {
name: string;
register(mcpServer: McpServer): void;
initialize?(): Promise<void>;
cleanup?(): Promise<void>;
}BaseConfig
class BaseConfig {
get apiKey(): string
get mongodbUri(): string | undefined
get ssePort(): number
get logLevel(): 'debug' | 'info' | 'warn' | 'error'
get mcpTimeout(): number
get sseTimeout(): number
get corsAllowOrigin(): string
get rateLimitWindowMs(): number
get rateLimitMaxRequests(): number
}🆘 Troubleshooting
Error: Cannot find module 'apprecio-mcp-base'
# Verificar link global
npm list -g apprecio-mcp-base --depth=0
# Si no está linkeado:
cd apprecio-mcp-base
npm run build
npm link
# En tu proyecto:
npm link apprecio-mcp-baseError: EACCES (Permission Denied)
# En el proyecto generado
./check-permissions.sh
# Arreglar permisos
sudo chown -R $(whoami) .
chmod -R 755 .Error: npm cache EACCES
# Arreglar caché de npm
sudo chown -R $(whoami) ~/.npm
npm cache clean --force
npm installCambios no se reflejan
# Rebuild apprecio-mcp-base
cd apprecio-mcp-base
npm run build
# Los proyectos linkeados ven cambios automáticamente💡 Best Practices
✅ DO:
- Usa el CLI para generar proyectos y features
- Mantén features pequeños y enfocados
- Usa el logger en lugar de console.log
- Implementa cleanup en features con recursos
- Usa TypeScript strict mode
- Valida inputs con Zod
❌ DON'T:
- No uses
sudo npm install - No modifies archivos generados manualmente
- No uses console.log en producción
- No olvides implementar cleanup
- No hardcodees configuración
🎯 Ejemplos
Ver examples/ para:
- Servidor MCP simple
- Servidor con MongoDB
- Servidor con múltiples features
- Feature con autenticación
- Feature con validación Zod
📖 Documentación
- Model Context Protocol - Especificación MCP
- TypeScript - TypeScript docs
- Winston - Logger docs
- Zod - Validation docs
🤝 Contribuir
- Fork el proyecto
- Crea una branch:
git checkout -b feature/amazing-feature - Commit cambios:
git commit -m 'Add amazing feature' - Push:
git push origin feature/amazing-feature - Abre un Pull Request
📄 Licencia
MIT © Apprecio
🔗 Links
Hecho con ❤️ por el equipo de Apprecio
