UNPKG

fluent-api-mcp-server

Version:

FluentAPI MCP Server - Enable AI assistants to facilitate seamless multilingual conversations

322 lines 15 kB
#!/usr/bin/env node /** * FluentAPI MCP Server * Enables AI assistants to facilitate seamless multilingual conversations */ 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 { z } from 'zod'; import { FluentAPIClient } from './fluent-client.js'; // Environment configuration const FLUENT_API_KEY = process.env.FLUENT_API_KEY; const FLUENT_API_BASE_URL = process.env.FLUENT_API_BASE_URL || 'https://www.fluentapi.io'; if (!FLUENT_API_KEY) { console.error('Error: FLUENT_API_KEY environment variable is required'); console.error(`Get your API key from: ${FLUENT_API_BASE_URL}/pricing.html`); process.exit(1); } // Initialize FluentAPI client const fluentClient = new FluentAPIClient(FLUENT_API_KEY, FLUENT_API_BASE_URL); // Schema definitions for tool parameters const TranslateMessageSchema = z.object({ message: z.string().min(1, 'Message cannot be empty'), target_language: z.string().min(1, 'Target language is required'), source_language: z.string().optional().default('auto'), conversation_id: z.string().optional(), sender_id: z.string().optional(), recipient_id: z.string().optional(), platform: z.string().optional().default('mcp'), }); const GetConversationSchema = z.object({ conversation_id: z.string().min(1, 'Conversation ID is required'), participant_id: z.string().optional(), language: z.string().optional(), }); const CreateConversationSchema = z.object({ conversation_id: z.string().min(1, 'Conversation ID is required'), participants: z.array(z.object({ id: z.string(), language: z.string(), })).optional(), }); // Create MCP server const server = new Server({ name: 'fluent-api-mcp', version: '1.0.0', }, { capabilities: { tools: {}, }, }); // List available tools server.setRequestHandler(ListToolsRequestSchema, async () => { return { tools: [ { name: 'translate_message', description: 'Translate a message between languages with conversation context. Perfect for facilitating multilingual conversations.', inputSchema: { type: 'object', properties: { message: { type: 'string', description: 'The message text to translate', }, target_language: { type: 'string', description: 'Target language code (e.g., "es" for Spanish, "fr" for French, "zh" for Chinese)', }, source_language: { type: 'string', description: 'Source language code (optional, defaults to "auto" for auto-detection)', default: 'auto', }, conversation_id: { type: 'string', description: 'Unique conversation identifier for context (optional, will generate if not provided)', }, sender_id: { type: 'string', description: 'ID of the message sender (optional)', }, recipient_id: { type: 'string', description: 'ID of the message recipient (optional)', }, platform: { type: 'string', description: 'Platform type (facebook, whatsapp, slack, discord, mcp)', default: 'mcp', }, }, required: ['message', 'target_language'], }, }, { name: 'get_conversation', description: 'Retrieve conversation history with messages translated to a specific participant\'s language.', inputSchema: { type: 'object', properties: { conversation_id: { type: 'string', description: 'The conversation ID to retrieve', }, participant_id: { type: 'string', description: 'Filter for specific participant (optional)', }, language: { type: 'string', description: 'Language to translate messages to (optional)', }, }, required: ['conversation_id'], }, }, { name: 'get_supported_languages', description: 'Get list of all supported languages with their codes and names.', inputSchema: { type: 'object', properties: {}, required: [], }, }, { name: 'create_conversation', description: 'Create a new conversation context for multilingual communication.', inputSchema: { type: 'object', properties: { conversation_id: { type: 'string', description: 'Unique identifier for the conversation', }, participants: { type: 'array', description: 'List of participants with their preferred languages', items: { type: 'object', properties: { id: { type: 'string', description: 'Participant ID' }, language: { type: 'string', description: 'Participant\'s preferred language code' }, }, required: ['id', 'language'], }, }, }, required: ['conversation_id'], }, }, ], }; }); // Handle tool calls server.setRequestHandler(CallToolRequestSchema, async (request) => { try { const { name, arguments: args } = request.params; switch (name) { case 'translate_message': { const params = TranslateMessageSchema.parse(args); // Generate conversation ID if not provided const conversationId = params.conversation_id || `mcp_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`; const result = await fluentClient.translate({ conversationId, senderId: params.sender_id, senderLang: params.source_language, recipientId: params.recipient_id, recipientLang: params.target_language, message: params.message, platformType: params.platform, }); return { content: [ { type: 'text', text: JSON.stringify({ success: true, conversation_id: result.conversationId, message_id: result.messageId, original: { text: result.original.text, language: result.original.language, language_name: fluentClient.getSupportedLanguages()[result.original.language] || result.original.language, }, translated: { text: result.translated.text, language: result.translated.language, language_name: fluentClient.getSupportedLanguages()[result.translated.language] || result.translated.language, }, display_format: result.displayOptions.format, platform_integrations: result.integrations, }, null, 2), }, ], }; } case 'get_conversation': { const params = GetConversationSchema.parse(args); const conversation = await fluentClient.getConversation(params.conversation_id, params.participant_id, params.language); return { content: [ { type: 'text', text: JSON.stringify({ conversation_id: conversation.conversationId, participants: conversation.participants, message_count: conversation.messageCount, messages: conversation.messages.map(msg => ({ id: msg.id, sender_id: msg.senderId, recipient_id: msg.recipientId, original: { text: msg.original.text, language: msg.original.language, language_name: fluentClient.getSupportedLanguages()[msg.original.language] || msg.original.language, }, translated: { text: msg.translated.text, language: msg.translated.language, language_name: fluentClient.getSupportedLanguages()[msg.translated.language] || msg.translated.language, }, display_text: msg.displayText, display_language: msg.displayLanguage, timestamp: msg.timestamp, platform: msg.platformType, })), }, null, 2), }, ], }; } case 'get_supported_languages': { const languages = fluentClient.getSupportedLanguages(); return { content: [ { type: 'text', text: JSON.stringify({ supported_languages: languages, language_count: Object.keys(languages).length, popular_languages: { 'en': languages['en'], 'es': languages['es'], 'fr': languages['fr'], 'de': languages['de'], 'zh': languages['zh'], 'ja': languages['ja'], 'ko': languages['ko'], 'ar': languages['ar'], 'hi': languages['hi'], 'pt': languages['pt'], 'ru': languages['ru'], }, }, null, 2), }, ], }; } case 'create_conversation': { const params = CreateConversationSchema.parse(args); // For conversation creation, we just return the structure // The actual conversation will be created on first message return { content: [ { type: 'text', text: JSON.stringify({ success: true, conversation_id: params.conversation_id, participants: params.participants || [], status: 'ready', message: 'Conversation context created. Send your first message using translate_message.', next_steps: [ 'Use translate_message to send messages in this conversation', 'Each participant can communicate in their native language', 'The API will handle all translations automatically', ], }, null, 2), }, ], }; } default: throw new McpError(ErrorCode.MethodNotFound, `Unknown tool: ${name}`); } } catch (error) { if (error instanceof z.ZodError) { throw new McpError(ErrorCode.InvalidParams, `Invalid parameters: ${error.errors.map(e => `${e.path.join('.')}: ${e.message}`).join(', ')}`); } if (error instanceof Error) { throw new McpError(ErrorCode.InternalError, `FluentAPI error: ${error.message}`); } throw new McpError(ErrorCode.InternalError, `Unknown error: ${String(error)}`); } }); async function main() { const transport = new StdioServerTransport(); await server.connect(transport); // Log startup message to stderr so it doesn't interfere with MCP protocol console.error('FluentAPI MCP Server started successfully'); console.error(`API Key: ${FLUENT_API_KEY?.slice(0, 20)}...`); console.error(`Base URL: ${FLUENT_API_BASE_URL}`); } // Handle graceful shutdown process.on('SIGINT', async () => { console.error('Shutting down FluentAPI MCP Server...'); await server.close(); process.exit(0); }); process.on('SIGTERM', async () => { console.error('Shutting down FluentAPI MCP Server...'); await server.close(); process.exit(0); }); main().catch((error) => { console.error('Fatal error starting FluentAPI MCP Server:', error); process.exit(1); }); //# sourceMappingURL=index.js.map