@capivv/mcp-server 0.2.0 → 0.5.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.
Files changed (108) hide show
  1. package/dist/client.d.ts +52 -1
  2. package/dist/client.js +189 -0
  3. package/dist/tools/approve-change-request.d.ts +3 -0
  4. package/dist/tools/approve-change-request.js +16 -0
  5. package/dist/tools/archive-app.d.ts +3 -0
  6. package/dist/tools/archive-app.js +9 -0
  7. package/dist/tools/check-drift.d.ts +3 -0
  8. package/dist/tools/check-drift.js +21 -0
  9. package/dist/tools/connect-apple-integration.d.ts +3 -0
  10. package/dist/tools/connect-apple-integration.js +27 -0
  11. package/dist/tools/connect-google-integration.d.ts +3 -0
  12. package/dist/tools/connect-google-integration.js +20 -0
  13. package/dist/tools/create-experiment.d.ts +3 -0
  14. package/dist/tools/create-experiment.js +43 -0
  15. package/dist/tools/create-paywall.d.ts +3 -0
  16. package/dist/tools/create-paywall.js +18 -0
  17. package/dist/tools/create-pricing-strategy.d.ts +3 -0
  18. package/dist/tools/create-pricing-strategy.js +49 -0
  19. package/dist/tools/create-product.js +43 -8
  20. package/dist/tools/create-promotion.d.ts +3 -0
  21. package/dist/tools/create-promotion.js +35 -0
  22. package/dist/tools/create-rescue-flow.d.ts +3 -0
  23. package/dist/tools/create-rescue-flow.js +20 -0
  24. package/dist/tools/delete-app.d.ts +3 -0
  25. package/dist/tools/delete-app.js +9 -0
  26. package/dist/tools/delete-entitlement.d.ts +3 -0
  27. package/dist/tools/delete-entitlement.js +11 -0
  28. package/dist/tools/delete-paywall.d.ts +3 -0
  29. package/dist/tools/delete-paywall.js +16 -0
  30. package/dist/tools/delete-promotion.d.ts +3 -0
  31. package/dist/tools/delete-promotion.js +11 -0
  32. package/dist/tools/delete-rescue-flow.d.ts +3 -0
  33. package/dist/tools/delete-rescue-flow.js +11 -0
  34. package/dist/tools/disconnect-integration.d.ts +3 -0
  35. package/dist/tools/disconnect-integration.js +13 -0
  36. package/dist/tools/get-entitlement.d.ts +3 -0
  37. package/dist/tools/get-entitlement.js +9 -0
  38. package/dist/tools/get-experiment-summary.d.ts +3 -0
  39. package/dist/tools/get-experiment-summary.js +9 -0
  40. package/dist/tools/get-offering.d.ts +3 -0
  41. package/dist/tools/get-offering.js +9 -0
  42. package/dist/tools/get-paywall-stats.d.ts +3 -0
  43. package/dist/tools/get-paywall-stats.js +6 -0
  44. package/dist/tools/get-product.d.ts +3 -0
  45. package/dist/tools/get-product.js +9 -0
  46. package/dist/tools/get-rescue-stats.d.ts +3 -0
  47. package/dist/tools/get-rescue-stats.js +12 -0
  48. package/dist/tools/get-rule.d.ts +3 -0
  49. package/dist/tools/get-rule.js +9 -0
  50. package/dist/tools/index.js +115 -0
  51. package/dist/tools/list-change-requests.d.ts +3 -0
  52. package/dist/tools/list-change-requests.js +14 -0
  53. package/dist/tools/list-integrations.d.ts +3 -0
  54. package/dist/tools/list-integrations.js +6 -0
  55. package/dist/tools/list-paywalls.d.ts +3 -0
  56. package/dist/tools/list-paywalls.js +6 -0
  57. package/dist/tools/list-pricing-strategies.d.ts +3 -0
  58. package/dist/tools/list-pricing-strategies.js +8 -0
  59. package/dist/tools/list-promotions.d.ts +3 -0
  60. package/dist/tools/list-promotions.js +6 -0
  61. package/dist/tools/list-rescue-flows.d.ts +3 -0
  62. package/dist/tools/list-rescue-flows.js +6 -0
  63. package/dist/tools/list-rule-versions.d.ts +3 -0
  64. package/dist/tools/list-rule-versions.js +9 -0
  65. package/dist/tools/next-step.js +3 -3
  66. package/dist/tools/preview-pricing.d.ts +3 -0
  67. package/dist/tools/preview-pricing.js +13 -0
  68. package/dist/tools/push-prices-to-stores.d.ts +3 -0
  69. package/dist/tools/push-prices-to-stores.js +9 -0
  70. package/dist/tools/recompute-prices.d.ts +3 -0
  71. package/dist/tools/recompute-prices.js +24 -0
  72. package/dist/tools/resolve-drift.d.ts +3 -0
  73. package/dist/tools/resolve-drift.js +15 -0
  74. package/dist/tools/restore-app.d.ts +3 -0
  75. package/dist/tools/restore-app.js +9 -0
  76. package/dist/tools/revert-app-autopilot.d.ts +3 -0
  77. package/dist/tools/revert-app-autopilot.js +9 -0
  78. package/dist/tools/rollback-rule.d.ts +3 -0
  79. package/dist/tools/rollback-rule.js +10 -0
  80. package/dist/tools/run-app-autopilot.d.ts +3 -0
  81. package/dist/tools/run-app-autopilot.js +9 -0
  82. package/dist/tools/set-country-price-override.d.ts +3 -0
  83. package/dist/tools/set-country-price-override.js +13 -0
  84. package/dist/tools/setup-wizard.js +1 -1
  85. package/dist/tools/start-experiment.d.ts +3 -0
  86. package/dist/tools/start-experiment.js +9 -0
  87. package/dist/tools/stop-experiment.d.ts +3 -0
  88. package/dist/tools/stop-experiment.js +9 -0
  89. package/dist/tools/sync-suggestions-count.d.ts +3 -0
  90. package/dist/tools/sync-suggestions-count.js +6 -0
  91. package/dist/tools/trigger-sync.d.ts +3 -0
  92. package/dist/tools/trigger-sync.js +6 -0
  93. package/dist/tools/update-app.d.ts +3 -0
  94. package/dist/tools/update-app.js +19 -0
  95. package/dist/tools/update-entitlement.d.ts +3 -0
  96. package/dist/tools/update-entitlement.js +13 -0
  97. package/dist/tools/update-experiment.d.ts +3 -0
  98. package/dist/tools/update-experiment.js +22 -0
  99. package/dist/tools/update-offering.d.ts +3 -0
  100. package/dist/tools/update-offering.js +31 -0
  101. package/dist/tools/update-paywall.d.ts +3 -0
  102. package/dist/tools/update-paywall.js +23 -0
  103. package/dist/tools/update-promotion.d.ts +3 -0
  104. package/dist/tools/update-promotion.js +20 -0
  105. package/dist/tools/update-rescue-flow.d.ts +3 -0
  106. package/dist/tools/update-rescue-flow.js +27 -0
  107. package/dist/types.d.ts +336 -0
  108. package/package.json +1 -1
