@zaapi/open-api-mcp 1.2.0 → 1.4.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 (69) hide show
  1. package/dist/client.js +5 -0
  2. package/dist/client.js.map +1 -1
  3. package/dist/instructions.js +77 -0
  4. package/dist/instructions.js.map +1 -0
  5. package/dist/server.js +134 -12
  6. package/dist/server.js.map +1 -1
  7. package/dist/tools/accounts/list-accounts.js +8 -18
  8. package/dist/tools/accounts/list-accounts.js.map +1 -1
  9. package/dist/tools/accounts/list-whatsapp-templates.js +49 -0
  10. package/dist/tools/accounts/list-whatsapp-templates.js.map +1 -0
  11. package/dist/tools/common.js +48 -26
  12. package/dist/tools/common.js.map +1 -1
  13. package/dist/tools/contacts/create-contact.js +13 -7
  14. package/dist/tools/contacts/create-contact.js.map +1 -1
  15. package/dist/tools/contacts/get-contact-by-id.js +6 -7
  16. package/dist/tools/contacts/get-contact-by-id.js.map +1 -1
  17. package/dist/tools/contacts/list-contact-fields.js +5 -3
  18. package/dist/tools/contacts/list-contact-fields.js.map +1 -1
  19. package/dist/tools/contacts/list-contacts.js +11 -6
  20. package/dist/tools/contacts/list-contacts.js.map +1 -1
  21. package/dist/tools/contacts/search-contacts.js +20 -0
  22. package/dist/tools/contacts/search-contacts.js.map +1 -0
  23. package/dist/tools/contacts/update-contact-field.js +12 -7
  24. package/dist/tools/contacts/update-contact-field.js.map +1 -1
  25. package/dist/tools/conversations/filter-conversations.js +11 -7
  26. package/dist/tools/conversations/filter-conversations.js.map +1 -1
  27. package/dist/tools/conversations/mark-conversation-read.js +4 -6
  28. package/dist/tools/conversations/mark-conversation-read.js.map +1 -1
  29. package/dist/tools/conversations/update-conversation-labels.js +10 -9
  30. package/dist/tools/conversations/update-conversation-labels.js.map +1 -1
  31. package/dist/tools/index.js +14 -0
  32. package/dist/tools/index.js.map +1 -1
  33. package/dist/tools/labels/list-labels.js +7 -4
  34. package/dist/tools/labels/list-labels.js.map +1 -1
  35. package/dist/tools/messages/create-internal-comment.js +9 -8
  36. package/dist/tools/messages/create-internal-comment.js.map +1 -1
  37. package/dist/tools/messages/get-messages.js +9 -7
  38. package/dist/tools/messages/get-messages.js.map +1 -1
  39. package/dist/tools/messages/list-internal-comments.js +8 -8
  40. package/dist/tools/messages/list-internal-comments.js.map +1 -1
  41. package/dist/tools/messages/search-messages.js +20 -0
  42. package/dist/tools/messages/search-messages.js.map +1 -0
  43. package/dist/tools/messages/send-email.js +27 -0
  44. package/dist/tools/messages/send-email.js.map +1 -0
  45. package/dist/tools/messages/send-new-email.js +27 -0
  46. package/dist/tools/messages/send-new-email.js.map +1 -0
  47. package/dist/tools/messages/send-new-whatsapp-template.js +35 -0
  48. package/dist/tools/messages/send-new-whatsapp-template.js.map +1 -0
  49. package/dist/tools/messages/send-plain-text-message.js +9 -8
  50. package/dist/tools/messages/send-plain-text-message.js.map +1 -1
  51. package/dist/tools/messages/send-whatsapp-template.js +32 -0
  52. package/dist/tools/messages/send-whatsapp-template.js.map +1 -0
  53. package/dist/tools/responses.js +303 -0
  54. package/dist/tools/responses.js.map +1 -0
  55. package/dist/tools/teams/list-teams.js +10 -5
  56. package/dist/tools/teams/list-teams.js.map +1 -1
  57. package/dist/tools/tickets/close-ticket.js +17 -10
  58. package/dist/tools/tickets/close-ticket.js.map +1 -1
  59. package/dist/tools/tickets/get-ticket-by-id.js +8 -8
  60. package/dist/tools/tickets/get-ticket-by-id.js.map +1 -1
  61. package/dist/tools/tickets/list-ticket-fields.js +7 -4
  62. package/dist/tools/tickets/list-ticket-fields.js.map +1 -1
  63. package/dist/tools/tickets/list-tickets.js +22 -22
  64. package/dist/tools/tickets/list-tickets.js.map +1 -1
  65. package/dist/tools/tickets/update-ticket-field.js +15 -8
  66. package/dist/tools/tickets/update-ticket-field.js.map +1 -1
  67. package/dist/tools/users/list-users.js +8 -5
  68. package/dist/tools/users/list-users.js.map +1 -1
  69. package/package.json +1 -1
