import 'dotenv/config';
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import {
CallToolRequestSchema,
ErrorCode,
ListToolsRequestSchema,
McpError,
} from '@modelcontextprotocol/sdk/types.js';
import { ContentCurationService } from './services/curation.service.js';
class TwygoCurationServer {
private server: Server;
private curationService: ContentCurationService;
constructor() {
this.server = new Server(
{
name: 'Twygo - Curadoria de Conteúdo',
version: '1.0.0',
},
{
capabilities: {
tools: {},
},
}
);
this.curationService = new ContentCurationService();
this.setupToolHandlers();
this.setupErrorHandling();
}
private setupToolHandlers() {
this.server.setRequestHandler(ListToolsRequestSchema, async () => ({
tools: [
{
name: 'suggest_category',
description: 'Sugere categoria mais apropriada para um curso usando IA',
inputSchema: {
type: 'object',
properties: {
title: { type: 'string', description: 'Título do curso' },
description: { type: 'string', description: 'Descrição do curso' },
},
required: ['title', 'description'],
},
},
{
name: 'suggest_tags',
description: 'Sugere tags relevantes para um curso usando IA',
inputSchema: {
type: 'object',
properties: {
title: { type: 'string', description: 'Título do curso' },
description: { type: 'string', description: 'Descrição do curso' },
},
required: ['title', 'description'],
},
},
{
name: 'improve_content',
description: 'Melhora título e descrição de um curso seguindo boas práticas',
inputSchema: {
type: 'object',
properties: {
title: { type: 'string', description: 'Título atual do curso' },
description: { type: 'string', description: 'Descrição atual do curso' },
},
required: ['title', 'description'],
},
},
],
}));
this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
const { name, arguments: args } = request.params;
try {
switch (name) {
case 'suggest_category':
return await this.handleSuggestCategory(args);
case 'suggest_tags':
return await this.handleSuggestTags(args);
case 'improve_content':
return await this.handleImproveContent(args);
default:
throw new McpError(ErrorCode.MethodNotFound, `Ferramenta desconhecida: ${name}`);
}
} catch (error) {
if (error instanceof McpError) {
throw error;
}
throw new McpError(ErrorCode.InternalError, `Erro ao executar ${name}: ${error}`);
}
});
}
private async handleSuggestCategory(args: any) {
const { title, description } = args;
const content = { title, description };
const result = await this.curationService.curateCourse(content);
return {
content: [
{
type: 'text',
text: JSON.stringify({
suggestedCategory: result.suggestedCategory,
aiEnabled: this.curationService.getAIStatus().enabled
}, null, 2),
},
],
};
}
private async handleSuggestTags(args: any) {
const { title, description } = args;
const content = { title, description };
const result = await this.curationService.curateCourse(content);
return {
content: [
{
type: 'text',
text: JSON.stringify({
suggestedTags: result.suggestedTags,
aiEnabled: this.curationService.getAIStatus().enabled
}, null, 2),
},
],
};
}
private async handleImproveContent(args: any) {
const { title, description } = args;
const content = { title, description };
const result = await this.curationService.curateCourse(content);
return {
content: [
{
type: 'text',
text: JSON.stringify({
titleImprovement: result.titleImprovement,
descriptionImprovement: result.descriptionImprovement,
aiEnabled: this.curationService.getAIStatus().enabled
}, null, 2),
},
],
};
}
private setupErrorHandling() {
this.server.onerror = (error) => {
console.error('[MCP Error]', error);
};
process.on('SIGINT', async () => {
await this.server.close();
process.exit(0);
});
}
async run() {
const transport = new StdioServerTransport();
await this.server.connect(transport);
console.error('🚀 Servidor MCP Twygo iniciado - Funcionalidades: Categoria, Tags, Melhorias');
}
}
const server = new TwygoCurationServer();
server.run().catch((error) => {
console.error('❌ Falha ao iniciar servidor:', error);
process.exit(1);
});