Files
printerCentral/server/api/mcp/index.post.ts
josedario87 bc5eb826e8
All checks were successful
build-and-deploy / build-and-deploy (push) Successful in 36s
fix: Autenticación por token para MCP Server
- Ruta /api/mcp agregada a rutas públicas de Traefik
- Validación de token Bearer en el endpoint
- Token configurado como secret MCP_AUTH_TOKEN
2025-11-25 12:56:04 -06:00

128 lines
3.2 KiB
TypeScript

// MCP Server Endpoint - JSON-RPC 2.0 over HTTP
// Protocolo MCP para agentes de IA
import { MCP_TOOLS, handleToolCall } from '../../utils/mcp'
interface JsonRpcRequest {
jsonrpc: '2.0'
id: string | number
method: string
params?: any
}
interface JsonRpcResponse {
jsonrpc: '2.0'
id: string | number | null
result?: any
error?: {
code: number
message: string
data?: any
}
}
export default defineEventHandler(async (event) => {
// Validar token de autenticación
const authHeader = getHeader(event, 'Authorization')
const expectedToken = process.env.MCP_AUTH_TOKEN
if (expectedToken) {
const providedToken = authHeader?.replace('Bearer ', '')
if (!providedToken || providedToken !== expectedToken) {
setResponseStatus(event, 401)
return createJsonRpcError(null, -32000, 'Unauthorized: Invalid or missing token')
}
}
try {
const body = await readBody(event) as JsonRpcRequest
// Validar JSON-RPC
if (body.jsonrpc !== '2.0') {
return createJsonRpcError(body.id, -32600, 'Invalid Request: jsonrpc must be "2.0"')
}
if (!body.method) {
return createJsonRpcError(body.id, -32600, 'Invalid Request: method is required')
}
// Manejar métodos MCP
switch (body.method) {
case 'initialize': {
// Handshake inicial del protocolo MCP
return createJsonRpcResponse(body.id, {
protocolVersion: '2024-11-05',
capabilities: {
tools: {}
},
serverInfo: {
name: 'printercentral-mcp',
version: '1.0.0'
}
})
}
case 'initialized': {
// Notificación de que el cliente está listo
return createJsonRpcResponse(body.id, {})
}
case 'tools/list': {
// Listar todas las tools disponibles
return createJsonRpcResponse(body.id, {
tools: MCP_TOOLS
})
}
case 'tools/call': {
// Ejecutar una tool
const { name, arguments: args } = body.params || {}
if (!name) {
return createJsonRpcError(body.id, -32602, 'Invalid params: tool name is required')
}
// Verificar que la tool existe
const tool = MCP_TOOLS.find(t => t.name === name)
if (!tool) {
return createJsonRpcError(body.id, -32602, `Tool not found: ${name}`)
}
// Ejecutar la tool
const result = await handleToolCall(name, args || {})
return createJsonRpcResponse(body.id, result)
}
case 'ping': {
return createJsonRpcResponse(body.id, {})
}
default:
return createJsonRpcError(body.id, -32601, `Method not found: ${body.method}`)
}
} catch (err: any) {
console.error('MCP Error:', err)
return createJsonRpcError(null, -32603, `Internal error: ${err.message}`)
}
})
function createJsonRpcResponse(id: string | number | null, result: any): JsonRpcResponse {
return {
jsonrpc: '2.0',
id: id ?? null,
result
}
}
function createJsonRpcError(id: string | number | null, code: number, message: string, data?: any): JsonRpcResponse {
return {
jsonrpc: '2.0',
id: id ?? null,
error: {
code,
message,
...(data && { data })
}
}
}