@@ -1,20 +1,20 @@
1
1
  import { z } from 'zod';
2
- import { describeHttpRequest, expand } from '../common.js';
2
+ import { expand } from '../common.js';
3
+ import { envelope, ticket } from '../responses.js';
3
4
  const queryKeys = ['ticketId', 'expand'];
4
5
  export const getTicketById = {
5
6
  name: 'getTicketById',
6
7
  title: 'Get a ticket by ID',
7
- description: `Required scope: tickets:read. ${describeHttpRequest('GET', '/v1/tickets', queryKeys)} Fetch a single ticket. Pass expand=account,conversation,assignee,handledBy to replace those ids with names.`,
8
+ description: 'Fetch one ticket by id, including its custom field values and the conversationId and contactId that the message and contact tools need. Read this before updateTicketField or closeTicket: the response carries the ticketFieldsUpdatedAt those calls must echo back. Requires the tickets:read scope.',
9
+ scope: 'tickets:read',
8
10
  method: 'GET',
9
11
  path: '/v1/tickets',
10
12
  queryKeys,
11
13
  inputSchema: z.object({
12
- ticketId: z
13
- .string()
14
- .min(1)
15
- .describe('Query parameter. The ID of the ticket.'),
16
- expand: expand('Comma-separated related objects to include: account, conversation, assignee, handledBy.'),
14
+ ticketId: z.string().min(1).describe('The ID of the ticket.'),
15
+ expand: expand(['account', 'conversation', 'assignee', 'handledBy'], 'Replace these ids with the named object, saving a follow-up call.'),
17
16
  }),
18
- annotations: { readOnlyHint: true },
17
+ outputSchema: envelope(ticket, 'The ticket.'),
18
+ annotations: { readOnlyHint: true, openWorldHint: true },
19
19
  };
20
20
  //# sourceMappingURL=get-ticket-by-id.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"get-ticket-by-id.js","sourceRoot":"","sources":["../../../src/tools/tickets/get-ticket-by-id.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,mBAAmB,EAAE,MAAM,EAAqB,MAAM,cAAc,CAAC;AAE9E,MAAM,SAAS,GAAG,CAAC,UAAU,EAAE,QAAQ,CAAU,CAAC;AAElD,MAAM,CAAC,MAAM,aAAa,GAAiB;IACzC,IAAI,EAAE,eAAe;IACrB,KAAK,EAAE,oBAAoB;IAC3B,WAAW,EAAE,iCAAiC,mBAAmB,CAAC,KAAK,EAAE,aAAa,EAAE,SAAS,CAAC,8GAA8G;IAChN,MAAM,EAAE,KAAK;IACb,IAAI,EAAE,aAAa;IACnB,SAAS;IACT,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC;QACpB,QAAQ,EAAE,CAAC;aACR,MAAM,EAAE;aACR,GAAG,CAAC,CAAC,CAAC;aACN,QAAQ,CAAC,wCAAwC,CAAC;QACrD,MAAM,EAAE,MAAM,CACZ,yFAAyF,CAC1F;KACF,CAAC;IACF,WAAW,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE;CACpC,CAAC"}
