mirlo-mcp 1.0.1 → 1.0.3

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.
package/dist/client.d.ts CHANGED
@@ -24,12 +24,13 @@ export declare class MirloClient {
24
24
  getTicket(id: string): Promise<any>;
25
25
  createTicket(data: Record<string, unknown>): Promise<any>;
26
26
  updateTicket(id: string, data: Record<string, unknown>): Promise<any>;
27
+ addTicketNote(ticketId: string, data: Record<string, unknown>): Promise<any>;
27
28
  listTasks(filters?: Record<string, string>): Promise<any>;
28
29
  createTask(data: Record<string, unknown>): Promise<any>;
29
30
  completeTask(id: string): Promise<any>;
30
31
  listPipelines(): Promise<any>;
31
- sendMessage(to: string, body: string, channel?: string): Promise<any>;
32
- sendTemplate(to: string, templateId: string, params?: Record<string, string>): Promise<any>;
32
+ sendMessage(organizationAddress: string, contactAddress: string, text: string, service?: string): Promise<any>;
33
+ sendTemplate(organizationAddress: string, to: string, metaTemplateId: string, components?: any[]): Promise<any>;
33
34
  listConversations(filters?: Record<string, string>): Promise<any>;
34
35
  listMessages(conversationId: string, limit?: number): Promise<any>;
35
36
  listCalls(filters?: Record<string, string>): Promise<any>;
package/dist/client.js CHANGED
@@ -86,6 +86,9 @@ export class MirloClient {
86
86
  async updateTicket(id, data) {
87
87
  return this.request('PATCH', `/crm/tickets/${id}`, data);
88
88
  }
89
+ async addTicketNote(ticketId, data) {
90
+ return this.request('POST', `/crm/tickets/${ticketId}/notes`, data);
91
+ }
89
92
  // ── CRM: Tasks ──
90
93
  async listTasks(filters) {
91
94
  const params = filters ? '?' + new URLSearchParams(filters).toString() : '';
@@ -102,11 +105,24 @@ export class MirloClient {
102
105
  return this.request('GET', '/crm/pipelines');
103
106
  }
104
107
  // ── Messaging ──
105
- async sendMessage(to, body, channel = 'whatsapp') {
106
- return this.request('POST', '/messages', { to, body, channel });
108
+ // Messages API is v2 with org in path
109
+ async sendMessage(organizationAddress, contactAddress, text, service = 'whatsapp') {
110
+ // v2 messages endpoint — org resolved from API key
111
+ return this.request('POST', '/messages', {
112
+ organization_address: organizationAddress,
113
+ service,
114
+ contact_address: contactAddress,
115
+ direction: 'outgoing',
116
+ content: { kind: 'text', text },
117
+ });
107
118
  }
108
- async sendTemplate(to, templateId, params) {
109
- return this.request('POST', '/messages/templates', { to, template_id: templateId, params });
119
+ async sendTemplate(organizationAddress, to, metaTemplateId, components) {
120
+ return this.request('POST', '/messages/send-template', {
121
+ organization_address: organizationAddress,
122
+ to,
123
+ meta_template_id: metaTemplateId,
124
+ components,
125
+ });
110
126
  }
111
127
  async listConversations(filters) {
112
128
  const params = filters ? '?' + new URLSearchParams(filters).toString() : '';
package/dist/tools.js CHANGED
@@ -175,6 +175,20 @@ const createTicket = {
175
175
  }),
176
176
  handler: async (client, args) => client.createTicket({ ...args, source: 'api' }),
177
177
  };
178
+ const addTicketNote = {
179
+ name: 'mirlo_add_ticket_note',
180
+ description: 'Add a comment/note to a ticket. Can be internal or public (visible to customer).',
181
+ schema: z.object({
182
+ ticket_id: z.string().describe('Ticket UUID'),
183
+ body: z.string().describe('Note content (text or HTML)'),
184
+ is_public: z.boolean().optional().default(false).describe('true = visible to customer on public ticket page'),
185
+ author_member_id: z.string().optional().describe('Author member UUID (if omitted, uses API key owner)'),
186
+ }),
187
+ handler: async (client, args) => {
188
+ const { ticket_id, body, is_public, author_member_id } = args;
189
+ return client.addTicketNote(ticket_id, { body_html: body, is_public, author_member_id: author_member_id || 'system' });
190
+ },
191
+ };
178
192
  // ── CRM: Tasks ──
179
193
  const listTasks = {
180
194
  name: 'mirlo_list_tasks',
@@ -228,23 +242,25 @@ const listPipelines = {
228
242
  // ── Messaging ──
229
243
  const sendMessage = {
230
244
  name: 'mirlo_send_message',
231
- description: 'Send a WhatsApp or SMS message to a phone number.',
245
+ description: 'Send a WhatsApp message to a phone number. Only works within the 24h window after the contact messaged you. Use send_template for first contact.',
232
246
  schema: z.object({
233
- to: z.string().describe('Recipient phone number (E.164 format)'),
234
- body: z.string().describe('Message text'),
235
- channel: z.enum(['whatsapp', 'sms']).optional().default('whatsapp'),
247
+ organization_address: z.string().describe('Your WhatsApp Phone Number ID (from Mirlo dashboard)'),
248
+ contact_address: z.string().describe('Recipient phone number WITHOUT + prefix (e.g. 5215512345678)'),
249
+ text: z.string().describe('Message text'),
250
+ service: z.enum(['whatsapp', 'instagram', 'messenger']).optional().default('whatsapp'),
236
251
  }),
237
- handler: async (client, args) => client.sendMessage(args.to, args.body, args.channel),
252
+ handler: async (client, args) => client.sendMessage(args.organization_address, args.contact_address, args.text, args.service),
238
253
  };
239
254
  const sendTemplate = {
240
255
  name: 'mirlo_send_template',
241
- description: 'Send a pre-approved WhatsApp template message.',
256
+ description: 'Send a pre-approved WhatsApp template message. Works outside the 24h window.',
242
257
  schema: z.object({
243
- to: z.string().describe('Recipient phone number'),
244
- template_id: z.string().describe('Template ID'),
245
- params: z.record(z.string(), z.string()).optional().describe('Template parameters'),
258
+ organization_address: z.string().describe('Your WhatsApp Phone Number ID'),
259
+ to: z.string().describe('Recipient phone number with + prefix (e.g. +525512345678)'),
260
+ meta_template_id: z.string().describe('Meta-approved template ID'),
261
+ components: z.any().optional().describe('Template components array with parameters'),
246
262
  }),
247
- handler: async (client, args) => client.sendTemplate(args.to, args.template_id, args.params),
263
+ handler: async (client, args) => client.sendTemplate(args.organization_address, args.to, args.meta_template_id, args.components),
248
264
  };
249
265
  const listConversations = {
250
266
  name: 'mirlo_list_conversations',
@@ -279,7 +295,7 @@ export const ALL_TOOLS = [
279
295
  listDeals, getDeal, createDeal, updateDeal, moveDealStage,
280
296
  listContacts, getContact, createContact,
281
297
  listAccounts, createAccount,
282
- listTickets, createTicket,
298
+ listTickets, createTicket, addTicketNote,
283
299
  listTasks, createTask, completeTask,
284
300
  listPipelines,
285
301
  // Messaging
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mirlo-mcp",
3
- "version": "1.0.1",
3
+ "version": "1.0.3",
4
4
  "description": "Mirlo MCP Server — CRM, Messaging & Voice tools for Claude, GPT, and other LLMs",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
package/src/client.ts CHANGED
@@ -114,6 +114,10 @@ export class MirloClient {
114
114
  return this.request<any>('PATCH', `/crm/tickets/${id}`, data);
115
115
  }
116
116
 
117
+ async addTicketNote(ticketId: string, data: Record<string, unknown>) {
118
+ return this.request<any>('POST', `/crm/tickets/${ticketId}/notes`, data);
119
+ }
120
+
117
121
  // ── CRM: Tasks ──
118
122
 
119
123
  async listTasks(filters?: Record<string, string>) {
@@ -136,13 +140,26 @@ export class MirloClient {
136
140
  }
137
141
 
138
142
  // ── Messaging ──
139
-
140
- async sendMessage(to: string, body: string, channel = 'whatsapp') {
141
- return this.request<any>('POST', '/messages', { to, body, channel });
143
+ // Messages API is v2 with org in path
144
+
145
+ async sendMessage(organizationAddress: string, contactAddress: string, text: string, service = 'whatsapp') {
146
+ // v2 messages endpoint — org resolved from API key
147
+ return this.request<any>('POST', '/messages', {
148
+ organization_address: organizationAddress,
149
+ service,
150
+ contact_address: contactAddress,
151
+ direction: 'outgoing',
152
+ content: { kind: 'text', text },
153
+ });
142
154
  }
143
155
 
144
- async sendTemplate(to: string, templateId: string, params?: Record<string, string>) {
145
- return this.request<any>('POST', '/messages/templates', { to, template_id: templateId, params });
156
+ async sendTemplate(organizationAddress: string, to: string, metaTemplateId: string, components?: any[]) {
157
+ return this.request<any>('POST', '/messages/send-template', {
158
+ organization_address: organizationAddress,
159
+ to,
160
+ meta_template_id: metaTemplateId,
161
+ components,
162
+ });
146
163
  }
147
164
 
148
165
  async listConversations(filters?: Record<string, string>) {
package/src/tools.ts CHANGED
@@ -203,6 +203,21 @@ const createTicket: ToolDef = {
203
203
  handler: async (client, args) => client.createTicket({ ...args, source: 'api' }),
204
204
  };
205
205
 
206
+ const addTicketNote: ToolDef = {
207
+ name: 'mirlo_add_ticket_note',
208
+ description: 'Add a comment/note to a ticket. Can be internal or public (visible to customer).',
209
+ schema: z.object({
210
+ ticket_id: z.string().describe('Ticket UUID'),
211
+ body: z.string().describe('Note content (text or HTML)'),
212
+ is_public: z.boolean().optional().default(false).describe('true = visible to customer on public ticket page'),
213
+ author_member_id: z.string().optional().describe('Author member UUID (if omitted, uses API key owner)'),
214
+ }),
215
+ handler: async (client, args) => {
216
+ const { ticket_id, body, is_public, author_member_id } = args;
217
+ return client.addTicketNote(ticket_id, { body_html: body, is_public, author_member_id: author_member_id || 'system' });
218
+ },
219
+ };
220
+
206
221
  // ── CRM: Tasks ──
207
222
 
208
223
  const listTasks: ToolDef = {
@@ -263,24 +278,26 @@ const listPipelines: ToolDef = {
263
278
 
264
279
  const sendMessage: ToolDef = {
265
280
  name: 'mirlo_send_message',
266
- description: 'Send a WhatsApp or SMS message to a phone number.',
281
+ description: 'Send a WhatsApp message to a phone number. Only works within the 24h window after the contact messaged you. Use send_template for first contact.',
267
282
  schema: z.object({
268
- to: z.string().describe('Recipient phone number (E.164 format)'),
269
- body: z.string().describe('Message text'),
270
- channel: z.enum(['whatsapp', 'sms']).optional().default('whatsapp'),
283
+ organization_address: z.string().describe('Your WhatsApp Phone Number ID (from Mirlo dashboard)'),
284
+ contact_address: z.string().describe('Recipient phone number WITHOUT + prefix (e.g. 5215512345678)'),
285
+ text: z.string().describe('Message text'),
286
+ service: z.enum(['whatsapp', 'instagram', 'messenger']).optional().default('whatsapp'),
271
287
  }),
272
- handler: async (client, args) => client.sendMessage(args.to, args.body, args.channel),
288
+ handler: async (client, args) => client.sendMessage(args.organization_address, args.contact_address, args.text, args.service),
273
289
  };
274
290
 
275
291
  const sendTemplate: ToolDef = {
276
292
  name: 'mirlo_send_template',
277
- description: 'Send a pre-approved WhatsApp template message.',
293
+ description: 'Send a pre-approved WhatsApp template message. Works outside the 24h window.',
278
294
  schema: z.object({
279
- to: z.string().describe('Recipient phone number'),
280
- template_id: z.string().describe('Template ID'),
281
- params: z.record(z.string(), z.string()).optional().describe('Template parameters'),
295
+ organization_address: z.string().describe('Your WhatsApp Phone Number ID'),
296
+ to: z.string().describe('Recipient phone number with + prefix (e.g. +525512345678)'),
297
+ meta_template_id: z.string().describe('Meta-approved template ID'),
298
+ components: z.any().optional().describe('Template components array with parameters'),
282
299
  }),
283
- handler: async (client, args) => client.sendTemplate(args.to, args.template_id, args.params),
300
+ handler: async (client, args) => client.sendTemplate(args.organization_address, args.to, args.meta_template_id, args.components),
284
301
  };
285
302
 
286
303
  const listConversations: ToolDef = {
@@ -321,7 +338,7 @@ export const ALL_TOOLS: ToolDef[] = [
321
338
  listDeals, getDeal, createDeal, updateDeal, moveDealStage,
322
339
  listContacts, getContact, createContact,
323
340
  listAccounts, createAccount,
324
- listTickets, createTicket,
341
+ listTickets, createTicket, addTicketNote,
325
342
  listTasks, createTask, completeTask,
326
343
  listPipelines,
327
344
  // Messaging