estimate_sms_cost
Calculate SMS pricing and message segmentation before sending, using recipient number and message content to provide cost estimates.
Instructions
Estimate cost and message segments for SMS without sending it
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| from | No | Sender phone number or name (optional, uses default if not specified) | |
| message | Yes | SMS message content to estimate cost for | |
| to | Yes | Recipient phone number with country code (e.g., +46XXXXXXXXX for Swedish numbers) |
Implementation Reference
- src/index.ts:273-324 (handler)Main execution logic for the 'estimate_sms_cost' tool: input validation, dry-run API call via ElksClient for estimation, segment calculation, and formatted response generation.case 'estimate_sms_cost': const { to: estimateTo, message: estimateMessage, from: estimateFrom } = args as { to: string; message: string; from?: string; }; // Validate inputs handleValidationError('phone number', validatePhoneNumber(estimateTo)); const estimateMessageValidation = validateSmsMessage(estimateMessage); handleValidationError('message', estimateMessageValidation); if (estimateFrom) { handleValidationError('sender ID', validateSenderId(estimateFrom)); } // Use dry run to get cost estimate const elksClientForEstimate = new ElksClient(); const estimateResponse = await elksClientForEstimate.sendSms(estimateTo, estimateMessage, estimateFrom, true); const estimatedCost = estimateResponse.estimated_cost ? estimateResponse.estimated_cost / 10000 : 0; const messageLength = estimateMessage.length; const segments = estimateResponse.parts || (messageLength <= 160 ? 1 : Math.ceil(messageLength / 153)); let costEstimateText = `💰 SMS Cost Estimate\n\n`; costEstimateText += `To: ${estimateTo}\n`; costEstimateText += `From: ${estimateResponse.from}\n`; costEstimateText += `Message length: ${messageLength} characters\n`; costEstimateText += `Message segments: ${segments}\n`; costEstimateText += `Estimated cost: ${estimatedCost.toFixed(2)} SEK\n\n`; if (segments > 1) { costEstimateText += `⚠️ Multi-part SMS: This message will be sent as ${segments} parts\n`; costEstimateText += `💡 Tip: Consider shortening to ≤160 characters for single SMS\n\n`; } costEstimateText += `📝 Message preview:\n"${estimateMessage}"\n\n`; // Add validation warning if present if (estimateMessageValidation.warning) { costEstimateText += `${estimateMessageValidation.warning}\n\n`; } costEstimateText += `🧪 This was an estimate only - no SMS was sent`; return { content: [ { type: 'text', text: costEstimateText } ] };
- src/index.ts:109-130 (schema)Input schema and metadata for the 'estimate_sms_cost' tool, defined in the ListTools response.{ name: 'estimate_sms_cost', description: 'Estimate cost and message segments for SMS without sending it', inputSchema: { type: 'object', properties: { to: { type: 'string', description: 'Recipient phone number with country code (e.g., +46XXXXXXXXX for Swedish numbers)' }, message: { type: 'string', description: 'SMS message content to estimate cost for' }, from: { type: 'string', description: 'Sender phone number or name (optional, uses default if not specified)' } }, required: ['to', 'message'] } },
- src/index.ts:32-149 (registration)Registration of all tools including 'estimate_sms_cost' via the ListToolsRequestHandler.server.setRequestHandler(ListToolsRequestSchema, async () => { return { tools: [ { name: 'send_sms', description: 'Send SMS message via 46elks', inputSchema: { type: 'object', properties: { to: { type: 'string', description: 'Recipient phone number with country code - MUST be a real phone number, not a placeholder (e.g., +46XXXXXXXXX for Swedish numbers)' }, message: { type: 'string', description: 'SMS message content (max 160 characters for single SMS)' }, from: { type: 'string', description: 'Sender phone number or name (optional, uses default if not specified)' }, flashsms: { type: 'string', description: 'Set to "yes" for flash SMS that displays immediately and is not stored (optional)' }, dry_run: { type: 'boolean', description: 'Test mode - verify request without sending actual SMS (optional, defaults to environment setting)' } }, required: ['to', 'message'] } }, { name: 'get_sms_messages', description: 'Retrieve SMS message history from 46elks', inputSchema: { type: 'object', properties: { limit: { type: 'number', description: 'Maximum number of messages to retrieve (default: 10, max: 100)', minimum: 1, maximum: 100 }, direction: { type: 'string', enum: ['inbound', 'outbound', 'both'], description: 'Filter messages by direction (default: both)' } }, required: [] } }, { name: 'check_sms_status', description: 'Check delivery status and details of a sent SMS', inputSchema: { type: 'object', properties: { message_id: { type: 'string', description: '46elks message ID returned when SMS was sent' } }, required: ['message_id'] } }, { name: 'check_account_balance', description: 'Check 46elks account balance and account information to verify funds availability for SMS sending', inputSchema: { type: 'object', properties: {}, required: [] } }, { name: 'estimate_sms_cost', description: 'Estimate cost and message segments for SMS without sending it', inputSchema: { type: 'object', properties: { to: { type: 'string', description: 'Recipient phone number with country code (e.g., +46XXXXXXXXX for Swedish numbers)' }, message: { type: 'string', description: 'SMS message content to estimate cost for' }, from: { type: 'string', description: 'Sender phone number or name (optional, uses default if not specified)' } }, required: ['to', 'message'] } }, { name: 'get_delivery_statistics', description: 'Get SMS delivery statistics and success rates from recent messages', inputSchema: { type: 'object', properties: { limit: { type: 'number', description: 'Number of recent messages to analyze for statistics (default: 50, max: 100)', minimum: 10, maximum: 100 } }, required: [] } } ] }; });
- src/elks-client.ts:110-143 (helper)ElksClient.sendSms method that implements dry-run mode (dryrun=yes) for cost estimation without sending actual SMS, used by the tool handler.async sendSms(to: string, message: string, from?: string, dryRun?: boolean, flashsms?: string): Promise<SendSmsResponse> { const formData = new URLSearchParams({ to, message, from: from || this.phoneNumber }); // Add dry run parameter if enabled const isDryRun = dryRun !== undefined ? dryRun : this.dryRun; if (isDryRun) { formData.append('dryrun', 'yes'); } // Add flash SMS parameter if specified if (flashsms === 'yes') { formData.append('flashsms', 'yes'); } const response = await fetch(`${this.baseUrl}/sms`, { method: 'POST', headers: { 'Authorization': this.auth, 'Content-Type': 'application/x-www-form-urlencoded' }, body: formData }); if (!response.ok) { const errorText = await response.text(); throw new Error(`Failed to send SMS: ${response.status} ${response.statusText} - ${errorText}`); } return await response.json(); }