@sendly/mcp 1.0.0 → 1.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 (2) hide show
  1. package/dist/index.js +152 -0
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -267,6 +267,158 @@ server.tool(
267
267
  }
268
268
  }
269
269
  );
270
+ server.tool(
271
+ "get_suggested_replies",
272
+ "Get AI-generated reply suggestions for a conversation based on message history and context. Returns 2-3 suggested responses with different tones (professional, friendly, concise).",
273
+ {
274
+ conversationId: z.string().describe("The conversation ID to generate suggestions for")
275
+ },
276
+ async ({ conversationId }) => {
277
+ try {
278
+ return ok(
279
+ await api("POST", `/conversations/${conversationId}/suggest-replies`)
280
+ );
281
+ } catch (e) {
282
+ return err(e);
283
+ }
284
+ }
285
+ );
286
+ server.tool(
287
+ "create_label",
288
+ "Create a label for categorizing conversations and messages. Labels have a name and optional color.",
289
+ {
290
+ name: z.string().describe("Label name (e.g., 'urgent', 'vip', 'follow-up')"),
291
+ color: z.string().optional().describe("Hex color code (default: #6b7280)"),
292
+ description: z.string().optional().describe("Label description")
293
+ },
294
+ async ({ name, color, description }) => {
295
+ try {
296
+ const body = { name };
297
+ if (color) body.color = color;
298
+ if (description) body.description = description;
299
+ return ok(await api("POST", "/labels", body));
300
+ } catch (e) {
301
+ return err(e);
302
+ }
303
+ }
304
+ );
305
+ server.tool(
306
+ "list_labels",
307
+ "List all labels available in your workspace.",
308
+ {},
309
+ async () => {
310
+ try {
311
+ return ok(await api("GET", "/labels"));
312
+ } catch (e) {
313
+ return err(e);
314
+ }
315
+ }
316
+ );
317
+ server.tool(
318
+ "add_conversation_label",
319
+ "Add one or more labels to a conversation for categorization.",
320
+ {
321
+ conversationId: z.string().describe("The conversation ID"),
322
+ labelIds: z.array(z.string()).describe("Array of label IDs to add")
323
+ },
324
+ async ({ conversationId, labelIds }) => {
325
+ try {
326
+ return ok(
327
+ await api("POST", `/conversations/${conversationId}/labels`, {
328
+ labelIds
329
+ })
330
+ );
331
+ } catch (e) {
332
+ return err(e);
333
+ }
334
+ }
335
+ );
336
+ server.tool(
337
+ "remove_conversation_label",
338
+ "Remove a label from a conversation.",
339
+ {
340
+ conversationId: z.string().describe("The conversation ID"),
341
+ labelId: z.string().describe("The label ID to remove")
342
+ },
343
+ async ({ conversationId, labelId }) => {
344
+ try {
345
+ return ok(
346
+ await api("DELETE", `/conversations/${conversationId}/labels/${labelId}`)
347
+ );
348
+ } catch (e) {
349
+ return err(e);
350
+ }
351
+ }
352
+ );
353
+ server.tool(
354
+ "create_draft",
355
+ "Create a message draft for human review before sending. The draft must be approved before it becomes a real SMS.",
356
+ {
357
+ conversationId: z.string().describe("The conversation ID"),
358
+ text: z.string().describe("Draft message text"),
359
+ source: z.string().optional().describe("Source of the draft (default: 'ai')")
360
+ },
361
+ async ({ conversationId, text, source }) => {
362
+ try {
363
+ const body = { conversationId, text };
364
+ if (source) body.source = source;
365
+ return ok(await api("POST", "/drafts", body));
366
+ } catch (e) {
367
+ return err(e);
368
+ }
369
+ }
370
+ );
371
+ server.tool(
372
+ "list_drafts",
373
+ "List message drafts, optionally filtered by conversation or status.",
374
+ {
375
+ conversationId: z.string().optional().describe("Filter by conversation ID"),
376
+ status: z.enum(["pending", "approved", "rejected", "sent", "failed"]).optional().describe("Filter by status")
377
+ },
378
+ async ({ conversationId, status }) => {
379
+ try {
380
+ return ok(
381
+ await api("GET", "/drafts", void 0, {
382
+ conversation_id: conversationId,
383
+ status
384
+ })
385
+ );
386
+ } catch (e) {
387
+ return err(e);
388
+ }
389
+ }
390
+ );
391
+ server.tool(
392
+ "approve_draft",
393
+ "Approve a pending draft and send it as a real SMS message. Runs compliance checks and deducts credits at approval time.",
394
+ {
395
+ draftId: z.string().describe("The draft ID to approve")
396
+ },
397
+ async ({ draftId }) => {
398
+ try {
399
+ return ok(await api("POST", `/drafts/${draftId}/approve`));
400
+ } catch (e) {
401
+ return err(e);
402
+ }
403
+ }
404
+ );
405
+ server.tool(
406
+ "reject_draft",
407
+ "Reject a pending draft with an optional reason. The message will not be sent.",
408
+ {
409
+ draftId: z.string().describe("The draft ID to reject"),
410
+ reason: z.string().optional().describe("Reason for rejection")
411
+ },
412
+ async ({ draftId, reason }) => {
413
+ try {
414
+ const body = {};
415
+ if (reason) body.reason = reason;
416
+ return ok(await api("POST", `/drafts/${draftId}/reject`, body));
417
+ } catch (e) {
418
+ return err(e);
419
+ }
420
+ }
421
+ );
270
422
  server.tool(
271
423
  "send_otp",
272
424
  "Send an OTP verification code via SMS. Use for phone verification, 2FA, or identity confirmation. Returns a verification ID to check the code against. In sandbox mode (test API key), the code is returned in the response for testing.",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sendly/mcp",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "Sendly MCP Server — SMS for AI agents. Send messages, manage conversations, verify phone numbers.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",