@@ -0,0 +1,9 @@
1
+ import { z } from 'zod';
2
+ export function registerRevertAppAutopilotTool(server, client) {
3
+ server.tool('capivv_revert_app_autopilot', 'Revert autopilot-generated artifacts for an app. Removes entitlements, products, offerings, and rules that were auto-created by capivv_run_app_autopilot. Manually-created records are preserved.', {
4
+ app_id: z.string().describe('App ID to revert autopilot on'),
5
+ }, async ({ app_id }) => {
6
+ const result = await client.revertAppAutopilot(app_id);
7
+ return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
8
+ });
9
+ }
@@ -0,0 +1,3 @@
1
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import type { CapivvClient } from '../client.js';
3
+ export declare function registerRollbackRuleTool(server: McpServer, client: CapivvClient): void;
@@ -0,0 +1,10 @@
1
+ import { z } from 'zod';
2
+ export function registerRollbackRuleTool(server, client) {
3
+ server.tool('capivv_rollback_rule', 'Roll a rule back to a previous version. Use capivv_list_rule_versions to find the target version number.', {
4
+ rule_id: z.string().describe('Rule ID'),
5
+ version: z.number().describe('Version number to roll back to'),
6
+ }, async ({ rule_id, version }) => {
7
+ const rule = await client.rollbackRule(rule_id, version);
8
+ return { content: [{ type: 'text', text: JSON.stringify(rule, null, 2) }] };
9
+ });
10
+ }
@@ -0,0 +1,3 @@
1
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import type { CapivvClient } from '../client.js';
3
+ export declare function registerRunAppAutopilotTool(server: McpServer, client: CapivvClient): void;
@@ -0,0 +1,9 @@
1
+ import { z } from 'zod';
2
+ export function registerRunAppAutopilotTool(server, client) {
3
+ server.tool('capivv_run_app_autopilot', 'Run autopilot for an app: idempotent re-seeding of entitlements, products, offerings, and rules from the connected store data. Safe to call repeatedly. Use capivv_revert_app_autopilot to undo.', {
4
+ app_id: z.string().describe('App ID to run autopilot on'),
5
+ }, async ({ app_id }) => {
6
+ const result = await client.runAppAutopilot(app_id);
7
+ return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
8
+ });
9
+ }
@@ -0,0 +1,3 @@
1
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import type { CapivvClient } from '../client.js';
3
+ export declare function registerSetCountryPriceOverrideTool(server: McpServer, client: CapivvClient): void;
@@ -0,0 +1,13 @@
1
+ import { z } from 'zod';
2
+ export function registerSetCountryPriceOverrideTool(server, client) {
3
+ server.tool('capivv_set_country_price_override', 'Set a manual price override for a product in a specific country. Overridden prices are NOT touched by capivv_recompute_prices — they hold the value the user set until cleared. Use capivv_push_prices_to_stores to propagate the override to App Store Connect / Google Play.', {
4
+ product_id: z.string().describe('Product ID'),
5
+ country_code: z.string().describe('ISO 3166-1 alpha-2 country code (e.g. "US", "DE", "JP")'),
6
+ store: z.string().describe('Which store this price targets: "apple", "google", or "both"'),
7
+ currency: z.string().describe('ISO 4217 currency code (e.g. "USD", "EUR")'),
8
+ amount_cents: z.number().describe('Price in cents (e.g. 999 for $9.99)'),
9
+ }, async (args) => {
10
+ const result = await client.setCountryPriceOverride(args);
11
+ return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
12
+ });
13
+ }
@@ -38,7 +38,7 @@ Example:
38
38
  name: z.string().describe('Product display name (e.g., "Monthly Plan")'),
