syncromsp-mcp 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 (108) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +244 -0
  3. package/dist/api-client.d.ts +21 -0
  4. package/dist/api-client.d.ts.map +1 -0
  5. package/dist/api-client.js +117 -0
  6. package/dist/api-client.js.map +1 -0
  7. package/dist/auth.d.ts +37 -0
  8. package/dist/auth.d.ts.map +1 -0
  9. package/dist/auth.js +133 -0
  10. package/dist/auth.js.map +1 -0
  11. package/dist/domains/admin.d.ts +4 -0
  12. package/dist/domains/admin.d.ts.map +1 -0
  13. package/dist/domains/admin.js +807 -0
  14. package/dist/domains/admin.js.map +1 -0
  15. package/dist/domains/appointments.d.ts +4 -0
  16. package/dist/domains/appointments.d.ts.map +1 -0
  17. package/dist/domains/appointments.js +231 -0
  18. package/dist/domains/appointments.js.map +1 -0
  19. package/dist/domains/assets.d.ts +4 -0
  20. package/dist/domains/assets.d.ts.map +1 -0
  21. package/dist/domains/assets.js +138 -0
  22. package/dist/domains/assets.js.map +1 -0
  23. package/dist/domains/contacts.d.ts +4 -0
  24. package/dist/domains/contacts.d.ts.map +1 -0
  25. package/dist/domains/contacts.js +148 -0
  26. package/dist/domains/contacts.js.map +1 -0
  27. package/dist/domains/contracts.d.ts +4 -0
  28. package/dist/domains/contracts.d.ts.map +1 -0
  29. package/dist/domains/contracts.js +125 -0
  30. package/dist/domains/contracts.js.map +1 -0
  31. package/dist/domains/customers.d.ts +4 -0
  32. package/dist/domains/customers.d.ts.map +1 -0
  33. package/dist/domains/customers.js +323 -0
  34. package/dist/domains/customers.js.map +1 -0
  35. package/dist/domains/estimates.d.ts +4 -0
  36. package/dist/domains/estimates.d.ts.map +1 -0
  37. package/dist/domains/estimates.js +262 -0
  38. package/dist/domains/estimates.js.map +1 -0
  39. package/dist/domains/index.d.ts +5 -0
  40. package/dist/domains/index.d.ts.map +1 -0
  41. package/dist/domains/index.js +34 -0
  42. package/dist/domains/index.js.map +1 -0
  43. package/dist/domains/invoices.d.ts +4 -0
  44. package/dist/domains/invoices.d.ts.map +1 -0
  45. package/dist/domains/invoices.js +292 -0
  46. package/dist/domains/invoices.js.map +1 -0
  47. package/dist/domains/leads.d.ts +4 -0
  48. package/dist/domains/leads.d.ts.map +1 -0
  49. package/dist/domains/leads.js +135 -0
  50. package/dist/domains/leads.js.map +1 -0
  51. package/dist/domains/payments.d.ts +4 -0
  52. package/dist/domains/payments.d.ts.map +1 -0
  53. package/dist/domains/payments.js +188 -0
  54. package/dist/domains/payments.js.map +1 -0
  55. package/dist/domains/products.d.ts +4 -0
  56. package/dist/domains/products.d.ts.map +1 -0
  57. package/dist/domains/products.js +350 -0
  58. package/dist/domains/products.js.map +1 -0
  59. package/dist/domains/rmm.d.ts +4 -0
  60. package/dist/domains/rmm.d.ts.map +1 -0
  61. package/dist/domains/rmm.js +100 -0
  62. package/dist/domains/rmm.js.map +1 -0
  63. package/dist/domains/scheduling.d.ts +4 -0
  64. package/dist/domains/scheduling.d.ts.map +1 -0
  65. package/dist/domains/scheduling.js +206 -0
  66. package/dist/domains/scheduling.js.map +1 -0
  67. package/dist/domains/tickets.d.ts +4 -0
  68. package/dist/domains/tickets.d.ts.map +1 -0
  69. package/dist/domains/tickets.js +533 -0
  70. package/dist/domains/tickets.js.map +1 -0
  71. package/dist/domains/time.d.ts +4 -0
  72. package/dist/domains/time.d.ts.map +1 -0
  73. package/dist/domains/time.js +93 -0
  74. package/dist/domains/time.js.map +1 -0
  75. package/dist/index.d.ts +3 -0
  76. package/dist/index.d.ts.map +1 -0
  77. package/dist/index.js +137 -0
  78. package/dist/index.js.map +1 -0
  79. package/dist/server.d.ts +5 -0
  80. package/dist/server.d.ts.map +1 -0
  81. package/dist/server.js +183 -0
  82. package/dist/server.js.map +1 -0
  83. package/dist/session.d.ts +12 -0
  84. package/dist/session.d.ts.map +1 -0
  85. package/dist/session.js +31 -0
  86. package/dist/session.js.map +1 -0
  87. package/dist/types.d.ts +46 -0
  88. package/dist/types.d.ts.map +1 -0
  89. package/dist/types.js +44 -0
  90. package/dist/types.js.map +1 -0
  91. package/dist/utils/pagination.d.ts +12 -0
  92. package/dist/utils/pagination.d.ts.map +1 -0
  93. package/dist/utils/pagination.js +18 -0
  94. package/dist/utils/pagination.js.map +1 -0
  95. package/dist/utils/rate-limiter.d.ts +15 -0
  96. package/dist/utils/rate-limiter.d.ts.map +1 -0
  97. package/dist/utils/rate-limiter.js +63 -0
  98. package/dist/utils/rate-limiter.js.map +1 -0
  99. package/dist/utils/validators.d.ts +9 -0
  100. package/dist/utils/validators.d.ts.map +1 -0
  101. package/dist/utils/validators.js +59 -0
  102. package/dist/utils/validators.js.map +1 -0
  103. package/dist/utils/version-check.d.ts +7 -0
  104. package/dist/utils/version-check.d.ts.map +1 -0
  105. package/dist/utils/version-check.js +59 -0
  106. package/dist/utils/version-check.js.map +1 -0
  107. package/manifest.json +64 -0
  108. package/package.json +57 -0
