@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.
- package/dist/client.d.ts +52 -1
- package/dist/client.js +189 -0
- package/dist/tools/approve-change-request.d.ts +3 -0
- package/dist/tools/approve-change-request.js +16 -0
- package/dist/tools/archive-app.d.ts +3 -0
- package/dist/tools/archive-app.js +9 -0
- package/dist/tools/check-drift.d.ts +3 -0
- package/dist/tools/check-drift.js +21 -0
- package/dist/tools/connect-apple-integration.d.ts +3 -0
- package/dist/tools/connect-apple-integration.js +27 -0
- package/dist/tools/connect-google-integration.d.ts +3 -0
- package/dist/tools/connect-google-integration.js +20 -0
- package/dist/tools/create-experiment.d.ts +3 -0
- package/dist/tools/create-experiment.js +43 -0
- package/dist/tools/create-paywall.d.ts +3 -0
- package/dist/tools/create-paywall.js +18 -0
- package/dist/tools/create-pricing-strategy.d.ts +3 -0
- package/dist/tools/create-pricing-strategy.js +49 -0
- package/dist/tools/create-product.js +43 -8
- package/dist/tools/create-promotion.d.ts +3 -0
- package/dist/tools/create-promotion.js +35 -0
- package/dist/tools/create-rescue-flow.d.ts +3 -0
- package/dist/tools/create-rescue-flow.js +20 -0
- package/dist/tools/delete-app.d.ts +3 -0
- package/dist/tools/delete-app.js +9 -0
- package/dist/tools/delete-entitlement.d.ts +3 -0
- package/dist/tools/delete-entitlement.js +11 -0
- package/dist/tools/delete-paywall.d.ts +3 -0
- package/dist/tools/delete-paywall.js +16 -0
- package/dist/tools/delete-promotion.d.ts +3 -0
- package/dist/tools/delete-promotion.js +11 -0
- package/dist/tools/delete-rescue-flow.d.ts +3 -0
- package/dist/tools/delete-rescue-flow.js +11 -0
- package/dist/tools/disconnect-integration.d.ts +3 -0
- package/dist/tools/disconnect-integration.js +13 -0
- package/dist/tools/get-entitlement.d.ts +3 -0
- package/dist/tools/get-entitlement.js +9 -0
- package/dist/tools/get-experiment-summary.d.ts +3 -0
- package/dist/tools/get-experiment-summary.js +9 -0
- package/dist/tools/get-offering.d.ts +3 -0
- package/dist/tools/get-offering.js +9 -0
- package/dist/tools/get-paywall-stats.d.ts +3 -0
- package/dist/tools/get-paywall-stats.js +6 -0
- package/dist/tools/get-product.d.ts +3 -0
- package/dist/tools/get-product.js +9 -0
- package/dist/tools/get-rescue-stats.d.ts +3 -0
- package/dist/tools/get-rescue-stats.js +12 -0
- package/dist/tools/get-rule.d.ts +3 -0
- package/dist/tools/get-rule.js +9 -0
- package/dist/tools/index.js +115 -0
- package/dist/tools/list-change-requests.d.ts +3 -0
- package/dist/tools/list-change-requests.js +14 -0
- package/dist/tools/list-integrations.d.ts +3 -0
- package/dist/tools/list-integrations.js +6 -0
- package/dist/tools/list-paywalls.d.ts +3 -0
- package/dist/tools/list-paywalls.js +6 -0
- package/dist/tools/list-pricing-strategies.d.ts +3 -0
- package/dist/tools/list-pricing-strategies.js +8 -0
- package/dist/tools/list-promotions.d.ts +3 -0
- package/dist/tools/list-promotions.js +6 -0
- package/dist/tools/list-rescue-flows.d.ts +3 -0
- package/dist/tools/list-rescue-flows.js +6 -0
- package/dist/tools/list-rule-versions.d.ts +3 -0
- package/dist/tools/list-rule-versions.js +9 -0
- package/dist/tools/next-step.js +3 -3
- package/dist/tools/preview-pricing.d.ts +3 -0
- package/dist/tools/preview-pricing.js +13 -0
- package/dist/tools/push-prices-to-stores.d.ts +3 -0
- package/dist/tools/push-prices-to-stores.js +9 -0
- package/dist/tools/recompute-prices.d.ts +3 -0
- package/dist/tools/recompute-prices.js +24 -0
- package/dist/tools/resolve-drift.d.ts +3 -0
- package/dist/tools/resolve-drift.js +15 -0
- package/dist/tools/restore-app.d.ts +3 -0
- package/dist/tools/restore-app.js +9 -0
- package/dist/tools/revert-app-autopilot.d.ts +3 -0
- package/dist/tools/revert-app-autopilot.js +9 -0
- package/dist/tools/rollback-rule.d.ts +3 -0
- package/dist/tools/rollback-rule.js +10 -0
- package/dist/tools/run-app-autopilot.d.ts +3 -0
- package/dist/tools/run-app-autopilot.js +9 -0
- package/dist/tools/set-country-price-override.d.ts +3 -0
- package/dist/tools/set-country-price-override.js +13 -0
- package/dist/tools/setup-wizard.js +1 -1
- package/dist/tools/start-experiment.d.ts +3 -0
- package/dist/tools/start-experiment.js +9 -0
- package/dist/tools/stop-experiment.d.ts +3 -0
- package/dist/tools/stop-experiment.js +9 -0
- package/dist/tools/sync-suggestions-count.d.ts +3 -0
- package/dist/tools/sync-suggestions-count.js +6 -0
- package/dist/tools/trigger-sync.d.ts +3 -0
- package/dist/tools/trigger-sync.js +6 -0
- package/dist/tools/update-app.d.ts +3 -0
- package/dist/tools/update-app.js +19 -0
- package/dist/tools/update-entitlement.d.ts +3 -0
- package/dist/tools/update-entitlement.js +13 -0
- package/dist/tools/update-experiment.d.ts +3 -0
- package/dist/tools/update-experiment.js +22 -0
- package/dist/tools/update-offering.d.ts +3 -0
- package/dist/tools/update-offering.js +31 -0
- package/dist/tools/update-paywall.d.ts +3 -0
- package/dist/tools/update-paywall.js +23 -0
- package/dist/tools/update-promotion.d.ts +3 -0
- package/dist/tools/update-promotion.js +20 -0
- package/dist/tools/update-rescue-flow.d.ts +3 -0
- package/dist/tools/update-rescue-flow.js +27 -0
- package/dist/types.d.ts +336 -0
- package/package.json +1 -1
package/dist/client.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Config } from './config.js';
|
|
2
|
-
import type { App, Product, Entitlement, Offering, Rule, Experiment, ExperimentSummary, AnalyticsOverview, OnboardingResponse, ImportPreviewResponse, CreateAppRequest, CreateEntitlementRequest, CreateProductRequest, CreateOfferingRequest, CreateRuleRequest, ValidateRuleRequest, ValidateRuleResponse, WhoamiResponse, ApiKeyUsageResponse } from './types.js';
|
|
2
|
+
import type { App, Product, Entitlement, Offering, Rule, Experiment, ExperimentSummary, AnalyticsOverview, OnboardingResponse, ImportPreviewResponse, CreateAppRequest, CreateEntitlementRequest, CreateProductRequest, CreateOfferingRequest, CreateRuleRequest, ValidateRuleRequest, ValidateRuleResponse, WhoamiResponse, ApiKeyUsageResponse, Paywall, CreatePaywallRequest, UpdatePaywallRequest, PaywallStats, Promotion, CreatePromotionRequest, UpdatePromotionRequest, RescueFlow, CreateRescueFlowRequest, UpdateRescueFlowRequest, RescueStats, PricingStrategy, CreatePricingStrategyRequest, PricingPreviewResult, PricingRecomputeRequest, PricingRecomputeResult, PricingPushResult, PricingChangeRequest, SetCountryPriceOverrideRequest, ExperimentWithVariants, CreateExperimentRequest, UpdateExperimentRequest, UpdateAppRequest, UpdateEntitlementRequest, UpdateOfferingRequest, AutopilotRunResult, SyncSuggestion, SyncSuggestionsCount, TriggerSyncResult, IntegrationSummary, ConnectAppleIntegrationRequest, ConnectAppleIntegrationResult, ConnectGoogleIntegrationRequest, ConnectGoogleIntegrationResult } from './types.js';
|
|
3
3
|
export declare class ApiError extends Error {
|
|
4
4
|
status: number;
|
|
5
5
|
code: string;
|
|
@@ -40,4 +40,55 @@ export declare class CapivvClient {
|
|
|
40
40
|
deleteRule(id: string): Promise<void>;
|
|
41
41
|
activateRule(id: string): Promise<Rule>;
|
|
42
42
|
deactivateRule(id: string): Promise<Rule>;
|
|
43
|
+
listPaywalls(): Promise<Paywall[]>;
|
|
44
|
+
createPaywall(data: CreatePaywallRequest): Promise<Paywall>;
|
|
45
|
+
updatePaywall(id: string, data: UpdatePaywallRequest): Promise<Paywall>;
|
|
46
|
+
deletePaywall(id: string): Promise<void>;
|
|
47
|
+
getPaywallStats(): Promise<PaywallStats>;
|
|
48
|
+
listPromotions(): Promise<Promotion[]>;
|
|
49
|
+
createPromotion(data: CreatePromotionRequest): Promise<Promotion>;
|
|
50
|
+
updatePromotion(id: string, data: UpdatePromotionRequest): Promise<Promotion>;
|
|
51
|
+
deletePromotion(id: string): Promise<void>;
|
|
52
|
+
listRescueFlows(): Promise<RescueFlow[]>;
|
|
53
|
+
createRescueFlow(data: CreateRescueFlowRequest): Promise<RescueFlow>;
|
|
54
|
+
updateRescueFlow(id: string, data: UpdateRescueFlowRequest): Promise<RescueFlow>;
|
|
55
|
+
deleteRescueFlow(id: string): Promise<void>;
|
|
56
|
+
getRescueStats(days?: number): Promise<RescueStats>;
|
|
57
|
+
listPricingStrategies(): Promise<PricingStrategy[]>;
|
|
58
|
+
createPricingStrategy(data: CreatePricingStrategyRequest): Promise<PricingStrategy>;
|
|
59
|
+
previewPricing(productId: string, strategyId?: string): Promise<PricingPreviewResult>;
|
|
60
|
+
recomputePrices(data: PricingRecomputeRequest): Promise<PricingRecomputeResult>;
|
|
61
|
+
pushPricesToStores(productId: string): Promise<PricingPushResult>;
|
|
62
|
+
listPricingChangeRequests(appId: string, status?: string, productId?: string): Promise<PricingChangeRequest[]>;
|
|
63
|
+
approvePricingChangeRequest(id: string): Promise<void>;
|
|
64
|
+
setCountryPriceOverride(data: SetCountryPriceOverrideRequest): Promise<unknown>;
|
|
65
|
+
createExperiment(data: CreateExperimentRequest): Promise<ExperimentWithVariants>;
|
|
66
|
+
getExperiment(id: string): Promise<ExperimentWithVariants>;
|
|
67
|
+
updateExperiment(id: string, data: UpdateExperimentRequest): Promise<ExperimentWithVariants>;
|
|
68
|
+
startExperiment(id: string): Promise<ExperimentWithVariants>;
|
|
69
|
+
stopExperiment(id: string): Promise<ExperimentWithVariants>;
|
|
70
|
+
getApp(id: string): Promise<App>;
|
|
71
|
+
updateApp(id: string, data: UpdateAppRequest): Promise<App>;
|
|
72
|
+
deleteApp(id: string): Promise<void>;
|
|
73
|
+
archiveApp(id: string): Promise<App>;
|
|
74
|
+
restoreApp(id: string): Promise<App>;
|
|
75
|
+
runAppAutopilot(id: string): Promise<AutopilotRunResult>;
|
|
76
|
+
revertAppAutopilot(id: string): Promise<AutopilotRunResult>;
|
|
77
|
+
getEntitlement(id: string): Promise<Entitlement>;
|
|
78
|
+
updateEntitlement(id: string, data: UpdateEntitlementRequest): Promise<Entitlement>;
|
|
79
|
+
deleteEntitlement(id: string): Promise<void>;
|
|
80
|
+
getProduct(id: string): Promise<Product>;
|
|
81
|
+
getRuleById(id: string): Promise<Rule>;
|
|
82
|
+
listRuleVersions(id: string): Promise<unknown>;
|
|
83
|
+
rollbackRule(id: string, version: number): Promise<Rule>;
|
|
84
|
+
getOffering(id: string): Promise<Offering>;
|
|
85
|
+
updateOffering(id: string, data: UpdateOfferingRequest): Promise<Offering>;
|
|
86
|
+
listSyncSuggestions(appId?: string, status?: string): Promise<SyncSuggestion[]>;
|
|
87
|
+
getSyncSuggestionsCount(): Promise<SyncSuggestionsCount>;
|
|
88
|
+
resolveSyncSuggestion(id: string, action: 'accept' | 'dismiss'): Promise<SyncSuggestion>;
|
|
89
|
+
triggerSync(): Promise<TriggerSyncResult>;
|
|
90
|
+
listIntegrations(): Promise<IntegrationSummary[]>;
|
|
91
|
+
connectAppleIntegration(data: ConnectAppleIntegrationRequest): Promise<ConnectAppleIntegrationResult>;
|
|
92
|
+
connectGoogleIntegration(data: ConnectGoogleIntegrationRequest): Promise<ConnectGoogleIntegrationResult>;
|
|
93
|
+
disconnectIntegration(provider: string): Promise<void>;
|
|
43
94
|
}
|
package/dist/client.js
CHANGED
|
@@ -150,4 +150,193 @@ export class CapivvClient {
|
|
|
150
150
|
async deactivateRule(id) {
|
|
151
151
|
return this.post(`/dashboard/rules/${encodeURIComponent(id)}/deactivate`);
|
|
152
152
|
}
|
|
153
|
+
// ---- Paywalls (V8 Phase B.1) ----
|
|
154
|
+
async listPaywalls() {
|
|
155
|
+
const resp = await this.get('/dashboard/paywalls');
|
|
156
|
+
return resp.paywalls;
|
|
157
|
+
}
|
|
158
|
+
async createPaywall(data) {
|
|
159
|
+
return this.post('/dashboard/paywalls', data);
|
|
160
|
+
}
|
|
161
|
+
async updatePaywall(id, data) {
|
|
162
|
+
return this.patch(`/dashboard/paywalls/${encodeURIComponent(id)}`, data);
|
|
163
|
+
}
|
|
164
|
+
async deletePaywall(id) {
|
|
165
|
+
await this.delete(`/dashboard/paywalls/${encodeURIComponent(id)}`);
|
|
166
|
+
}
|
|
167
|
+
async getPaywallStats() {
|
|
168
|
+
return this.get('/dashboard/paywalls/stats');
|
|
169
|
+
}
|
|
170
|
+
// ---- Promotions (V8 Phase B.2) ----
|
|
171
|
+
async listPromotions() {
|
|
172
|
+
const resp = await this.get('/dashboard/promotions');
|
|
173
|
+
return resp.promotions;
|
|
174
|
+
}
|
|
175
|
+
async createPromotion(data) {
|
|
176
|
+
return this.post('/dashboard/promotions', data);
|
|
177
|
+
}
|
|
178
|
+
async updatePromotion(id, data) {
|
|
179
|
+
return this.patch(`/dashboard/promotions/${encodeURIComponent(id)}`, data);
|
|
180
|
+
}
|
|
181
|
+
async deletePromotion(id) {
|
|
182
|
+
await this.delete(`/dashboard/promotions/${encodeURIComponent(id)}`);
|
|
183
|
+
}
|
|
184
|
+
// ---- Rescue Flows (V8 Phase B.3) ----
|
|
185
|
+
async listRescueFlows() {
|
|
186
|
+
const resp = await this.get('/dashboard/rescue-flows');
|
|
187
|
+
return resp.flows;
|
|
188
|
+
}
|
|
189
|
+
async createRescueFlow(data) {
|
|
190
|
+
return this.post('/dashboard/rescue-flows', data);
|
|
191
|
+
}
|
|
192
|
+
async updateRescueFlow(id, data) {
|
|
193
|
+
return this.patch(`/dashboard/rescue-flows/${encodeURIComponent(id)}`, data);
|
|
194
|
+
}
|
|
195
|
+
async deleteRescueFlow(id) {
|
|
196
|
+
await this.delete(`/dashboard/rescue-flows/${encodeURIComponent(id)}`);
|
|
197
|
+
}
|
|
198
|
+
async getRescueStats(days = 30) {
|
|
199
|
+
return this.get(`/dashboard/rescue-flows/stats?days=${days}`);
|
|
200
|
+
}
|
|
201
|
+
// ---- Pricing (V8 Phase B.4) ----
|
|
202
|
+
async listPricingStrategies() {
|
|
203
|
+
const resp = await this.get('/dashboard/pricing/strategies');
|
|
204
|
+
return resp.strategies;
|
|
205
|
+
}
|
|
206
|
+
async createPricingStrategy(data) {
|
|
207
|
+
const resp = await this.post('/dashboard/pricing/strategies', data);
|
|
208
|
+
return resp.strategy;
|
|
209
|
+
}
|
|
210
|
+
async previewPricing(productId, strategyId) {
|
|
211
|
+
return this.post('/dashboard/pricing/preview', {
|
|
212
|
+
product_id: productId,
|
|
213
|
+
strategy_id: strategyId,
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
async recomputePrices(data) {
|
|
217
|
+
return this.post('/dashboard/pricing/recompute', data);
|
|
218
|
+
}
|
|
219
|
+
async pushPricesToStores(productId) {
|
|
220
|
+
return this.post('/dashboard/pricing/push', { product_id: productId });
|
|
221
|
+
}
|
|
222
|
+
async listPricingChangeRequests(appId, status, productId) {
|
|
223
|
+
const params = new URLSearchParams({ app_id: appId });
|
|
224
|
+
if (status)
|
|
225
|
+
params.set('status', status);
|
|
226
|
+
if (productId)
|
|
227
|
+
params.set('product_id', productId);
|
|
228
|
+
const resp = await this.get(`/dashboard/pricing/change-requests?${params.toString()}`);
|
|
229
|
+
return resp.change_requests;
|
|
230
|
+
}
|
|
231
|
+
async approvePricingChangeRequest(id) {
|
|
232
|
+
await this.post(`/dashboard/pricing/change-requests/${encodeURIComponent(id)}/approve`);
|
|
233
|
+
}
|
|
234
|
+
async setCountryPriceOverride(data) {
|
|
235
|
+
const { product_id, country_code, ...body } = data;
|
|
236
|
+
return this.request('PUT', `/dashboard/products/${encodeURIComponent(product_id)}/prices/${encodeURIComponent(country_code)}`, body);
|
|
237
|
+
}
|
|
238
|
+
// ---- Experiment writes (V8 Phase B.5) ----
|
|
239
|
+
async createExperiment(data) {
|
|
240
|
+
return this.post('/dashboard/experiments', data);
|
|
241
|
+
}
|
|
242
|
+
async getExperiment(id) {
|
|
243
|
+
return this.get(`/dashboard/experiments/${encodeURIComponent(id)}`);
|
|
244
|
+
}
|
|
245
|
+
async updateExperiment(id, data) {
|
|
246
|
+
return this.patch(`/dashboard/experiments/${encodeURIComponent(id)}`, data);
|
|
247
|
+
}
|
|
248
|
+
async startExperiment(id) {
|
|
249
|
+
return this.post(`/dashboard/experiments/${encodeURIComponent(id)}/start`);
|
|
250
|
+
}
|
|
251
|
+
async stopExperiment(id) {
|
|
252
|
+
return this.post(`/dashboard/experiments/${encodeURIComponent(id)}/stop`);
|
|
253
|
+
}
|
|
254
|
+
// ---- Apps gap-fillers (V8 Phase B.6) ----
|
|
255
|
+
async getApp(id) {
|
|
256
|
+
return this.get(`/dashboard/apps/${encodeURIComponent(id)}`);
|
|
257
|
+
}
|
|
258
|
+
async updateApp(id, data) {
|
|
259
|
+
return this.patch(`/dashboard/apps/${encodeURIComponent(id)}`, data);
|
|
260
|
+
}
|
|
261
|
+
async deleteApp(id) {
|
|
262
|
+
await this.delete(`/dashboard/apps/${encodeURIComponent(id)}`);
|
|
263
|
+
}
|
|
264
|
+
async archiveApp(id) {
|
|
265
|
+
return this.post(`/dashboard/apps/${encodeURIComponent(id)}/archive`);
|
|
266
|
+
}
|
|
267
|
+
async restoreApp(id) {
|
|
268
|
+
return this.post(`/dashboard/apps/${encodeURIComponent(id)}/restore`);
|
|
269
|
+
}
|
|
270
|
+
async runAppAutopilot(id) {
|
|
271
|
+
return this.post(`/dashboard/apps/${encodeURIComponent(id)}/autopilot/run`);
|
|
272
|
+
}
|
|
273
|
+
async revertAppAutopilot(id) {
|
|
274
|
+
return this.post(`/dashboard/apps/${encodeURIComponent(id)}/autopilot/revert`);
|
|
275
|
+
}
|
|
276
|
+
// ---- Entitlements gap-fillers (V8 Phase B.7) ----
|
|
277
|
+
async getEntitlement(id) {
|
|
278
|
+
return this.get(`/dashboard/entitlements/${encodeURIComponent(id)}`);
|
|
279
|
+
}
|
|
280
|
+
async updateEntitlement(id, data) {
|
|
281
|
+
return this.patch(`/dashboard/entitlements/${encodeURIComponent(id)}`, data);
|
|
282
|
+
}
|
|
283
|
+
async deleteEntitlement(id) {
|
|
284
|
+
await this.delete(`/dashboard/entitlements/${encodeURIComponent(id)}`);
|
|
285
|
+
}
|
|
286
|
+
// ---- Products gap-filler (V8 Phase B.8) ----
|
|
287
|
+
async getProduct(id) {
|
|
288
|
+
return this.get(`/dashboard/products/${encodeURIComponent(id)}`);
|
|
289
|
+
}
|
|
290
|
+
// ---- Rules gap-fillers (V8 Phase B.9) ----
|
|
291
|
+
async getRuleById(id) {
|
|
292
|
+
return this.get(`/dashboard/rules/${encodeURIComponent(id)}`);
|
|
293
|
+
}
|
|
294
|
+
async listRuleVersions(id) {
|
|
295
|
+
return this.get(`/dashboard/rules/${encodeURIComponent(id)}/versions`);
|
|
296
|
+
}
|
|
297
|
+
async rollbackRule(id, version) {
|
|
298
|
+
return this.post(`/dashboard/rules/${encodeURIComponent(id)}/rollback`, { version });
|
|
299
|
+
}
|
|
300
|
+
// ---- Offerings gap-fillers (V8 Phase B.10) ----
|
|
301
|
+
async getOffering(id) {
|
|
302
|
+
return this.get(`/dashboard/offerings/${encodeURIComponent(id)}`);
|
|
303
|
+
}
|
|
304
|
+
async updateOffering(id, data) {
|
|
305
|
+
return this.patch(`/dashboard/offerings/${encodeURIComponent(id)}`, data);
|
|
306
|
+
}
|
|
307
|
+
// ---- Drift detection (V8 Phase C) ----
|
|
308
|
+
async listSyncSuggestions(appId, status) {
|
|
309
|
+
const params = new URLSearchParams();
|
|
310
|
+
if (appId)
|
|
311
|
+
params.set('app_id', appId);
|
|
312
|
+
if (status)
|
|
313
|
+
params.set('status', status);
|
|
314
|
+
const qs = params.toString();
|
|
315
|
+
return this.get(`/dashboard/sync/suggestions${qs ? `?${qs}` : ''}`);
|
|
316
|
+
}
|
|
317
|
+
async getSyncSuggestionsCount() {
|
|
318
|
+
return this.get('/dashboard/sync/suggestions/count');
|
|
319
|
+
}
|
|
320
|
+
async resolveSyncSuggestion(id, action) {
|
|
321
|
+
return this.post(`/dashboard/sync/suggestions/${encodeURIComponent(id)}/resolve`, {
|
|
322
|
+
action,
|
|
323
|
+
});
|
|
324
|
+
}
|
|
325
|
+
async triggerSync() {
|
|
326
|
+
return this.post('/dashboard/sync/trigger');
|
|
327
|
+
}
|
|
328
|
+
// ---- Integrations (V8.1) ----
|
|
329
|
+
async listIntegrations() {
|
|
330
|
+
const resp = await this.get('/dashboard/integrations');
|
|
331
|
+
return resp.integrations;
|
|
332
|
+
}
|
|
333
|
+
async connectAppleIntegration(data) {
|
|
334
|
+
return this.post('/dashboard/integrations/apple/connect', data);
|
|
335
|
+
}
|
|
336
|
+
async connectGoogleIntegration(data) {
|
|
337
|
+
return this.post('/dashboard/integrations/google/connect', data);
|
|
338
|
+
}
|
|
339
|
+
async disconnectIntegration(provider) {
|
|
340
|
+
await this.post(`/dashboard/integrations/${encodeURIComponent(provider)}/disconnect`);
|
|
341
|
+
}
|
|
153
342
|
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export function registerApproveChangeRequestTool(server, client) {
|
|
3
|
+
server.tool('capivv_approve_change_request', 'Approve a pending pricing change request. The new price is applied to Capivv immediately. Use capivv_push_prices_to_stores afterwards to propagate to App Store Connect / Google Play.', {
|
|
4
|
+
change_request_id: z.string().describe('Change request ID to approve'),
|
|
5
|
+
}, async ({ change_request_id }) => {
|
|
6
|
+
await client.approvePricingChangeRequest(change_request_id);
|
|
7
|
+
return {
|
|
8
|
+
content: [
|
|
9
|
+
{
|
|
10
|
+
type: 'text',
|
|
11
|
+
text: `Change request ${change_request_id} approved. The new price is now in Capivv. Call capivv_push_prices_to_stores to propagate to the stores.`,
|
|
12
|
+
},
|
|
13
|
+
],
|
|
14
|
+
};
|
|
15
|
+
});
|
|
16
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export function registerArchiveAppTool(server, client) {
|
|
3
|
+
server.tool('capivv_archive_app', 'Archive an app (soft delete). The app stops serving new traffic but its data is preserved. Use capivv_restore_app to bring it back. Prefer this over capivv_delete_app unless permanent removal is required.', {
|
|
4
|
+
app_id: z.string().describe('App ID to archive'),
|
|
5
|
+
}, async ({ app_id }) => {
|
|
6
|
+
const app = await client.archiveApp(app_id);
|
|
7
|
+
return { content: [{ type: 'text', text: JSON.stringify(app, null, 2) }] };
|
|
8
|
+
});
|
|
9
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export function registerCheckDriftTool(server, client) {
|
|
3
|
+
server.tool('capivv_check_drift', [
|
|
4
|
+
'List drift between Capivv and the connected store(s) — products that exist in the store but not in Capivv, prices that differ, metadata that changed, products deleted from the store.',
|
|
5
|
+
'Each entry has a `suggestion_type` (new_product | price_changed | metadata_changed | product_deleted) and a `diff_details` payload describing the mismatch.',
|
|
6
|
+
'Use capivv_resolve_drift to accept (apply the change) or dismiss (ignore) each one.',
|
|
7
|
+
'Drift is detected continuously by the background sync worker; call capivv_trigger_sync to force an immediate scan if you suspect the listing is stale.',
|
|
8
|
+
].join(' '), {
|
|
9
|
+
app_id: z
|
|
10
|
+
.string()
|
|
11
|
+
.optional()
|
|
12
|
+
.describe('Filter by app. When omitted, the API returns drift for the first app in the workspace.'),
|
|
13
|
+
status: z
|
|
14
|
+
.string()
|
|
15
|
+
.optional()
|
|
16
|
+
.describe('Filter by status: pending (default), accepted, dismissed, auto_resolved'),
|
|
17
|
+
}, async ({ app_id, status }) => {
|
|
18
|
+
const suggestions = await client.listSyncSuggestions(app_id, status);
|
|
19
|
+
return { content: [{ type: 'text', text: JSON.stringify(suggestions, null, 2) }] };
|
|
20
|
+
});
|
|
21
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export function registerConnectAppleIntegrationTool(server, client) {
|
|
3
|
+
server.tool('capivv_connect_apple_integration', [
|
|
4
|
+
'Connect an App Store Connect API key to the workspace. After this succeeds, capivv_create_product can write subscriptions / IAPs to App Store Connect on the customer\'s behalf.',
|
|
5
|
+
'',
|
|
6
|
+
'WARNING — the .p8 private key is sensitive. Make sure the key has at least App Manager role (Developer is not sufficient for write operations). The credentials are encrypted at rest.',
|
|
7
|
+
'',
|
|
8
|
+
'You can find issuer_id, key_id, and download the .p8 in App Store Connect → Users and Access → Integrations → App Store Connect API.',
|
|
9
|
+
].join(' '), {
|
|
10
|
+
issuer_id: z
|
|
11
|
+
.string()
|
|
12
|
+
.describe('Issuer ID (UUID) shown in App Store Connect → Integrations'),
|
|
13
|
+
key_id: z
|
|
14
|
+
.string()
|
|
15
|
+
.describe('Key ID (10-character string) shown next to the key in App Store Connect'),
|
|
16
|
+
private_key: z
|
|
17
|
+
.string()
|
|
18
|
+
.describe('Full PEM contents of the .p8 file: starts with "-----BEGIN PRIVATE KEY-----" and ends with "-----END PRIVATE KEY-----".'),
|
|
19
|
+
shared_secret: z
|
|
20
|
+
.string()
|
|
21
|
+
.optional()
|
|
22
|
+
.describe('Optional legacy shared secret for verifyReceipt fallback (rarely needed for new integrations).'),
|
|
23
|
+
}, async (args) => {
|
|
24
|
+
const result = await client.connectAppleIntegration(args);
|
|
25
|
+
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
|
|
26
|
+
});
|
|
27
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export function registerConnectGoogleIntegrationTool(server, client) {
|
|
3
|
+
server.tool('capivv_connect_google_integration', [
|
|
4
|
+
'Connect a Google Play service account key to the workspace. After this succeeds, capivv_create_product can write subscriptions / IAPs to Google Play on the customer\'s behalf.',
|
|
5
|
+
'',
|
|
6
|
+
'WARNING — service account JSON contains a private key and is sensitive. The service account needs the "Financial data" + "Manage orders and subscriptions" permissions in Google Play Console. The credentials are encrypted at rest.',
|
|
7
|
+
'',
|
|
8
|
+
'Each package_name is validated against the Play Developer API; invalid ones are returned in `errors` so the customer can fix them and retry.',
|
|
9
|
+
].join(' '), {
|
|
10
|
+
service_account_json: z
|
|
11
|
+
.string()
|
|
12
|
+
.describe('Raw JSON contents of the service account key file (the whole {...} blob).'),
|
|
13
|
+
package_names: z
|
|
14
|
+
.array(z.string())
|
|
15
|
+
.describe('Bundle IDs (Android package names) the service account should be able to manage, e.g. ["com.example.app"].'),
|
|
16
|
+
}, async (args) => {
|
|
17
|
+
const result = await client.connectGoogleIntegration(args);
|
|
18
|
+
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
|
|
19
|
+
});
|
|
20
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export function registerCreateExperimentTool(server, client) {
|
|
3
|
+
server.tool('capivv_create_experiment', [
|
|
4
|
+
'Create an A/B experiment with variants. Variants split traffic by `traffic_percent` (must sum to 100). Exactly one variant should have `is_control: true`.',
|
|
5
|
+
'Common metrics: "paywall_conversion", "trial_to_paid", "arpu". `entity_type` + `entity_id` scope the experiment to a specific paywall, product, or pricing strategy.',
|
|
6
|
+
'New experiments start in `draft` status — call capivv_start_experiment to enroll users.',
|
|
7
|
+
].join(' '), {
|
|
8
|
+
name: z.string().describe('Display name'),
|
|
9
|
+
description: z.string().optional().describe('Optional description'),
|
|
10
|
+
target_metric: z
|
|
11
|
+
.string()
|
|
12
|
+
.describe('Metric to optimize (e.g. "paywall_conversion", "trial_to_paid", "arpu")'),
|
|
13
|
+
entity_type: z
|
|
14
|
+
.string()
|
|
15
|
+
.optional()
|
|
16
|
+
.describe('Scope: "paywall", "product", "pricing_strategy", etc.'),
|
|
17
|
+
entity_id: z.string().optional().describe('ID of the scoped entity'),
|
|
18
|
+
start_date: z.string().optional().describe('ISO 8601 start timestamp'),
|
|
19
|
+
end_date: z.string().optional().describe('ISO 8601 end timestamp'),
|
|
20
|
+
sample_size_target: z
|
|
21
|
+
.number()
|
|
22
|
+
.optional()
|
|
23
|
+
.describe('Target sample size before considering the experiment conclusive'),
|
|
24
|
+
confidence_level: z.number().optional().describe('Confidence level (e.g. 95). Defaults to 95.'),
|
|
25
|
+
metadata: z.record(z.string(), z.unknown()).optional().describe('Free-form metadata'),
|
|
26
|
+
variants: z
|
|
27
|
+
.array(z.object({
|
|
28
|
+
name: z.string().describe('Variant name (e.g. "Control", "Variant A")'),
|
|
29
|
+
is_control: z.boolean().describe('Exactly one variant should be the control.'),
|
|
30
|
+
traffic_percent: z
|
|
31
|
+
.number()
|
|
32
|
+
.describe('Traffic allocation percentage (0-100). Sum across variants must be 100.'),
|
|
33
|
+
config: z
|
|
34
|
+
.record(z.string(), z.unknown())
|
|
35
|
+
.optional()
|
|
36
|
+
.describe('Variant-specific overrides (paywall config, price, etc.)'),
|
|
37
|
+
}))
|
|
38
|
+
.describe('Variants to create with the experiment'),
|
|
39
|
+
}, async (args) => {
|
|
40
|
+
const exp = await client.createExperiment(args);
|
|
41
|
+
return { content: [{ type: 'text', text: JSON.stringify(exp, null, 2) }] };
|
|
42
|
+
});
|
|
43
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export function registerCreatePaywallTool(server, client) {
|
|
3
|
+
server.tool('capivv_create_paywall', [
|
|
4
|
+
'Create a new paywall on a Capivv app.',
|
|
5
|
+
'paywall_type controls behavior: "hard" (block until purchase), "soft" (skippable), "upsell" (offer to existing users), or "promo" (limited-time offer).',
|
|
6
|
+
'Use capivv_update_paywall after creation to attach a template, configure the layout, or schedule A/B variants — those are not part of the create call.',
|
|
7
|
+
].join(' '), {
|
|
8
|
+
app_id: z.string().describe('App ID this paywall belongs to'),
|
|
9
|
+
name: z.string().describe('Display name shown in the dashboard (e.g. "Onboarding paywall")'),
|
|
10
|
+
identifier: z
|
|
11
|
+
.string()
|
|
12
|
+
.describe('Stable identifier the SDK uses to fetch this paywall (e.g. "onboarding_v2")'),
|
|
13
|
+
paywall_type: z.string().describe('One of: hard, soft, upsell, promo'),
|
|
14
|
+
}, async (args) => {
|
|
15
|
+
const paywall = await client.createPaywall(args);
|
|
16
|
+
return { content: [{ type: 'text', text: JSON.stringify(paywall, null, 2) }] };
|
|
17
|
+
});
|
|
18
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export function registerCreatePricingStrategyTool(server, client) {
|
|
3
|
+
server.tool('capivv_create_pricing_strategy', [
|
|
4
|
+
'Create a localized pricing strategy for an app.',
|
|
5
|
+
'Combines three signals — Purchasing Power Parity (PPP), Big Mac index, and FX-neutral conversion — using configurable weights to derive a country price.',
|
|
6
|
+
'Affordability is then clamped per income tier (1–4) so emerging markets don\'t collapse to pennies and rich markets don\'t inflate above the base price.',
|
|
7
|
+
'Guardrails (`max_auto_change_pct`, `max_auto_decrease_pct`) block changes that exceed the threshold; those go to a change-request queue instead of auto-applying.',
|
|
8
|
+
'Defaults work fine for most cases — start with just `app_id` and `name`.',
|
|
9
|
+
].join(' '), {
|
|
10
|
+
app_id: z.string().describe('App ID this strategy applies to'),
|
|
11
|
+
name: z.string().describe('Display name (e.g. "Worldwide PPP-blended pricing")'),
|
|
12
|
+
w_ppp: z.number().optional().describe('PPP weight (0-1). Default 0.6.'),
|
|
13
|
+
w_bigmac: z.number().optional().describe('Big Mac index weight (0-1). Default 0.2.'),
|
|
14
|
+
w_fx_neutral: z
|
|
15
|
+
.number()
|
|
16
|
+
.optional()
|
|
17
|
+
.describe('FX-neutral weight (0-1). Default 0.2. The three weights should sum to ~1.0.'),
|
|
18
|
+
tier1_min_aff: z
|
|
19
|
+
.number()
|
|
20
|
+
.optional()
|
|
21
|
+
.describe('Minimum affordability for tier 1 (lowest income). Default 0.25.'),
|
|
22
|
+
tier1_max_aff: z.number().optional().describe('Maximum affordability for tier 1.'),
|
|
23
|
+
tier2_min_aff: z.number().optional().describe('Minimum affordability for tier 2.'),
|
|
24
|
+
tier2_max_aff: z.number().optional().describe('Maximum affordability for tier 2.'),
|
|
25
|
+
tier3_min_aff: z.number().optional().describe('Minimum affordability for tier 3.'),
|
|
26
|
+
tier3_max_aff: z.number().optional().describe('Maximum affordability for tier 3.'),
|
|
27
|
+
tier4_min_aff: z.number().optional().describe('Minimum affordability for tier 4.'),
|
|
28
|
+
tier4_max_aff: z.number().optional().describe('Maximum affordability for tier 4.'),
|
|
29
|
+
anti_arbitrage_floor_factor: z
|
|
30
|
+
.number()
|
|
31
|
+
.optional()
|
|
32
|
+
.describe('Floor multiplier (e.g. 0.5 means prices can\'t go below 50% of base).'),
|
|
33
|
+
max_auto_change_pct: z
|
|
34
|
+
.number()
|
|
35
|
+
.optional()
|
|
36
|
+
.describe('Max % change auto-applied without approval. Larger changes go to change requests.'),
|
|
37
|
+
max_auto_decrease_pct: z
|
|
38
|
+
.number()
|
|
39
|
+
.optional()
|
|
40
|
+
.describe('Max % decrease auto-applied (prevents accidental fire-sale pricing).'),
|
|
41
|
+
excluded_countries: z
|
|
42
|
+
.array(z.string())
|
|
43
|
+
.optional()
|
|
44
|
+
.describe('ISO country codes to skip (manual pricing only).'),
|
|
45
|
+
}, async (args) => {
|
|
46
|
+
const strategy = await client.createPricingStrategy(args);
|
|
47
|
+
return { content: [{ type: 'text', text: JSON.stringify(strategy, null, 2) }] };
|
|
48
|
+
});
|
|
49
|
+
}
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
export function registerCreateProductTool(server, client) {
|
|
3
3
|
server.tool('capivv_create_product', [
|
|
4
|
-
'Create a
|
|
5
|
-
'
|
|
4
|
+
'Create a subscription, consumable, or non-consumable product end-to-end.',
|
|
5
|
+
'By default this creates the Capivv-side product record AND the matching subscription / IAP in App Store Connect or Google Play (whichever store is connected for the app).',
|
|
6
|
+
'If the requested price does not match a store tier exactly, Capivv snaps to the nearest valid tier and returns both the requested and the actual price so you can show the customer the delta.',
|
|
7
|
+
'Pass `skip_store_write: true` to opt out of the store-side write — only useful when migrating an existing store-side product into Capivv (rare).',
|
|
6
8
|
'',
|
|
7
|
-
'
|
|
8
|
-
'For purchases to validate, a product with the SAME `external_id` must also exist in App Store Connect (and/or Google Play) at the same price you set here.',
|
|
9
|
-
'Typical flow: create or confirm the product in App Store Connect at $X.XX, then call this tool with `external_id` matching the App Store Connect product ID.',
|
|
10
|
-
'Skip-to-import path: if products already exist in App Store Connect and your tenant has store credentials connected, use capivv_import_products instead — it pulls them in automatically.',
|
|
9
|
+
'On success the response includes a `store_create` block with the store-side product ID and snapped prices. On store failure the Capivv-side record is rolled back and the verbatim store error is returned.',
|
|
11
10
|
].join(' '), {
|
|
12
11
|
app_id: z.string().describe('App ID this product belongs to'),
|
|
13
12
|
external_id: z.string().describe('Store product ID (e.g., "com.example.pro_monthly")'),
|
|
@@ -35,8 +34,44 @@ export function registerCreateProductTool(server, client) {
|
|
|
35
34
|
}))
|
|
36
35
|
.optional()
|
|
37
36
|
.describe('Product prices'),
|
|
37
|
+
skip_store_write: z
|
|
38
|
+
.boolean()
|
|
39
|
+
.optional()
|
|
40
|
+
.describe('When true, only creates the Capivv-side record and skips writing to App Store Connect / Google Play. Use only when migrating an existing store-side product.'),
|
|
41
|
+
default_locale: z
|
|
42
|
+
.string()
|
|
43
|
+
.optional()
|
|
44
|
+
.describe('Locale used for store-side product localization. Defaults to "en-US".'),
|
|
38
45
|
}, async (args) => {
|
|
39
|
-
const
|
|
40
|
-
|
|
46
|
+
const { skip_store_write, ...rest } = args;
|
|
47
|
+
const product = await client.createProduct({
|
|
48
|
+
...rest,
|
|
49
|
+
also_create_in_store: skip_store_write !== true,
|
|
50
|
+
});
|
|
51
|
+
const summary = formatStoreCreateSummary(product);
|
|
52
|
+
const text = summary
|
|
53
|
+
? `${summary}\n\n${JSON.stringify(product, null, 2)}`
|
|
54
|
+
: JSON.stringify(product, null, 2);
|
|
55
|
+
return { content: [{ type: 'text', text }] };
|
|
41
56
|
});
|
|
42
57
|
}
|
|
58
|
+
function formatStoreCreateSummary(product) {
|
|
59
|
+
const sc = product.store_create;
|
|
60
|
+
if (!sc)
|
|
61
|
+
return null;
|
|
62
|
+
const lines = [];
|
|
63
|
+
lines.push(`Created ${product.display_name} on ${sc.store === 'apple' ? 'App Store Connect' : 'Google Play'} (id: ${sc.store_product_id}).`);
|
|
64
|
+
for (const sp of sc.snapped_prices) {
|
|
65
|
+
if (sp.requested_cents === sp.actual_cents) {
|
|
66
|
+
lines.push(` ${sp.currency}: ${formatCents(sp.actual_cents, sp.currency)} (matches your request exactly).`);
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
lines.push(` ${sp.currency}: used ${formatCents(sp.actual_cents, sp.currency)} — closest store tier to your ${formatCents(sp.requested_cents, sp.currency)} request.`);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return lines.join('\n');
|
|
73
|
+
}
|
|
74
|
+
function formatCents(cents, currency) {
|
|
75
|
+
const major = (cents / 100).toFixed(2);
|
|
76
|
+
return `${major} ${currency}`;
|
|
77
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export function registerCreatePromotionTool(server, client) {
|
|
3
|
+
server.tool('capivv_create_promotion', [
|
|
4
|
+
'Create a promotion (flash sale, bundle, segmented offer, or referral campaign).',
|
|
5
|
+
'campaign_type controls behavior: "flash_sale" (time-bound discount), "bundle" (multi-product offer), "segment" (target a user segment), "referral" (reward referrers).',
|
|
6
|
+
'When starts_at / ends_at are omitted, the promotion runs for 30 days starting now.',
|
|
7
|
+
].join(' '), {
|
|
8
|
+
name: z.string().describe('Display name (e.g. "Summer 20% off")'),
|
|
9
|
+
identifier: z
|
|
10
|
+
.string()
|
|
11
|
+
.optional()
|
|
12
|
+
.describe('Stable identifier the SDK can target (e.g. "summer_2026")'),
|
|
13
|
+
description: z.string().optional().describe('Free-form description'),
|
|
14
|
+
campaign_type: z.string().describe('One of: flash_sale, bundle, segment, referral'),
|
|
15
|
+
discount_percent: z
|
|
16
|
+
.number()
|
|
17
|
+
.optional()
|
|
18
|
+
.describe('Percentage discount (0-100). Omit for non-discount campaigns.'),
|
|
19
|
+
starts_at: z
|
|
20
|
+
.string()
|
|
21
|
+
.optional()
|
|
22
|
+
.describe('ISO 8601 start timestamp. Defaults to now.'),
|
|
23
|
+
ends_at: z
|
|
24
|
+
.string()
|
|
25
|
+
.optional()
|
|
26
|
+
.describe('ISO 8601 end timestamp. Defaults to now + 30 days.'),
|
|
27
|
+
max_redemptions: z
|
|
28
|
+
.number()
|
|
29
|
+
.optional()
|
|
30
|
+
.describe('Redemption cap across the workspace. Omit for unlimited.'),
|
|
31
|
+
}, async (args) => {
|
|
32
|
+
const promotion = await client.createPromotion(args);
|
|
33
|
+
return { content: [{ type: 'text', text: JSON.stringify(promotion, null, 2) }] };
|
|
34
|
+
});
|
|
35
|
+
}
|