39
39
  external_id: z
40
40
  .string()
41
- .describe('Store product ID must match App Store Connect / Google Play exactly'),
41
+ .describe('Store product ID. With a connected store integration, Capivv creates this product in App Store Connect / Google Play too — pass the ID you want it to have there.'),
42
42
  billing_period: z
43
43
  .string()
44
44
  .describe('Billing period: week, month, three_months, six_months, or year'),
@@ -0,0 +1,3 @@
1
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import type { CapivvClient } from '../client.js';
3
+ export declare function registerStartExperimentTool(server: McpServer, client: CapivvClient): void;
@@ -0,0 +1,9 @@
1
+ import { z } from 'zod';
2
+ export function registerStartExperimentTool(server, client) {
3
+ server.tool('capivv_start_experiment', 'Flip an experiment from draft to running. New users now get assigned to variants based on traffic_percent. Use capivv_get_experiment_summary to monitor progress.', {
4
+ experiment_id: z.string().describe('Experiment ID to start'),
5
+ }, async ({ experiment_id }) => {
6
+ const exp = await client.startExperiment(experiment_id);
7
+ return { content: [{ type: 'text', text: JSON.stringify(exp, null, 2) }] };
8
+ });
9
+ }
@@ -0,0 +1,3 @@
1
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import type { CapivvClient } from '../client.js';
3
+ export declare function registerStopExperimentTool(server: McpServer, client: CapivvClient): void;
@@ -0,0 +1,9 @@
1
+ import { z } from 'zod';
2
+ export function registerStopExperimentTool(server, client) {
3
+ server.tool('capivv_stop_experiment', 'Mark an experiment as completed. New users stop being assigned to variants; existing assignments are preserved for analysis. Use capivv_get_experiment_summary to read final results.', {
4
+ experiment_id: z.string().describe('Experiment ID to stop'),
5
+ }, async ({ experiment_id }) => {
6
+ const exp = await client.stopExperiment(experiment_id);
7
+ return { content: [{ type: 'text', text: JSON.stringify(exp, null, 2) }] };
8
+ });
9
+ }
@@ -0,0 +1,3 @@
1
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import type { CapivvClient } from '../client.js';
3
+ export declare function registerSyncSuggestionsCountTool(server: McpServer, client: CapivvClient): void;
@@ -0,0 +1,6 @@
1
+ export function registerSyncSuggestionsCountTool(server, client) {
2
+ server.tool('capivv_sync_suggestions_count', 'Get the count of pending drift suggestions across the workspace. A quick health check before deciding whether to call capivv_check_drift for full details.', async () => {
3
+ const count = await client.getSyncSuggestionsCount();
4
+ return { content: [{ type: 'text', text: JSON.stringify(count, null, 2) }] };
5
+ });
6
+ }
@@ -0,0 +1,3 @@
1
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import type { CapivvClient } from '../client.js';
3
+ export declare function registerTriggerSyncTool(server: McpServer, client: CapivvClient): void;
@@ -0,0 +1,6 @@
1
+ export function registerTriggerSyncTool(server, client) {
2
+ server.tool('capivv_trigger_sync', 'Force an immediate sync run for every connected store integration in the workspace. Useful right after creating products in App Store Connect or Google Play to surface them as drift suggestions without waiting for the worker\'s scheduled interval.', async () => {
3
+ const result = await client.triggerSync();
4
+ return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
5
+ });
6
+ }
@@ -0,0 +1,3 @@
1
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import type { CapivvClient } from '../client.js';
3
+ export declare function registerUpdateAppTool(server: McpServer, client: CapivvClient): void;
@@ -0,0 +1,19 @@
1
+ import { z } from 'zod';
2
+ export function registerUpdateAppTool(server, client) {
3
+ server.tool('capivv_update_app', 'Update an app by ID. Provide only the fields you want to change. Common uses: rename, fix a placeholder bundle_id, edit settings.', {
4
+ app_id: z.string().describe('App ID'),
5
+ name: z.string().optional().describe('New display name'),
6
+ bundle_id: z
7
+ .string()
8
+ .optional()
9
+ .describe('New bundle ID (use to fix a placeholder like com.example.myapp)'),
10
+ settings: z
11
+ .record(z.string(), z.unknown())
12
+ .optional()
13
+ .describe('Free-form settings JSON (merged into existing)'),
14
+ }, async (args) => {
15
+ const { app_id, ...rest } = args;
16
+ const app = await client.updateApp(app_id, rest);
17
+ return { content: [{ type: 'text', text: JSON.stringify(app, null, 2) }] };
18
+ });
19
+ }
@@ -0,0 +1,3 @@
1
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import type { CapivvClient } from '../client.js';
3
+ export declare function registerUpdateEntitlementTool(server: McpServer, client: CapivvClient): void;
@@ -0,0 +1,13 @@
1
+ import { z } from 'zod';
2
+ export function registerUpdateEntitlementTool(server, client) {
3
+ server.tool('capivv_update_entitlement', 'Update an entitlement by ID. Provide only the fields you want to change.', {
4
+ entitlement_id: z.string().describe('Entitlement ID'),
5
+ identifier: z.string().optional().describe('New stable identifier'),
6
+ display_name: z.string().optional().describe('New display name'),
7
+ description: z.string().optional().describe('New description'),
8
+ }, async (args) => {
9
+ const { entitlement_id, ...rest } = args;
10
+ const ent = await client.updateEntitlement(entitlement_id, rest);
11
+ return { content: [{ type: 'text', text: JSON.stringify(ent, null, 2) }] };
12
+ });
13
+ }
@@ -0,0 +1,3 @@
1
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import type { CapivvClient } from '../client.js';
3
+ export declare function registerUpdateExperimentTool(server: McpServer, client: CapivvClient): void;
@@ -0,0 +1,22 @@
1
+ import { z } from 'zod';
2
+ export function registerUpdateExperimentTool(server, client) {
3
+ server.tool('capivv_update_experiment', 'Update an experiment by ID. Provide only the fields you want to change. Use capivv_start_experiment / capivv_stop_experiment for status flips so audit logs and assignment freezing fire correctly.', {
4
+ experiment_id: z.string().describe('Experiment ID to update'),
5
+ name: z.string().optional().describe('New display name'),
6
+ description: z.string().optional().describe('New description'),
7
+ status: z
8
+ .string()
9
+ .optional()
10
+ .describe('New status (draft / running / paused / completed). Prefer start/stop tools.'),
11
+ target_metric: z.string().optional().describe('New target metric'),
12
+ start_date: z.string().optional().describe('New start timestamp (ISO 8601)'),
13
+ end_date: z.string().optional().describe('New end timestamp (ISO 8601)'),
14
+ sample_size_target: z.number().optional().describe('New sample size target'),
15
+ confidence_level: z.number().optional().describe('New confidence level'),
16
+ metadata: z.record(z.string(), z.unknown()).optional().describe('Free-form metadata'),
17
+ }, async (args) => {
18
+ const { experiment_id, ...rest } = args;
19
+ const exp = await client.updateExperiment(experiment_id, rest);
20
+ return { content: [{ type: 'text', text: JSON.stringify(exp, null, 2) }] };
21
+ });
22
+ }
@@ -0,0 +1,3 @@
1
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import type { CapivvClient } from '../client.js';
3
+ export declare function registerUpdateOfferingTool(server: McpServer, client: CapivvClient): void;
@@ -0,0 +1,31 @@
1
+ import { z } from 'zod';
2
+ export function registerUpdateOfferingTool(server, client) {
3
+ server.tool('capivv_update_offering', 'Update an offering by ID. Provide only the fields you want to change. Pass `packages` to replace the package list (full replacement, not merge — include every package you want to keep).', {
4
+ offering_id: z.string().describe('Offering ID'),
5
+ display_name: z.string().optional().describe('New display name'),
6
+ description: z.string().optional().describe('New description'),
7
+ is_default: z
8
+ .boolean()
9
+ .optional()
10
+ .describe('Whether this is the default offering for its app'),
11
+ packages: z
12
+ .array(z.object({
13
+ identifier: z.string(),
14
+ product_id: z.string(),
15
+ display_name: z.string(),
16
+ description: z.string().optional(),
17
+ package_type: z.string().describe('monthly | annual | weekly | lifetime | custom'),
18
+ position: z.number(),
19
+ }))
20
+ .optional()
21
+ .describe('Replacement package list (full replacement, not merge)'),
22
+ metadata: z
23
+ .record(z.string(), z.unknown())
24
+ .optional()
25
+ .describe('Free-form metadata (replaces existing)'),
26
+ }, async (args) => {
27
+ const { offering_id, ...rest } = args;
28
+ const offering = await client.updateOffering(offering_id, rest);
29
+ return { content: [{ type: 'text', text: JSON.stringify(offering, null, 2) }] };
30
+ });
31
+ }
@@ -0,0 +1,3 @@
1
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import type { CapivvClient } from '../client.js';
3
+ export declare function registerUpdatePaywallTool(server: McpServer, client: CapivvClient): void;
@@ -0,0 +1,23 @@
1
+ import { z } from 'zod';
2
+ export function registerUpdatePaywallTool(server, client) {
3
+ server.tool('capivv_update_paywall', 'Update a paywall by ID. Provide only the fields you want to change. Use this to attach a template, swap the config blob, or update metadata. Use capivv_list_paywalls to discover the paywall_id.', {
4
+ paywall_id: z.string().describe('Paywall ID to update'),
5
+ name: z.string().optional().describe('New display name'),
6
+ template: z
7
+ .string()
8
+ .optional()
9
+ .describe('Template identifier (e.g. "default", "minimal", "image_first")'),
10
+ config: z
11
+ .record(z.string(), z.unknown())
12
+ .optional()
13
+ .describe('Paywall configuration JSON (layout, copy, products to display, etc.)'),
14
+ metadata: z
15
+ .record(z.string(), z.unknown())
16
+ .optional()
17
+ .describe('Free-form metadata stored alongside the paywall'),
18
+ }, async (args) => {
19
+ const { paywall_id, ...rest } = args;
20
+ const paywall = await client.updatePaywall(paywall_id, rest);
21
+ return { content: [{ type: 'text', text: JSON.stringify(paywall, null, 2) }] };
22
+ });
23
+ }
@@ -0,0 +1,3 @@
1
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import type { CapivvClient } from '../client.js';
3
+ export declare function registerUpdatePromotionTool(server: McpServer, client: CapivvClient): void;
@@ -0,0 +1,20 @@
1
+ import { z } from 'zod';
2
+ export function registerUpdatePromotionTool(server, client) {
3
+ server.tool('capivv_update_promotion', 'Update a promotion by ID. Provide only the fields you want to change. Use capivv_list_promotions to discover the promotion_id.', {
4
+ promotion_id: z.string().describe('Promotion ID to update'),
5
+ name: z.string().optional().describe('New display name'),
6
+ description: z.string().optional().describe('New description'),
7
+ discount_percent: z
8
+ .number()
9
+ .optional()
10
+ .describe('New percentage discount (0-100)'),
11
+ max_redemptions: z
12
+ .number()
13
+ .optional()
14
+ .describe('New redemption cap. Reduce only — increasing past current_redemptions is a no-op.'),
15
+ }, async (args) => {
16
+ const { promotion_id, ...rest } = args;
17
+ const promotion = await client.updatePromotion(promotion_id, rest);
18
+ return { content: [{ type: 'text', text: JSON.stringify(promotion, null, 2) }] };
19
+ });
20
+ }
@@ -0,0 +1,3 @@
1
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import type { CapivvClient } from '../client.js';
3
+ export declare function registerUpdateRescueFlowTool(server: McpServer, client: CapivvClient): void;
@@ -0,0 +1,27 @@
1
+ import { z } from 'zod';
2
+ export function registerUpdateRescueFlowTool(server, client) {
3
+ server.tool('capivv_update_rescue_flow', [
4
+ 'Update a rescue flow by ID. Provide only the fields you want to change.',
5
+ '`conditions` is an eligibility filter object (e.g. { product_ids: [...], min_tenure_days: 30 }).',
6
+ '`steps` is the offer ladder shown to the user during cancellation (e.g. [{ type: "discount", percent: 50 }, { type: "pause", months: 1 }]).',
7
+ 'Use capivv_list_rescue_flows to discover the rescue_flow_id.',
8
+ ].join(' '), {
9
+ rescue_flow_id: z.string().describe('Rescue flow ID to update'),
10
+ name: z.string().optional().describe('New display name'),
11
+ description: z.string().optional().describe('New description'),
12
+ priority: z.number().optional().describe('New priority'),
13
+ conditions: z
14
+ .record(z.string(), z.unknown())
15
+ .optional()
16
+ .describe('Eligibility filter object'),
17
+ steps: z
18
+ .record(z.string(), z.unknown())
19
+ .optional()
20
+ .describe('Offer ladder configuration'),
21
+ metadata: z.record(z.string(), z.unknown()).optional().describe('Free-form metadata'),
22
+ }, async (args) => {
23
+ const { rescue_flow_id, ...rest } = args;
24
+ const flow = await client.updateRescueFlow(rescue_flow_id, rest);
25
+ return { content: [{ type: 'text', text: JSON.stringify(flow, null, 2) }] };
26
+ });
27
+ }