#!/usr/bin/env node
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js';
import { RAGService } from './rag/rag-service.js';
import { FileService } from './connectors/file-service.js';
import { WebService } from './connectors/web-service.js';
import { TaskService } from './connectors/task-service.js';
import { HttpTransport } from './transports/http-transport.js';
class AIOpsHubServer {
private server: Server;
private ragService: RAGService;
private fileService: FileService;
private webService: WebService;
private taskService: TaskService;
private httpTransport?: HttpTransport;
constructor() {
this.server = new Server(
{
name: 'ai-ops-hub',
version: '0.1.0',
}
);
// Инициализируем сервисы
this.ragService = new RAGService();
this.fileService = new FileService();
this.webService = new WebService();
this.taskService = new TaskService();
this.setupToolHandlers();
}
private setupToolHandlers() {
// RAG инструменты
this.server.setRequestHandler(ListToolsRequestSchema, async () => {
return {
tools: [
{
name: 'rag_search',
description: 'Поиск по личному корпусу документов',
inputSchema: {
type: 'object',
properties: {
query: {
type: 'string',
description: 'Поисковый запрос',
},
limit: {
type: 'number',
description: 'Максимальное количество результатов',
default: 5,
},
},
required: ['query'],
},
},
{
name: 'rag_add_document',
description: 'Добавить документ в RAG корпус',
inputSchema: {
type: 'object',
properties: {
uri: {
type: 'string',
description: 'URI документа',
},
content: {
type: 'string',
description: 'Содержимое документа',
},
title: {
type: 'string',
description: 'Заголовок документа',
},
},
required: ['uri', 'content', 'title'],
},
},
// Файловые инструменты
{
name: 'file_read',
description: 'Читать содержимое файла',
inputSchema: {
type: 'object',
properties: {
path: {
type: 'string',
description: 'Путь к файлу',
},
},
required: ['path'],
},
},
{
name: 'file_write',
description: 'Записать содержимое в файл',
inputSchema: {
type: 'object',
properties: {
path: {
type: 'string',
description: 'Путь к файлу',
},
content: {
type: 'string',
description: 'Содержимое для записи',
},
},
required: ['path', 'content'],
},
},
// Веб инструменты
{
name: 'web_fetch',
description: 'Получить содержимое веб-страницы',
inputSchema: {
type: 'object',
properties: {
url: {
type: 'string',
description: 'URL страницы',
},
},
required: ['url'],
},
},
// Инструменты задач
{
name: 'task_create',
description: 'Создать новую задачу',
inputSchema: {
type: 'object',
properties: {
title: {
type: 'string',
description: 'Заголовок задачи',
},
project: {
type: 'string',
description: 'Проект',
},
due: {
type: 'string',
description: 'Срок выполнения (YYYY-MM-DD)',
},
},
required: ['title'],
},
},
{
name: 'task_list',
description: 'Список задач',
inputSchema: {
type: 'object',
properties: {
project: {
type: 'string',
description: 'Фильтр по проекту',
},
status: {
type: 'string',
description: 'Статус (open/completed)',
enum: ['open', 'completed'],
},
},
},
},
],
};
});
// Обработчики вызовов инструментов
this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
const { name, arguments: args } = request.params;
if (!args) {
throw new Error('Аргументы не предоставлены');
}
try {
switch (name) {
case 'rag_search':
return {
content: await this.ragService.search(args.query as string, (args.limit as number) || 5)
};
case 'rag_add_document':
await this.ragService.addDocument(args.uri as string, args.content as string, args.title as string);
return { content: 'Документ добавлен' };
case 'file_read':
return {
content: await this.fileService.readFile(args.path as string)
};
case 'file_write':
await this.fileService.writeFile(args.path as string, args.content as string);
return { content: 'Файл записан' };
case 'web_fetch':
return {
content: await this.webService.fetchPage(args.url as string)
};
case 'task_create':
return {
content: await this.taskService.createTask(args.title as string, args.project as string, args.due as string)
};
case 'task_list':
return {
content: await this.taskService.listTasks(args.project as string, args.status as string)
};
default:
throw new Error(`Неизвестный инструмент: ${name}`);
}
} catch (error) {
console.error(`Ошибка выполнения инструмента ${name}:`, error);
throw error;
}
});
}
async start() {
// Запускаем stdio транспорт (для локального использования)
const stdioTransport = new StdioServerTransport();
await this.server.connect(stdioTransport);
console.error('📡 AI Ops Hub MCP сервер запущен (stdio)');
// Запускаем HTTP транспорт (для удаленного доступа)
const httpPort = parseInt(process.env.HTTP_PORT || '3333');
this.httpTransport = new HttpTransport(httpPort);
await this.httpTransport.connect();
console.error(`🌐 HTTP MCP сервер запущен на порту ${httpPort}`);
}
async stop() {
if (this.httpTransport) {
await this.httpTransport.disconnect();
}
console.error('🛑 AI Ops Hub MCP сервер остановлен');
}
}
// Запуск сервера
const server = new AIOpsHubServer();
server.start().catch((error) => {
console.error('Ошибка запуска сервера:', error);
process.exit(1);
});