Twilio Messaging MCP Server
by deshartman
Verified
#!/usr/bin/env node
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";
import { TwilioMessagingServer } from "./servers/TwilioMessagingServer.js";
import { logOut, logError } from "./utils/logger.js";
// Get configuration parameters from the command line arguments
/****************************************************
*
* Twilio API Credentials
*
****************************************************/
// NOTE: we are enforcing use of API Keys here instead of Auth Token, as it is a better posture for message level sends
const accountSid = process.argv[2] || '';
const apiKey = process.argv[3] || '';
const apiSecret = process.argv[4] || '';
const number = process.argv[5] || '';
// Validate required configuration
if (!accountSid || !apiKey || !apiSecret || !number) {
logError("TwilioMessagingServer", "Missing required configuration parameters");
console.error("Usage: twilio-messaging-mcp-server <accountSid> <apiKey> <apiSecret> <number>");
process.exit(1);
}
// Validate Twilio Account SID format
if (!accountSid.startsWith('AC')) {
logError("TwilioMessagingServer", "Invalid Account SID format. Twilio Account SID must start with 'AC'");
console.error("Error: Account SID must start with 'AC'");
process.exit(1);
}
// Create Twilio service with provided credentials
const twilioMessagingServer = new TwilioMessagingServer(
accountSid,
apiKey,
apiSecret,
number
);
/****************************************************
*
* MCP server
*
****************************************************/
// Server configuration with clear naming for the messaging service
const SERVER_CONFIG = {
name: "TwilioMessagingServer",
description: "MCP server for sending SMS messages via Twilio API",
version: "1.0.0"
};
const mcpServer = new McpServer(SERVER_CONFIG);
// Register the SMS sending tool
mcpServer.tool(
"send-sms",
"Send an SMS message via Twilio",
{
to: z.string().describe("Destination phone number in +E.164 format (+XXXXXXXXXX)"),
message: z.string().describe("Message content to send")
},
async ({ to, message }) => {
try {
const response = await twilioMessagingServer.sendSMS(to, message);
const sid = response?.sid;
if (sid) {
return {
content: [{
type: "text",
text: `Message sent successfully. SID: ${sid}`
}]
};
} else {
return {
content: [{
type: "text",
text: "Failed to send message. Check logs for details."
}],
isError: true
};
}
} catch (error) {
const errorMessage = error instanceof Error ? error.message : String(error);
logError("TwilioMessagingServer", `Error sending SMS: ${errorMessage}`);
return {
content: [{
type: "text",
text: `Error sending message: ${errorMessage}`
}],
isError: true
};
}
}
);
// Start the server
async function main() {
try {
const transport = new StdioServerTransport();
await mcpServer.connect(transport);
logOut("TwilioMessagingServer", "Server started successfully");
} catch (error) {
logError("TwilioMessagingServer", `Error starting server: ${error}`);
process.exit(1);
}
}
// Handle clean shutdown
process.on("SIGINT", async () => {
logOut("TwilioMessagingServer", "Shutting down...");
await mcpServer.close();
process.exit(0);
});
// Start the server
main().catch(error => {
logError("TwilioMessagingServer", `Fatal error: ${error}`);
process.exit(1);
});