🚀 Socket Launch Week Day 5:Introducing Repository Access Permissions and Custom Roles.Learn more
Sign In

@sendly/mcp

Package Overview
Dependencies
Maintainers
1
Versions
11
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@sendly/mcp - npm Package Compare versions

Comparing version
1.1.0
to
1.2.0
+71
-1
dist/index.js

@@ -7,2 +7,3 @@ #!/usr/bin/env node

import { z } from "zod";
var VERSION = "1.2.0";
var API_KEY = process.env.SENDLY_API_KEY;

@@ -16,3 +17,26 @@ var BASE_URL = process.env.SENDLY_BASE_URL || "https://sendly.live";

}
if (!BASE_URL.startsWith("https://") && !BASE_URL.startsWith("http://localhost") && !BASE_URL.startsWith("http://127.0.0.1")) {
process.stderr.write(
"SENDLY_BASE_URL must use HTTPS in production.\nHTTP is only allowed for localhost development.\n"
);
process.exit(1);
}
var RATE_LIMIT_WINDOW_MS = 6e4;
var RATE_LIMIT_MAX = 30;
var rateLimitTokens = RATE_LIMIT_MAX;
var rateLimitResetAt = Date.now() + RATE_LIMIT_WINDOW_MS;
function checkRateLimit() {
const now = Date.now();
if (now >= rateLimitResetAt) {
rateLimitTokens = RATE_LIMIT_MAX;
rateLimitResetAt = now + RATE_LIMIT_WINDOW_MS;
}
if (rateLimitTokens <= 0) return false;
rateLimitTokens--;
return true;
}
async function api(method, path, body, query) {
if (!checkRateLimit()) {
throw new Error("Rate limited \u2014 too many requests. Wait a moment and try again.");
}
const url = new URL(`/api/v1${path}`, BASE_URL);

@@ -34,2 +58,8 @@ if (query) {

if (res.status === 204) return { success: true };
if (res.status === 429) {
const retryAfter = res.headers.get("Retry-After");
throw new Error(
`Rate limited by API. ${retryAfter ? `Retry after ${retryAfter} seconds.` : "Wait a moment and try again."}`
);
}
const data = await res.json();

@@ -56,3 +86,3 @@ if (!res.ok) {

name: "sendly",
version: "1.0.0"
version: VERSION
});

@@ -171,2 +201,21 @@ server.tool(

server.tool(
"get_conversation_context",
"Get LLM-ready formatted conversation context. Returns a pre-formatted text string with timestamped messages, AI classification, and business context \u2014 ready to paste into a prompt. More efficient than get_conversation for AI agents.",
{
conversationId: z.string().describe("The conversation ID"),
maxMessages: z.number().optional().describe("Max messages to include (default 20, max 50)")
},
async ({ conversationId, maxMessages }) => {
try {
return ok(
await api("GET", `/conversations/${conversationId}/context`, void 0, {
max_messages: maxMessages?.toString()
})
);
} catch (e) {
return err(e);
}
}
);
server.tool(
"get_conversation",

@@ -489,3 +538,24 @@ "Get a conversation thread by ID. Set includeMessages=true to load the message history.",

);
server.tool(
"generate_business_page",
"Generate a hosted business landing page for verification. Use when a business doesn't have their own website. Returns a URL at sendly.live/biz/{slug} that satisfies carrier website requirements.",
{
businessName: z.string().describe("Business name"),
useCase: z.string().optional().describe("Use case (e.g., Insurance Services, Appointment Reminders, 2FA)"),
useCaseSummary: z.string().optional().describe("Brief description of what the business does"),
contactEmail: z.string().optional().describe("Business contact email"),
contactPhone: z.string().optional().describe("Business phone number"),
businessAddress: z.string().optional().describe("City, State ZIP (e.g., Chicago, IL 60601)")
},
async (params) => {
try {
return ok(
await api("POST", "/enterprise/business-page/generate", params)
);
} catch (e) {
return err(e);
}
}
);
var transport = new StdioServerTransport();
await server.connect(transport);
+1
-1
{
"name": "@sendly/mcp",
"version": "1.1.0",
"version": "1.2.0",
"description": "Sendly MCP Server — SMS for AI agents. Send messages, manage conversations, verify phone numbers.",

@@ -5,0 +5,0 @@ "type": "module",