@armor/zuora-mcp 1.0.1

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/tools.js ADDED
@@ -0,0 +1,1336 @@
1
+ /**
2
+ * MCP Tool Definitions for Zuora Billing Operations
3
+ * Provides account, invoice, subscription, payment, and ZOQL query tools
4
+ */
5
+ import { z } from "zod";
6
+ // ==================== Helpers ====================
7
+ function isValidCalendarDate(dateStr) {
8
+ const [year, month, day] = dateStr.split("-").map(Number);
9
+ const date = new Date(year, month - 1, day);
10
+ return (date.getFullYear() === year &&
11
+ date.getMonth() === month - 1 &&
12
+ date.getDate() === day);
13
+ }
14
+ // ==================== Shared Schemas ====================
15
+ /** Contact fields for account creation (name + email required) */
16
+ const contactSchema = z.object({
17
+ firstName: z.string().min(1).max(100).describe("First name"),
18
+ lastName: z.string().min(1).max(100).describe("Last name"),
19
+ workEmail: z.string().email("Must be a valid email address").describe("Work email address"),
20
+ address1: z.string().max(255).optional().describe("Street address line 1"),
21
+ city: z.string().max(100).optional().describe("City"),
22
+ state: z.string().max(100).optional().describe("State or province"),
23
+ postalCode: z.string().max(20).optional().describe("Postal/ZIP code"),
24
+ country: z.string().max(100).optional().describe("Country (ISO 3166 name or code)"),
25
+ });
26
+ /** Contact fields for account updates (all fields optional for partial updates) */
27
+ const partialContactSchema = contactSchema.partial();
28
+ // ==================== Input Schemas ====================
29
+ export const schemas = {
30
+ // Account Tools
31
+ getAccount: z.object({
32
+ accountKey: z
33
+ .string()
34
+ .min(1)
35
+ .describe("Account ID or account number (e.g., 2c92c0f8..., or A00000001)"),
36
+ }),
37
+ getAccountSummary: z.object({
38
+ accountKey: z
39
+ .string()
40
+ .min(1)
41
+ .describe("Account ID or account number"),
42
+ }),
43
+ // Invoice Tools
44
+ getInvoice: z.object({
45
+ invoiceId: z
46
+ .string()
47
+ .min(1)
48
+ .describe("Invoice ID (e.g., 2c92c0f8...)"),
49
+ }),
50
+ listInvoices: z.object({
51
+ accountKey: z
52
+ .string()
53
+ .min(1)
54
+ .describe("Account ID or account number to list invoices for"),
55
+ page: z
56
+ .number()
57
+ .int()
58
+ .min(1)
59
+ .default(1)
60
+ .describe("Page number (default: 1)"),
61
+ pageSize: z
62
+ .number()
63
+ .int()
64
+ .min(1)
65
+ .max(40)
66
+ .default(20)
67
+ .describe("Records per page (default: 20, max: 40)"),
68
+ }),
69
+ // Subscription Tools
70
+ getSubscription: z.object({
71
+ subscriptionKey: z
72
+ .string()
73
+ .min(1)
74
+ .describe("Subscription key or ID (e.g., A-S00000001)"),
75
+ }),
76
+ listSubscriptions: z.object({
77
+ accountKey: z
78
+ .string()
79
+ .min(1)
80
+ .describe("Account ID or account number"),
81
+ }),
82
+ // Payment Tools
83
+ getPayment: z.object({
84
+ paymentId: z.string().min(1).describe("Payment ID"),
85
+ }),
86
+ listPayments: z.object({
87
+ accountKey: z
88
+ .string()
89
+ .optional()
90
+ .describe("Account key to filter payments (optional, lists all if omitted)"),
91
+ page: z
92
+ .number()
93
+ .int()
94
+ .min(1)
95
+ .default(1)
96
+ .describe("Page number (default: 1)"),
97
+ pageSize: z
98
+ .number()
99
+ .int()
100
+ .min(1)
101
+ .max(40)
102
+ .default(20)
103
+ .describe("Records per page (default: 20, max: 40)"),
104
+ }),
105
+ // ZOQL Query Tools
106
+ executeZoqlQuery: z.object({
107
+ zoqlQuery: z
108
+ .string()
109
+ .min(1)
110
+ .max(10000)
111
+ .refine((q) => /^\s*SELECT\s+/i.test(q), {
112
+ message: "ZOQL query must begin with SELECT",
113
+ })
114
+ .describe("ZOQL (Zuora Object Query Language) query string. " +
115
+ "Syntax: SELECT field1, field2 FROM ObjectName WHERE condition. " +
116
+ "Key objects: Account, Invoice, Payment, Subscription, RatePlan, " +
117
+ "RatePlanCharge, Product, ProductRatePlan, Contact. " +
118
+ "Limitations: No JOINs. Max 2000 records per call. " +
119
+ "Use continue_zoql_query with queryLocator for pagination. " +
120
+ "Example: SELECT Id, AccountNumber, Balance FROM Account WHERE Status = 'Active'"),
121
+ }),
122
+ continueZoqlQuery: z.object({
123
+ queryLocator: z
124
+ .string()
125
+ .min(1)
126
+ .describe("Query locator from a previous ZOQL query result for pagination"),
127
+ }),
128
+ // Product Catalog Tools
129
+ listProducts: z.object({
130
+ page: z
131
+ .number()
132
+ .int()
133
+ .min(1)
134
+ .default(1)
135
+ .describe("Page number (default: 1)"),
136
+ pageSize: z
137
+ .number()
138
+ .int()
139
+ .min(1)
140
+ .max(40)
141
+ .default(20)
142
+ .describe("Records per page (default: 20, max: 40)"),
143
+ }),
144
+ // Phase 2: Extended Read Tools
145
+ getInvoiceFiles: z.object({
146
+ invoiceId: z
147
+ .string()
148
+ .min(1)
149
+ .describe("Invoice ID to retrieve associated PDF files for"),
150
+ }),
151
+ getCreditMemo: z.object({
152
+ creditMemoId: z
153
+ .string()
154
+ .min(1)
155
+ .describe("Credit memo ID (e.g., 2c92c0f8...)"),
156
+ }),
157
+ listCreditMemos: z.object({
158
+ accountId: z
159
+ .string()
160
+ .optional()
161
+ .describe("Zuora account UUID (e.g., 2c92c0f8...) to filter credit memos. " +
162
+ "Use get_account to retrieve the account ID from an account number. " +
163
+ "Optional; lists all if omitted."),
164
+ page: z
165
+ .number()
166
+ .int()
167
+ .min(1)
168
+ .default(1)
169
+ .describe("Page number (default: 1)"),
170
+ pageSize: z
171
+ .number()
172
+ .int()
173
+ .min(1)
174
+ .max(40)
175
+ .default(20)
176
+ .describe("Records per page (default: 20, max: 40)"),
177
+ }),
178
+ searchAccounts: z.object({
179
+ field: z
180
+ .enum([
181
+ "Name",
182
+ "AccountNumber",
183
+ "Status",
184
+ "Currency",
185
+ "Balance",
186
+ ])
187
+ .describe("Account field to search by (Name, AccountNumber, Status, Currency, Balance)"),
188
+ value: z
189
+ .string()
190
+ .min(1)
191
+ .max(255)
192
+ .refine((v) => /[^%_]/.test(v), {
193
+ message: "Value must contain at least one non-wildcard character",
194
+ })
195
+ .describe("Value to search for"),
196
+ operator: z
197
+ .enum(["=", "!=", "LIKE", ">", "<", ">=", "<="])
198
+ .default("=")
199
+ .describe("Comparison operator (default: =). Use LIKE for partial name matches with % wildcard."),
200
+ }),
201
+ listUsage: z.object({
202
+ accountKey: z
203
+ .string()
204
+ .min(1)
205
+ .describe("Account ID or account number to retrieve usage records for"),
206
+ page: z
207
+ .number()
208
+ .int()
209
+ .min(1)
210
+ .default(1)
211
+ .describe("Page number (default: 1)"),
212
+ pageSize: z
213
+ .number()
214
+ .int()
215
+ .min(1)
216
+ .max(40)
217
+ .default(20)
218
+ .describe("Records per page (default: 20, max: 40)"),
219
+ }),
220
+ // Phase 3: Write Operations
221
+ createPayment: z.object({
222
+ accountId: z
223
+ .string()
224
+ .min(1)
225
+ .describe("Zuora account UUID to create the payment for"),
226
+ amount: z
227
+ .number()
228
+ .positive()
229
+ .max(1_000_000)
230
+ .refine((n) => Math.round(n * 100) === n * 100, "Amount must have at most 2 decimal places")
231
+ .describe("Payment amount (positive, max 1,000,000, up to 2 decimal places)"),
232
+ effectiveDate: z
233
+ .string()
234
+ .regex(/^\d{4}-\d{2}-\d{2}$/, "Date must be YYYY-MM-DD format")
235
+ .refine(isValidCalendarDate, "Must be a valid calendar date")
236
+ .describe("Payment effective date in YYYY-MM-DD format"),
237
+ type: z
238
+ .enum(["Electronic", "External"])
239
+ .describe("Payment type: Electronic (gateway) or External (check, wire, etc.)"),
240
+ paymentMethodId: z
241
+ .string()
242
+ .optional()
243
+ .describe("Payment method ID. Required for Electronic type. " +
244
+ "Use get_account to find available payment methods."),
245
+ comment: z
246
+ .string()
247
+ .max(1000)
248
+ .optional()
249
+ .describe("Optional comment for the payment record"),
250
+ idempotencyKey: z
251
+ .string()
252
+ .uuid("Idempotency key must be a valid UUID")
253
+ .describe("UUID to prevent duplicate payments on retries. " +
254
+ "Generate a new UUID v4 for each distinct payment intent."),
255
+ }).superRefine((data, ctx) => {
256
+ if (data.type === "Electronic" && !data.paymentMethodId) {
257
+ ctx.addIssue({
258
+ code: z.ZodIssueCode.custom,
259
+ path: ["paymentMethodId"],
260
+ message: "paymentMethodId is required when type is Electronic",
261
+ });
262
+ }
263
+ }),
264
+ applyPayment: z.object({
265
+ paymentId: z
266
+ .string()
267
+ .min(1)
268
+ .describe("ID of the unapplied payment to apply to invoices"),
269
+ invoices: z
270
+ .array(z.object({
271
+ invoiceId: z.string().min(1).describe("Invoice ID to apply payment to"),
272
+ amount: z
273
+ .number()
274
+ .positive()
275
+ .max(1_000_000)
276
+ .refine((n) => Math.round(n * 100) === n * 100, "Amount must have at most 2 decimal places")
277
+ .describe("Amount to apply to this invoice"),
278
+ }))
279
+ .min(1)
280
+ .max(50)
281
+ .describe("Invoice allocations: which invoices to apply the payment to and how much. " +
282
+ "Max 50 per call; split larger batches into multiple calls."),
283
+ effectiveDate: z
284
+ .string()
285
+ .regex(/^\d{4}-\d{2}-\d{2}$/, "Date must be YYYY-MM-DD format")
286
+ .refine(isValidCalendarDate, "Must be a valid calendar date")
287
+ .optional()
288
+ .describe("Effective date for the application in YYYY-MM-DD format (optional)"),
289
+ }),
290
+ createInvoice: z.object({
291
+ accountId: z
292
+ .string()
293
+ .min(1)
294
+ .describe("Zuora account UUID to create the invoice for"),
295
+ invoiceDate: z
296
+ .string()
297
+ .regex(/^\d{4}-\d{2}-\d{2}$/, "Date must be YYYY-MM-DD format")
298
+ .refine(isValidCalendarDate, "Must be a valid calendar date")
299
+ .describe("Invoice date in YYYY-MM-DD format"),
300
+ dueDate: z
301
+ .string()
302
+ .regex(/^\d{4}-\d{2}-\d{2}$/, "Date must be YYYY-MM-DD format")
303
+ .refine(isValidCalendarDate, "Must be a valid calendar date")
304
+ .optional()
305
+ .describe("Due date in YYYY-MM-DD format (optional, uses payment terms if omitted)"),
306
+ idempotencyKey: z
307
+ .string()
308
+ .uuid("Idempotency key must be a valid UUID")
309
+ .describe("UUID to prevent duplicate invoice creation on retries. " +
310
+ "Generate a new UUID v4 for each distinct invoice intent."),
311
+ }),
312
+ postInvoice: z.object({
313
+ invoiceId: z
314
+ .string()
315
+ .min(1)
316
+ .describe("ID of the draft invoice to post. " +
317
+ "Once posted, the invoice is immutable and affects account balance."),
318
+ }),
319
+ cancelSubscription: z.object({
320
+ subscriptionKey: z
321
+ .string()
322
+ .min(1)
323
+ .describe("Subscription key or ID (e.g., A-S00000001) to cancel"),
324
+ cancellationPolicy: z
325
+ .enum(["EndOfCurrentTerm", "EndOfLastInvoicePeriod", "SpecificDate"])
326
+ .describe("When the cancellation takes effect: " +
327
+ "EndOfCurrentTerm (cancel at term end), " +
328
+ "EndOfLastInvoicePeriod (cancel at end of last billed period), " +
329
+ "SpecificDate (cancel on a specific date, requires cancellationEffectiveDate)"),
330
+ cancellationEffectiveDate: z
331
+ .string()
332
+ .regex(/^\d{4}-\d{2}-\d{2}$/, "Date must be YYYY-MM-DD format")
333
+ .refine(isValidCalendarDate, "Must be a valid calendar date")
334
+ .optional()
335
+ .describe("Required when cancellationPolicy is SpecificDate. The date cancellation takes effect."),
336
+ invoiceCollect: z
337
+ .boolean()
338
+ .default(false)
339
+ .describe("Whether to generate and collect an invoice for the cancellation charges (default: false)"),
340
+ }).superRefine((data, ctx) => {
341
+ if (data.cancellationPolicy === "SpecificDate" && !data.cancellationEffectiveDate) {
342
+ ctx.addIssue({
343
+ code: z.ZodIssueCode.custom,
344
+ path: ["cancellationEffectiveDate"],
345
+ message: "cancellationEffectiveDate is required when cancellationPolicy is SpecificDate",
346
+ });
347
+ }
348
+ }),
349
+ // Phase 4: Advanced Operations
350
+ createSubscription: z.object({
351
+ accountKey: z
352
+ .string()
353
+ .min(1)
354
+ .describe("Account ID or account number to create the subscription for"),
355
+ contractEffectiveDate: z
356
+ .string()
357
+ .regex(/^\d{4}-\d{2}-\d{2}$/, "Date must be YYYY-MM-DD format")
358
+ .refine(isValidCalendarDate, "Must be a valid calendar date")
359
+ .describe("Date the subscription contract takes effect in YYYY-MM-DD format"),
360
+ serviceActivationDate: z
361
+ .string()
362
+ .regex(/^\d{4}-\d{2}-\d{2}$/, "Date must be YYYY-MM-DD format")
363
+ .refine(isValidCalendarDate, "Must be a valid calendar date")
364
+ .optional()
365
+ .describe("Date the subscription service is activated (optional). " +
366
+ "Required if the Zuora tenant has 'Require Service Activation' enabled."),
367
+ customerAcceptanceDate: z
368
+ .string()
369
+ .regex(/^\d{4}-\d{2}-\d{2}$/, "Date must be YYYY-MM-DD format")
370
+ .refine(isValidCalendarDate, "Must be a valid calendar date")
371
+ .optional()
372
+ .describe("Date the customer accepted the subscription (optional). " +
373
+ "Required if the Zuora tenant has 'Require Customer Acceptance' enabled."),
374
+ termType: z
375
+ .enum(["TERMED", "EVERGREEN"])
376
+ .describe("Subscription term type: TERMED (fixed duration) or EVERGREEN (no end date)"),
377
+ initialTerm: z
378
+ .number()
379
+ .int()
380
+ .positive()
381
+ .max(1200)
382
+ .optional()
383
+ .describe("Initial term length (required for TERMED). Max 1200."),
384
+ initialTermPeriodType: z
385
+ .enum(["Month", "Year", "Day", "Week"])
386
+ .optional()
387
+ .describe("Period type for the initial term (required for TERMED)"),
388
+ renewalTerm: z
389
+ .number()
390
+ .int()
391
+ .positive()
392
+ .max(1200)
393
+ .optional()
394
+ .describe("Renewal term length (optional)"),
395
+ renewalTermPeriodType: z
396
+ .enum(["Month", "Year", "Day", "Week"])
397
+ .optional()
398
+ .describe("Period type for the renewal term"),
399
+ autoRenew: z
400
+ .boolean()
401
+ .default(false)
402
+ .describe("Whether the subscription auto-renews at term end (default: false)"),
403
+ subscribeToRatePlans: z
404
+ .array(z.object({
405
+ productRatePlanId: z
406
+ .string()
407
+ .min(1)
408
+ .describe("Product rate plan ID from the product catalog"),
409
+ }))
410
+ .min(1)
411
+ .max(50)
412
+ .describe("Rate plans to subscribe to. Use list_products to find productRatePlanIds. " +
413
+ "At least 1, max 50 per call."),
414
+ notes: z
415
+ .string()
416
+ .max(2000)
417
+ .optional()
418
+ .describe("Optional notes for the subscription"),
419
+ idempotencyKey: z
420
+ .string()
421
+ .uuid("Idempotency key must be a valid UUID")
422
+ .describe("UUID to prevent duplicate subscriptions on retries. " +
423
+ "Generate a new UUID v4 for each distinct subscription intent."),
424
+ }).superRefine((data, ctx) => {
425
+ if (data.termType === "TERMED" && !data.initialTerm) {
426
+ ctx.addIssue({
427
+ code: z.ZodIssueCode.custom,
428
+ path: ["initialTerm"],
429
+ message: "initialTerm is required when termType is TERMED",
430
+ });
431
+ }
432
+ if (data.termType === "TERMED" && !data.initialTermPeriodType) {
433
+ ctx.addIssue({
434
+ code: z.ZodIssueCode.custom,
435
+ path: ["initialTermPeriodType"],
436
+ message: "initialTermPeriodType is required when termType is TERMED",
437
+ });
438
+ }
439
+ if ((data.renewalTerm !== undefined) !== (data.renewalTermPeriodType !== undefined)) {
440
+ ctx.addIssue({
441
+ code: z.ZodIssueCode.custom,
442
+ path: [data.renewalTerm !== undefined ? "renewalTermPeriodType" : "renewalTerm"],
443
+ message: "renewalTerm and renewalTermPeriodType must be provided together",
444
+ });
445
+ }
446
+ }),
447
+ updateSubscription: z.object({
448
+ subscriptionKey: z
449
+ .string()
450
+ .min(1)
451
+ .describe("Subscription key or ID to update (e.g., A-S00000001)"),
452
+ autoRenew: z
453
+ .boolean()
454
+ .optional()
455
+ .describe("Whether the subscription auto-renews at term end"),
456
+ renewalTerm: z
457
+ .number()
458
+ .int()
459
+ .positive()
460
+ .max(1200)
461
+ .optional()
462
+ .describe("Renewal term length"),
463
+ renewalTermPeriodType: z
464
+ .enum(["Month", "Year", "Day", "Week"])
465
+ .optional()
466
+ .describe("Period type for the renewal term"),
467
+ notes: z
468
+ .string()
469
+ .max(2000)
470
+ .optional()
471
+ .describe("Notes for the subscription"),
472
+ }).superRefine((data, ctx) => {
473
+ const { subscriptionKey: _, ...updateFields } = data;
474
+ const hasUpdate = Object.values(updateFields).some((v) => v !== undefined);
475
+ if (!hasUpdate) {
476
+ ctx.addIssue({
477
+ code: z.ZodIssueCode.custom,
478
+ path: [],
479
+ message: "At least one field to update must be provided (autoRenew, renewalTerm, renewalTermPeriodType, or notes)",
480
+ });
481
+ }
482
+ if ((data.renewalTerm !== undefined) !== (data.renewalTermPeriodType !== undefined)) {
483
+ ctx.addIssue({
484
+ code: z.ZodIssueCode.custom,
485
+ path: [data.renewalTerm !== undefined ? "renewalTermPeriodType" : "renewalTerm"],
486
+ message: "renewalTerm and renewalTermPeriodType must be provided together",
487
+ });
488
+ }
489
+ }),
490
+ createAccount: z.object({
491
+ name: z
492
+ .string()
493
+ .min(1)
494
+ .max(255)
495
+ .describe("Account name"),
496
+ currency: z
497
+ .string()
498
+ .regex(/^[A-Z]{3}$/, "Currency must be a 3-letter ISO 4217 code (e.g., USD, EUR)")
499
+ .describe("ISO 4217 currency code (e.g., USD, EUR, GBP)"),
500
+ billCycleDay: z
501
+ .number()
502
+ .int()
503
+ .min(1)
504
+ .max(31)
505
+ .describe("Day of month for billing cycle (1-31). Zuora normalizes values beyond a month's last day."),
506
+ billToContact: contactSchema
507
+ .describe("Bill-to contact information (required)"),
508
+ soldToContact: contactSchema
509
+ .optional()
510
+ .describe("Sold-to contact information (optional, defaults to bill-to if omitted)"),
511
+ paymentTerm: z
512
+ .string()
513
+ .max(100)
514
+ .optional()
515
+ .describe("Payment terms (e.g., 'Net 30', 'Due Upon Receipt')"),
516
+ autoPay: z
517
+ .boolean()
518
+ .default(false)
519
+ .describe("Whether to auto-collect payments (default: false)"),
520
+ notes: z
521
+ .string()
522
+ .max(2000)
523
+ .optional()
524
+ .describe("Optional account notes"),
525
+ idempotencyKey: z
526
+ .string()
527
+ .uuid("Idempotency key must be a valid UUID")
528
+ .describe("UUID to prevent duplicate account creation on retries. " +
529
+ "Generate a new UUID v4 for each distinct account intent."),
530
+ }),
531
+ updateAccount: z.object({
532
+ accountKey: z
533
+ .string()
534
+ .min(1)
535
+ .describe("Account ID or account number to update"),
536
+ name: z
537
+ .string()
538
+ .min(1)
539
+ .max(255)
540
+ .optional()
541
+ .describe("Updated account name"),
542
+ notes: z
543
+ .string()
544
+ .max(2000)
545
+ .optional()
546
+ .describe("Updated account notes"),
547
+ autoPay: z
548
+ .boolean()
549
+ .optional()
550
+ .describe("Whether to auto-collect payments"),
551
+ paymentTerm: z
552
+ .string()
553
+ .max(100)
554
+ .optional()
555
+ .describe("Updated payment terms (e.g., 'Net 30')"),
556
+ billToContact: partialContactSchema
557
+ .optional()
558
+ .describe("Updated bill-to contact fields (only include fields to change)"),
559
+ soldToContact: partialContactSchema
560
+ .optional()
561
+ .describe("Updated sold-to contact fields (only include fields to change)"),
562
+ }).superRefine((data, ctx) => {
563
+ const { accountKey: _, ...updateFields } = data;
564
+ const hasUpdate = Object.values(updateFields).some((v) => v !== undefined);
565
+ if (!hasUpdate) {
566
+ ctx.addIssue({
567
+ code: z.ZodIssueCode.custom,
568
+ path: [],
569
+ message: "At least one field to update must be provided",
570
+ });
571
+ }
572
+ }),
573
+ createRefund: z.object({
574
+ paymentId: z
575
+ .string()
576
+ .min(1)
577
+ .describe("ID of the original payment to refund. " +
578
+ "Use get_payment to verify the payment exists and has sufficient applied amount."),
579
+ amount: z
580
+ .number()
581
+ .positive()
582
+ .max(1_000_000)
583
+ .refine((n) => Math.round(n * 100) === n * 100, "Amount must have at most 2 decimal places")
584
+ .describe("Refund amount (positive, max 1,000,000, up to 2 decimal places)"),
585
+ type: z
586
+ .enum(["Electronic", "External"])
587
+ .describe("Refund type: Electronic (refund via payment gateway) or External (manual refund record)"),
588
+ comment: z
589
+ .string()
590
+ .max(1000)
591
+ .optional()
592
+ .describe("Optional reason/comment for the refund"),
593
+ idempotencyKey: z
594
+ .string()
595
+ .uuid("Idempotency key must be a valid UUID")
596
+ .describe("UUID to prevent duplicate refunds on retries. " +
597
+ "Generate a new UUID v4 for each distinct refund intent."),
598
+ }),
599
+ };
600
+ // ==================== Tool Handlers ====================
601
+ export class ToolHandlers {
602
+ client;
603
+ constructor(client) {
604
+ this.client = client;
605
+ }
606
+ // --- Account Handlers ---
607
+ async getAccount(input) {
608
+ try {
609
+ const { accountKey } = schemas.getAccount.parse(input);
610
+ const account = await this.client.getAccount(accountKey);
611
+ return {
612
+ success: true,
613
+ message: `Retrieved account ${accountKey}`,
614
+ data: account,
615
+ };
616
+ }
617
+ catch (error) {
618
+ return {
619
+ success: false,
620
+ message: `Failed to get account: ${error instanceof Error ? error.message : String(error)}`,
621
+ };
622
+ }
623
+ }
624
+ async getAccountSummary(input) {
625
+ try {
626
+ const { accountKey } = schemas.getAccountSummary.parse(input);
627
+ const summary = await this.client.getAccountSummary(accountKey);
628
+ return {
629
+ success: true,
630
+ message: `Retrieved account summary for ${accountKey}`,
631
+ data: summary,
632
+ };
633
+ }
634
+ catch (error) {
635
+ return {
636
+ success: false,
637
+ message: `Failed to get account summary: ${error instanceof Error ? error.message : String(error)}`,
638
+ };
639
+ }
640
+ }
641
+ // --- Invoice Handlers ---
642
+ async getInvoice(input) {
643
+ try {
644
+ const { invoiceId } = schemas.getInvoice.parse(input);
645
+ const invoice = await this.client.getInvoice(invoiceId);
646
+ return {
647
+ success: true,
648
+ message: `Retrieved invoice ${invoice.invoiceNumber ?? invoiceId}`,
649
+ data: invoice,
650
+ };
651
+ }
652
+ catch (error) {
653
+ return {
654
+ success: false,
655
+ message: `Failed to get invoice: ${error instanceof Error ? error.message : String(error)}`,
656
+ };
657
+ }
658
+ }
659
+ async listInvoices(input) {
660
+ try {
661
+ const { accountKey, page, pageSize } = schemas.listInvoices.parse(input);
662
+ const result = await this.client.listInvoices(accountKey, page, pageSize);
663
+ const count = result.invoices?.length ?? 0;
664
+ return {
665
+ success: true,
666
+ message: `Found ${count} invoice(s) for account ${accountKey}`,
667
+ data: result,
668
+ };
669
+ }
670
+ catch (error) {
671
+ return {
672
+ success: false,
673
+ message: `Failed to list invoices: ${error instanceof Error ? error.message : String(error)}`,
674
+ };
675
+ }
676
+ }
677
+ // --- Subscription Handlers ---
678
+ async getSubscription(input) {
679
+ try {
680
+ const { subscriptionKey } = schemas.getSubscription.parse(input);
681
+ const subscription = await this.client.getSubscription(subscriptionKey);
682
+ return {
683
+ success: true,
684
+ message: `Retrieved subscription ${subscription.subscriptionNumber ?? subscriptionKey}`,
685
+ data: subscription,
686
+ };
687
+ }
688
+ catch (error) {
689
+ return {
690
+ success: false,
691
+ message: `Failed to get subscription: ${error instanceof Error ? error.message : String(error)}`,
692
+ };
693
+ }
694
+ }
695
+ async listSubscriptions(input) {
696
+ try {
697
+ const { accountKey } = schemas.listSubscriptions.parse(input);
698
+ const result = await this.client.listSubscriptionsByAccount(accountKey);
699
+ const count = result.subscriptions?.length ?? 0;
700
+ return {
701
+ success: true,
702
+ message: `Found ${count} subscription(s) for account ${accountKey}`,
703
+ data: result,
704
+ };
705
+ }
706
+ catch (error) {
707
+ return {
708
+ success: false,
709
+ message: `Failed to list subscriptions: ${error instanceof Error ? error.message : String(error)}`,
710
+ };
711
+ }
712
+ }
713
+ // --- Payment Handlers ---
714
+ async getPayment(input) {
715
+ try {
716
+ const { paymentId } = schemas.getPayment.parse(input);
717
+ const payment = await this.client.getPayment(paymentId);
718
+ return {
719
+ success: true,
720
+ message: `Retrieved payment ${payment.paymentNumber ?? paymentId}`,
721
+ data: payment,
722
+ };
723
+ }
724
+ catch (error) {
725
+ return {
726
+ success: false,
727
+ message: `Failed to get payment: ${error instanceof Error ? error.message : String(error)}`,
728
+ };
729
+ }
730
+ }
731
+ async listPayments(input) {
732
+ try {
733
+ const { accountKey, page, pageSize } = schemas.listPayments.parse(input);
734
+ const result = accountKey
735
+ ? await this.client.listPaymentsByAccount(accountKey, page, pageSize)
736
+ : await this.client.listPayments(page, pageSize);
737
+ const count = result.payments?.length ?? 0;
738
+ const scope = accountKey
739
+ ? ` for account ${accountKey}`
740
+ : "";
741
+ return {
742
+ success: true,
743
+ message: `Found ${count} payment(s)${scope}`,
744
+ data: result,
745
+ };
746
+ }
747
+ catch (error) {
748
+ return {
749
+ success: false,
750
+ message: `Failed to list payments: ${error instanceof Error ? error.message : String(error)}`,
751
+ };
752
+ }
753
+ }
754
+ // --- ZOQL Query Handlers ---
755
+ async executeZoqlQuery(input) {
756
+ try {
757
+ const { zoqlQuery } = schemas.executeZoqlQuery.parse(input);
758
+ const result = await this.client.executeQuery(zoqlQuery);
759
+ const moreAvailable = result.queryLocator
760
+ ? " (more available via continue_zoql_query)"
761
+ : "";
762
+ return {
763
+ success: true,
764
+ message: `Query returned ${result.records?.length ?? 0} record(s)${moreAvailable}`,
765
+ data: result,
766
+ };
767
+ }
768
+ catch (error) {
769
+ return {
770
+ success: false,
771
+ message: `ZOQL query failed: ${error instanceof Error ? error.message : String(error)}`,
772
+ };
773
+ }
774
+ }
775
+ async continueZoqlQuery(input) {
776
+ try {
777
+ const { queryLocator } = schemas.continueZoqlQuery.parse(input);
778
+ const result = await this.client.queryMore(queryLocator);
779
+ const moreAvailable = result.queryLocator
780
+ ? " (more available)"
781
+ : "";
782
+ return {
783
+ success: true,
784
+ message: `Continuation returned ${result.records?.length ?? 0} record(s)${moreAvailable}`,
785
+ data: result,
786
+ };
787
+ }
788
+ catch (error) {
789
+ return {
790
+ success: false,
791
+ message: `ZOQL continuation failed: ${error instanceof Error ? error.message : String(error)}`,
792
+ };
793
+ }
794
+ }
795
+ // --- Product Catalog Handlers ---
796
+ async listProducts(input) {
797
+ try {
798
+ const { page, pageSize } = schemas.listProducts.parse(input);
799
+ const result = await this.client.listProducts(page, pageSize);
800
+ const count = result.products?.length ?? 0;
801
+ return {
802
+ success: true,
803
+ message: `Found ${count} product(s)`,
804
+ data: result,
805
+ };
806
+ }
807
+ catch (error) {
808
+ return {
809
+ success: false,
810
+ message: `Failed to list products: ${error instanceof Error ? error.message : String(error)}`,
811
+ };
812
+ }
813
+ }
814
+ // --- Phase 2: Extended Read Handlers ---
815
+ async getInvoiceFiles(input) {
816
+ try {
817
+ const { invoiceId } = schemas.getInvoiceFiles.parse(input);
818
+ const result = await this.client.getInvoiceFiles(invoiceId);
819
+ const count = result.invoiceFiles?.length ?? 0;
820
+ return {
821
+ success: true,
822
+ message: `Found ${count} file(s) for invoice ${invoiceId}`,
823
+ data: result,
824
+ };
825
+ }
826
+ catch (error) {
827
+ return {
828
+ success: false,
829
+ message: `Failed to get invoice files: ${error instanceof Error ? error.message : String(error)}`,
830
+ };
831
+ }
832
+ }
833
+ async getCreditMemo(input) {
834
+ try {
835
+ const { creditMemoId } = schemas.getCreditMemo.parse(input);
836
+ const creditMemo = await this.client.getCreditMemo(creditMemoId);
837
+ return {
838
+ success: true,
839
+ message: `Retrieved credit memo ${creditMemo.number ?? creditMemoId}`,
840
+ data: creditMemo,
841
+ };
842
+ }
843
+ catch (error) {
844
+ return {
845
+ success: false,
846
+ message: `Failed to get credit memo: ${error instanceof Error ? error.message : String(error)}`,
847
+ };
848
+ }
849
+ }
850
+ async listCreditMemos(input) {
851
+ try {
852
+ const { accountId, page, pageSize } = schemas.listCreditMemos.parse(input);
853
+ const result = await this.client.listCreditMemos(accountId, page, pageSize);
854
+ const count = result.creditMemos?.length ?? 0;
855
+ const scope = accountId ? ` for account ${accountId}` : "";
856
+ return {
857
+ success: true,
858
+ message: `Found ${count} credit memo(s)${scope}`,
859
+ data: result,
860
+ };
861
+ }
862
+ catch (error) {
863
+ return {
864
+ success: false,
865
+ message: `Failed to list credit memos: ${error instanceof Error ? error.message : String(error)}`,
866
+ };
867
+ }
868
+ }
869
+ async searchAccounts(input) {
870
+ try {
871
+ const { field, value, operator } = schemas.searchAccounts.parse(input);
872
+ const result = await this.client.searchAccounts(field, value, operator);
873
+ const count = result.records?.length ?? 0;
874
+ return {
875
+ success: true,
876
+ message: `Found ${count} account(s) matching search criteria`,
877
+ data: result,
878
+ };
879
+ }
880
+ catch (error) {
881
+ return {
882
+ success: false,
883
+ message: `Failed to search accounts: ${error instanceof Error ? error.message : String(error)}`,
884
+ };
885
+ }
886
+ }
887
+ async listUsage(input) {
888
+ try {
889
+ const { accountKey, page, pageSize } = schemas.listUsage.parse(input);
890
+ const result = await this.client.listUsage(accountKey, page, pageSize);
891
+ const count = result.usage?.length ?? 0;
892
+ return {
893
+ success: true,
894
+ message: `Found ${count} usage record(s) for account ${accountKey}`,
895
+ data: result,
896
+ };
897
+ }
898
+ catch (error) {
899
+ return {
900
+ success: false,
901
+ message: `Failed to get usage: ${error instanceof Error ? error.message : String(error)}`,
902
+ };
903
+ }
904
+ }
905
+ // --- Phase 3: Write Operation Handlers ---
906
+ async createPayment(input) {
907
+ try {
908
+ const { idempotencyKey, ...paymentData } = schemas.createPayment.parse(input);
909
+ const result = await this.client.createPayment(paymentData, idempotencyKey);
910
+ return {
911
+ success: true,
912
+ message: `Created payment ${result.paymentNumber} successfully`,
913
+ data: result,
914
+ };
915
+ }
916
+ catch (error) {
917
+ return {
918
+ success: false,
919
+ message: `Failed to create payment: ${error instanceof Error ? error.message : String(error)}`,
920
+ };
921
+ }
922
+ }
923
+ async applyPayment(input) {
924
+ try {
925
+ const { paymentId, invoices, effectiveDate } = schemas.applyPayment.parse(input);
926
+ const result = await this.client.applyPayment(paymentId, {
927
+ invoices,
928
+ effectiveDate,
929
+ });
930
+ return {
931
+ success: true,
932
+ message: `Applied payment ${result.paymentNumber} successfully`,
933
+ data: result,
934
+ };
935
+ }
936
+ catch (error) {
937
+ return {
938
+ success: false,
939
+ message: `Failed to apply payment: ${error instanceof Error ? error.message : String(error)}`,
940
+ };
941
+ }
942
+ }
943
+ async createInvoice(input) {
944
+ try {
945
+ const { idempotencyKey, ...invoiceData } = schemas.createInvoice.parse(input);
946
+ const result = await this.client.createInvoice(invoiceData, idempotencyKey);
947
+ return {
948
+ success: true,
949
+ message: `Created draft invoice ${result.invoiceNumber} for account ${invoiceData.accountId}`,
950
+ data: result,
951
+ };
952
+ }
953
+ catch (error) {
954
+ return {
955
+ success: false,
956
+ message: `Failed to create invoice: ${error instanceof Error ? error.message : String(error)}`,
957
+ };
958
+ }
959
+ }
960
+ async postInvoice(input) {
961
+ try {
962
+ const { invoiceId } = schemas.postInvoice.parse(input);
963
+ const result = await this.client.postInvoice(invoiceId);
964
+ return {
965
+ success: true,
966
+ message: `Posted invoice ${result.invoiceNumber} (status: ${result.status})`,
967
+ data: result,
968
+ };
969
+ }
970
+ catch (error) {
971
+ return {
972
+ success: false,
973
+ message: `Failed to post invoice: ${error instanceof Error ? error.message : String(error)}`,
974
+ };
975
+ }
976
+ }
977
+ async cancelSubscription(input) {
978
+ try {
979
+ const { subscriptionKey, ...cancellationData } = schemas.cancelSubscription.parse(input);
980
+ const result = await this.client.cancelSubscription(subscriptionKey, cancellationData);
981
+ return {
982
+ success: true,
983
+ message: `Cancelled subscription ${subscriptionKey} (id: ${result.subscriptionId}) effective ${result.cancelledDate}`,
984
+ data: result,
985
+ };
986
+ }
987
+ catch (error) {
988
+ return {
989
+ success: false,
990
+ message: `Failed to cancel subscription: ${error instanceof Error ? error.message : String(error)}`,
991
+ };
992
+ }
993
+ }
994
+ // --- Phase 4: Advanced Operation Handlers ---
995
+ async createSubscription(input) {
996
+ try {
997
+ const { idempotencyKey, ...subscriptionData } = schemas.createSubscription.parse(input);
998
+ const result = await this.client.createSubscription(subscriptionData, idempotencyKey);
999
+ return {
1000
+ success: true,
1001
+ message: `Created subscription ${result.subscriptionNumber} for account ${subscriptionData.accountKey}`,
1002
+ data: result,
1003
+ };
1004
+ }
1005
+ catch (error) {
1006
+ return {
1007
+ success: false,
1008
+ message: `Failed to create subscription: ${error instanceof Error ? error.message : String(error)}`,
1009
+ };
1010
+ }
1011
+ }
1012
+ async updateSubscription(input) {
1013
+ try {
1014
+ const { subscriptionKey, ...updateData } = schemas.updateSubscription.parse(input);
1015
+ const result = await this.client.updateSubscription(subscriptionKey, updateData);
1016
+ return {
1017
+ success: true,
1018
+ message: `Updated subscription ${subscriptionKey} (id: ${result.subscriptionId})`,
1019
+ data: result,
1020
+ };
1021
+ }
1022
+ catch (error) {
1023
+ return {
1024
+ success: false,
1025
+ message: `Failed to update subscription: ${error instanceof Error ? error.message : String(error)}`,
1026
+ };
1027
+ }
1028
+ }
1029
+ async createAccount(input) {
1030
+ try {
1031
+ const { idempotencyKey, ...accountData } = schemas.createAccount.parse(input);
1032
+ const result = await this.client.createAccount(accountData, idempotencyKey);
1033
+ return {
1034
+ success: true,
1035
+ message: `Created account ${result.accountNumber} (id: ${result.accountId})`,
1036
+ data: result,
1037
+ };
1038
+ }
1039
+ catch (error) {
1040
+ return {
1041
+ success: false,
1042
+ message: `Failed to create account: ${error instanceof Error ? error.message : String(error)}`,
1043
+ };
1044
+ }
1045
+ }
1046
+ async updateAccount(input) {
1047
+ try {
1048
+ const { accountKey, ...updateData } = schemas.updateAccount.parse(input);
1049
+ const result = await this.client.updateAccount(accountKey, updateData);
1050
+ return {
1051
+ success: true,
1052
+ message: `Updated account ${accountKey} successfully`,
1053
+ data: result,
1054
+ };
1055
+ }
1056
+ catch (error) {
1057
+ return {
1058
+ success: false,
1059
+ message: `Failed to update account: ${error instanceof Error ? error.message : String(error)}`,
1060
+ };
1061
+ }
1062
+ }
1063
+ async createRefund(input) {
1064
+ try {
1065
+ const { idempotencyKey, paymentId, ...refundData } = schemas.createRefund.parse(input);
1066
+ const result = await this.client.createRefund(paymentId, refundData, idempotencyKey);
1067
+ return {
1068
+ success: true,
1069
+ message: `Created refund ${result.number} (status: ${result.status})`,
1070
+ data: result,
1071
+ };
1072
+ }
1073
+ catch (error) {
1074
+ return {
1075
+ success: false,
1076
+ message: `Failed to create refund: ${error instanceof Error ? error.message : String(error)}`,
1077
+ };
1078
+ }
1079
+ }
1080
+ }
1081
+ export const toolRegistrations = [
1082
+ // Account Tools
1083
+ {
1084
+ name: "get_account",
1085
+ description: "Get Zuora account details by account key (ID or account number). " +
1086
+ "Returns name, status, currency, balance, and billing info.",
1087
+ inputSchema: schemas.getAccount,
1088
+ invoke: (handlers, args) => handlers.getAccount(args),
1089
+ },
1090
+ {
1091
+ name: "get_account_summary",
1092
+ description: "Get a comprehensive summary of a Zuora account including balances, " +
1093
+ "active subscriptions, recent invoices, and payments in a single call.",
1094
+ inputSchema: schemas.getAccountSummary,
1095
+ invoke: (handlers, args) => handlers.getAccountSummary(args),
1096
+ },
1097
+ // Invoice Tools
1098
+ {
1099
+ name: "get_invoice",
1100
+ description: "Get full details of a Zuora invoice including line items, amount, " +
1101
+ "due date, status, and payment status.",
1102
+ inputSchema: schemas.getInvoice,
1103
+ invoke: (handlers, args) => handlers.getInvoice(args),
1104
+ },
1105
+ {
1106
+ name: "list_invoices",
1107
+ description: "List invoices for a specific Zuora account with pagination. " +
1108
+ "Returns invoice numbers, amounts, dates, and statuses.",
1109
+ inputSchema: schemas.listInvoices,
1110
+ invoke: (handlers, args) => handlers.listInvoices(args),
1111
+ },
1112
+ // Subscription Tools
1113
+ {
1114
+ name: "get_subscription",
1115
+ description: "Get details of a Zuora subscription by subscription key or ID. " +
1116
+ "Returns plan info, status, term dates, and rate plan charges.",
1117
+ inputSchema: schemas.getSubscription,
1118
+ invoke: (handlers, args) => handlers.getSubscription(args),
1119
+ },
1120
+ {
1121
+ name: "list_subscriptions",
1122
+ description: "List all subscriptions for a Zuora account. " +
1123
+ "Returns subscription names, statuses, and term dates.",
1124
+ inputSchema: schemas.listSubscriptions,
1125
+ invoke: (handlers, args) => handlers.listSubscriptions(args),
1126
+ },
1127
+ // Payment Tools
1128
+ {
1129
+ name: "get_payment",
1130
+ description: "Get details of a specific Zuora payment including amount, date, " +
1131
+ "status, and which invoices it was applied to.",
1132
+ inputSchema: schemas.getPayment,
1133
+ invoke: (handlers, args) => handlers.getPayment(args),
1134
+ },
1135
+ {
1136
+ name: "list_payments",
1137
+ description: "List payments with optional account filter and pagination. " +
1138
+ "Returns payment amounts, dates, methods, and statuses.",
1139
+ inputSchema: schemas.listPayments,
1140
+ invoke: (handlers, args) => handlers.listPayments(args),
1141
+ },
1142
+ // ZOQL Query Tools
1143
+ {
1144
+ name: "execute_zoql_query",
1145
+ description: "Execute a ZOQL (Zuora Object Query Language) query for ad-hoc data retrieval. " +
1146
+ "Syntax: SELECT field1, field2 FROM ObjectName WHERE condition. " +
1147
+ "Key objects: Account, Invoice, Payment, Subscription, RatePlan, " +
1148
+ "RatePlanCharge, Product, ProductRatePlan, Contact. " +
1149
+ "Limitations: No JOINs supported. Max 2000 records per call. " +
1150
+ "Use continue_zoql_query with queryLocator for pagination. " +
1151
+ "Example: SELECT Id, AccountNumber, Name, Balance FROM Account WHERE Status = 'Active'",
1152
+ inputSchema: schemas.executeZoqlQuery,
1153
+ invoke: (handlers, args) => handlers.executeZoqlQuery(args),
1154
+ },
1155
+ {
1156
+ name: "continue_zoql_query",
1157
+ description: "Continue a previous ZOQL query that returned a queryLocator " +
1158
+ "(indicates more records available). Returns the next batch of up to 2000 records.",
1159
+ inputSchema: schemas.continueZoqlQuery,
1160
+ invoke: (handlers, args) => handlers.continueZoqlQuery(args),
1161
+ },
1162
+ // Product Catalog
1163
+ {
1164
+ name: "list_products",
1165
+ description: "List products from the Zuora product catalog with rate plans and charges. " +
1166
+ "Useful for understanding available products and pricing.",
1167
+ inputSchema: schemas.listProducts,
1168
+ invoke: (handlers, args) => handlers.listProducts(args),
1169
+ },
1170
+ // Phase 2: Extended Read Tools
1171
+ // Invoice Files
1172
+ {
1173
+ name: "get_invoice_files",
1174
+ description: "Get PDF file references for a specific Zuora invoice. " +
1175
+ "Returns file IDs and authenticated URLs for invoice PDFs. " +
1176
+ "Note: URLs require a valid Bearer token to access.",
1177
+ inputSchema: schemas.getInvoiceFiles,
1178
+ invoke: (handlers, args) => handlers.getInvoiceFiles(args),
1179
+ },
1180
+ // Credit Memo Tools
1181
+ {
1182
+ name: "get_credit_memo",
1183
+ description: "Get full details of a Zuora credit memo including amount, status, " +
1184
+ "applied/unapplied amounts, and line items.",
1185
+ inputSchema: schemas.getCreditMemo,
1186
+ invoke: (handlers, args) => handlers.getCreditMemo(args),
1187
+ },
1188
+ {
1189
+ name: "list_credit_memos",
1190
+ description: "List credit memos with optional account filter and pagination. " +
1191
+ "Returns credit memo numbers, amounts, statuses, and dates.",
1192
+ inputSchema: schemas.listCreditMemos,
1193
+ invoke: (handlers, args) => handlers.listCreditMemos(args),
1194
+ },
1195
+ // Account Search
1196
+ {
1197
+ name: "search_accounts",
1198
+ description: "Search Zuora accounts by field value. Supports searching by Name, " +
1199
+ "AccountNumber, Status, Currency, or Balance. Use LIKE operator with % " +
1200
+ "wildcard for partial name matching (e.g., field='Name', operator='LIKE', " +
1201
+ "value='Acme%'). Returns Id, AccountNumber, Name, Status, Balance, Currency. " +
1202
+ "For additional fields, use execute_zoql_query directly.",
1203
+ inputSchema: schemas.searchAccounts,
1204
+ invoke: (handlers, args) => handlers.searchAccounts(args),
1205
+ },
1206
+ // Usage
1207
+ {
1208
+ name: "list_usage",
1209
+ description: "List usage records for a Zuora account with pagination. " +
1210
+ "Returns usage quantities, units of measure, dates, and status.",
1211
+ inputSchema: schemas.listUsage,
1212
+ invoke: (handlers, args) => handlers.listUsage(args),
1213
+ },
1214
+ // Phase 3: Write Operations (require confirmation before calling)
1215
+ // Payment Creation (HIGH risk)
1216
+ {
1217
+ name: "create_payment",
1218
+ description: "FINANCIAL WRITE OPERATION (HIGH RISK): Create a payment record in Zuora. " +
1219
+ "This charges the customer or records an external payment. " +
1220
+ "IMPORTANT: Confirm the account ID, amount, and effective date with the user before calling. " +
1221
+ "Requires a UUID idempotency key to prevent duplicate payments. " +
1222
+ "Electronic payments require a paymentMethodId and process through the payment gateway. " +
1223
+ "External payments are manual records (check, wire, etc.). " +
1224
+ "This action cannot be easily undone - refunds require a separate operation.",
1225
+ inputSchema: schemas.createPayment,
1226
+ invoke: (handlers, args) => handlers.createPayment(args),
1227
+ },
1228
+ // Payment Application (HIGH risk)
1229
+ {
1230
+ name: "apply_payment",
1231
+ description: "FINANCIAL WRITE OPERATION (HIGH RISK): Apply an unapplied payment to one or more invoices. " +
1232
+ "This reduces invoice balances and allocates payment funds. " +
1233
+ "IMPORTANT: Confirm the payment ID, invoice IDs, and amounts with the user before calling. " +
1234
+ "The total applied amount across all invoices must not exceed the payment's unapplied amount. " +
1235
+ "ALWAYS use get_payment first to verify the unapplied balance before applying.",
1236
+ inputSchema: schemas.applyPayment,
1237
+ invoke: (handlers, args) => handlers.applyPayment(args),
1238
+ },
1239
+ // Invoice Creation (MEDIUM risk)
1240
+ {
1241
+ name: "create_invoice",
1242
+ description: "FINANCIAL WRITE OPERATION (MEDIUM RISK): Create a draft invoice for a Zuora account. " +
1243
+ "The invoice is created in Draft status and must be posted separately using post_invoice. " +
1244
+ "Requires a UUID idempotency key to prevent duplicate invoices. " +
1245
+ "Confirm the account ID and dates with the user before calling.",
1246
+ inputSchema: schemas.createInvoice,
1247
+ invoke: (handlers, args) => handlers.createInvoice(args),
1248
+ },
1249
+ // Invoice Posting (MEDIUM risk)
1250
+ {
1251
+ name: "post_invoice",
1252
+ description: "FINANCIAL WRITE OPERATION (MEDIUM RISK): Post a draft invoice, changing its status to Posted. " +
1253
+ "IMPORTANT: Once posted, the invoice is IMMUTABLE - it cannot be edited or deleted. " +
1254
+ "Posted invoices affect the account balance and are visible to the customer. " +
1255
+ "ALWAYS use get_invoice to review the draft invoice before posting. " +
1256
+ "To reverse a posted invoice, you must create a credit memo.",
1257
+ inputSchema: schemas.postInvoice,
1258
+ invoke: (handlers, args) => handlers.postInvoice(args),
1259
+ },
1260
+ // Subscription Cancellation (HIGH risk)
1261
+ {
1262
+ name: "cancel_subscription",
1263
+ description: "DESTRUCTIVE FINANCIAL OPERATION (HIGH RISK): Cancel a Zuora subscription. " +
1264
+ "IMPORTANT: This action may be irreversible depending on the cancellation policy. " +
1265
+ "Confirm the subscription key and cancellation policy with the user before calling. " +
1266
+ "EndOfCurrentTerm: Cancels at the end of the current billing term. " +
1267
+ "EndOfLastInvoicePeriod: Cancels at the end of the last invoiced period. " +
1268
+ "SpecificDate: Cancels on a specific date (requires cancellationEffectiveDate). " +
1269
+ "ALWAYS use get_subscription to review the subscription details before cancelling.",
1270
+ inputSchema: schemas.cancelSubscription,
1271
+ invoke: (handlers, args) => handlers.cancelSubscription(args),
1272
+ },
1273
+ // Phase 4: Advanced Operations
1274
+ // Subscription Creation (HIGH risk)
1275
+ {
1276
+ name: "create_subscription",
1277
+ description: "FINANCIAL WRITE OPERATION (HIGH RISK): Create a new subscription for a Zuora account. " +
1278
+ "IMPORTANT: Confirm the account, rate plans, term type, and effective date with the user before calling. " +
1279
+ "Requires a UUID idempotency key to prevent duplicate subscriptions. " +
1280
+ "Use list_products to find available productRatePlanIds before creating. " +
1281
+ "TERMED subscriptions require initialTerm and initialTermPeriodType. " +
1282
+ "EVERGREEN subscriptions have no fixed end date. " +
1283
+ "This creates a binding billing relationship that affects invoicing.",
1284
+ inputSchema: schemas.createSubscription,
1285
+ invoke: (handlers, args) => handlers.createSubscription(args),
1286
+ },
1287
+ // Subscription Update (MEDIUM risk)
1288
+ {
1289
+ name: "update_subscription",
1290
+ description: "FINANCIAL WRITE OPERATION (MEDIUM RISK): Update a Zuora subscription's renewal terms or settings. " +
1291
+ "Can modify autoRenew, renewalTerm, renewalTermPeriodType, and notes. " +
1292
+ "Confirm the subscription key and changes with the user before calling. " +
1293
+ "ALWAYS use get_subscription to review current settings before updating. " +
1294
+ "Changes to renewal terms take effect at the next renewal.",
1295
+ inputSchema: schemas.updateSubscription,
1296
+ invoke: (handlers, args) => handlers.updateSubscription(args),
1297
+ },
1298
+ // Account Creation (MEDIUM risk)
1299
+ {
1300
+ name: "create_account",
1301
+ description: "FINANCIAL WRITE OPERATION (MEDIUM RISK): Create a new billing account in Zuora. " +
1302
+ "Requires account name, currency, bill cycle day, and bill-to contact information. " +
1303
+ "Confirm all details with the user before calling. " +
1304
+ "Requires a UUID idempotency key to prevent duplicate accounts. " +
1305
+ "The account is created in Active status and can receive subscriptions immediately. " +
1306
+ "Currency cannot be changed after account creation.",
1307
+ inputSchema: schemas.createAccount,
1308
+ invoke: (handlers, args) => handlers.createAccount(args),
1309
+ },
1310
+ // Account Update (LOW risk)
1311
+ {
1312
+ name: "update_account",
1313
+ description: "WRITE OPERATION (LOW RISK): Update a Zuora account's name, notes, payment terms, " +
1314
+ "auto-pay setting, or contact information. " +
1315
+ "Confirm the account key and changes with the user before calling. " +
1316
+ "ALWAYS use get_account to review current settings before updating. " +
1317
+ "Only include fields that need to change.",
1318
+ inputSchema: schemas.updateAccount,
1319
+ invoke: (handlers, args) => handlers.updateAccount(args),
1320
+ },
1321
+ // Refund Creation (HIGH risk)
1322
+ {
1323
+ name: "create_refund",
1324
+ description: "FINANCIAL WRITE OPERATION (HIGH RISK): Create a refund against a specific payment in Zuora. " +
1325
+ "IMPORTANT: Confirm the payment ID, amount, and refund type with the user before calling. " +
1326
+ "ALWAYS use get_payment to verify the payment exists and has sufficient applied amount. " +
1327
+ "The refund amount must not exceed the original payment's applied amount. " +
1328
+ "Electronic refunds are processed through the payment gateway and may take days to settle. " +
1329
+ "External refunds are manual records (check, wire, etc.). " +
1330
+ "Requires a UUID idempotency key to prevent duplicate refunds. " +
1331
+ "This action cannot be easily undone.",
1332
+ inputSchema: schemas.createRefund,
1333
+ invoke: (handlers, args) => handlers.createRefund(args),
1334
+ },
1335
+ ];
1336
+ //# sourceMappingURL=tools.js.map