/**
* MCP Controller - Implementa o protocolo Model Calling Protocol
* Gerencia requisições JSON-RPC e ferramentas disponíveis
*/
import { Request, Response } from 'express';
// @ts-ignore
const jsonrpc = require('jsonrpc-lite');
import * as toolsManager from './toolsManager';
import logger from '../utils/logger';
interface RpcRequest {
method: string;
params?: any;
id?: string | number | null;
}
interface JsonRpcResponse {
id: string | number | null;
error?: any;
result?: any;
jsonrpc: string;
}
/**
* Processa uma requisição JSON-RPC para o MCP
* @param req - Requisição Express
* @param res - Resposta Express
*/
export async function handleRpcRequest(req: Request, res: Response): Promise<void> {
const rpcRequest: RpcRequest = req.body;
if (!rpcRequest || !rpcRequest.method) {
res.status(400).json(
jsonrpc.error(null, new jsonrpc.JsonRpcError('Invalid JSON-RPC request', -32600))
);
return;
}
try {
let response;
// Roteamento de métodos RPC
switch (rpcRequest.method) {
case 'tools.list':
response = handleToolsList(rpcRequest);
break;
case 'tools.get':
response = handleToolsGet(rpcRequest);
break;
case 'run':
response = await handleRun(rpcRequest);
break;
default:
response = jsonrpc.error(
rpcRequest.id || null,
new jsonrpc.JsonRpcError(`Method ${rpcRequest.method} not found`, -32601)
);
}
res.json(response);
} catch (error) {
const err = error as Error;
logger.error('RPC Error:', err);
res.json(
jsonrpc.error(
rpcRequest.id || null,
new jsonrpc.JsonRpcError(err.message || 'Internal server error', -32603)
)
);
}
}
/**
* Processa requisição tools.list
* @param rpcRequest - Requisição JSON-RPC
* @returns Resposta JSON-RPC
*/
function handleToolsList(rpcRequest: RpcRequest): any {
const tools = toolsManager.listTools();
return jsonrpc.success(rpcRequest.id || null, tools);
}
/**
* Processa requisição tools.get
* @param rpcRequest - Requisição JSON-RPC
* @returns Resposta JSON-RPC
*/
function handleToolsGet(rpcRequest: RpcRequest): any {
const { params } = rpcRequest;
if (!params || !params.name) {
return jsonrpc.error(
rpcRequest.id || null,
new jsonrpc.JsonRpcError('Missing tool name parameter', -32602)
);
}
const tool = toolsManager.getTool(params.name);
if (!tool) {
return jsonrpc.error(
rpcRequest.id || null,
new jsonrpc.JsonRpcError(`Tool '${params.name}' not found`, 404)
);
}
return jsonrpc.success(rpcRequest.id || null, tool);
}
/**
* Processa requisição run para executar uma ferramenta
* @param rpcRequest - Requisição JSON-RPC
* @returns Resposta JSON-RPC
*/
async function handleRun(rpcRequest: RpcRequest): Promise<any> {
const { params } = rpcRequest;
if (!params || !params.name) {
return jsonrpc.error(
rpcRequest.id || null,
new jsonrpc.JsonRpcError('Missing tool name parameter', -32602)
);
}
try {
const result = await toolsManager.runTool(params.name, params.arguments || {});
return jsonrpc.success(rpcRequest.id || null, result);
} catch (error) {
const err = error as Error;
logger.error('Tool execution error:', err);
return jsonrpc.error(
rpcRequest.id || null,
new jsonrpc.JsonRpcError(err.message || 'Tool execution failed', 500)
);
}
}
/**
* Handler para verificar a saúde do servidor
*/
export function healthCheck(req: Request, res: Response): void {
res.json({
status: 'ok',
timestamp: new Date().toISOString()
});
}