@@ -0,0 +1,262 @@
1
+ import { jsonResult, textResult } from "../types.js";
2
+ import { requireId, optionalString, optionalNumber, optionalBoolean, optionalId, pickDefined } from "../utils/validators.js";
3
+ export function createDomain(client) {
4
+ const tools = [
5
+ {
6
+ definition: {
7
+ name: "estimates_list",
8
+ description: "List estimates with optional filters",
9
+ inputSchema: {
10
+ type: "object",
11
+ properties: {
12
+ status: { type: "string", description: "Filter by status (Fresh, Draft, Approved, Declined)" },
13
+ customer_id: { type: "number", description: "Filter by customer ID" },
14
+ page: { type: "number", description: "Page number" },
15
+ },
16
+ },
17
+ },
18
+ handler: async (args) => {
19
+ const params = pickDefined({
20
+ status: optionalString(args.status),
21
+ customer_id: optionalId(args.customer_id),
22
+ page: optionalNumber(args.page),
23
+ });
24
+ return jsonResult(await client.get("/estimates", params));
25
+ },
26
+ },
27
+ {
28
+ definition: {
29
+ name: "estimates_get",
30
+ description: "Get a single estimate by ID",
31
+ inputSchema: {
32
+ type: "object",
33
+ properties: { id: { type: "number", description: "Estimate ID" } },
34
+ required: ["id"],
35
+ },
36
+ },
37
+ handler: async (args) => jsonResult(await client.get(`/estimates/${requireId(args.id)}`)),
38
+ },
39
+ {
40
+ definition: {
41
+ name: "estimates_create",
42
+ description: "Create a new estimate. Note: line_items array in the create body is IGNORED by the API -- add line items via estimates_add_line_item after creation.",
43
+ inputSchema: {
44
+ type: "object",
45
+ properties: {
46
+ customer_id: { type: "number", description: "Customer ID (required)" },
47
+ name: { type: "string", description: "Estimate name" },
48
+ number: { type: "string", description: "Estimate number" },
49
+ date: { type: "string", description: "Date" },
50
+ note: { type: "string", description: "Note" },
51
+ status: { type: "string", description: "Status: Fresh, Draft, Approved, Declined" },
52
+ ticket_id: { type: "number", description: "Associated ticket ID" },
53
+ location_id: { type: "number", description: "Location ID" },
54
+ line_items: { type: "array", description: "Array of line item objects" },
55
+ },
56
+ required: ["customer_id"],
57
+ },
58
+ },
59
+ handler: async (args) => {
60
+ const body = pickDefined({
61
+ customer_id: requireId(args.customer_id, "customer_id"),
62
+ name: optionalString(args.name),
63
+ number: optionalString(args.number),
64
+ date: optionalString(args.date),
65
+ note: optionalString(args.note),
66
+ status: optionalString(args.status),
67
+ ticket_id: optionalId(args.ticket_id),
68
+ location_id: optionalId(args.location_id),
69
+ line_items: args.line_items,
70
+ });
71
+ return jsonResult(await client.post("/estimates", body));
72
+ },
73
+ },
74
+ {
75
+ definition: {
76
+ name: "estimates_update",
77
+ description: "Update an existing estimate",
78
+ inputSchema: {
79
+ type: "object",
80
+ properties: {
81
+ id: { type: "number", description: "Estimate ID (required)" },
82
+ customer_id: { type: "number", description: "Customer ID" },
83
+ name: { type: "string", description: "Estimate name" },
84
+ number: { type: "string", description: "Number" },
85
+ date: { type: "string", description: "Date" },
86
+ note: { type: "string", description: "Note" },
87
+ status: { type: "string", description: "Status: Fresh, Draft, Approved, Declined" },
88
+ ticket_id: { type: "number", description: "Ticket ID" },
89
+ location_id: { type: "number", description: "Location ID" },
90
+ },
91
+ required: ["id"],
92
+ },
93
+ },
94
+ handler: async (args) => {
95
+ const id = requireId(args.id);
96
+ const body = pickDefined({
97
+ customer_id: optionalId(args.customer_id),
98
+ name: optionalString(args.name),
99
+ number: optionalString(args.number),
100
+ date: optionalString(args.date),
101
+ note: optionalString(args.note),
102
+ status: optionalString(args.status),
103
+ ticket_id: optionalId(args.ticket_id),
104
+ location_id: optionalId(args.location_id),
105
+ });
106
+ return jsonResult(await client.put(`/estimates/${id}`, body));
107
+ },
108
+ },
109
+ {
110
+ definition: {
111
+ name: "estimates_delete",
112
+ description: "DELETE an estimate permanently. The user MUST confirm.",
113
+ inputSchema: {
114
+ type: "object",
115
+ properties: {
116
+ id: { type: "number", description: "Estimate ID" },
117
+ confirmed: { type: "boolean", description: "Must be true" },
118
+ },
119
+ required: ["id", "confirmed"],
120
+ },
121
+ },
122
+ handler: async (args) => {
123
+ const id = requireId(args.id);
124
+ if (args.confirmed !== true)
125
+ return textResult(`⚠️ CONFIRMATION REQUIRED: Permanently delete estimate #${id}? Call again with confirmed: true.`);
126
+ const result = await client.delete(`/estimates/${id}`);
127
+ return result ? jsonResult(result) : textResult(`Estimate #${id} deleted.`);
128
+ },
129
+ },
130
+ {
131
+ definition: {
132
+ name: "estimates_print",
133
+ description: "Generate a printable PDF for an estimate",
134
+ inputSchema: {
135
+ type: "object",
136
+ properties: { id: { type: "number", description: "Estimate ID" } },
137
+ required: ["id"],
138
+ },
139
+ },
140
+ handler: async (args) => jsonResult(await client.post(`/estimates/${requireId(args.id)}/print`)),
141
+ },
142
+ {
143
+ definition: {
144
+ name: "estimates_email",
145
+ description: "Email an estimate to the customer",
146
+ inputSchema: {
147
+ type: "object",
148
+ properties: { id: { type: "number", description: "Estimate ID" } },
149
+ required: ["id"],
150
+ },
151
+ },
152
+ handler: async (args) => jsonResult(await client.post(`/estimates/${requireId(args.id)}/email`)),
153
+ },
154
+ {
155
+ definition: {
156
+ name: "estimates_convert_to_invoice",
157
+ description: "Convert an estimate to an invoice",
158
+ inputSchema: {
159
+ type: "object",
160
+ properties: { id: { type: "number", description: "Estimate ID" } },
161
+ required: ["id"],
162
+ },
163
+ },
164
+ handler: async (args) => jsonResult(await client.post(`/estimates/${requireId(args.id)}/convert_to_invoice`)),
165
+ },
166
+ {
167
+ definition: {
168
+ name: "estimates_add_line_item",
169
+ description: "Add a line item to an estimate. When using product_id, only product_id + quantity are needed -- the API auto-fills name, cost, and price from the product catalog.",
170
+ inputSchema: {
171
+ type: "object",
172
+ properties: {
173
+ id: { type: "number", description: "Estimate ID" },
174
+ item: { type: "string", description: "Item name" },
175
+ name: { type: "string", description: "Display name" },
176
+ quantity: { type: "number", description: "Quantity" },
177
+ price: { type: "number", description: "Price" },
178
+ cost: { type: "number", description: "Cost" },
179
+ product_id: { type: "number", description: "Product ID" },
180
+ upc_code: { type: "string", description: "UPC code" },
181
+ discount_percent: { type: "number", description: "Discount %" },
182
+ taxable: { type: "boolean", description: "Whether taxable" },
183
+ tax_rate_id: { type: "number", description: "Tax rate ID" },
184
+ position: { type: "number", description: "Sort position" },
185
+ },
186
+ required: ["id"],
187
+ },
188
+ },
189
+ handler: async (args) => {
190
+ const id = requireId(args.id);
191
+ const body = pickDefined({
192
+ item: optionalString(args.item),
193
+ name: optionalString(args.name),
194
+ quantity: optionalNumber(args.quantity),
195
+ price: optionalNumber(args.price),
196
+ cost: optionalNumber(args.cost),
197
+ product_id: optionalId(args.product_id),
198
+ upc_code: optionalString(args.upc_code),
199
+ discount_percent: optionalNumber(args.discount_percent),
200
+ taxable: optionalBoolean(args.taxable),
201
+ tax_rate_id: optionalId(args.tax_rate_id),
202
+ position: optionalNumber(args.position),
203
+ });
204
+ return jsonResult(await client.post(`/estimates/${id}/line_items`, body));
205
+ },
206
+ },
207
+ {
208
+ definition: {
209
+ name: "estimates_update_line_item",
210
+ description: "Update a line item on an estimate",
211
+ inputSchema: {
212
+ type: "object",
213
+ properties: {
214
+ id: { type: "number", description: "Estimate ID" },
215
+ line_item_id: { type: "number", description: "Line item ID" },
216
+ item: { type: "string" }, name: { type: "string" },
217
+ quantity: { type: "number" }, price: { type: "number" },
218
+ cost: { type: "number" }, discount_percent: { type: "number" },
219
+ taxable: { type: "boolean" },
220
+ },
221
+ required: ["id", "line_item_id"],
222
+ },
223
+ },
224
+ handler: async (args) => {
225
+ const id = requireId(args.id);
226
+ const lineItemId = requireId(args.line_item_id, "line_item_id");
227
+ const body = pickDefined({
228
+ item: optionalString(args.item), name: optionalString(args.name),
229
+ quantity: optionalNumber(args.quantity), price: optionalNumber(args.price),
230
+ cost: optionalNumber(args.cost), discount_percent: optionalNumber(args.discount_percent),
231
+ taxable: optionalBoolean(args.taxable),
232
+ });
233
+ return jsonResult(await client.put(`/estimates/${id}/line_items/${lineItemId}`, body));
234
+ },
235
+ },
236
+ {
237
+ definition: {
238
+ name: "estimates_delete_line_item",
239
+ description: "Delete a line item from an estimate. The user MUST confirm.",
240
+ inputSchema: {
241
+ type: "object",
242
+ properties: {
243
+ id: { type: "number", description: "Estimate ID" },
244
+ line_item_id: { type: "number", description: "Line item ID" },
245
+ confirmed: { type: "boolean", description: "Must be true" },
246
+ },
247
+ required: ["id", "line_item_id", "confirmed"],
248
+ },
249
+ },
250
+ handler: async (args) => {
251
+ const id = requireId(args.id);
252
+ const lineItemId = requireId(args.line_item_id, "line_item_id");
253
+ if (args.confirmed !== true)
254
+ return textResult(`⚠️ CONFIRMATION REQUIRED: Delete line item #${lineItemId} from estimate #${id}? Call again with confirmed: true.`);
255
+ const result = await client.delete(`/estimates/${id}/line_items/${lineItemId}`);
256
+ return result ? jsonResult(result) : textResult(`Line item deleted.`);
257
+ },
258
+ },
259
+ ];
260
+ return { name: "estimates", description: "Estimates, line items, print/email, convert to invoice", getTools: () => tools };
261
+ }
262
+ //# sourceMappingURL=estimates.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"estimates.js","sourceRoot":"","sources":["../../src/domains/estimates.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,cAAc,EAAE,eAAe,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAE7H,MAAM,UAAU,YAAY,CAAC,MAAuB;IAClD,MAAM,KAAK,GAAiB;QAC1B;YACE,UAAU,EAAE;gBACV,IAAI,EAAE,gBAAgB;gBACtB,WAAW,EAAE,sCAAsC;gBACnD,WAAW,EAAE;oBACX,IAAI,EAAE,QAAiB;oBACvB,UAAU,EAAE;wBACV,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,qDAAqD,EAAE;wBAC9F,WAAW,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,uBAAuB,EAAE;wBACrE,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,aAAa,EAAE;qBACrD;iBACF;aACF;YACD,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;gBACtB,MAAM,MAAM,GAAG,WAAW,CAAC;oBACzB,MAAM,EAAE,cAAc,CAAC,IAAI,CAAC,MAAM,CAAC;oBACnC,WAAW,EAAE,UAAU,CAAC,IAAI,CAAC,WAAW,CAAC;oBACzC,IAAI,EAAE,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC;iBAChC,CAAC,CAAC;gBACH,OAAO,UAAU,CAAC,MAAM,MAAM,CAAC,GAAG,CAAC,YAAY,EAAE,MAAmD,CAAC,CAAC,CAAC;YACzG,CAAC;SACF;QACD;YACE,UAAU,EAAE;gBACV,IAAI,EAAE,eAAe;gBACrB,WAAW,EAAE,6BAA6B;gBAC1C,WAAW,EAAE;oBACX,IAAI,EAAE,QAAiB;oBACvB,UAAU,EAAE,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,aAAa,EAAE,EAAE;oBAClE,QAAQ,EAAE,CAAC,IAAI,CAAC;iBACjB;aACF;YACD,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,CAAC,UAAU,CAAC,MAAM,MAAM,CAAC,GAAG,CAAC,cAAc,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;SAC1F;QACD;YACE,UAAU,EAAE;gBACV,IAAI,EAAE,kBAAkB;gBACxB,WAAW,EAAE,sJAAsJ;gBACnK,WAAW,EAAE;oBACX,IAAI,EAAE,QAAiB;oBACvB,UAAU,EAAE;wBACV,WAAW,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,wBAAwB,EAAE;wBACtE,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,eAAe,EAAE;wBACtD,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,iBAAiB,EAAE;wBAC1D,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,EAAE;wBAC7C,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,EAAE;wBAC7C,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,0CAA0C,EAAE;wBACnF,SAAS,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,sBAAsB,EAAE;wBAClE,WAAW,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,aAAa,EAAE;wBAC3D,UAAU,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,WAAW,EAAE,4BAA4B,EAAE;qBACzE;oBACD,QAAQ,EAAE,CAAC,aAAa,CAAC;iBAC1B;aACF;YACD,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;gBACtB,MAAM,IAAI,GAAG,WAAW,CAAC;oBACvB,WAAW,EAAE,SAAS,CAAC,IAAI,CAAC,WAAW,EAAE,aAAa,CAAC;oBACvD,IAAI,EAAE,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC;oBAC/B,MAAM,EAAE,cAAc,CAAC,IAAI,CAAC,MAAM,CAAC;oBACnC,IAAI,EAAE,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC;oBAC/B,IAAI,EAAE,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC;oBAC/B,MAAM,EAAE,cAAc,CAAC,IAAI,CAAC,MAAM,CAAC;oBACnC,SAAS,EAAE,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC;oBACrC,WAAW,EAAE,UAAU,CAAC,IAAI,CAAC,WAAW,CAAC;oBACzC,UAAU,EAAE,IAAI,CAAC,UAAU;iBAC5B,CAAC,CAAC;gBACH,OAAO,UAAU,CAAC,MAAM,MAAM,CAAC,IAAI,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC,CAAC;YAC3D,CAAC;SACF;QACD;YACE,UAAU,EAAE;gBACV,IAAI,EAAE,kBAAkB;gBACxB,WAAW,EAAE,6BAA6B;gBAC1C,WAAW,EAAE;oBACX,IAAI,EAAE,QAAiB;oBACvB,UAAU,EAAE;wBACV,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,wBAAwB,EAAE;wBAC7D,WAAW,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,aAAa,EAAE;wBAC3D,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,eAAe,EAAE;wBACtD,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,QAAQ,EAAE;wBACjD,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,EAAE;wBAC7C,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,EAAE;wBAC7C,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,0CAA0C,EAAE;wBACnF,SAAS,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,WAAW,EAAE;wBACvD,WAAW,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,aAAa,EAAE;qBAC5D;oBACD,QAAQ,EAAE,CAAC,IAAI,CAAC;iBACjB;aACF;YACD,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;gBACtB,MAAM,EAAE,GAAG,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;gBAC9B,MAAM,IAAI,GAAG,WAAW,CAAC;oBACvB,WAAW,EAAE,UAAU,CAAC,IAAI,CAAC,WAAW,CAAC;oBACzC,IAAI,EAAE,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC;oBAC/B,MAAM,EAAE,cAAc,CAAC,IAAI,CAAC,MAAM,CAAC;oBACnC,IAAI,EAAE,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC;oBAC/B,IAAI,EAAE,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC;oBAC/B,MAAM,EAAE,cAAc,CAAC,IAAI,CAAC,MAAM,CAAC;oBACnC,SAAS,EAAE,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC;oBACrC,WAAW,EAAE,UAAU,CAAC,IAAI,CAAC,WAAW,CAAC;iBAC1C,CAAC,CAAC;gBACH,OAAO,UAAU,CAAC,MAAM,MAAM,CAAC,GAAG,CAAC,cAAc,EAAE,EAAE,EAAE,IAAI,CAAC,CAAC,CAAC;YAChE,CAAC;SACF;QACD;YACE,UAAU,EAAE;gBACV,IAAI,EAAE,kBAAkB;gBACxB,WAAW,EAAE,wDAAwD;gBACrE,WAAW,EAAE;oBACX,IAAI,EAAE,QAAiB;oBACvB,UAAU,EAAE;wBACV,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,aAAa,EAAE;wBAClD,SAAS,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,WAAW,EAAE,cAAc,EAAE;qBAC5D;oBACD,QAAQ,EAAE,CAAC,IAAI,EAAE,WAAW,CAAC;iBAC9B;aACF;YACD,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;gBACtB,MAAM,EAAE,GAAG,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;gBAC9B,IAAI,IAAI,CAAC,SAAS,KAAK,IAAI;oBAAE,OAAO,UAAU,CAAC,0DAA0D,EAAE,oCAAoC,CAAC,CAAC;gBACjJ,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC;gBACvD,OAAO,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,aAAa,EAAE,WAAW,CAAC,CAAC;YAC9E,CAAC;SACF;QACD;YACE,UAAU,EAAE;gBACV,IAAI,EAAE,iBAAiB;gBACvB,WAAW,EAAE,0CAA0C;gBACvD,WAAW,EAAE;oBACX,IAAI,EAAE,QAAiB;oBACvB,UAAU,EAAE,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,aAAa,EAAE,EAAE;oBAClE,QAAQ,EAAE,CAAC,IAAI,CAAC;iBACjB;aACF;YACD,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,CAAC,UAAU,CAAC,MAAM,MAAM,CAAC,IAAI,CAAC,cAAc,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC;SACjG;QACD;YACE,UAAU,EAAE;gBACV,IAAI,EAAE,iBAAiB;gBACvB,WAAW,EAAE,mCAAmC;gBAChD,WAAW,EAAE;oBACX,IAAI,EAAE,QAAiB;oBACvB,UAAU,EAAE,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,aAAa,EAAE,EAAE;oBAClE,QAAQ,EAAE,CAAC,IAAI,CAAC;iBACjB;aACF;YACD,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,CAAC,UAAU,CAAC,MAAM,MAAM,CAAC,IAAI,CAAC,cAAc,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC;SACjG;QACD;YACE,UAAU,EAAE;gBACV,IAAI,EAAE,8BAA8B;gBACpC,WAAW,EAAE,mCAAmC;gBAChD,WAAW,EAAE;oBACX,IAAI,EAAE,QAAiB;oBACvB,UAAU,EAAE,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,aAAa,EAAE,EAAE;oBAClE,QAAQ,EAAE,CAAC,IAAI,CAAC;iBACjB;aACF;YACD,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,CAAC,UAAU,CAAC,MAAM,MAAM,CAAC,IAAI,CAAC,cAAc,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,qBAAqB,CAAC,CAAC;SAC9G;QACD;YACE,UAAU,EAAE;gBACV,IAAI,EAAE,yBAAyB;gBAC/B,WAAW,EAAE,oKAAoK;gBACjL,WAAW,EAAE;oBACX,IAAI,EAAE,QAAiB;oBACvB,UAAU,EAAE;wBACV,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,aAAa,EAAE;wBAClD,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,WAAW,EAAE;wBAClD,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,cAAc,EAAE;wBACrD,QAAQ,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,UAAU,EAAE;wBACrD,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,OAAO,EAAE;wBAC/C,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,EAAE;wBAC7C,UAAU,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,YAAY,EAAE;wBACzD,QAAQ,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,UAAU,EAAE;wBACrD,gBAAgB,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,YAAY,EAAE;wBAC/D,OAAO,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,WAAW,EAAE,iBAAiB,EAAE;wBAC5D,WAAW,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,aAAa,EAAE;wBAC3D,QAAQ,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,eAAe,EAAE;qBAC3D;oBACD,QAAQ,EAAE,CAAC,IAAI,CAAC;iBACjB;aACF;YACD,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;gBACtB,MAAM,EAAE,GAAG,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;gBAC9B,MAAM,IAAI,GAAG,WAAW,CAAC;oBACvB,IAAI,EAAE,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC;oBAC/B,IAAI,EAAE,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC;oBAC/B,QAAQ,EAAE,cAAc,CAAC,IAAI,CAAC,QAAQ,CAAC;oBACvC,KAAK,EAAE,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC;oBACjC,IAAI,EAAE,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC;oBAC/B,UAAU,EAAE,UAAU,CAAC,IAAI,CAAC,UAAU,CAAC;oBACvC,QAAQ,EAAE,cAAc,CAAC,IAAI,CAAC,QAAQ,CAAC;oBACvC,gBAAgB,EAAE,cAAc,CAAC,IAAI,CAAC,gBAAgB,CAAC;oBACvD,OAAO,EAAE,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC;oBACtC,WAAW,EAAE,UAAU,CAAC,IAAI,CAAC,WAAW,CAAC;oBACzC,QAAQ,EAAE,cAAc,CAAC,IAAI,CAAC,QAAQ,CAAC;iBACxC,CAAC,CAAC;gBACH,OAAO,UAAU,CAAC,MAAM,MAAM,CAAC,IAAI,CAAC,cAAc,EAAE,aAAa,EAAE,IAAI,CAAC,CAAC,CAAC;YAC5E,CAAC;SACF;QACD;YACE,UAAU,EAAE;gBACV,IAAI,EAAE,4BAA4B;gBAClC,WAAW,EAAE,mCAAmC;gBAChD,WAAW,EAAE;oBACX,IAAI,EAAE,QAAiB;oBACvB,UAAU,EAAE;wBACV,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,aAAa,EAAE;wBAClD,YAAY,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,cAAc,EAAE;wBAC7D,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;wBAClD,QAAQ,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;wBACvD,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,gBAAgB,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;wBAC9D,OAAO,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE;qBAC7B;oBACD,QAAQ,EAAE,CAAC,IAAI,EAAE,cAAc,CAAC;iBACjC;aACF;YACD,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;gBACtB,MAAM,EAAE,GAAG,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;gBAC9B,MAAM,UAAU,GAAG,SAAS,CAAC,IAAI,CAAC,YAAY,EAAE,cAAc,CAAC,CAAC;gBAChE,MAAM,IAAI,GAAG,WAAW,CAAC;oBACvB,IAAI,EAAE,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC;oBAChE,QAAQ,EAAE,cAAc,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,KAAK,EAAE,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC;oBAC1E,IAAI,EAAE,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,gBAAgB,EAAE,cAAc,CAAC,IAAI,CAAC,gBAAgB,CAAC;oBACxF,OAAO,EAAE,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC;iBACvC,CAAC,CAAC;gBACH,OAAO,UAAU,CAAC,MAAM,MAAM,CAAC,GAAG,CAAC,cAAc,EAAE,eAAe,UAAU,EAAE,EAAE,IAAI,CAAC,CAAC,CAAC;YACzF,CAAC;SACF;QACD;YACE,UAAU,EAAE;gBACV,IAAI,EAAE,4BAA4B;gBAClC,WAAW,EAAE,6DAA6D;gBAC1E,WAAW,EAAE;oBACX,IAAI,EAAE,QAAiB;oBACvB,UAAU,EAAE;wBACV,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,aAAa,EAAE;wBAClD,YAAY,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,cAAc,EAAE;wBAC7D,SAAS,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,WAAW,EAAE,cAAc,EAAE;qBAC5D;oBACD,QAAQ,EAAE,CAAC,IAAI,EAAE,cAAc,EAAE,WAAW,CAAC;iBAC9C;aACF;YACD,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;gBACtB,MAAM,EAAE,GAAG,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;gBAC9B,MAAM,UAAU,GAAG,SAAS,CAAC,IAAI,CAAC,YAAY,EAAE,cAAc,CAAC,CAAC;gBAChE,IAAI,IAAI,CAAC,SAAS,KAAK,IAAI;oBAAE,OAAO,UAAU,CAAC,+CAA+C,UAAU,mBAAmB,EAAE,oCAAoC,CAAC,CAAC;gBACnK,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,cAAc,EAAE,eAAe,UAAU,EAAE,CAAC,CAAC;gBAChF,OAAO,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,oBAAoB,CAAC,CAAC;YACxE,CAAC;SACF;KACF,CAAC;IAEF,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,WAAW,EAAE,wDAAwD,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC,KAAK,EAAE,CAAC;AAC7H,CAAC"}
@@ -0,0 +1,5 @@
1
+ import type { DomainHandler, DomainName } from "../types.js";
2
+ import type { SyncroApiClient } from "../api-client.js";
3
+ export declare function loadDomain(name: DomainName, client: SyncroApiClient): Promise<DomainHandler>;
4
+ export declare function clearDomainCache(): void;
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/domains/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAC7D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAsBxD,wBAAsB,UAAU,CAAC,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,aAAa,CAAC,CAWlG;AAED,wBAAgB,gBAAgB,IAAI,IAAI,CAEvC"}
@@ -0,0 +1,34 @@
1
+ const domainCache = new Map();
2
+ const domainLoaders = {
3
+ tickets: () => import("./tickets.js"),
4
+ customers: () => import("./customers.js"),
5
+ assets: () => import("./assets.js"),
6
+ contacts: () => import("./contacts.js"),
7
+ invoices: () => import("./invoices.js"),
8
+ estimates: () => import("./estimates.js"),
9
+ appointments: () => import("./appointments.js"),
10
+ products: () => import("./products.js"),
11
+ payments: () => import("./payments.js"),
12
+ leads: () => import("./leads.js"),
13
+ contracts: () => import("./contracts.js"),
14
+ rmm: () => import("./rmm.js"),
15
+ scheduling: () => import("./scheduling.js"),
16
+ time: () => import("./time.js"),
17
+ admin: () => import("./admin.js"),
18
+ };
19
+ export async function loadDomain(name, client) {
20
+ const cached = domainCache.get(name);
21
+ if (cached)
22
+ return cached;
23
+ const loader = domainLoaders[name];
24
+ if (!loader)
25
+ throw new Error(`Unknown domain: ${name}`);
26
+ const module = await loader();
27
+ const handler = module.createDomain(client);
28
+ domainCache.set(name, handler);
29
+ return handler;
30
+ }
31
+ export function clearDomainCache() {
32
+ domainCache.clear();
33
+ }
34
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/domains/index.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,GAAG,IAAI,GAAG,EAA6B,CAAC;AAEzD,MAAM,aAAa,GAAoG;IACrH,OAAO,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,cAAc,CAAC;IACrC,SAAS,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,gBAAgB,CAAC;IACzC,MAAM,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,aAAa,CAAC;IACnC,QAAQ,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,eAAe,CAAC;IACvC,QAAQ,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,eAAe,CAAC;IACvC,SAAS,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,gBAAgB,CAAC;IACzC,YAAY,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,mBAAmB,CAAC;IAC/C,QAAQ,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,eAAe,CAAC;IACvC,QAAQ,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,eAAe,CAAC;IACvC,KAAK,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,YAAY,CAAC;IACjC,SAAS,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,gBAAgB,CAAC;IACzC,GAAG,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC;IAC7B,UAAU,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,iBAAiB,CAAC;IAC3C,IAAI,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,WAAW,CAAC;IAC/B,KAAK,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,YAAY,CAAC;CAClC,CAAC;AAEF,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,IAAgB,EAAE,MAAuB;IACxE,MAAM,MAAM,GAAG,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACrC,IAAI,MAAM;QAAE,OAAO,MAAM,CAAC;IAE1B,MAAM,MAAM,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC;IACnC,IAAI,CAAC,MAAM;QAAE,MAAM,IAAI,KAAK,CAAC,mBAAmB,IAAI,EAAE,CAAC,CAAC;IAExD,MAAM,MAAM,GAAG,MAAM,MAAM,EAAE,CAAC;IAC9B,MAAM,OAAO,GAAG,MAAM,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;IAC5C,WAAW,CAAC,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IAC/B,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,UAAU,gBAAgB;IAC9B,WAAW,CAAC,KAAK,EAAE,CAAC;AACtB,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { SyncroApiClient } from "../api-client.js";
2
+ import type { DomainHandler } from "../types.js";
3
+ export declare function createDomain(client: SyncroApiClient): DomainHandler;
4
+ //# sourceMappingURL=invoices.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"invoices.d.ts","sourceRoot":"","sources":["../../src/domains/invoices.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACxD,OAAO,KAAK,EAAE,aAAa,EAAc,MAAM,aAAa,CAAC;AAI7D,wBAAgB,YAAY,CAAC,MAAM,EAAE,eAAe,GAAG,aAAa,CAiSnE"}
@@ -0,0 +1,292 @@
1
+ import { jsonResult, textResult } from "../types.js";
2
+ import { requireId, optionalString, optionalNumber, optionalBoolean, optionalId, pickDefined } from "../utils/validators.js";
3
+ export function createDomain(client) {
4
+ const tools = [
5
+ {
6
+ definition: {
7
+ name: "invoices_list",
8
+ description: "List invoices with optional filters",
9
+ inputSchema: {
10
+ type: "object",
11
+ properties: {
12
+ paid: { type: "boolean", description: "Filter paid invoices only" },
13
+ unpaid: { type: "boolean", description: "Filter unpaid invoices only" },
14
+ ticket_id: { type: "number", description: "Filter by ticket ID" },
15
+ since_updated_at: { type: "string", description: "ISO 8601 date - invoices updated after this date" },
16
+ page: { type: "number", description: "Page number" },
17
+ },
18
+ },
19
+ },
20
+ handler: async (args) => {
21
+ const params = pickDefined({
22
+ paid: optionalBoolean(args.paid),
23
+ unpaid: optionalBoolean(args.unpaid),
24
+ ticket_id: optionalId(args.ticket_id),
25
+ since_updated_at: optionalString(args.since_updated_at),
26
+ page: optionalNumber(args.page),
27
+ });
28
+ return jsonResult(await client.get("/invoices", params));
29
+ },
30
+ },
31
+ {
32
+ definition: {
33
+ name: "invoices_get",
34
+ description: "Get a single invoice by ID",
35
+ inputSchema: {
36
+ type: "object",
37
+ properties: { id: { type: "number", description: "Invoice ID" } },
38
+ required: ["id"],
39
+ },
40
+ },
41
+ handler: async (args) => jsonResult(await client.get(`/invoices/${requireId(args.id)}`)),
42
+ },
43
+ {
44
+ definition: {
45
+ name: "invoices_create",
46
+ description: "Create a new invoice. Note: line_items in the create body are IGNORED by the API -- add line items via invoices_add_line_item after creation.",
47
+ inputSchema: {
48
+ type: "object",
49
+ properties: {
50
+ customer_id: { type: "number", description: "Customer ID (required)" },
51
+ date: { type: "string", description: "Invoice date" },
52
+ due_date: { type: "string", description: "Due date" },
53
+ number: { type: "string", description: "Invoice number" },
54
+ ticket_id: { type: "number", description: "Associated ticket ID" },
55
+ location_id: { type: "number", description: "Location ID" },
56
+ po_number: { type: "string", description: "PO number" },
57
+ contact_id: { type: "number", description: "Contact ID" },
58
+ note: { type: "string", description: "Invoice note" },
59
+ hardwarecost: { type: "number", description: "Hardware cost" },
60
+ line_items: { type: "array", description: "Array of line item objects" },
61
+ },
62
+ required: ["customer_id"],
63
+ },
64
+ },
65
+ handler: async (args) => {
66
+ const body = pickDefined({
67
+ customer_id: requireId(args.customer_id, "customer_id"),
68
+ date: optionalString(args.date),
69
+ due_date: optionalString(args.due_date),
70
+ number: optionalString(args.number),
71
+ ticket_id: optionalId(args.ticket_id),
72
+ location_id: optionalId(args.location_id),
73
+ po_number: optionalString(args.po_number),
74
+ contact_id: optionalId(args.contact_id),
75
+ note: optionalString(args.note),
76
+ hardwarecost: optionalNumber(args.hardwarecost),
77
+ line_items: args.line_items,
78
+ });
79
+ return jsonResult(await client.post("/invoices", body));
80
+ },
81
+ },
82
+ {
83
+ definition: {
84
+ name: "invoices_update",
85
+ description: "Update an existing invoice",
86
+ inputSchema: {
87
+ type: "object",
88
+ properties: {
89
+ id: { type: "number", description: "Invoice ID (required)" },
90
+ customer_id: { type: "number", description: "Customer ID" },
91
+ date: { type: "string", description: "Invoice date" },
92
+ due_date: { type: "string", description: "Due date" },
93
+ number: { type: "string", description: "Invoice number" },
94
+ ticket_id: { type: "number", description: "Ticket ID" },
95
+ location_id: { type: "number", description: "Location ID" },
96
+ po_number: { type: "string", description: "PO number" },
97
+ contact_id: { type: "number", description: "Contact ID" },
98
+ note: { type: "string", description: "Invoice note" },
99
+ hardwarecost: { type: "number", description: "Hardware cost" },
100
+ },
101
+ required: ["id"],
102
+ },
103
+ },
104
+ handler: async (args) => {
105
+ const id = requireId(args.id);
106
+ const body = pickDefined({
107
+ customer_id: optionalId(args.customer_id),
108
+ date: optionalString(args.date),
109
+ due_date: optionalString(args.due_date),
110
+ number: optionalString(args.number),
111
+ ticket_id: optionalId(args.ticket_id),
112
+ location_id: optionalId(args.location_id),
113
+ po_number: optionalString(args.po_number),
114
+ contact_id: optionalId(args.contact_id),
115
+ note: optionalString(args.note),
116
+ hardwarecost: optionalNumber(args.hardwarecost),
117
+ });
118
+ return jsonResult(await client.put(`/invoices/${id}`, body));
119
+ },
120
+ },
121
+ {
122
+ definition: {
123
+ name: "invoices_delete",
124
+ description: "DELETE an invoice permanently. The user MUST confirm.",
125
+ inputSchema: {
126
+ type: "object",
127
+ properties: {
128
+ id: { type: "number", description: "Invoice ID" },
129
+ confirmed: { type: "boolean", description: "Must be true to confirm deletion" },
130
+ },
131
+ required: ["id", "confirmed"],
132
+ },
133
+ },
134
+ handler: async (args) => {
135
+ const id = requireId(args.id);
136
+ if (args.confirmed !== true) {
137
+ return textResult(`⚠️ CONFIRMATION REQUIRED: Permanently delete invoice #${id}? Call again with confirmed: true.`);
138
+ }
139
+ const result = await client.delete(`/invoices/${id}`);
140
+ return result ? jsonResult(result) : textResult(`Invoice #${id} deleted successfully.`);
141
+ },
142
+ },
143
+ {
144
+ definition: {
145
+ name: "invoices_get_ticket",
146
+ description: "Get the ticket associated with an invoice",
147
+ inputSchema: {
148
+ type: "object",
149
+ properties: { id: { type: "number", description: "Invoice ID" } },
150
+ required: ["id"],
151
+ },
152
+ },
153
+ handler: async (args) => jsonResult(await client.get(`/invoices/${requireId(args.id)}/ticket`)),
154
+ },
155
+ {
156
+ definition: {
157
+ name: "invoices_print",
158
+ description: "Generate a printable PDF for an invoice",
159
+ inputSchema: {
160
+ type: "object",
161
+ properties: { id: { type: "number", description: "Invoice ID" } },
162
+ required: ["id"],
163
+ },
164
+ },
165
+ handler: async (args) => jsonResult(await client.post(`/invoices/${requireId(args.id)}/print`)),
166
+ },
167
+ {
168
+ definition: {
169
+ name: "invoices_email",
170
+ description: "Email an invoice to the customer",
171
+ inputSchema: {
172
+ type: "object",
173
+ properties: { id: { type: "number", description: "Invoice ID" } },
174
+ required: ["id"],
175
+ },
176
+ },
177
+ handler: async (args) => jsonResult(await client.post(`/invoices/${requireId(args.id)}/email`)),
178
+ },
179
+ {
180
+ definition: {
181
+ name: "invoices_add_line_item",
182
+ description: "Add a line item to an invoice. When using product_id, only product_id + quantity are needed -- the API auto-fills name, cost, and price from the product catalog.",
183
+ inputSchema: {
184
+ type: "object",
185
+ properties: {
186
+ id: { type: "number", description: "Invoice ID" },
187
+ item: { type: "string", description: "Item name" },
188
+ name: { type: "string", description: "Display name" },
189
+ quantity: { type: "number", description: "Quantity" },
190
+ price: { type: "number", description: "Price per unit" },
191
+ cost: { type: "number", description: "Cost per unit" },
192
+ product_id: { type: "number", description: "Product ID" },
193
+ upc_code: { type: "string", description: "UPC code" },
194
+ discount_percent: { type: "number", description: "Discount percentage" },
195
+ taxable: { type: "boolean", description: "Whether taxable" },
196
+ tax_note: { type: "string", description: "Tax note" },
197
+ tax_rate_id: { type: "number", description: "Tax rate ID" },
198
+ user_id: { type: "number", description: "User ID" },
199
+ position: { type: "number", description: "Sort position" },
200
+ product_category: { type: "string", description: "Product category" },
201
+ },
202
+ required: ["id"],
203
+ },
204
+ },
205
+ handler: async (args) => {
206
+ const id = requireId(args.id);
207
+ const body = pickDefined({
208
+ item: optionalString(args.item),
209
+ name: optionalString(args.name),
210
+ quantity: optionalNumber(args.quantity),
211
+ price: optionalNumber(args.price),
212
+ cost: optionalNumber(args.cost),
213
+ product_id: optionalId(args.product_id),
214
+ upc_code: optionalString(args.upc_code),
215
+ discount_percent: optionalNumber(args.discount_percent),
216
+ taxable: optionalBoolean(args.taxable),
217
+ tax_note: optionalString(args.tax_note),
218
+ tax_rate_id: optionalId(args.tax_rate_id),
219
+ user_id: optionalId(args.user_id),
220
+ position: optionalNumber(args.position),
221
+ product_category: optionalString(args.product_category),
222
+ });
223
+ return jsonResult(await client.post(`/invoices/${id}/line_items`, body));
224
+ },
225
+ },
226
+ {
227
+ definition: {
228
+ name: "invoices_update_line_item",
229
+ description: "Update a line item on an invoice",
230
+ inputSchema: {
231
+ type: "object",
232
+ properties: {
233
+ id: { type: "number", description: "Invoice ID" },
234
+ line_item_id: { type: "number", description: "Line item ID" },
235
+ item: { type: "string", description: "Item name" },
236
+ name: { type: "string", description: "Display name" },
237
+ quantity: { type: "number", description: "Quantity" },
238
+ price: { type: "number", description: "Price" },
239
+ cost: { type: "number", description: "Cost" },
240
+ discount_percent: { type: "number", description: "Discount %" },
241
+ taxable: { type: "boolean", description: "Whether taxable" },
242
+ },
243
+ required: ["id", "line_item_id"],
244
+ },
245
+ },
246
+ handler: async (args) => {
247
+ const id = requireId(args.id);
248
+ const lineItemId = requireId(args.line_item_id, "line_item_id");
249
+ const body = pickDefined({
250
+ item: optionalString(args.item),
251
+ name: optionalString(args.name),
252
+ quantity: optionalNumber(args.quantity),
253
+ price: optionalNumber(args.price),
254
+ cost: optionalNumber(args.cost),
255
+ discount_percent: optionalNumber(args.discount_percent),
256
+ taxable: optionalBoolean(args.taxable),
257
+ });
258
+ return jsonResult(await client.put(`/invoices/${id}/line_items/${lineItemId}`, body));
259
+ },
260
+ },
261
+ {
262
+ definition: {
263
+ name: "invoices_delete_line_item",
264
+ description: "Delete a line item from an invoice. The user MUST confirm.",
265
+ inputSchema: {
266
+ type: "object",
267
+ properties: {
268
+ id: { type: "number", description: "Invoice ID" },
269
+ line_item_id: { type: "number", description: "Line item ID" },
270
+ confirmed: { type: "boolean", description: "Must be true to confirm deletion" },
271
+ },
272
+ required: ["id", "line_item_id", "confirmed"],
273
+ },
274
+ },
275
+ handler: async (args) => {
276
+ const id = requireId(args.id);
277
+ const lineItemId = requireId(args.line_item_id, "line_item_id");
278
+ if (args.confirmed !== true) {
279
+ return textResult(`⚠️ CONFIRMATION REQUIRED: Delete line item #${lineItemId} from invoice #${id}? Call again with confirmed: true.`);
280
+ }
281
+ const result = await client.delete(`/invoices/${id}/line_items/${lineItemId}`);
282
+ return result ? jsonResult(result) : textResult(`Line item deleted from invoice #${id}.`);
283
+ },
284
+ },
285
+ ];
286
+ return {
287
+ name: "invoices",
288
+ description: "Invoices, line items, print/email",
289
+ getTools: () => tools,
290
+ };
291
+ }
292
+ //# sourceMappingURL=invoices.js.map