@smsmasivos/mcp-server 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/README.md +86 -0
  2. package/dist/api-client.d.ts +7 -0
  3. package/dist/api-client.js +69 -0
  4. package/dist/api-client.js.map +1 -0
  5. package/dist/errors.d.ts +30 -0
  6. package/dist/errors.js +61 -0
  7. package/dist/errors.js.map +1 -0
  8. package/dist/schemas.d.ts +117 -0
  9. package/dist/schemas.js +69 -0
  10. package/dist/schemas.js.map +1 -0
  11. package/dist/stdio.d.ts +2 -0
  12. package/dist/stdio.js +22 -0
  13. package/dist/stdio.js.map +1 -0
  14. package/dist/tools/add-contact.d.ts +3 -0
  15. package/dist/tools/add-contact.js +23 -0
  16. package/dist/tools/add-contact.js.map +1 -0
  17. package/dist/tools/check-balance.d.ts +3 -0
  18. package/dist/tools/check-balance.js +22 -0
  19. package/dist/tools/check-balance.js.map +1 -0
  20. package/dist/tools/check-verification.d.ts +3 -0
  21. package/dist/tools/check-verification.js +22 -0
  22. package/dist/tools/check-verification.js.map +1 -0
  23. package/dist/tools/get-campaign-stats.d.ts +3 -0
  24. package/dist/tools/get-campaign-stats.js +25 -0
  25. package/dist/tools/get-campaign-stats.js.map +1 -0
  26. package/dist/tools/get-contacts.d.ts +3 -0
  27. package/dist/tools/get-contacts.js +22 -0
  28. package/dist/tools/get-contacts.js.map +1 -0
  29. package/dist/tools/index.d.ts +3 -0
  30. package/dist/tools/index.js +19 -0
  31. package/dist/tools/index.js.map +1 -0
  32. package/dist/tools/list-agendas.d.ts +3 -0
  33. package/dist/tools/list-agendas.js +22 -0
  34. package/dist/tools/list-agendas.js.map +1 -0
  35. package/dist/tools/send-sms.d.ts +3 -0
  36. package/dist/tools/send-sms.js +25 -0
  37. package/dist/tools/send-sms.js.map +1 -0
  38. package/dist/tools/verify-phone.d.ts +3 -0
  39. package/dist/tools/verify-phone.js +22 -0
  40. package/dist/tools/verify-phone.js.map +1 -0
  41. package/package.json +48 -0