1
+ {"version":3,"file":"get-ticket-by-id.js","sourceRoot":"","sources":["../../../src/tools/tickets/get-ticket-by-id.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,MAAM,EAAqB,MAAM,cAAc,CAAC;AACzD,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAEnD,MAAM,SAAS,GAAG,CAAC,UAAU,EAAE,QAAQ,CAAU,CAAC;AAElD,MAAM,CAAC,MAAM,aAAa,GAAiB;IACzC,IAAI,EAAE,eAAe;IACrB,KAAK,EAAE,oBAAoB;IAC3B,WAAW,EACT,wSAAwS;IAC1S,KAAK,EAAE,cAAc;IACrB,MAAM,EAAE,KAAK;IACb,IAAI,EAAE,aAAa;IACnB,SAAS;IACT,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC;QACpB,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,uBAAuB,CAAC;QAC7D,MAAM,EAAE,MAAM,CACZ,CAAC,SAAS,EAAE,cAAc,EAAE,UAAU,EAAE,WAAW,CAAC,EACpD,mEAAmE,CACpE;KACF,CAAC;IACF,YAAY,EAAE,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC;IAC7C,WAAW,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE;CACzD,CAAC"}
@@ -1,16 +1,19 @@
1
1
  import { z } from 'zod';
2
- import { describeHttpRequest, expand } from '../common.js';
2
+ import { expand } from '../common.js';
3
+ import { envelope, ticketField } from '../responses.js';
3
4
  const queryKeys = ['expand'];
4
5
  export const listTicketFields = {
5
6
  name: 'listTicketFields',
6
7
  title: 'List ticket fields',
7
- description: `Required scope: tickets:read. ${describeHttpRequest('GET', '/v1/tickets/fields', queryKeys)} Full catalog of custom ticket field definitions, in display order. Not paginated. Pass expand=accounts to include the accounts each field applies to.`,
8
+ description: "Full catalog of the store's custom ticket field definitions, in display order. Not paginated. Call this first whenever a request names a field by its label — the ids, data types and select options here are what updateTicketField and the listTickets advancedFilters.ticketFields filter take. Requires the tickets:read scope.",
9
+ scope: 'tickets:read',
8
10
  method: 'GET',
9
11
  path: '/v1/tickets/fields',
10
12
  queryKeys,
11
13
  inputSchema: z.object({
12
- expand: expand('Pass accounts to include the accounts each field applies to.'),
14
+ expand: expand(['accounts'], 'Include the accounts each field applies to.'),
13
15
  }),
14
- annotations: { readOnlyHint: true },
16
+ outputSchema: envelope(z.array(ticketField), 'Every ticket field definition on the store, in display order.'),
17
+ annotations: { readOnlyHint: true, openWorldHint: true },
15
18
  };
16
19
  //# sourceMappingURL=list-ticket-fields.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"list-ticket-fields.js","sourceRoot":"","sources":["../../../src/tools/tickets/list-ticket-fields.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,mBAAmB,EAAE,MAAM,EAAqB,MAAM,cAAc,CAAC;AAE9E,MAAM,SAAS,GAAG,CAAC,QAAQ,CAAU,CAAC;AAEtC,MAAM,CAAC,MAAM,gBAAgB,GAAiB;IAC5C,IAAI,EAAE,kBAAkB;IACxB,KAAK,EAAE,oBAAoB;IAC3B,WAAW,EAAE,iCAAiC,mBAAmB,CAAC,KAAK,EAAE,oBAAoB,EAAE,SAAS,CAAC,wJAAwJ;IACjQ,MAAM,EAAE,KAAK;IACb,IAAI,EAAE,oBAAoB;IAC1B,SAAS;IACT,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC;QACpB,MAAM,EAAE,MAAM,CACZ,8DAA8D,CAC/D;KACF,CAAC;IACF,WAAW,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE;CACpC,CAAC"}
1
+ {"version":3,"file":"list-ticket-fields.js","sourceRoot":"","sources":["../../../src/tools/tickets/list-ticket-fields.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,MAAM,EAAqB,MAAM,cAAc,CAAC;AACzD,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAExD,MAAM,SAAS,GAAG,CAAC,QAAQ,CAAU,CAAC;AAEtC,MAAM,CAAC,MAAM,gBAAgB,GAAiB;IAC5C,IAAI,EAAE,kBAAkB;IACxB,KAAK,EAAE,oBAAoB;IAC3B,WAAW,EACT,qUAAqU;IACvU,KAAK,EAAE,cAAc;IACrB,MAAM,EAAE,KAAK;IACb,IAAI,EAAE,oBAAoB;IAC1B,SAAS;IACT,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC;QACpB,MAAM,EAAE,MAAM,CAAC,CAAC,UAAU,CAAC,EAAE,6CAA6C,CAAC;KAC5E,CAAC;IACF,YAAY,EAAE,QAAQ,CACpB,CAAC,CAAC,KAAK,CAAC,WAAW,CAAC,EACpB,+DAA+D,CAChE;IACD,WAAW,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE;CACzD,CAAC"}
@@ -1,37 +1,39 @@
1
1
  import { z } from 'zod';
2
- import { describeHttpRequest, expand, fieldValue, paginationFields, paginationQueryKeys, } from '../common.js';
2
+ import { expand, fieldValue, paginationFields, paginationQueryKeys, } from '../common.js';
3
+ import { envelope, ticket } from '../responses.js';
3
4
  const TICKET_FILTER_ARRAY_MAX = 20;
4
5
  export const listTickets = {
5
6
  name: 'listTickets',
6
7
  title: 'List tickets',
7
- description: `Required scope: tickets:read. ${describeHttpRequest('POST', '/v1/tickets/list', paginationQueryKeys)} Page through tickets, newest message first. An omitted or empty JSON body returns open, non-spam tickets that are not snoozed. When conversationId is set and statuses is omitted, open and closed tickets for that conversation are returned. Do not send assigneeUserIds together with unassigned: true.`,
8
+ description: 'The main way into the store: page through tickets, newest message first, and read the conversationId and contactId off them to reach messages, labels and contacts. Send no filters at all for the current queue — open, non-spam, not snoozed. Setting conversationId with statuses omitted returns every ticket on that thread instead, open and closed. assigneeUserIds and handledByUserIds take user UUIDs, the userId from listUsers rather than the id beside it, and assigneeUserIds cannot be combined with unassigned: true. Requires the tickets:read scope.',
9
+ scope: 'tickets:read',
8
10
  method: 'POST',
9
11
  path: '/v1/tickets/list',
10
12
  queryKeys: paginationQueryKeys,
11
13
  inputSchema: z.object({
12
14
  ...paginationFields,
13
- expand: expand('Pass account,conversation,assignee,handledBy to replace those ids with names.'),
15
+ expand: expand(['account', 'conversation', 'assignee', 'handledBy'], 'Replace these ids on every ticket with the named object, saving a follow-up call.'),
14
16
  statuses: z
15
17
  .array(z.enum(['open', 'closed']))
16
18
  .optional()
17
- .describe('JSON body. Open and/or closed tickets. Omit to return open tickets only. When conversationId is set, omitting statuses returns every status for that conversation.'),
19
+ .describe('Open and/or closed tickets. Omit to return open tickets only. When conversationId is set, omitting statuses returns every status for that conversation.'),
18
20
  conversationId: z
19
21
  .string()
20
22
  .min(1)
21
23
  .optional()
22
- .describe('JSON body. Restrict results to tickets belonging to this conversation.'),
24
+ .describe('Restrict results to tickets belonging to this conversation.'),
23
25
  accountIds: z
24
26
  .array(z.string())
25
27
  .optional()
26
- .describe('JSON body. Restrict results to these account IDs.'),
28
+ .describe('Restrict results to these account IDs, from listAccounts.'),
27
29
  assigneeUserIds: z
28
30
  .array(z.string())
29
31
  .optional()
30
- .describe('JSON body. Restrict results to these assignee user IDs. Cannot be combined with unassigned: true.'),
32
+ .describe('Restrict results to these assignee user UUIDs (User.userId). Cannot be combined with unassigned: true.'),
31
33
  handledByUserIds: z
32
34
  .array(z.string())
33
35
  .optional()
34
- .describe('JSON body. Restrict results to tickets handled by these user IDs.'),
36
+ .describe('Restrict results to tickets handled by these user UUIDs (User.userId).'),
35
37
  resolutionStatuses: z
36
38
  .array(z.enum([
37
39
  'none',
@@ -41,19 +43,16 @@ export const listTickets = {
41
43
  'ai_partial_resolution',
42
44
  ]))
43
45
  .optional()
44
- .describe('JSON body. Restrict results to these resolution statuses.'),
46
+ .describe('Restrict results to these resolution statuses.'),
45
47
  unassigned: z
46
48
  .boolean()
47
49
  .optional()
48
- .describe('JSON body. When true, only tickets with no assignee. Cannot be combined with assigneeUserIds.'),
49
- isFollowUp: z
50
- .boolean()
51
- .optional()
52
- .describe('JSON body. Filter by follow-up flag.'),
50
+ .describe('When true, only tickets with no assignee. Cannot be combined with assigneeUserIds.'),
51
+ isFollowUp: z.boolean().optional().describe('Filter by follow-up flag.'),
53
52
  isSpam: z
54
53
  .boolean()
55
54
  .optional()
56
- .describe('JSON body. Filter by spam flag. Defaults to non-spam tickets when omitted.'),
55
+ .describe('Filter by spam flag. Defaults to non-spam tickets when omitted.'),
57
56
  advancedFilters: z
58
57
  .object({
59
58
  labels: z
@@ -66,12 +65,12 @@ export const listTickets = {
66
65
  labelIds: z.array(z.string()).min(1).max(TICKET_FILTER_ARRAY_MAX),
67
66
  })
68
67
  .optional()
69
- .describe('JSON body. Filter tickets by conversation labels.'),
68
+ .describe('Filter tickets by conversation labels. Label ids come from listLabels.'),
70
69
  ticketFields: z
71
70
  .array(z.object({
72
71
  ticketFieldId: z
73
72
  .string()
74
- .describe('Custom field id, or a system key: aiCsat, aiSummary, salesRevenue, isConverted.'),
73
+ .describe('Custom field id from listTicketFields, or a system key: aiCsat, aiSummary, salesRevenue, isConverted.'),
75
74
  operator: z.enum([
76
75
  'equal',
77
76
  'not_equal',
@@ -99,13 +98,13 @@ export const listTickets = {
99
98
  .describe('Upper bound for between. Required with min when operator is between.'),
100
99
  }))
101
100
  .optional()
102
- .describe('JSON body. Filter on custom ticket fields or system fields.'),
101
+ .describe('Filter on custom ticket fields or system fields.'),
103
102
  waitingForReply: z
104
103
  .object({
105
104
  value: z.number().int().min(1).max(43200),
106
105
  })
107
106
  .optional()
108
- .describe('JSON body. Tickets where the buyer has been waiting at least this many minutes (1–43200).'),
107
+ .describe('Tickets where the buyer has been waiting at least this many minutes (1–43200).'),
109
108
  openedAt: z
110
109
  .object({
111
110
  operator: z.enum(['between', 'greater_than', 'less_than']),
@@ -123,11 +122,12 @@ export const listTickets = {
123
122
  .describe('ISO 8601 date-time. Upper bound when operator is between.'),
124
123
  })
125
124
  .optional()
126
- .describe('JSON body. Filter by ticket opened-at time.'),
125
+ .describe('Filter by ticket opened-at time.'),
127
126
  })
128
127
  .optional()
129
- .describe('JSON body. Optional extra filters on labels, ticket fields, waiting time, and opened-at.'),
128
+ .describe('Optional extra filters on labels, ticket fields, waiting time, and opened-at.'),
130
129
  }),
131
- annotations: { readOnlyHint: true },
130
+ outputSchema: envelope(z.array(ticket), 'A page of tickets, newest message first.', { paginated: true }),
131
+ annotations: { readOnlyHint: true, openWorldHint: true },
132
132
  };
133
133
  //# sourceMappingURL=list-tickets.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"list-tickets.js","sourceRoot":"","sources":["../../../src/tools/tickets/list-tickets.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"list-tickets.js","sourceRoot":"","sources":["../../../src/tools/tickets/list-tickets.ts"],"names":[],"mappings":"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"}
@@ -1,26 +1,33 @@
1
1
  import { z } from 'zod';
2
- import { describeHttpRequest, expand, fieldValue, } from '../common.js';
2
+ import { expand, fieldValue } from '../common.js';
3
+ import { envelope, ticket } from '../responses.js';
3
4
  const queryKeys = ['expand'];
4
5
  export const updateTicketField = {
5
6
  name: 'updateTicketField',
6
7
  title: 'Update a ticket field value',
7
- description: `Required scope: tickets:write. ${describeHttpRequest('PATCH', '/v1/tickets/fields', queryKeys)} Set or clear one field on a ticket. Send null as newValue to unset. Send ticketFieldsUpdatedAt from the last read; a mismatch returns 409.`,
8
+ description: 'Set or clear exactly one custom field on a ticket, and return the updated ticket. Resolve ticketFieldId with listTicketFields and read the ticket first: ticketFieldsUpdatedAt must be the value from that read, or the write is rejected with 409 because someone else changed a field in the meantime — re-read and retry. Send null as newValue to unset. Requires the tickets:write scope.',
9
+ scope: 'tickets:write',
8
10
  method: 'PATCH',
9
11
  path: '/v1/tickets/fields',
10
12
  queryKeys,
11
13
  inputSchema: z.object({
12
- expand: expand('Related objects to include on the updated ticket: account, conversation, assignee, handledBy.'),
13
- ticketId: z.string().min(1).describe('JSON body. The ID of the ticket.'),
14
+ expand: expand(['account', 'conversation', 'assignee', 'handledBy'], 'Replace these ids on the returned ticket with the named object.'),
15
+ ticketId: z.string().min(1).describe('The ID of the ticket.'),
14
16
  ticketFieldId: z
15
17
  .string()
16
18
  .min(1)
17
- .describe('JSON body. The ID of the ticket field.'),
19
+ .describe('The ID of the ticket field, from listTicketFields.'),
18
20
  ticketFieldsUpdatedAt: z
19
21
  .string()
20
22
  .optional()
21
- .describe('JSON body. ISO 8601 date-time from the last read. Omit if the ticket has never had a field update.'),
22
- newValue: fieldValue.describe('JSON body. The new field value. Send null to unset.'),
23
+ .describe('ISO 8601 date-time. The ticketFieldsUpdatedAt you last read. Omit only when the ticket has never had a field update.'),
24
+ newValue: fieldValue.describe('The new value, matching the field dataType. Send null to unset.'),
23
25
  }),
24
- annotations: { readOnlyHint: false, destructiveHint: false },
26
+ outputSchema: envelope(ticket, 'The ticket after the update.'),
27
+ annotations: {
28
+ readOnlyHint: false,
29
+ destructiveHint: false,
30
+ openWorldHint: true,
31
+ },
25
32
  };
26
33
  //# sourceMappingURL=update-ticket-field.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"update-ticket-field.js","sourceRoot":"","sources":["../../../src/tools/tickets/update-ticket-field.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EACL,mBAAmB,EACnB,MAAM,EACN,UAAU,GAEX,MAAM,cAAc,CAAC;AAEtB,MAAM,SAAS,GAAG,CAAC,QAAQ,CAAU,CAAC;AAEtC,MAAM,CAAC,MAAM,iBAAiB,GAAiB;IAC7C,IAAI,EAAE,mBAAmB;IACzB,KAAK,EAAE,6BAA6B;IACpC,WAAW,EAAE,kCAAkC,mBAAmB,CAAC,OAAO,EAAE,oBAAoB,EAAE,SAAS,CAAC,6IAA6I;IACzP,MAAM,EAAE,OAAO;IACf,IAAI,EAAE,oBAAoB;IAC1B,SAAS;IACT,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC;QACpB,MAAM,EAAE,MAAM,CACZ,+FAA+F,CAChG;QACD,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,kCAAkC,CAAC;QACxE,aAAa,EAAE,CAAC;aACb,MAAM,EAAE;aACR,GAAG,CAAC,CAAC,CAAC;aACN,QAAQ,CAAC,wCAAwC,CAAC;QACrD,qBAAqB,EAAE,CAAC;aACrB,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CACP,oGAAoG,CACrG;QACH,QAAQ,EAAE,UAAU,CAAC,QAAQ,CAC3B,qDAAqD,CACtD;KACF,CAAC;IACF,WAAW,EAAE,EAAE,YAAY,EAAE,KAAK,EAAE,eAAe,EAAE,KAAK,EAAE;CAC7D,CAAC"}
1
+ {"version":3,"file":"update-ticket-field.js","sourceRoot":"","sources":["../../../src/tools/tickets/update-ticket-field.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,MAAM,EAAE,UAAU,EAAqB,MAAM,cAAc,CAAC;AACrE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAEnD,MAAM,SAAS,GAAG,CAAC,QAAQ,CAAU,CAAC;AAEtC,MAAM,CAAC,MAAM,iBAAiB,GAAiB;IAC7C,IAAI,EAAE,mBAAmB;IACzB,KAAK,EAAE,6BAA6B;IACpC,WAAW,EACT,gYAAgY;IAClY,KAAK,EAAE,eAAe;IACtB,MAAM,EAAE,OAAO;IACf,IAAI,EAAE,oBAAoB;IAC1B,SAAS;IACT,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC;QACpB,MAAM,EAAE,MAAM,CACZ,CAAC,SAAS,EAAE,cAAc,EAAE,UAAU,EAAE,WAAW,CAAC,EACpD,iEAAiE,CAClE;QACD,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,uBAAuB,CAAC;QAC7D,aAAa,EAAE,CAAC;aACb,MAAM,EAAE;aACR,GAAG,CAAC,CAAC,CAAC;aACN,QAAQ,CAAC,oDAAoD,CAAC;QACjE,qBAAqB,EAAE,CAAC;aACrB,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CACP,sHAAsH,CACvH;QACH,QAAQ,EAAE,UAAU,CAAC,QAAQ,CAC3B,iEAAiE,CAClE;KACF,CAAC;IACF,YAAY,EAAE,QAAQ,CAAC,MAAM,EAAE,8BAA8B,CAAC;IAC9D,WAAW,EAAE;QACX,YAAY,EAAE,KAAK;QACnB,eAAe,EAAE,KAAK;QACtB,aAAa,EAAE,IAAI;KACpB;CACF,CAAC"}
@@ -1,10 +1,12 @@
1
1
  import { z } from 'zod';
2
- import { describeHttpRequest, expand } from '../common.js';
2
+ import { expand } from '../common.js';
3
+ import { envelope, user } from '../responses.js';
3
4
  const queryKeys = ['userId', 'expand'];
4
5
  export const listUsers = {
5
6
  name: 'listUsers',
6
7
  title: 'List users',
7
- description: `Required scope: users:read. ${describeHttpRequest('GET', '/v1/users', queryKeys)} Full list of users on the store. Not paginated. Optionally filter to one userId (UUID). Pass expand=role to include { id, name } for the role.`,
8
+ description: 'Full list of the seats on the store, with the role of each. Not paginated. Call this to turn an agent’s name into an id — and take userId, the UUID, not the id beside it: userId is what ticket assignment, handledBy and the listTeams filter match on. Requires the users:read scope.',
9
+ scope: 'users:read',
8
10
  method: 'GET',
9
11
  path: '/v1/users',
10
12
  queryKeys,
@@ -13,9 +15,10 @@ export const listUsers = {
13
15
  .string()
14
16
  .min(1)
15
17
  .optional()
16
- .describe('Query parameter. Restrict to this user (UUID).'),
17
- expand: expand('Pass role to include { id, name } for the role. Without expand, the response keeps roleId.'),
18
+ .describe('Restrict to this user UUID.'),
19
+ expand: expand(['role'], 'Replace roleId with { id, name }.'),
18
20
  }),
19
- annotations: { readOnlyHint: true },
21
+ outputSchema: envelope(z.array(user), 'Every user seat on the store.'),
22
+ annotations: { readOnlyHint: true, openWorldHint: true },
20
23
  };
21
24
  //# sourceMappingURL=list-users.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"list-users.js","sourceRoot":"","sources":["../../../src/tools/users/list-users.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,mBAAmB,EAAE,MAAM,EAAqB,MAAM,cAAc,CAAC;AAE9E,MAAM,SAAS,GAAG,CAAC,QAAQ,EAAE,QAAQ,CAAU,CAAC;AAEhD,MAAM,CAAC,MAAM,SAAS,GAAiB;IACrC,IAAI,EAAE,WAAW;IACjB,KAAK,EAAE,YAAY;IACnB,WAAW,EAAE,+BAA+B,mBAAmB,CAAC,KAAK,EAAE,WAAW,EAAE,SAAS,CAAC,iJAAiJ;IAC/O,MAAM,EAAE,KAAK;IACb,IAAI,EAAE,WAAW;IACjB,SAAS;IACT,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC;QACpB,MAAM,EAAE,CAAC;aACN,MAAM,EAAE;aACR,GAAG,CAAC,CAAC,CAAC;aACN,QAAQ,EAAE;aACV,QAAQ,CAAC,gDAAgD,CAAC;QAC7D,MAAM,EAAE,MAAM,CACZ,4FAA4F,CAC7F;KACF,CAAC;IACF,WAAW,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE;CACpC,CAAC"}
1
+ {"version":3,"file":"list-users.js","sourceRoot":"","sources":["../../../src/tools/users/list-users.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,MAAM,EAAqB,MAAM,cAAc,CAAC;AACzD,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAEjD,MAAM,SAAS,GAAG,CAAC,QAAQ,EAAE,QAAQ,CAAU,CAAC;AAEhD,MAAM,CAAC,MAAM,SAAS,GAAiB;IACrC,IAAI,EAAE,WAAW;IACjB,KAAK,EAAE,YAAY;IACnB,WAAW,EACT,0RAA0R;IAC5R,KAAK,EAAE,YAAY;IACnB,MAAM,EAAE,KAAK;IACb,IAAI,EAAE,WAAW;IACjB,SAAS;IACT,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC;QACpB,MAAM,EAAE,CAAC;aACN,MAAM,EAAE;aACR,GAAG,CAAC,CAAC,CAAC;aACN,QAAQ,EAAE;aACV,QAAQ,CAAC,6BAA6B,CAAC;QAC1C,MAAM,EAAE,MAAM,CAAC,CAAC,MAAM,CAAC,EAAE,mCAAmC,CAAC;KAC9D,CAAC;IACF,YAAY,EAAE,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,+BAA+B,CAAC;IACtE,WAAW,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE;CACzD,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zaapi/open-api-mcp",
3
- "version": "1.2.0",
3
+ "version": "1.4.0",
4
4
  "description": "MCP server for the Zaapi Open API",
5
5
  "homepage": "https://github.com/Zaapi/zaapi-open-api-mcp#readme",
6
6
  "bugs": {