UNPKG

mcp-sms-ir

Version:

MCP Server for SMS.ir messaging services

295 lines (271 loc) 9.14 kB
#!/usr/bin/env node import axios from 'axios'; // Main function to handle async operations const main = async () => { try { // Dynamically import the MCP SDK const mcp = await import('@modelcontextprotocol/sdk'); const { Server, StdioServerTransport, CallToolRequestSchema, ListToolsRequestSchema, ErrorCode } = mcp; // Get API key from environment variables const API_KEY = process.env.SMS_IR_API_KEY; if (!API_KEY) { console.error('SMS_IR_API_KEY environment variable is required'); process.exit(1); } // SMS.ir API base URL const BASE_URL = 'https://api.sms.ir/v1'; class SmsIrServer { constructor(apiKey) { this.server = new Server( { name: 'sms-ir-server', version: '1.0.0', }, { capabilities: { tools: {}, }, } ); // Configure axios instance with default headers and base URL this.axiosInstance = axios.create({ baseURL: BASE_URL, headers: { 'Content-Type': 'application/json', 'Accept': 'text/plain', 'x-api-key': apiKey, } }); this.setupToolHandlers(); // Error handling this.server.onerror = (error) => console.error('[MCP Error]', error); process.on('SIGINT', async () => { await this.server.close(); process.exit(0); }); } setupToolHandlers() { // List available tools this.server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: [ { name: 'send_sms', description: 'Send a SMS message to a single recipient', inputSchema: { type: 'object', properties: { mobile: { type: 'string', description: 'Recipient mobile number (e.g., 09121234567)', }, message: { type: 'string', description: 'Message content', }, lineNumber: { type: 'string', description: 'Sender line number (optional)', }, sendDateTime: { type: 'string', description: 'Scheduled date and time for sending the message (optional, ISO format)', }, }, required: ['mobile', 'message'], }, }, { name: 'send_bulk_sms', description: 'Send the same SMS message to multiple recipients', inputSchema: { type: 'object', properties: { mobiles: { type: 'array', items: { type: 'string', }, description: 'Array of recipient mobile numbers', }, messageText: { type: 'string', description: 'Message content to send to all recipients', }, lineNumber: { type: 'string', description: 'Sender line number (optional)', }, sendDateTime: { type: 'string', description: 'Scheduled date and time for sending the message (optional, ISO format)', }, }, required: ['mobiles', 'messageText'], }, }, { name: 'send_verification_code', description: 'Send a verification code SMS using a template', inputSchema: { type: 'object', properties: { mobile: { type: 'string', description: 'Recipient mobile number', }, templateId: { type: 'string', description: 'Template ID from SMS.ir panel', }, parameters: { type: 'array', items: { type: 'object', properties: { name: { type: 'string', description: 'Parameter name as defined in the template', }, value: { type: 'string', description: 'Parameter value to replace in the template', }, }, required: ['name', 'value'], }, description: 'Array of parameters to substitute in the template', }, }, required: ['mobile', 'templateId', 'parameters'], }, }, { name: 'check_credit', description: 'Check the remaining credit in your SMS.ir account', inputSchema: { type: 'object', properties: {}, required: [], }, }, ], })); // Handle tool calls this.server.setRequestHandler(CallToolRequestSchema, async (request) => { try { switch (request.params.name) { case 'send_sms': { return await this.handleSendSms(request.params.arguments); } case 'send_bulk_sms': { return await this.handleSendBulkSms(request.params.arguments); } case 'send_verification_code': { return await this.handleSendVerification(request.params.arguments); } case 'check_credit': { return await this.handleCheckCredit(); } default: throw { code: ErrorCode.MethodNotFound, message: `Unknown tool: ${request.params.name}` }; } } catch (error) { if (axios.isAxiosError(error)) { const statusCode = error.response?.status; const responseData = error.response?.data; return { content: [ { type: 'text', text: `SMS.ir API error (${statusCode}): ${JSON.stringify(responseData)}`, }, ], isError: true, }; } return { content: [ { type: 'text', text: `Unexpected error: ${error.message || JSON.stringify(error)}`, }, ], isError: true, }; } }); } async handleSendSms(params) { const response = await this.axiosInstance.post('/send', { mobile: params.mobile, message: params.message, lineNumber: params.lineNumber, sendDateTime: params.sendDateTime, }); return { content: [ { type: 'text', text: JSON.stringify(response.data, null, 2), }, ], }; } async handleSendBulkSms(params) { const response = await this.axiosInstance.post('/send/bulk', { lineNumber: params.lineNumber, messageText: params.messageText, mobiles: params.mobiles, sendDateTime: params.sendDateTime, }); return { content: [ { type: 'text', text: JSON.stringify(response.data, null, 2), }, ], }; } async handleSendVerification(params) { const response = await this.axiosInstance.post('/send/verify', { mobile: params.mobile, templateId: params.templateId, parameters: params.parameters, }); return { content: [ { type: 'text', text: JSON.stringify(response.data, null, 2), }, ], }; } async handleCheckCredit() { const response = await this.axiosInstance.get('/credit'); return { content: [ { type: 'text', text: JSON.stringify(response.data, null, 2), }, ], }; } async run() { const transport = new StdioServerTransport(); await this.server.connect(transport); console.error('SMS.ir MCP server running on stdio'); } } // Create and run server const server = new SmsIrServer(API_KEY); await server.run(); } catch (error) { console.error('Failed to start SMS.ir MCP server:', error); process.exit(1); } }; // Run the main function main().catch(console.error);