package/README.md ADDED
@@ -0,0 +1,86 @@
1
+ # @smsmasivos/mcp-server
2
+
3
+ MCP server para [SMS Masivos](https://www.smsmasivos.com.mx) — plataforma de SMS masivos para Mexico y LATAM.
4
+
5
+ Permite a Claude, Cursor, Windsurf y cualquier MCP client enviar SMS, consultar creditos, gestionar contactos y verificar numeros de telefono usando lenguaje natural.
6
+
7
+ ## Instalacion
8
+
9
+ ```bash
10
+ npm install -g @smsmasivos/mcp-server
11
+ ```
12
+
13
+ O ejecutar directamente:
14
+
15
+ ```bash
16
+ npx @smsmasivos/mcp-server
17
+ ```
18
+
19
+ ## Configuracion
20
+
21
+ Necesitas una API key de SMS Masivos. Obtenla en tu panel: https://app.smsmasivos.com.mx
22
+
23
+ ### Claude Desktop
24
+
25
+ Agrega esto a tu configuracion de Claude Desktop (`~/Library/Application Support/Claude/claude_desktop_config.json` en Mac):
26
+
27
+ ```json
28
+ {
29
+ "mcpServers": {
30
+ "smsmasivos": {
31
+ "command": "npx",
32
+ "args": ["-y", "@smsmasivos/mcp-server"],
33
+ "env": {
34
+ "SMSMASIVOS_API_KEY": "tu-api-key-aqui"
35
+ }
36
+ }
37
+ }
38
+ }
39
+ ```
40
+
41
+ ### Claude Code
42
+
43
+ ```bash
44
+ SMSMASIVOS_API_KEY=tu-api-key npx @smsmasivos/mcp-server
45
+ ```
46
+
47
+ ### Cursor / Windsurf
48
+
49
+ Agrega el MCP server en la configuracion de tu editor con los mismos parametros.
50
+
51
+ ## Tools disponibles
52
+
53
+ | Tool | Descripcion |
54
+ |------|-------------|
55
+ | `check_balance` | Consulta creditos SMS disponibles |
56
+ | `send_sms` | Envia SMS a uno o varios numeros (max 500) |
57
+ | `list_agendas` | Lista tus agendas (listas de contactos) |
58
+ | `get_contacts` | Obtiene contactos de una agenda |
59
+ | `add_contact` | Agrega contacto a una agenda |
60
+ | `get_campaign_stats` | Estadisticas de entrega de una campana |
61
+ | `verify_phone` | Inicia verificacion OTP por SMS/voz/WhatsApp |
62
+ | `check_verification` | Verifica codigo OTP |
63
+
64
+ ## Ejemplos
65
+
66
+ Una vez configurado, puedes pedirle a Claude:
67
+
68
+ - "Cuantos creditos me quedan?"
69
+ - "Envia un SMS al 5512345678 con el texto: Tu cita es manana a las 10am"
70
+ - "Muestrame mis agendas de contactos"
71
+ - "Como fue la entrega de mi campana 12345?"
72
+ - "Verifica el numero 5598765432 por SMS"
73
+
74
+ ## Desarrollo
75
+
76
+ ```bash
77
+ git clone https://github.com/SMS-Masivos/mcp-server.git
78
+ cd mcp-server
79
+ npm install
80
+ npm run build
81
+ npm test
82
+ ```
83
+
84
+ ## Licencia
85
+
86
+ MIT
@@ -0,0 +1,7 @@
1
+ export interface ApiClientConfig {
2
+ apiKey: string;
3
+ baseUrl?: string;
4
+ timeout?: number;
5
+ }
6
+ export type ApiCall = <T>(endpoint: string, params?: Record<string, unknown>) => Promise<T>;
7
+ export declare function createApiClient(config: ApiClientConfig): ApiCall;
@@ -0,0 +1,69 @@
1
+ import { SmsmasivosError, AuthError, RateLimitError, NetworkError, TimeoutError, } from "./errors.js";
2
+ const DEFAULT_BASE_URL = "https://api.smsmasivos.com.mx";
3
+ const DEFAULT_TIMEOUT = 30_000;
4
+ export function createApiClient(config) {
5
+ const baseUrl = config.baseUrl ?? DEFAULT_BASE_URL;
6
+ const timeout = config.timeout ?? DEFAULT_TIMEOUT;
7
+ async function apiCall(endpoint, params) {
8
+ return executeWithRetry(baseUrl, endpoint, config.apiKey, timeout, params);
9
+ }
10
+ return apiCall;
11
+ }
12
+ async function executeWithRetry(baseUrl, endpoint, apiKey, timeout, params, attempt = 1) {
13
+ const controller = new AbortController();
14
+ const timer = setTimeout(() => controller.abort(), timeout);
15
+ try {
16
+ const response = await fetch(`${baseUrl}${endpoint}`, {
17
+ method: "POST",
18
+ headers: {
19
+ "Content-Type": "application/json",
20
+ apikey: apiKey,
21
+ },
22
+ body: JSON.stringify(params ?? {}),
23
+ signal: controller.signal,
24
+ });
25
+ clearTimeout(timer);
26
+ if (response.status === 401) {
27
+ throw new AuthError();
28
+ }
29
+ if (response.status === 429) {
30
+ if (attempt < 2) {
31
+ const retryAfter = parseInt(response.headers.get("Retry-After") ?? "2", 10);
32
+ await sleep(retryAfter * 1000);
33
+ return executeWithRetry(baseUrl, endpoint, apiKey, timeout, params, attempt + 1);
34
+ }
35
+ throw new RateLimitError();
36
+ }
37
+ let body;
38
+ try {
39
+ body = (await response.json());
40
+ }
41
+ catch {
42
+ throw new NetworkError("Respuesta inválida de la API (JSON malformado)");
43
+ }
44
+ if (body.success === false) {
45
+ throw SmsmasivosError.fromApiResponse(body);
46
+ }
47
+ return body;
48
+ }
49
+ catch (error) {
50
+ clearTimeout(timer);
51
+ if (error instanceof SmsmasivosError) {
52
+ throw error;
53
+ }
54
+ if (error instanceof DOMException && error.name === "AbortError") {
55
+ if (attempt < 2) {
56
+ return executeWithRetry(baseUrl, endpoint, apiKey, timeout, params, attempt + 1);
57
+ }
58
+ throw new TimeoutError();
59
+ }
60
+ if (error instanceof TypeError) {
61
+ throw new NetworkError(error.message);
62
+ }
63
+ throw new NetworkError(String(error));
64
+ }
65
+ }
66
+ function sleep(ms) {
67
+ return new Promise((resolve) => setTimeout(resolve, ms));
68
+ }
69
+ //# sourceMappingURL=api-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-client.js","sourceRoot":"","sources":["../src/api-client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ export declare class SmsmasivosError extends Error {
2
+ code: string;
3
+ statusCode: number;
4
+ constructor(message: string, code: string, statusCode?: number);
5
+ static fromApiResponse(body: {
6
+ success: boolean;
7
+ message?: string;
8
+ code?: string;
9
+ status?: number;
10
+ }): SmsmasivosError;
11
+ }
12
+ export declare class AuthError extends SmsmasivosError {
13
+ constructor(message?: string);
14
+ }
15
+ export declare class InsufficientCreditsError extends SmsmasivosError {
16
+ constructor(message?: string);
17
+ }
18
+ export declare class ValidationError extends SmsmasivosError {
19
+ constructor(message: string, code?: string);
20
+ }
21
+ export declare class RateLimitError extends SmsmasivosError {
22
+ retryAfter?: number;
23
+ constructor(retryAfter?: number);
24
+ }
25
+ export declare class NetworkError extends SmsmasivosError {
26
+ constructor(message?: string);
27
+ }
28
+ export declare class TimeoutError extends NetworkError {
29
+ constructor(message?: string);
30
+ }
package/dist/errors.js ADDED
@@ -0,0 +1,61 @@
1
+ export class SmsmasivosError extends Error {
2
+ code;
3
+ statusCode;
4
+ constructor(message, code, statusCode = 200) {
5
+ super(message);
6
+ this.name = "SmsmasivosError";
7
+ this.code = code;
8
+ this.statusCode = statusCode;
9
+ }
10
+ static fromApiResponse(body) {
11
+ const message = body.message ?? "Unknown API error";
12
+ const code = body.code ?? "unknown";
13
+ if (code === "auth_01" || body.status === 401) {
14
+ return new AuthError(message);
15
+ }
16
+ if (code === "sms_06") {
17
+ return new InsufficientCreditsError(message);
18
+ }
19
+ return new ValidationError(message, code);
20
+ }
21
+ }
22
+ export class AuthError extends SmsmasivosError {
23
+ constructor(message = "API key inválida o expirada") {
24
+ super(message, "auth_01", 401);
25
+ this.name = "AuthError";
26
+ }
27
+ }
28
+ export class InsufficientCreditsError extends SmsmasivosError {
29
+ constructor(message = "Créditos insuficientes") {
30
+ super(message, "sms_06", 402);
31
+ this.name = "InsufficientCreditsError";
32
+ }
33
+ }
34
+ export class ValidationError extends SmsmasivosError {
35
+ constructor(message, code = "validation") {
36
+ super(message, code);
37
+ this.name = "ValidationError";
38
+ }
39
+ }
40
+ export class RateLimitError extends SmsmasivosError {
41
+ retryAfter;
42
+ constructor(retryAfter) {
43
+ super("Rate limit excedido. Intenta de nuevo en unos segundos.", "rate_limit", 429);
44
+ this.name = "RateLimitError";
45
+ this.retryAfter = retryAfter;
46
+ }
47
+ }
48
+ export class NetworkError extends SmsmasivosError {
49
+ constructor(message = "Error de conexión con la API") {
50
+ super(message, "network_error", 0);
51
+ this.name = "NetworkError";
52
+ }
53
+ }
54
+ export class TimeoutError extends NetworkError {
55
+ constructor(message = "La solicitud excedió el tiempo de espera") {
56
+ super(message);
57
+ this.name = "TimeoutError";
58
+ this.code = "timeout";
59
+ }
60
+ }
61
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,eAAgB,SAAQ,KAAK;IACxC,IAAI,CAAS;IACb,UAAU,CAAS;IAEnB,YAAY,OAAe,EAAE,IAAY,EAAE,aAAqB,GAAG;QACjE,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;QAC9B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;IAC/B,CAAC;IAED,MAAM,CAAC,eAAe,CAAC,IAKtB;QACC,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,mBAAmB,CAAC;QACpD,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,SAAS,CAAC;QAEpC,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;YAC9C,OAAO,IAAI,SAAS,CAAC,OAAO,CAAC,CAAC;QAChC,CAAC;QACD,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;YACtB,OAAO,IAAI,wBAAwB,CAAC,OAAO,CAAC,CAAC;QAC/C,CAAC;QACD,OAAO,IAAI,eAAe,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IAC5C,CAAC;CACF;AAED,MAAM,OAAO,SAAU,SAAQ,eAAe;IAC5C,YAAY,UAAkB,6BAA6B;QACzD,KAAK,CAAC,OAAO,EAAE,SAAS,EAAE,GAAG,CAAC,CAAC;QAC/B,IAAI,CAAC,IAAI,GAAG,WAAW,CAAC;IAC1B,CAAC;CACF;AAED,MAAM,OAAO,wBAAyB,SAAQ,eAAe;IAC3D,YAAY,UAAkB,wBAAwB;QACpD,KAAK,CAAC,OAAO,EAAE,QAAQ,EAAE,GAAG,CAAC,CAAC;QAC9B,IAAI,CAAC,IAAI,GAAG,0BAA0B,CAAC;IACzC,CAAC;CACF;AAED,MAAM,OAAO,eAAgB,SAAQ,eAAe;IAClD,YAAY,OAAe,EAAE,OAAe,YAAY;QACtD,KAAK,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;QACrB,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;IAChC,CAAC;CACF;AAED,MAAM,OAAO,cAAe,SAAQ,eAAe;IACjD,UAAU,CAAU;IAEpB,YAAY,UAAmB;QAC7B,KAAK,CAAC,yDAAyD,EAAE,YAAY,EAAE,GAAG,CAAC,CAAC;QACpF,IAAI,CAAC,IAAI,GAAG,gBAAgB,CAAC;QAC7B,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;IAC/B,CAAC;CACF;AAED,MAAM,OAAO,YAAa,SAAQ,eAAe;IAC/C,YAAY,UAAkB,8BAA8B;QAC1D,KAAK,CAAC,OAAO,EAAE,eAAe,EAAE,CAAC,CAAC,CAAC;QACnC,IAAI,CAAC,IAAI,GAAG,cAAc,CAAC;IAC7B,CAAC;CACF;AAED,MAAM,OAAO,YAAa,SAAQ,YAAY;IAC5C,YAAY,UAAkB,0CAA0C;QACtE,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,cAAc,CAAC;QAC3B,IAAI,CAAC,IAAI,GAAG,SAAS,CAAC;IACxB,CAAC;CACF"}
@@ -0,0 +1,117 @@
1
+ import { z } from "zod";
2
+ export declare const checkBalanceInput: z.ZodObject<{}, "strip", z.ZodTypeAny, {}, {}>;
3
+ export declare const sendSmsInput: z.ZodObject<{
4
+ numbers: z.ZodEffects<z.ZodString, string, string>;
5
+ message: z.ZodString;
6
+ country_code: z.ZodDefault<z.ZodString>;
7
+ sandbox: z.ZodOptional<z.ZodEnum<["0", "1"]>>;
8
+ sender: z.ZodOptional<z.ZodString>;
9
+ date: z.ZodOptional<z.ZodString>;
10
+ shorten_url: z.ZodOptional<z.ZodEnum<["0", "1"]>>;
11
+ flash: z.ZodOptional<z.ZodEnum<["0", "1"]>>;
12
+ }, "strip", z.ZodTypeAny, {
13
+ message: string;
14
+ numbers: string;
15
+ country_code: string;
16
+ date?: string | undefined;
17
+ sandbox?: "0" | "1" | undefined;
18
+ sender?: string | undefined;
19
+ shorten_url?: "0" | "1" | undefined;
20
+ flash?: "0" | "1" | undefined;
21
+ }, {
22
+ message: string;
23
+ numbers: string;
24
+ date?: string | undefined;
25
+ country_code?: string | undefined;
26
+ sandbox?: "0" | "1" | undefined;
27
+ sender?: string | undefined;
28
+ shorten_url?: "0" | "1" | undefined;
29
+ flash?: "0" | "1" | undefined;
30
+ }>;
31
+ export declare const listAgendasInput: z.ZodObject<{}, "strip", z.ZodTypeAny, {}, {}>;
32
+ export declare const getContactsInput: z.ZodObject<{
33
+ list_key: z.ZodString;
34
+ }, "strip", z.ZodTypeAny, {
35
+ list_key: string;
36
+ }, {
37
+ list_key: string;
38
+ }>;
39
+ export declare const addContactInput: z.ZodObject<{
40
+ list_key: z.ZodString;
41
+ number: z.ZodString;
42
+ name: z.ZodOptional<z.ZodString>;
43
+ email: z.ZodOptional<z.ZodString>;
44
+ country_code: z.ZodDefault<z.ZodOptional<z.ZodString>>;
45
+ custom_field_1: z.ZodOptional<z.ZodString>;
46
+ custom_field_2: z.ZodOptional<z.ZodString>;
47
+ custom_field_3: z.ZodOptional<z.ZodString>;
48
+ custom_field_4: z.ZodOptional<z.ZodString>;
49
+ birthday_date: z.ZodOptional<z.ZodString>;
50
+ }, "strip", z.ZodTypeAny, {
51
+ number: string;
52
+ country_code: string;
53
+ list_key: string;
54
+ name?: string | undefined;
55
+ email?: string | undefined;
56
+ custom_field_1?: string | undefined;
57
+ custom_field_2?: string | undefined;
58
+ custom_field_3?: string | undefined;
59
+ custom_field_4?: string | undefined;
60
+ birthday_date?: string | undefined;
61
+ }, {
62
+ number: string;
63
+ list_key: string;
64
+ country_code?: string | undefined;
65
+ name?: string | undefined;
66
+ email?: string | undefined;
67
+ custom_field_1?: string | undefined;
68
+ custom_field_2?: string | undefined;
69
+ custom_field_3?: string | undefined;
70
+ custom_field_4?: string | undefined;
71
+ birthday_date?: string | undefined;
72
+ }>;
73
+ export declare const getCampaignStatsInput: z.ZodObject<{
74
+ campaign_id: z.ZodString;
75
+ sandbox: z.ZodOptional<z.ZodEnum<["0", "1"]>>;
76
+ }, "strip", z.ZodTypeAny, {
77
+ campaign_id: string;
78
+ sandbox?: "0" | "1" | undefined;
79
+ }, {
80
+ campaign_id: string;
81
+ sandbox?: "0" | "1" | undefined;
82
+ }>;
83
+ export declare const verifyPhoneInput: z.ZodObject<{
84
+ phone_number: z.ZodString;
85
+ country_code: z.ZodDefault<z.ZodString>;
86
+ code_type: z.ZodOptional<z.ZodEnum<["numeric", "alphanumeric"]>>;
87
+ expiration_date: z.ZodOptional<z.ZodString>;
88
+ voice: z.ZodOptional<z.ZodEnum<["0", "1"]>>;
89
+ whatsapp: z.ZodOptional<z.ZodEnum<["0", "1"]>>;
90
+ }, "strip", z.ZodTypeAny, {
91
+ country_code: string;
92
+ phone_number: string;
93
+ code_type?: "numeric" | "alphanumeric" | undefined;
94
+ expiration_date?: string | undefined;
95
+ voice?: "0" | "1" | undefined;
96
+ whatsapp?: "0" | "1" | undefined;
97
+ }, {
98
+ phone_number: string;
99
+ country_code?: string | undefined;
100
+ code_type?: "numeric" | "alphanumeric" | undefined;
101
+ expiration_date?: string | undefined;
102
+ voice?: "0" | "1" | undefined;
103
+ whatsapp?: "0" | "1" | undefined;
104
+ }>;
105
+ export declare const checkVerificationInput: z.ZodObject<{
106
+ phone_number: z.ZodString;
107
+ country_code: z.ZodDefault<z.ZodString>;
108
+ verification_code: z.ZodString;
109
+ }, "strip", z.ZodTypeAny, {
110
+ country_code: string;
111
+ phone_number: string;
112
+ verification_code: string;
113
+ }, {
114
+ phone_number: string;
115
+ verification_code: string;
116
+ country_code?: string | undefined;
117
+ }>;
@@ -0,0 +1,69 @@
1
+ import { z } from "zod";
2
+ export const checkBalanceInput = z.object({});
3
+ export const sendSmsInput = z.object({
4
+ numbers: z
5
+ .string()
6
+ .describe("Números de teléfono separados por coma, sin código de país (ej: '5512345678,5598765432'). Máximo 500.")
7
+ .transform((val) => val.replace(/\+/g, "")),
8
+ message: z.string().min(1).describe("Texto del mensaje SMS"),
9
+ country_code: z
10
+ .string()
11
+ .default("52")
12
+ .describe("Código de país (ej: '52' para México, '1' para USA)"),
13
+ sandbox: z
14
+ .enum(["0", "1"])
15
+ .optional()
16
+ .describe("Enviar en modo sandbox (no envía realmente, no consume créditos). '1' para activar."),
17
+ sender: z.string().optional().describe("Remitente personalizado (si tu cuenta lo permite)"),
18
+ date: z
19
+ .string()
20
+ .optional()
21
+ .describe("Fecha de envío programado en formato 'YYYY-MM-DD HH:mm:ss' (hora de México)"),
22
+ shorten_url: z
23
+ .enum(["0", "1"])
24
+ .optional()
25
+ .describe("'1' para acortar automáticamente URLs en el mensaje"),
26
+ flash: z.enum(["0", "1"]).optional().describe("'1' para enviar como SMS flash (se muestra sin guardar)"),
27
+ });
28
+ export const listAgendasInput = z.object({});
29
+ export const getContactsInput = z.object({
30
+ list_key: z.string().describe("Clave única de la agenda (list_key). Obtenla con list_agendas."),
31
+ });
32
+ export const addContactInput = z.object({
33
+ list_key: z.string().describe("Clave única de la agenda donde agregar el contacto"),
34
+ number: z.string().describe("Número de teléfono del contacto (mínimo 10 dígitos)"),
35
+ name: z.string().optional().describe("Nombre del contacto"),
36
+ email: z.string().optional().describe("Email del contacto"),
37
+ country_code: z.string().optional().default("52").describe("Código de país (default: 52 México)"),
38
+ custom_field_1: z.string().optional().describe("Campo personalizado 1"),
39
+ custom_field_2: z.string().optional().describe("Campo personalizado 2"),
40
+ custom_field_3: z.string().optional().describe("Campo personalizado 3"),
41
+ custom_field_4: z.string().optional().describe("Campo personalizado 4"),
42
+ birthday_date: z.string().optional().describe("Fecha de cumpleaños en formato YYYY-MM-DD"),
43
+ });
44
+ export const getCampaignStatsInput = z.object({
45
+ campaign_id: z
46
+ .string()
47
+ .describe("ID de la campaña SMS. Obtenlo del resultado de send_sms (campo campaignId)."),
48
+ sandbox: z.enum(["0", "1"]).optional().describe("'1' si la campaña fue enviada en modo sandbox"),
49
+ });
50
+ export const verifyPhoneInput = z.object({
51
+ phone_number: z.string().describe("Número de teléfono sin código de país (ej: '5512345678')"),
52
+ country_code: z.string().default("52").describe("Código de país (default: 52 México)"),
53
+ code_type: z
54
+ .enum(["numeric", "alphanumeric"])
55
+ .optional()
56
+ .describe("Tipo de código: 'numeric' (solo dígitos) o 'alphanumeric'"),
57
+ expiration_date: z
58
+ .string()
59
+ .optional()
60
+ .describe("Fecha de expiración del código en formato 'YYYY-MM-DD HH:mm:ss'"),
61
+ voice: z.enum(["0", "1"]).optional().describe("'1' para enviar el código por llamada de voz"),
62
+ whatsapp: z.enum(["0", "1"]).optional().describe("'1' para enviar el código por WhatsApp"),
63
+ });
64
+ export const checkVerificationInput = z.object({
65
+ phone_number: z.string().describe("Número de teléfono que recibió el código"),
66
+ country_code: z.string().default("52").describe("Código de país"),
67
+ verification_code: z.string().describe("Código de verificación ingresado por el usuario"),
68
+ });
69
+ //# sourceMappingURL=schemas.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schemas.js","sourceRoot":"","sources":["../src/schemas.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/stdio.js ADDED
@@ -0,0 +1,22 @@
1
+ #!/usr/bin/env node
2
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
3
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4
+ import { createApiClient } from "./api-client.js";
5
+ import { registerAllTools } from "./tools/index.js";
6
+ const apiKey = process.env.SMSMASIVOS_API_KEY;
7
+ if (!apiKey) {
8
+ process.stderr.write("Error: La variable de entorno SMSMASIVOS_API_KEY es requerida.\n" +
9
+ "Configúrala con tu API key de SMS Masivos.\n");
10
+ process.exit(1);
11
+ }
12
+ const server = new McpServer({ name: "smsmasivos", version: "0.1.0" }, {
13
+ instructions: "Servidor MCP para SMS Masivos — plataforma de SMS masivos para México y LATAM. " +
14
+ "Usa check_balance antes de enviar SMS para verificar créditos disponibles. " +
15
+ "Usa sandbox='1' en send_sms para pruebas sin envío real. " +
16
+ "El código de país por defecto es 52 (México).",
17
+ });
18
+ const apiCall = createApiClient({ apiKey });
19
+ registerAllTools(server, apiCall);
20
+ const transport = new StdioServerTransport();
21
+ await server.connect(transport);
22
+ //# sourceMappingURL=stdio.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stdio.js","sourceRoot":"","sources":["../src/stdio.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAEpD,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC;AAE9C,IAAI,CAAC,MAAM,EAAE,CAAC;IACZ,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,kEAAkE;QAChE,8CAA8C,CACjD,CAAC;IACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,MAAM,MAAM,GAAG,IAAI,SAAS,CAC1B,EAAE,IAAI,EAAE,YAAY,EAAE,OAAO,EAAE,OAAO,EAAE,EACxC;IACE,YAAY,EACV,iFAAiF;QACjF,6EAA6E;QAC7E,2DAA2D;QAC3D,+CAA+C;CAClD,CACF,CAAC;AAEF,MAAM,OAAO,GAAG,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;AAC5C,gBAAgB,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAElC,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;AAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import type { ApiCall } from "../api-client.js";
3
+ export declare function registerAddContact(server: McpServer, apiCall: ApiCall): void;
@@ -0,0 +1,23 @@
1
+ import { addContactInput } from "../schemas.js";
2
+ import { SmsmasivosError } from "../errors.js";
3
+ export function registerAddContact(server, apiCall) {
4
+ server.tool("add_contact", "Agrega un nuevo contacto a una agenda existente en SMS Masivos. Requiere el list_key de la agenda y el número de teléfono. Si el número ya existe en la agenda, se actualiza.", addContactInput.shape, async (params) => {
5
+ try {
6
+ const result = await apiCall("/contacts/add", params);
7
+ const c = result.callback;
8
+ return {
9
+ content: [
10
+ {
11
+ type: "text",
12
+ text: `✓ Contacto agregado: ${c.name || "(sin nombre)"} — ${c.number} (ID: ${c.id})`,
13
+ },
14
+ ],
15
+ };
16
+ }
17
+ catch (error) {
18
+ const message = error instanceof SmsmasivosError ? error.message : String(error);
19
+ return { content: [{ type: "text", text: `Error: ${message}` }], isError: true };
20
+ }
21
+ });
22
+ }
23
+ //# sourceMappingURL=add-contact.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"add-contact.js","sourceRoot":"","sources":["../../src/tools/add-contact.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAW/C,MAAM,UAAU,kBAAkB,CAAC,MAAiB,EAAE,OAAgB;IACpE,MAAM,CAAC,IAAI,CACT,aAAa,EACb,+KAA+K,EAC/K,eAAe,CAAC,KAAK,EACrB,KAAK,EAAE,MAAM,EAAE,EAAE;QACf,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,OAAO,CAAqB,eAAe,EAAE,MAAM,CAAC,CAAC;YAC1E,MAAM,CAAC,GAAG,MAAM,CAAC,QAAQ,CAAC;YAC1B,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE,wBAAwB,CAAC,CAAC,IAAI,IAAI,cAAc,MAAM,CAAC,CAAC,MAAM,SAAS,CAAC,CAAC,EAAE,GAAG;qBACrF;iBACF;aACF,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,OAAO,GAAG,KAAK,YAAY,eAAe,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACjF,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,UAAU,OAAO,EAAE,EAAE,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QAC5F,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import type { ApiCall } from "../api-client.js";
3
+ export declare function registerCheckBalance(server: McpServer, apiCall: ApiCall): void;
@@ -0,0 +1,22 @@
1
+ import { checkBalanceInput } from "../schemas.js";
2
+ import { SmsmasivosError } from "../errors.js";
3
+ export function registerCheckBalance(server, apiCall) {
4
+ server.tool("check_balance", "Consulta el saldo de créditos SMS disponibles en tu cuenta de SMS Masivos. Cada SMS consume 1 crédito. Usa esta herramienta para verificar saldo antes de enviar mensajes.", checkBalanceInput.shape, async () => {
5
+ try {
6
+ const result = await apiCall("/credits/consult");
7
+ return {
8
+ content: [
9
+ {
10
+ type: "text",
11
+ text: `Créditos disponibles: ${result.credit}`,
12
+ },
13
+ ],
14
+ };
15
+ }
16
+ catch (error) {
17
+ const message = error instanceof SmsmasivosError ? error.message : String(error);
18
+ return { content: [{ type: "text", text: `Error: ${message}` }], isError: true };
19
+ }
20
+ });
21
+ }
22
+ //# sourceMappingURL=check-balance.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"check-balance.js","sourceRoot":"","sources":["../../src/tools/check-balance.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAM/C,MAAM,UAAU,oBAAoB,CAAC,MAAiB,EAAE,OAAgB;IACtE,MAAM,CAAC,IAAI,CACT,eAAe,EACf,4KAA4K,EAC5K,iBAAiB,CAAC,KAAK,EACvB,KAAK,IAAI,EAAE;QACT,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,OAAO,CAAkB,kBAAkB,CAAC,CAAC;YAClE,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE,yBAAyB,MAAM,CAAC,MAAM,EAAE;qBAC/C;iBACF;aACF,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,OAAO,GAAG,KAAK,YAAY,eAAe,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACjF,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,UAAU,OAAO,EAAE,EAAE,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QAC5F,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import type { ApiCall } from "../api-client.js";
3
+ export declare function registerCheckVerification(server: McpServer, apiCall: ApiCall): void;
@@ -0,0 +1,22 @@
1
+ import { checkVerificationInput } from "../schemas.js";
2
+ import { SmsmasivosError } from "../errors.js";
3
+ export function registerCheckVerification(server, apiCall) {
4
+ server.tool("check_verification", "Verifica un código OTP previamente enviado a un número de teléfono con verify_phone. Ingresa el mismo número, código de país y el código que el usuario recibió.", checkVerificationInput.shape, async (params) => {
5
+ try {
6
+ const result = await apiCall("/protected/json/phones/verification/check", params);
7
+ if (result.success) {
8
+ return {
9
+ content: [{ type: "text", text: "✓ Código verificado correctamente." }],
10
+ };
11
+ }
12
+ return {
13
+ content: [{ type: "text", text: `✗ Verificación fallida: ${result.message}` }],
14
+ };
15
+ }
16
+ catch (error) {
17
+ const message = error instanceof SmsmasivosError ? error.message : String(error);
18
+ return { content: [{ type: "text", text: `Error: ${message}` }], isError: true };
19
+ }
20
+ });
21
+ }
22
+ //# sourceMappingURL=check-verification.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"check-verification.js","sourceRoot":"","sources":["../../src/tools/check-verification.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAC;AACvD,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAO/C,MAAM,UAAU,yBAAyB,CAAC,MAAiB,EAAE,OAAgB;IAC3E,MAAM,CAAC,IAAI,CACT,oBAAoB,EACpB,kKAAkK,EAClK,sBAAsB,CAAC,KAAK,EAC5B,KAAK,EAAE,MAAM,EAAE,EAAE;QACf,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,OAAO,CAC1B,2CAA2C,EAC3C,MAAM,CACP,CAAC;YACF,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;gBACnB,OAAO;oBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,oCAAoC,EAAE,CAAC;iBACjF,CAAC;YACJ,CAAC;YACD,OAAO;gBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,2BAA2B,MAAM,CAAC,OAAO,EAAE,EAAE,CAAC;aACxF,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,OAAO,GAAG,KAAK,YAAY,eAAe,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACjF,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,UAAU,OAAO,EAAE,EAAE,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QAC5F,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import type { ApiCall } from "../api-client.js";
3
+ export declare function registerGetCampaignStats(server: McpServer, apiCall: ApiCall): void;
@@ -0,0 +1,25 @@
1
+ import { getCampaignStatsInput } from "../schemas.js";
2
+ import { SmsmasivosError } from "../errors.js";
3
+ export function registerGetCampaignStats(server, apiCall) {
4
+ server.tool("get_campaign_stats", "Obtiene las estadísticas de entrega de una campaña SMS por su ID. Muestra: efectividad (%), entregados, fallidos, pendientes y no cobrados. Solo funciona para campañas que ya terminaron de procesarse.", getCampaignStatsInput.shape, async (params) => {
5
+ try {
6
+ const result = await apiCall("/reports/details", params);
7
+ const d = result.details;
8
+ const lines = [
9
+ `Estadísticas de campaña ${params.campaign_id}:`,
10
+ ` Efectividad: ${d.effectiveness}%`,
11
+ ` Total mensajes: ${d.totals}`,
12
+ ` Entregados: ${d.delivered}`,
13
+ ` Fallidos: ${d.failed}`,
14
+ ` Pendientes: ${d.pending}`,
15
+ ` No cobrados: ${d.not_charged}`,
16
+ ];
17
+ return { content: [{ type: "text", text: lines.join("\n") }] };
18
+ }
19
+ catch (error) {
20
+ const message = error instanceof SmsmasivosError ? error.message : String(error);
21
+ return { content: [{ type: "text", text: `Error: ${message}` }], isError: true };
22
+ }
23
+ });
24
+ }
25
+ //# sourceMappingURL=get-campaign-stats.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-campaign-stats.js","sourceRoot":"","sources":["../../src/tools/get-campaign-stats.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAa/C,MAAM,UAAU,wBAAwB,CAAC,MAAiB,EAAE,OAAgB;IAC1E,MAAM,CAAC,IAAI,CACT,oBAAoB,EACpB,0MAA0M,EAC1M,qBAAqB,CAAC,KAAK,EAC3B,KAAK,EAAE,MAAM,EAAE,EAAE;QACf,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,OAAO,CAAwB,kBAAkB,EAAE,MAAM,CAAC,CAAC;YAChF,MAAM,CAAC,GAAG,MAAM,CAAC,OAAO,CAAC;YACzB,MAAM,KAAK,GAAG;gBACZ,2BAA2B,MAAM,CAAC,WAAW,GAAG;gBAChD,kBAAkB,CAAC,CAAC,aAAa,GAAG;gBACpC,qBAAqB,CAAC,CAAC,MAAM,EAAE;gBAC/B,iBAAiB,CAAC,CAAC,SAAS,EAAE;gBAC9B,eAAe,CAAC,CAAC,MAAM,EAAE;gBACzB,iBAAiB,CAAC,CAAC,OAAO,EAAE;gBAC5B,kBAAkB,CAAC,CAAC,WAAW,EAAE;aAClC,CAAC;YACF,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC;QAC1E,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,OAAO,GAAG,KAAK,YAAY,eAAe,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACjF,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,UAAU,OAAO,EAAE,EAAE,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QAC5F,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import type { ApiCall } from "../api-client.js";
3
+ export declare function registerGetContacts(server: McpServer, apiCall: ApiCall): void;
@@ -0,0 +1,22 @@
1
+ import { getContactsInput } from "../schemas.js";
2
+ import { SmsmasivosError } from "../errors.js";
3
+ export function registerGetContacts(server, apiCall) {
4
+ server.tool("get_contacts", "Obtiene todos los contactos de una agenda específica usando su list_key. Usa list_agendas primero para obtener el list_key.", getContactsInput.shape, async (params) => {
5
+ try {
6
+ const result = await apiCall("/agendas/get_contacts", params);
7
+ const contacts = result.result ?? [];
8
+ if (contacts.length === 0) {
9
+ return { content: [{ type: "text", text: "Esta agenda no tiene contactos." }] };
10
+ }
11
+ const lines = contacts.map((c) => `- ${c.contact_name || "(sin nombre)"}: ${c.contact_number} ${c.contact_email ? `(${c.contact_email})` : ""}`);
12
+ return {
13
+ content: [{ type: "text", text: `${contacts.length} contacto(s):\n${lines.join("\n")}` }],
14
+ };
15
+ }
16
+ catch (error) {
17
+ const message = error instanceof SmsmasivosError ? error.message : String(error);
18
+ return { content: [{ type: "text", text: `Error: ${message}` }], isError: true };
19
+ }
20
+ });
21
+ }
22
+ //# sourceMappingURL=get-contacts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-contacts.js","sourceRoot":"","sources":["../../src/tools/get-contacts.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAa/C,MAAM,UAAU,mBAAmB,CAAC,MAAiB,EAAE,OAAgB;IACrE,MAAM,CAAC,IAAI,CACT,cAAc,EACd,6HAA6H,EAC7H,gBAAgB,CAAC,KAAK,EACtB,KAAK,EAAE,MAAM,EAAE,EAAE;QACf,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,OAAO,CAAsB,uBAAuB,EAAE,MAAM,CAAC,CAAC;YACnF,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,IAAI,EAAE,CAAC;YAErC,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAC1B,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,iCAAiC,EAAE,CAAC,EAAE,CAAC;YAC3F,CAAC;YAED,MAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,CACxB,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,YAAY,IAAI,cAAc,KAAK,CAAC,CAAC,cAAc,IAAI,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,aAAa,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CACrH,CAAC;YACF,OAAO;gBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,GAAG,QAAQ,CAAC,MAAM,kBAAkB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC;aACnG,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,OAAO,GAAG,KAAK,YAAY,eAAe,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACjF,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,UAAU,OAAO,EAAE,EAAE,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QAC5F,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import type { ApiCall } from "../api-client.js";
3
+ export declare function registerAllTools(server: McpServer, apiCall: ApiCall): void;
@@ -0,0 +1,19 @@
1
+ import { registerCheckBalance } from "./check-balance.js";
2
+ import { registerSendSms } from "./send-sms.js";
3
+ import { registerListAgendas } from "./list-agendas.js";
4
+ import { registerGetContacts } from "./get-contacts.js";
5
+ import { registerAddContact } from "./add-contact.js";
6
+ import { registerGetCampaignStats } from "./get-campaign-stats.js";
7
+ import { registerVerifyPhone } from "./verify-phone.js";
8
+ import { registerCheckVerification } from "./check-verification.js";
9
+ export function registerAllTools(server, apiCall) {
10
+ registerCheckBalance(server, apiCall);
11
+ registerSendSms(server, apiCall);
12
+ registerListAgendas(server, apiCall);
13
+ registerGetContacts(server, apiCall);
14
+ registerAddContact(server, apiCall);
15
+ registerGetCampaignStats(server, apiCall);
16
+ registerVerifyPhone(server, apiCall);
17
+ registerCheckVerification(server, apiCall);
18
+ }
19
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AACnE,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,yBAAyB,EAAE,MAAM,yBAAyB,CAAC;AAEpE,MAAM,UAAU,gBAAgB,CAAC,MAAiB,EAAE,OAAgB;IAClE,oBAAoB,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACtC,eAAe,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,mBAAmB,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,mBAAmB,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,kBAAkB,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACpC,wBAAwB,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC1C,mBAAmB,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,yBAAyB,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAC7C,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import type { ApiCall } from "../api-client.js";
3
+ export declare function registerListAgendas(server: McpServer, apiCall: ApiCall): void;
@@ -0,0 +1,22 @@
1
+ import { listAgendasInput } from "../schemas.js";
2
+ import { SmsmasivosError } from "../errors.js";
3
+ export function registerListAgendas(server, apiCall) {
4
+ server.tool("list_agendas", "Lista todas las agendas (listas de contactos) de tu cuenta en SMS Masivos. Cada agenda tiene un list_key único que necesitas para obtener contactos o agregar nuevos.", listAgendasInput.shape, async () => {
5
+ try {
6
+ const result = await apiCall("/agendas/get");
7
+ const agendas = result.result ?? [];
8
+ if (agendas.length === 0) {
9
+ return { content: [{ type: "text", text: "No tienes agendas creadas." }] };
10
+ }
11
+ const lines = agendas.map((a) => `- ${a.agenda_name} (${a.agenda_description || "sin descripción"}) — key: ${a.list_key}`);
12
+ return {
13
+ content: [{ type: "text", text: `${agendas.length} agenda(s):\n${lines.join("\n")}` }],
14
+ };
15
+ }
16
+ catch (error) {
17
+ const message = error instanceof SmsmasivosError ? error.message : String(error);
18
+ return { content: [{ type: "text", text: `Error: ${message}` }], isError: true };
19
+ }
20
+ });
21
+ }
22
+ //# sourceMappingURL=list-agendas.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list-agendas.js","sourceRoot":"","sources":["../../src/tools/list-agendas.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAa/C,MAAM,UAAU,mBAAmB,CAAC,MAAiB,EAAE,OAAgB;IACrE,MAAM,CAAC,IAAI,CACT,cAAc,EACd,uKAAuK,EACvK,gBAAgB,CAAC,KAAK,EACtB,KAAK,IAAI,EAAE;QACT,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,OAAO,CAAsB,cAAc,CAAC,CAAC;YAClE,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,IAAI,EAAE,CAAC;YAEpC,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACzB,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,4BAA4B,EAAE,CAAC,EAAE,CAAC;YACtF,CAAC;YAED,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CACvB,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,WAAW,KAAK,CAAC,CAAC,kBAAkB,IAAI,iBAAiB,YAAY,CAAC,CAAC,QAAQ,EAAE,CAChG,CAAC;YACF,OAAO;gBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC,MAAM,gBAAgB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC;aAChG,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,OAAO,GAAG,KAAK,YAAY,eAAe,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACjF,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,UAAU,OAAO,EAAE,EAAE,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QAC5F,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import type { ApiCall } from "../api-client.js";
3
+ export declare function registerSendSms(server: McpServer, apiCall: ApiCall): void;
@@ -0,0 +1,25 @@
1
+ import { sendSmsInput } from "../schemas.js";
2
+ import { SmsmasivosError } from "../errors.js";
3
+ export function registerSendSms(server, apiCall) {
4
+ server.tool("send_sms", "Envía uno o varios mensajes SMS a través de SMS Masivos. Requiere números de teléfono (separados por coma, máximo 500), texto del mensaje y código de país. Usa sandbox='1' para pruebas sin envío real. El código de país por defecto es 52 (México).", sendSmsInput.shape, async (params) => {
5
+ try {
6
+ const result = await apiCall("/sms/send", {
7
+ ...params,
8
+ showCampaignId: "true",
9
+ });
10
+ const lines = [
11
+ `✓ ${result.total_messages} mensaje(s) enviado(s)`,
12
+ `Créditos restantes: ${result.credit}`,
13
+ ];
14
+ if (result.campaignId) {
15
+ lines.push(`ID de campaña: ${result.campaignId} (úsalo con get_campaign_stats para ver resultados)`);
16
+ }
17
+ return { content: [{ type: "text", text: lines.join("\n") }] };
18
+ }
19
+ catch (error) {
20
+ const message = error instanceof SmsmasivosError ? error.message : String(error);
21
+ return { content: [{ type: "text", text: `Error: ${message}` }], isError: true };
22
+ }
23
+ });
24
+ }
25
+ //# sourceMappingURL=send-sms.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"send-sms.js","sourceRoot":"","sources":["../../src/tools/send-sms.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAS/C,MAAM,UAAU,eAAe,CAAC,MAAiB,EAAE,OAAgB;IACjE,MAAM,CAAC,IAAI,CACT,UAAU,EACV,wPAAwP,EACxP,YAAY,CAAC,KAAK,EAClB,KAAK,EAAE,MAAM,EAAE,EAAE;QACf,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,OAAO,CAAkB,WAAW,EAAE;gBACzD,GAAG,MAAM;gBACT,cAAc,EAAE,MAAM;aACvB,CAAC,CAAC;YAEH,MAAM,KAAK,GAAG;gBACZ,KAAK,MAAM,CAAC,cAAc,wBAAwB;gBAClD,uBAAuB,MAAM,CAAC,MAAM,EAAE;aACvC,CAAC;YACF,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;gBACtB,KAAK,CAAC,IAAI,CAAC,kBAAkB,MAAM,CAAC,UAAU,qDAAqD,CAAC,CAAC;YACvG,CAAC;YAED,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC;QAC1E,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,OAAO,GAAG,KAAK,YAAY,eAAe,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACjF,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,UAAU,OAAO,EAAE,EAAE,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QAC5F,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import type { ApiCall } from "../api-client.js";
3
+ export declare function registerVerifyPhone(server: McpServer, apiCall: ApiCall): void;
@@ -0,0 +1,22 @@
1
+ import { verifyPhoneInput } from "../schemas.js";
2
+ import { SmsmasivosError } from "../errors.js";
3
+ export function registerVerifyPhone(server, apiCall) {
4
+ server.tool("verify_phone", "Inicia una verificación de número de teléfono enviando un código OTP por SMS. Opcionalmente puede enviarse por llamada de voz o WhatsApp. Después usa check_verification para verificar el código que ingrese el usuario.", verifyPhoneInput.shape, async (params) => {
5
+ try {
6
+ const result = await apiCall("/protected/json/phones/verification/start", params);
7
+ return {
8
+ content: [
9
+ {
10
+ type: "text",
11
+ text: `✓ Código de verificación enviado a ${result.number}. Referencia: ${result.reference}. Créditos restantes: ${result.credit}`,
12
+ },
13
+ ],
14
+ };
15
+ }
16
+ catch (error) {
17
+ const message = error instanceof SmsmasivosError ? error.message : String(error);
18
+ return { content: [{ type: "text", text: `Error: ${message}` }], isError: true };
19
+ }
20
+ });
21
+ }
22
+ //# sourceMappingURL=verify-phone.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verify-phone.js","sourceRoot":"","sources":["../../src/tools/verify-phone.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAQ/C,MAAM,UAAU,mBAAmB,CAAC,MAAiB,EAAE,OAAgB;IACrE,MAAM,CAAC,IAAI,CACT,cAAc,EACd,2NAA2N,EAC3N,gBAAgB,CAAC,KAAK,EACtB,KAAK,EAAE,MAAM,EAAE,EAAE;QACf,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,OAAO,CAC1B,2CAA2C,EAC3C,MAAM,CACP,CAAC;YACF,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE,sCAAsC,MAAM,CAAC,MAAM,iBAAiB,MAAM,CAAC,SAAS,yBAAyB,MAAM,CAAC,MAAM,EAAE;qBACnI;iBACF;aACF,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,OAAO,GAAG,KAAK,YAAY,eAAe,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACjF,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,UAAU,OAAO,EAAE,EAAE,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QAC5F,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
package/package.json ADDED
@@ -0,0 +1,48 @@
1
+ {
2
+ "name": "@smsmasivos/mcp-server",
3
+ "version": "0.1.0",
4
+ "description": "MCP server for SMS Masivos — bulk SMS platform for Mexico/LATAM",
5
+ "type": "module",
6
+ "main": "dist/stdio.js",
7
+ "bin": {
8
+ "smsmasivos-mcp": "dist/stdio.js"
9
+ },
10
+ "files": [
11
+ "dist",
12
+ "README.md"
13
+ ],
14
+ "scripts": {
15
+ "build": "tsc",
16
+ "dev": "tsc --watch",
17
+ "start": "node dist/stdio.js",
18
+ "test": "vitest run",
19
+ "test:watch": "vitest",
20
+ "prepublishOnly": "npm run build"
21
+ },
22
+ "dependencies": {
23
+ "@modelcontextprotocol/sdk": "^1.12.0",
24
+ "zod": "^3.24.0"
25
+ },
26
+ "devDependencies": {
27
+ "@types/node": "^22.0.0",
28
+ "typescript": "^5.7.0",
29
+ "vitest": "^2.1.0"
30
+ },
31
+ "engines": {
32
+ "node": ">=18"
33
+ },
34
+ "license": "MIT",
35
+ "keywords": [
36
+ "mcp",
37
+ "sms",
38
+ "smsmasivos",
39
+ "mexico",
40
+ "latam",
41
+ "bulk-sms",
42
+ "model-context-protocol"
43
+ ],
44
+ "repository": {
45
+ "type": "git",
46
+ "url": "https://github.com/SMS-Masivos/mcp-server.git"
47
+ }
48
+ }