@capivv/mcp-server 0.5.8 → 0.5.10
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 +4 -1
- package/dist/client.js +12 -0
- package/dist/tools/index.js +13 -0
- package/dist/tools/probe-submission.d.ts +3 -0
- package/dist/tools/probe-submission.js +32 -0
- package/dist/tools/set-app-privacy-url.d.ts +3 -0
- package/dist/tools/set-app-privacy-url.js +25 -0
- package/dist/tools/set-iap-review-screenshot.d.ts +3 -0
- package/dist/tools/set-iap-review-screenshot.js +47 -0
- package/dist/tools/touch-subscription.js +3 -3
- package/dist/types.d.ts +52 -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, 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, SetSubscriptionReviewScreenshotRequest, SetSubscriptionReviewScreenshotResult, SubscriptionStateInfo, TouchSubscriptionResult } 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, SetSubscriptionReviewScreenshotRequest, SetSubscriptionReviewScreenshotResult, SubscriptionStateInfo, TouchSubscriptionResult, ProbeSubmissionRequest, ProbeSubmissionResult, SetAppPrivacyUrlRequest, SetAppPrivacyUrlResult, SetIapReviewScreenshotRequest, SetIapReviewScreenshotResult } from './types.js';
|
|
3
3
|
export declare class ApiError extends Error {
|
|
4
4
|
status: number;
|
|
5
5
|
code: string;
|
|
@@ -94,4 +94,7 @@ export declare class CapivvClient {
|
|
|
94
94
|
setSubscriptionReviewScreenshot(data: SetSubscriptionReviewScreenshotRequest): Promise<SetSubscriptionReviewScreenshotResult>;
|
|
95
95
|
getSubscriptionState(appleSubscriptionId: string): Promise<SubscriptionStateInfo>;
|
|
96
96
|
touchSubscription(appleSubscriptionId: string): Promise<TouchSubscriptionResult>;
|
|
97
|
+
probeAppleSubmission(req: ProbeSubmissionRequest): Promise<ProbeSubmissionResult>;
|
|
98
|
+
setAppPrivacyUrl(req: SetAppPrivacyUrlRequest): Promise<SetAppPrivacyUrlResult>;
|
|
99
|
+
setIapReviewScreenshot(req: SetIapReviewScreenshotRequest): Promise<SetIapReviewScreenshotResult>;
|
|
97
100
|
}
|
package/dist/client.js
CHANGED
|
@@ -350,4 +350,16 @@ export class CapivvClient {
|
|
|
350
350
|
async touchSubscription(appleSubscriptionId) {
|
|
351
351
|
return this.post(`/dashboard/subscriptions/${encodeURIComponent(appleSubscriptionId)}/touch`);
|
|
352
352
|
}
|
|
353
|
+
// ---- V0.5.10 — Submission probe / privacy URL / IAP screenshot ----
|
|
354
|
+
async probeAppleSubmission(req) {
|
|
355
|
+
return this.post(`/dashboard/store/apple/${encodeURIComponent(req.product_type)}/${encodeURIComponent(req.apple_product_id)}/probe-submission`);
|
|
356
|
+
}
|
|
357
|
+
async setAppPrivacyUrl(req) {
|
|
358
|
+
const { app_id, ...body } = req;
|
|
359
|
+
return this.post(`/dashboard/apps/${encodeURIComponent(app_id)}/privacy-policy-url`, body);
|
|
360
|
+
}
|
|
361
|
+
async setIapReviewScreenshot(req) {
|
|
362
|
+
const { apple_iap_id, ...body } = req;
|
|
363
|
+
return this.post(`/dashboard/iap/${encodeURIComponent(apple_iap_id)}/review-screenshot`, body);
|
|
364
|
+
}
|
|
353
365
|
}
|
package/dist/tools/index.js
CHANGED
|
@@ -75,6 +75,9 @@ import { registerDisconnectIntegrationTool } from './disconnect-integration.js';
|
|
|
75
75
|
import { registerSetSubscriptionReviewScreenshotTool } from './set-subscription-review-screenshot.js';
|
|
76
76
|
import { registerGetSubscriptionStateTool } from './get-subscription-state.js';
|
|
77
77
|
import { registerTouchSubscriptionTool } from './touch-subscription.js';
|
|
78
|
+
import { registerProbeSubmissionTool } from './probe-submission.js';
|
|
79
|
+
import { registerSetAppPrivacyUrlTool } from './set-app-privacy-url.js';
|
|
80
|
+
import { registerSetIapReviewScreenshotTool } from './set-iap-review-screenshot.js';
|
|
78
81
|
export function registerAllTools(server, client) {
|
|
79
82
|
// Identity — call this first to verify which workspace you're connected to
|
|
80
83
|
registerWhoamiTool(server, client);
|
|
@@ -185,4 +188,14 @@ export function registerAllTools(server, client) {
|
|
|
185
188
|
// MISSING_METADATA after a successful create.)
|
|
186
189
|
registerGetSubscriptionStateTool(server, client);
|
|
187
190
|
registerTouchSubscriptionTool(server, client);
|
|
191
|
+
// V0.5.10 — diagnostic + app-info + IAP screenshot tools.
|
|
192
|
+
// - Submission probe surfaces Apple's exact "what's still missing"
|
|
193
|
+
// diagnostics so the agent stops surfacing misleading "Permission
|
|
194
|
+
// denied" errors.
|
|
195
|
+
// - App privacy URL fixes ENTITY_ERROR.APP_MISSING_PRIVACY_POLICY_URL
|
|
196
|
+
// without sending the user to ASC.
|
|
197
|
+
// - IAP review screenshot mirrors the subscription helper for IAPs.
|
|
198
|
+
registerProbeSubmissionTool(server, client);
|
|
199
|
+
registerSetAppPrivacyUrlTool(server, client);
|
|
200
|
+
registerSetIapReviewScreenshotTool(server, client);
|
|
188
201
|
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export function registerProbeSubmissionTool(server, client) {
|
|
3
|
+
server.tool('capivv_probe_submission', [
|
|
4
|
+
'Probe an Apple subscription or in-app purchase for what is still gating App Store submission.',
|
|
5
|
+
'',
|
|
6
|
+
"Apple's `*Submissions` endpoint reliably returns 409 on a brand-new product with an `errors` body that says exactly what's missing. This tool POSTs to `/v1/subscriptionSubmissions` (or `/v1/inAppPurchaseSubmissions`) and returns a structured result:",
|
|
7
|
+
'- `ready`: submission accepted (rare on first probe; means metadata is complete).',
|
|
8
|
+
'- `missing_pricing_data` with a `territories` list: re-run pricing for those territories.',
|
|
9
|
+
'- `missing_privacy_policy_url`: call `capivv_set_app_privacy_url` to fix.',
|
|
10
|
+
'- `awaiting_first_app_version`: Apple policy — first sub/IAP on a new app must ship with the first version. Not an error from your side.',
|
|
11
|
+
'- `other` with `code` + `detail`: surface verbatim to the customer.',
|
|
12
|
+
'',
|
|
13
|
+
'Get `apple_product_id` from the `store_create.store_product_id` field of capivv_create_product, or from App Store Connect.',
|
|
14
|
+
].join(' '), {
|
|
15
|
+
apple_product_id: z
|
|
16
|
+
.string()
|
|
17
|
+
.describe('Apple product ID (e.g. "6764778053") — NOT the Capivv product UUID.'),
|
|
18
|
+
product_type: z
|
|
19
|
+
.enum(['subscription', 'iap'])
|
|
20
|
+
.describe('"subscription" for auto-renewing subscriptions; "iap" for consumables and non-consumables.'),
|
|
21
|
+
}, async (args) => {
|
|
22
|
+
const result = await client.probeAppleSubmission(args);
|
|
23
|
+
return {
|
|
24
|
+
content: [
|
|
25
|
+
{
|
|
26
|
+
type: 'text',
|
|
27
|
+
text: JSON.stringify(result, null, 2),
|
|
28
|
+
},
|
|
29
|
+
],
|
|
30
|
+
};
|
|
31
|
+
});
|
|
32
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export function registerSetAppPrivacyUrlTool(server, client) {
|
|
3
|
+
server.tool('capivv_set_app_privacy_url', [
|
|
4
|
+
"Set the App Store Connect app's privacy policy URL on its in-progress en-US localization.",
|
|
5
|
+
'',
|
|
6
|
+
'Call this when `capivv_probe_submission` returns `missing_privacy_policy_url`. The backend resolves the app via Capivv `app_id` → bundle id → ASC app, then PATCHes `appInfoLocalizations.privacyPolicyUrl` on the editable appInfo (states: PREPARE_FOR_SUBMISSION, REJECTED, METADATA_REJECTED, DEVELOPER_REJECTED).',
|
|
7
|
+
'',
|
|
8
|
+
'URL must be HTTPS.',
|
|
9
|
+
].join(' '), {
|
|
10
|
+
app_id: z.string().describe('Capivv app UUID.'),
|
|
11
|
+
privacy_policy_url: z
|
|
12
|
+
.string()
|
|
13
|
+
.describe('HTTPS URL pointing at the privacy policy.'),
|
|
14
|
+
}, async (args) => {
|
|
15
|
+
const result = await client.setAppPrivacyUrl(args);
|
|
16
|
+
return {
|
|
17
|
+
content: [
|
|
18
|
+
{
|
|
19
|
+
type: 'text',
|
|
20
|
+
text: JSON.stringify(result, null, 2),
|
|
21
|
+
},
|
|
22
|
+
],
|
|
23
|
+
};
|
|
24
|
+
});
|
|
25
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export function registerSetIapReviewScreenshotTool(server, client) {
|
|
3
|
+
server.tool('capivv_set_iap_review_screenshot', [
|
|
4
|
+
'Upload the App Store review screenshot for an in-app purchase (consumable or non-consumable). Mirrors capivv_set_subscription_review_screenshot but uses the IAP endpoint.',
|
|
5
|
+
'',
|
|
6
|
+
'Apple expects 640x920 (or larger) PNG / JPEG. Provide either `image_url` (Capivv backend fetches it via HTTPS) or `image_base64` (raw bytes inline). The backend handles the 3-step Apple flow: reserve → PUT bytes to S3 → PATCH uploaded=true with MD5.',
|
|
7
|
+
'',
|
|
8
|
+
'Get `apple_iap_id` from the `store_create.store_product_id` field of capivv_create_product (when the product type is consumable or non_consumable), or from App Store Connect.',
|
|
9
|
+
].join(' '), {
|
|
10
|
+
apple_iap_id: z
|
|
11
|
+
.string()
|
|
12
|
+
.describe('Apple in-app purchase ID (e.g. "6765812345") — NOT the Capivv product UUID.'),
|
|
13
|
+
image_url: z
|
|
14
|
+
.string()
|
|
15
|
+
.optional()
|
|
16
|
+
.describe('Public HTTPS URL of the screenshot. Mutually exclusive with image_base64.'),
|
|
17
|
+
image_base64: z
|
|
18
|
+
.string()
|
|
19
|
+
.optional()
|
|
20
|
+
.describe('Base64-encoded raw image bytes. Use for non-HTTPS sources. Mutually exclusive with image_url.'),
|
|
21
|
+
file_name: z
|
|
22
|
+
.string()
|
|
23
|
+
.optional()
|
|
24
|
+
.describe('Filename Apple stores on the screenshot resource. Defaults to "screenshot.png".'),
|
|
25
|
+
}, async (args) => {
|
|
26
|
+
if (!args.image_url && !args.image_base64) {
|
|
27
|
+
return {
|
|
28
|
+
isError: true,
|
|
29
|
+
content: [
|
|
30
|
+
{
|
|
31
|
+
type: 'text',
|
|
32
|
+
text: 'Provide either image_url (HTTPS) or image_base64 (raw bytes).',
|
|
33
|
+
},
|
|
34
|
+
],
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
const result = await client.setIapReviewScreenshot(args);
|
|
38
|
+
return {
|
|
39
|
+
content: [
|
|
40
|
+
{
|
|
41
|
+
type: 'text',
|
|
42
|
+
text: JSON.stringify(result, null, 2),
|
|
43
|
+
},
|
|
44
|
+
],
|
|
45
|
+
};
|
|
46
|
+
});
|
|
47
|
+
}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
export function registerTouchSubscriptionTool(server, client) {
|
|
3
3
|
server.tool('capivv_touch_subscription', [
|
|
4
|
-
'
|
|
4
|
+
'Nudge Apple to recompute the subscription\'s state after the screenshot has uploaded.',
|
|
5
5
|
'',
|
|
6
|
-
'After capivv_create_product creates the subscription via Apple\'s /v1/subscriptions endpoint, a legacy /v1/inAppPurchases mirror is also created with its own state machine. The legacy record can stay at WAITING_FOR_SCREENSHOT (which keeps the modern view at MISSING_METADATA)
|
|
6
|
+
'After capivv_create_product creates the subscription via Apple\'s /v1/subscriptions endpoint, a legacy /v1/inAppPurchases mirror is also created with its own state machine. The legacy record can stay at WAITING_FOR_SCREENSHOT (which keeps the modern view at MISSING_METADATA) until something writes to the modern resource. This tool does a no-op PATCH on the subscription (re-set name to its current value), which mirrors clicking "Save" in App Store Connect\'s web UI and reliably triggers the recompute.',
|
|
7
7
|
'',
|
|
8
|
-
'
|
|
8
|
+
'Call capivv_get_subscription_state 30-60 seconds afterwards to confirm the state has progressed.',
|
|
9
9
|
].join(' '), {
|
|
10
10
|
apple_subscription_id: z
|
|
11
11
|
.string()
|
package/dist/types.d.ts
CHANGED
|
@@ -600,3 +600,55 @@ export interface TouchSubscriptionResult {
|
|
|
600
600
|
touched: boolean;
|
|
601
601
|
next_action: string;
|
|
602
602
|
}
|
|
603
|
+
/**
|
|
604
|
+
* Result of POSTing a `*Submissions` record to App Store Connect. Apple
|
|
605
|
+
* reliably 409s on a brand-new product with an `errors` array describing
|
|
606
|
+
* exactly what's still missing — so we map known codes to actionable
|
|
607
|
+
* variants. The backend returns this discriminated union as JSON.
|
|
608
|
+
*/
|
|
609
|
+
export type SubmissionProbeResult = {
|
|
610
|
+
status: 'ready';
|
|
611
|
+
} | {
|
|
612
|
+
status: 'missing_pricing_data';
|
|
613
|
+
territories: string[];
|
|
614
|
+
} | {
|
|
615
|
+
status: 'missing_privacy_policy_url';
|
|
616
|
+
} | {
|
|
617
|
+
status: 'awaiting_first_app_version';
|
|
618
|
+
} | {
|
|
619
|
+
status: 'other';
|
|
620
|
+
code: string;
|
|
621
|
+
detail: string;
|
|
622
|
+
};
|
|
623
|
+
export interface ProbeSubmissionRequest {
|
|
624
|
+
apple_product_id: string;
|
|
625
|
+
/** "subscription" or "iap". */
|
|
626
|
+
product_type: 'subscription' | 'iap';
|
|
627
|
+
}
|
|
628
|
+
export interface ProbeSubmissionResult {
|
|
629
|
+
apple_product_id: string;
|
|
630
|
+
product_type: string;
|
|
631
|
+
submission_status: SubmissionProbeResult;
|
|
632
|
+
}
|
|
633
|
+
export interface SetAppPrivacyUrlRequest {
|
|
634
|
+
app_id: string;
|
|
635
|
+
privacy_policy_url: string;
|
|
636
|
+
}
|
|
637
|
+
export interface SetAppPrivacyUrlResult {
|
|
638
|
+
app_id: string;
|
|
639
|
+
bundle_id: string;
|
|
640
|
+
privacy_policy_url: string;
|
|
641
|
+
localization_id: string;
|
|
642
|
+
app_store_state: string;
|
|
643
|
+
}
|
|
644
|
+
export interface SetIapReviewScreenshotRequest {
|
|
645
|
+
apple_iap_id: string;
|
|
646
|
+
image_url?: string;
|
|
647
|
+
image_base64?: string;
|
|
648
|
+
file_name?: string;
|
|
649
|
+
}
|
|
650
|
+
export interface SetIapReviewScreenshotResult {
|
|
651
|
+
apple_iap_id: string;
|
|
652
|
+
screenshot_id: string;
|
|
653
|
+
bytes_uploaded: number;
|
|
654
|
+
}
|