@capivv/mcp-server 0.1.3 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +73 -2
- package/dist/client.d.ts +62 -3
- package/dist/client.js +220 -5
- package/dist/config.js +1 -1
- package/dist/http.d.ts +12 -0
- package/dist/http.js +102 -0
- package/dist/resources/guides.d.ts +2 -0
- package/dist/resources/guides.js +81 -0
- package/dist/resources/index.js +4 -0
- package/dist/resources/quickstart.d.ts +2 -0
- package/dist/resources/quickstart.js +173 -0
- package/dist/resources/rules.js +8 -2
- package/dist/tools/activate-rule.d.ts +3 -0
- package/dist/tools/activate-rule.js +9 -0
- package/dist/tools/api-key-usage.d.ts +3 -0
- package/dist/tools/api-key-usage.js +70 -0
- package/dist/tools/apply-rule.js +54 -13
- 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/autopilot-status.d.ts +3 -0
- package/dist/tools/autopilot-status.js +117 -0
- package/dist/tools/check-drift.d.ts +3 -0
- package/dist/tools/check-drift.js +21 -0
- package/dist/tools/create-app.d.ts +3 -0
- package/dist/tools/create-app.js +13 -0
- package/dist/tools/create-entitlement.d.ts +3 -0
- package/dist/tools/create-entitlement.js +11 -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.d.ts +3 -0
- package/dist/tools/create-product.js +77 -0
- 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-product.d.ts +3 -0
- package/dist/tools/delete-product.js +9 -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/delete-rule.d.ts +3 -0
- package/dist/tools/delete-rule.js +9 -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/import-products.js +7 -5
- package/dist/tools/index.js +143 -1
- package/dist/tools/list-change-requests.d.ts +3 -0
- package/dist/tools/list-change-requests.js +14 -0
- package/dist/tools/list-entitlements.d.ts +3 -0
- package/dist/tools/list-entitlements.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/list-rules.js +4 -2
- package/dist/tools/next-step.d.ts +3 -0
- package/dist/tools/next-step.js +123 -0
- 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.d.ts +3 -0
- package/dist/tools/setup-wizard.js +259 -0
- package/dist/tools/start-experiment.d.ts +3 -0
- package/dist/tools/start-experiment.js +9 -0
- package/dist/tools/status.js +25 -1
- 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-product.d.ts +3 -0
- package/dist/tools/update-product.js +16 -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/tools/verify-setup.d.ts +3 -0
- package/dist/tools/verify-setup.js +200 -0
- package/dist/tools/whoami.d.ts +3 -0
- package/dist/tools/whoami.js +31 -0
- package/dist/types.d.ts +417 -79
- package/dist/types.js +0 -2
- package/mcp.json +89 -0
- package/package.json +8 -2
package/README.md
CHANGED
|
@@ -20,7 +20,7 @@ The server requires an API key from your Capivv dashboard.
|
|
|
20
20
|
| Environment Variable | Required | Description |
|
|
21
21
|
|---------------------|----------|-------------|
|
|
22
22
|
| `CAPIVV_API_KEY` | Yes | API key from Settings > Developer > API Keys |
|
|
23
|
-
| `CAPIVV_API_URL` | No | API base URL (default: `https://
|
|
23
|
+
| `CAPIVV_API_URL` | No | API base URL (default: `https://app.capivv.com`) |
|
|
24
24
|
| `CAPIVV_ORG_ID` | No | Organization ID for multi-org accounts |
|
|
25
25
|
|
|
26
26
|
## Setup
|
|
@@ -85,25 +85,96 @@ The server uses stdio transport. Start it with:
|
|
|
85
85
|
CAPIVV_API_KEY=your-api-key npx @capivv/mcp-server
|
|
86
86
|
```
|
|
87
87
|
|
|
88
|
+
## Getting Started
|
|
89
|
+
|
|
90
|
+
After installing, ask your AI assistant:
|
|
91
|
+
|
|
92
|
+
> "Set up Capivv for my iOS app com.mycompany.myapp with a monthly ($7.99) and annual ($49.99) subscription"
|
|
93
|
+
|
|
94
|
+
The assistant will use `capivv_setup_wizard` to create everything in one shot. Or go step-by-step:
|
|
95
|
+
|
|
96
|
+
1. **`capivv_next_step`** — tells you exactly what to do next based on your current setup
|
|
97
|
+
2. **`capivv_setup_wizard`** — creates app + entitlement + products + offering in one call
|
|
98
|
+
3. **`capivv_verify_setup`** — checks everything is configured correctly
|
|
99
|
+
|
|
100
|
+
Read the `capivv://docs/quickstart` resource for a full walkthrough.
|
|
101
|
+
|
|
88
102
|
## Available Tools
|
|
89
103
|
|
|
104
|
+
### Identity
|
|
105
|
+
|
|
106
|
+
| Tool | Description |
|
|
107
|
+
|------|-------------|
|
|
108
|
+
| `capivv_whoami` | Show which workspace (org) and apps your API key reaches. Call this first if anything looks wrong |
|
|
109
|
+
|
|
110
|
+
### Onboarding & Guidance
|
|
111
|
+
|
|
112
|
+
| Tool | Description |
|
|
113
|
+
|------|-------------|
|
|
114
|
+
| `capivv_next_step` | Analyze your setup and get exact instructions for the next step |
|
|
115
|
+
| `capivv_setup_wizard` | One-shot setup: app + entitlement + products + offering in one call |
|
|
116
|
+
| `capivv_verify_setup` | Pass/fail checklist verifying your entire setup with fix instructions |
|
|
117
|
+
|
|
118
|
+
### Status & Analytics
|
|
119
|
+
|
|
90
120
|
| Tool | Description |
|
|
91
121
|
|------|-------------|
|
|
92
122
|
| `capivv_status` | Get setup progress, resource counts, and key metrics |
|
|
123
|
+
| `capivv_get_analytics` | Get MRR, ARR, churn rate, ARPU, and period comparison |
|
|
124
|
+
|
|
125
|
+
### Apps
|
|
126
|
+
|
|
127
|
+
| Tool | Description |
|
|
128
|
+
|------|-------------|
|
|
93
129
|
| `capivv_list_apps` | List all apps with platform and bundle ID |
|
|
130
|
+
| `capivv_create_app` | Register a new app (iOS, Android, or Web) |
|
|
131
|
+
|
|
132
|
+
### Entitlements
|
|
133
|
+
|
|
134
|
+
| Tool | Description |
|
|
135
|
+
|------|-------------|
|
|
136
|
+
| `capivv_list_entitlements` | List all entitlements (feature access identifiers) |
|
|
137
|
+
| `capivv_create_entitlement` | Create a new entitlement |
|
|
138
|
+
|
|
139
|
+
### Products
|
|
140
|
+
|
|
141
|
+
| Tool | Description |
|
|
142
|
+
|------|-------------|
|
|
94
143
|
| `capivv_list_products` | List products with store IDs and entitlements (optional `app_id` filter) |
|
|
144
|
+
| `capivv_create_product` | Create a subscription, consumable, or non-consumable product |
|
|
145
|
+
| `capivv_update_product` | Update product fields (name, entitlements, external ID) |
|
|
146
|
+
| `capivv_delete_product` | Delete a product (irreversible) |
|
|
95
147
|
| `capivv_import_products` | Preview store product import from App Store Connect / Google Play |
|
|
148
|
+
|
|
149
|
+
### Offerings
|
|
150
|
+
|
|
151
|
+
| Tool | Description |
|
|
152
|
+
|------|-------------|
|
|
96
153
|
| `capivv_list_offerings` | List offerings with packages and products |
|
|
97
154
|
| `capivv_create_offering` | Create a new offering with packages |
|
|
155
|
+
|
|
156
|
+
### Rules
|
|
157
|
+
|
|
158
|
+
| Tool | Description |
|
|
159
|
+
|------|-------------|
|
|
98
160
|
| `capivv_list_rules` | List YAML business rules with status and priority |
|
|
99
161
|
| `capivv_apply_rule` | Validate and apply a YAML rule configuration |
|
|
162
|
+
| `capivv_activate_rule` | Activate an existing rule |
|
|
163
|
+
| `capivv_delete_rule` | Delete a rule (irreversible) |
|
|
164
|
+
|
|
165
|
+
### Experiments
|
|
166
|
+
|
|
167
|
+
| Tool | Description |
|
|
168
|
+
|------|-------------|
|
|
100
169
|
| `capivv_list_experiments` | List A/B experiments with results and confidence |
|
|
101
|
-
| `capivv_get_analytics` | Get MRR, ARR, churn rate, ARPU, and period comparison |
|
|
102
170
|
|
|
103
171
|
## Available Resources
|
|
104
172
|
|
|
105
173
|
| URI | Description |
|
|
106
174
|
|-----|-------------|
|
|
175
|
+
| `capivv://docs/quickstart` | Step-by-step setup guide — **start here** |
|
|
176
|
+
| `capivv://docs/guides/ios` | Complete iOS integration guide with code examples |
|
|
177
|
+
| `capivv://docs/guides/ai-prompts` | Ready-to-use prompts for AI code generators (Lovable, Bolt, Cursor) |
|
|
107
178
|
| `capivv://status` | Current platform status as JSON |
|
|
108
179
|
| `capivv://rules/{ruleId}` | Individual rule YAML content |
|
|
109
180
|
| `capivv://docs/concepts` | Glossary of subscription platform concepts |
|
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, CreateOfferingRequest, CreateRuleRequest, ValidateRuleResponse } 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 } from './types.js';
|
|
3
3
|
export declare class ApiError extends Error {
|
|
4
4
|
status: number;
|
|
5
5
|
code: string;
|
|
@@ -14,6 +14,8 @@ export declare class CapivvClient {
|
|
|
14
14
|
private get;
|
|
15
15
|
private post;
|
|
16
16
|
healthCheck(): Promise<boolean>;
|
|
17
|
+
whoami(): Promise<WhoamiResponse>;
|
|
18
|
+
getApiKeyUsage(apiKeyId: string, hours?: number): Promise<ApiKeyUsageResponse>;
|
|
17
19
|
listApps(): Promise<App[]>;
|
|
18
20
|
listProducts(appId?: string): Promise<Product[]>;
|
|
19
21
|
listEntitlements(): Promise<Entitlement[]>;
|
|
@@ -21,11 +23,68 @@ export declare class CapivvClient {
|
|
|
21
23
|
createOffering(data: CreateOfferingRequest): Promise<Offering>;
|
|
22
24
|
listRules(): Promise<Rule[]>;
|
|
23
25
|
getRule(id: string): Promise<Rule>;
|
|
24
|
-
|
|
25
|
-
validateRule(
|
|
26
|
+
createRule(data: CreateRuleRequest): Promise<Rule>;
|
|
27
|
+
validateRule(data: ValidateRuleRequest): Promise<ValidateRuleResponse>;
|
|
26
28
|
listExperiments(): Promise<Experiment[]>;
|
|
27
29
|
getExperimentSummaries(): Promise<ExperimentSummary[]>;
|
|
28
30
|
getAnalyticsOverview(): Promise<AnalyticsOverview>;
|
|
29
31
|
getOnboarding(): Promise<OnboardingResponse>;
|
|
30
32
|
getImportPreview(appId: string): Promise<ImportPreviewResponse>;
|
|
33
|
+
createApp(data: CreateAppRequest): Promise<App>;
|
|
34
|
+
createEntitlement(data: CreateEntitlementRequest): Promise<Entitlement>;
|
|
35
|
+
createProduct(data: CreateProductRequest): Promise<Product>;
|
|
36
|
+
private patch;
|
|
37
|
+
private delete;
|
|
38
|
+
updateProduct(id: string, data: Partial<Omit<CreateProductRequest, 'app_id'>>): Promise<Product>;
|
|
39
|
+
deleteProduct(id: string): Promise<void>;
|
|
40
|
+
deleteRule(id: string): Promise<void>;
|
|
41
|
+
activateRule(id: string): Promise<Rule>;
|
|
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>;
|
|
31
90
|
}
|
package/dist/client.js
CHANGED
|
@@ -53,13 +53,21 @@ export class CapivvClient {
|
|
|
53
53
|
}
|
|
54
54
|
async healthCheck() {
|
|
55
55
|
try {
|
|
56
|
-
|
|
57
|
-
|
|
56
|
+
// Health endpoint is at root, not under /v1
|
|
57
|
+
const url = this.baseUrl.replace(/\/v1$/, '') + '/health';
|
|
58
|
+
const response = await fetch(url);
|
|
59
|
+
return response.ok;
|
|
58
60
|
}
|
|
59
61
|
catch {
|
|
60
62
|
return false;
|
|
61
63
|
}
|
|
62
64
|
}
|
|
65
|
+
async whoami() {
|
|
66
|
+
return this.get('/dashboard/whoami');
|
|
67
|
+
}
|
|
68
|
+
async getApiKeyUsage(apiKeyId, hours = 24) {
|
|
69
|
+
return this.get(`/dashboard/settings/api-keys/${encodeURIComponent(apiKeyId)}/usage?hours=${hours}`);
|
|
70
|
+
}
|
|
63
71
|
async listApps() {
|
|
64
72
|
const resp = await this.get('/dashboard/apps');
|
|
65
73
|
return resp.apps;
|
|
@@ -87,11 +95,11 @@ export class CapivvClient {
|
|
|
87
95
|
async getRule(id) {
|
|
88
96
|
return this.get(`/dashboard/rules/${encodeURIComponent(id)}`);
|
|
89
97
|
}
|
|
90
|
-
async
|
|
98
|
+
async createRule(data) {
|
|
91
99
|
return this.post('/dashboard/rules', data);
|
|
92
100
|
}
|
|
93
|
-
async validateRule(
|
|
94
|
-
return this.post('/dashboard/rules/validate',
|
|
101
|
+
async validateRule(data) {
|
|
102
|
+
return this.post('/dashboard/rules/validate', data);
|
|
95
103
|
}
|
|
96
104
|
async listExperiments() {
|
|
97
105
|
const resp = await this.get('/dashboard/experiments/active');
|
|
@@ -110,4 +118,211 @@ export class CapivvClient {
|
|
|
110
118
|
async getImportPreview(appId) {
|
|
111
119
|
return this.get(`/dashboard/onboarding/import-preview?app_id=${encodeURIComponent(appId)}`);
|
|
112
120
|
}
|
|
121
|
+
// ---- Create methods ----
|
|
122
|
+
async createApp(data) {
|
|
123
|
+
return this.post('/dashboard/apps', data);
|
|
124
|
+
}
|
|
125
|
+
async createEntitlement(data) {
|
|
126
|
+
return this.post('/dashboard/entitlements', data);
|
|
127
|
+
}
|
|
128
|
+
async createProduct(data) {
|
|
129
|
+
return this.post('/dashboard/products', data);
|
|
130
|
+
}
|
|
131
|
+
// ---- Update methods ----
|
|
132
|
+
patch(path, body) {
|
|
133
|
+
return this.request('PATCH', path, body);
|
|
134
|
+
}
|
|
135
|
+
delete(path) {
|
|
136
|
+
return this.request('DELETE', path);
|
|
137
|
+
}
|
|
138
|
+
async updateProduct(id, data) {
|
|
139
|
+
return this.patch(`/dashboard/products/${encodeURIComponent(id)}`, data);
|
|
140
|
+
}
|
|
141
|
+
async deleteProduct(id) {
|
|
142
|
+
await this.delete(`/dashboard/products/${encodeURIComponent(id)}`);
|
|
143
|
+
}
|
|
144
|
+
async deleteRule(id) {
|
|
145
|
+
await this.delete(`/dashboard/rules/${encodeURIComponent(id)}`);
|
|
146
|
+
}
|
|
147
|
+
async activateRule(id) {
|
|
148
|
+
return this.post(`/dashboard/rules/${encodeURIComponent(id)}/activate`);
|
|
149
|
+
}
|
|
150
|
+
async deactivateRule(id) {
|
|
151
|
+
return this.post(`/dashboard/rules/${encodeURIComponent(id)}/deactivate`);
|
|
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
|
+
}
|
|
113
328
|
}
|
package/dist/config.js
CHANGED
|
@@ -10,7 +10,7 @@ export function loadConfig() {
|
|
|
10
10
|
throw new ConfigError('CAPIVV_API_KEY environment variable is required. ' +
|
|
11
11
|
'Create an API key in the Capivv dashboard under Settings > Developer > API Keys.');
|
|
12
12
|
}
|
|
13
|
-
const apiUrl = (process.env.CAPIVV_API_URL || 'https://
|
|
13
|
+
const apiUrl = (process.env.CAPIVV_API_URL || 'https://app.capivv.com').replace(/\/+$/, '');
|
|
14
14
|
const orgId = process.env.CAPIVV_ORG_ID || undefined;
|
|
15
15
|
return { apiKey, apiUrl, orgId };
|
|
16
16
|
}
|
package/dist/http.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* MCP Remote HTTP Server
|
|
4
|
+
*
|
|
5
|
+
* Exposes the Capivv MCP server over Streamable HTTP transport.
|
|
6
|
+
* Clients authenticate with their Capivv API key as a Bearer token.
|
|
7
|
+
*
|
|
8
|
+
* Usage in Lovable / other MCP clients:
|
|
9
|
+
* Server URL: https://app.capivv.com/mcp
|
|
10
|
+
* Auth: Bearer token → paste your Capivv secret API key
|
|
11
|
+
*/
|
|
12
|
+
export {};
|
package/dist/http.js
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* MCP Remote HTTP Server
|
|
4
|
+
*
|
|
5
|
+
* Exposes the Capivv MCP server over Streamable HTTP transport.
|
|
6
|
+
* Clients authenticate with their Capivv API key as a Bearer token.
|
|
7
|
+
*
|
|
8
|
+
* Usage in Lovable / other MCP clients:
|
|
9
|
+
* Server URL: https://app.capivv.com/mcp
|
|
10
|
+
* Auth: Bearer token → paste your Capivv secret API key
|
|
11
|
+
*/
|
|
12
|
+
import express from 'express';
|
|
13
|
+
import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
|
|
14
|
+
import { createServer } from './server.js';
|
|
15
|
+
const PORT = parseInt(process.env.MCP_PORT || '3100', 10);
|
|
16
|
+
const HOST = process.env.MCP_HOST || '0.0.0.0';
|
|
17
|
+
const API_URL = (process.env.CAPIVV_API_URL || 'https://app.capivv.com').replace(/\/+$/, '');
|
|
18
|
+
const app = express();
|
|
19
|
+
app.use(express.json());
|
|
20
|
+
// Health check
|
|
21
|
+
app.get('/health', (_req, res) => {
|
|
22
|
+
res.json({ status: 'ok', service: 'capivv-mcp' });
|
|
23
|
+
});
|
|
24
|
+
// Public origin used in the WWW-Authenticate header so OAuth-aware MCP clients
|
|
25
|
+
// (Cursor, Claude Desktop) can discover our authorization server. Falls back to
|
|
26
|
+
// CAPIVV_API_URL because in production the MCP and API share the same hostname
|
|
27
|
+
// behind Caddy.
|
|
28
|
+
const PUBLIC_URL = (process.env.CAPIVV_PUBLIC_URL || API_URL).replace(/\/+$/, '');
|
|
29
|
+
function unauthorized(res, description) {
|
|
30
|
+
// RFC 9728: point the client at the protected-resource metadata so it can
|
|
31
|
+
// discover our authorization server and start the OAuth flow.
|
|
32
|
+
res.setHeader('WWW-Authenticate', `Bearer realm="capivv-mcp", error="invalid_token", error_description="${description}", resource_metadata="${PUBLIC_URL}/.well-known/oauth-protected-resource"`);
|
|
33
|
+
res.status(401).json({
|
|
34
|
+
jsonrpc: '2.0',
|
|
35
|
+
error: { code: -32000, message: description },
|
|
36
|
+
id: null,
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
// MCP endpoint — Streamable HTTP
|
|
40
|
+
app.post('/mcp', async (req, res) => {
|
|
41
|
+
try {
|
|
42
|
+
// Extract API key from Authorization header
|
|
43
|
+
const authHeader = req.headers.authorization;
|
|
44
|
+
if (!authHeader) {
|
|
45
|
+
unauthorized(res, 'Missing Authorization header. Sign in via your MCP client or set Bearer <your-capivv-api-key>.');
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
const apiKey = authHeader.startsWith('Bearer ')
|
|
49
|
+
? authHeader.slice(7).trim()
|
|
50
|
+
: authHeader.trim();
|
|
51
|
+
if (!apiKey) {
|
|
52
|
+
unauthorized(res, 'Empty bearer token.');
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
// Create a config using the client's API key
|
|
56
|
+
const config = {
|
|
57
|
+
apiKey,
|
|
58
|
+
apiUrl: API_URL,
|
|
59
|
+
orgId: undefined,
|
|
60
|
+
};
|
|
61
|
+
// Create a fresh server + transport per request (stateless)
|
|
62
|
+
const server = createServer(config);
|
|
63
|
+
const transport = new StreamableHTTPServerTransport({
|
|
64
|
+
sessionIdGenerator: undefined, // stateless — no session tracking
|
|
65
|
+
});
|
|
66
|
+
await server.connect(transport);
|
|
67
|
+
await transport.handleRequest(req, res, req.body);
|
|
68
|
+
}
|
|
69
|
+
catch (error) {
|
|
70
|
+
console.error('[mcp-http] Error handling request:', error);
|
|
71
|
+
if (!res.headersSent) {
|
|
72
|
+
res.status(500).json({
|
|
73
|
+
jsonrpc: '2.0',
|
|
74
|
+
error: { code: -32603, message: 'Internal server error' },
|
|
75
|
+
id: null,
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
// Handle GET for SSE streams (server-initiated messages)
|
|
81
|
+
app.get('/mcp', async (_req, res) => {
|
|
82
|
+
// In stateless mode, we don't support server-initiated SSE
|
|
83
|
+
res.status(405).json({
|
|
84
|
+
jsonrpc: '2.0',
|
|
85
|
+
error: { code: -32000, message: 'Server-initiated SSE not supported in stateless mode. Use POST.' },
|
|
86
|
+
id: null,
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
// Handle DELETE for session termination
|
|
90
|
+
app.delete('/mcp', async (_req, res) => {
|
|
91
|
+
// Stateless — no sessions to terminate
|
|
92
|
+
res.status(405).json({
|
|
93
|
+
jsonrpc: '2.0',
|
|
94
|
+
error: { code: -32000, message: 'No sessions to terminate (stateless server).' },
|
|
95
|
+
id: null,
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
app.listen(PORT, HOST, () => {
|
|
99
|
+
console.log(`[capivv-mcp] HTTP server listening on http://${HOST}:${PORT}/mcp`);
|
|
100
|
+
console.log(`[capivv-mcp] API URL: ${API_URL}`);
|
|
101
|
+
console.log(`[capivv-mcp] Auth: Bearer token (use your Capivv API key)`);
|
|
102
|
+
});
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { readFile } from 'fs/promises';
|
|
2
|
+
import { resolve, dirname } from 'path';
|
|
3
|
+
import { fileURLToPath } from 'url';
|
|
4
|
+
// Resolve path to the docs/ directory relative to the package root
|
|
5
|
+
function docsDir() {
|
|
6
|
+
// packages/mcp-server/src/resources/guides.ts → packages/mcp-server/
|
|
7
|
+
const packageRoot = resolve(dirname(fileURLToPath(import.meta.url)), '..', '..');
|
|
8
|
+
// packages/mcp-server/ → project root docs/
|
|
9
|
+
return resolve(packageRoot, '..', '..', 'docs');
|
|
10
|
+
}
|
|
11
|
+
const GUIDES = [
|
|
12
|
+
{
|
|
13
|
+
name: 'guide-ios',
|
|
14
|
+
uri: 'capivv://docs/guides/ios',
|
|
15
|
+
file: 'IOS_INTEGRATION_GUIDE.md',
|
|
16
|
+
description: 'Step-by-step iOS integration guide: App Store Connect setup, SDK installation, purchases, entitlements, testing, and troubleshooting.',
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
name: 'guide-ai-prompts',
|
|
20
|
+
uri: 'capivv://docs/guides/ai-prompts',
|
|
21
|
+
file: 'AI_INTEGRATION_PROMPTS.md',
|
|
22
|
+
description: 'Ready-to-use prompts for AI code generators (Lovable, Bolt, Cursor) to integrate Capivv on iOS, Android, Flutter, Web, and Ionic.',
|
|
23
|
+
},
|
|
24
|
+
];
|
|
25
|
+
// Fallback content if the file can't be read (e.g., when running from npm package without docs/)
|
|
26
|
+
const FALLBACK = {
|
|
27
|
+
'IOS_INTEGRATION_GUIDE.md': `# iOS Integration Guide
|
|
28
|
+
|
|
29
|
+
This guide is available at https://docs.capivv.com/guides/ios
|
|
30
|
+
|
|
31
|
+
## Quick Steps
|
|
32
|
+
|
|
33
|
+
1. **App Store Connect**: Create subscription products, set pricing, enable Server Notifications V2 pointing to \`https://app.capivv.com/v1/webhooks/apple\`
|
|
34
|
+
2. **Capivv Dashboard**: Create app (iOS, your bundle ID), create entitlements (e.g., "pro"), create products matching your store IDs, link products to entitlements
|
|
35
|
+
3. **Install SDK**: Add \`https://github.com/capivv/capivv-ios\` via Swift Package Manager
|
|
36
|
+
4. **Initialize**: Call \`Capivv.shared.configure(apiKey: "capivv_pk_...")\` in your App.init()
|
|
37
|
+
5. **Identify users**: Call \`Capivv.shared.login(userId: "...")\` after authentication
|
|
38
|
+
6. **Check entitlements**: Use \`Capivv.shared.hasEntitlement("pro")\` to gate features
|
|
39
|
+
7. **Show paywall**: Use \`PaywallView(identifier: "default")\` or build a custom one with \`Capivv.shared.getOfferings()\`
|
|
40
|
+
8. **Test**: Use StoreKit Configuration files in Xcode, sandbox Apple IDs
|
|
41
|
+
|
|
42
|
+
For the full guide with code examples, read capivv://docs/quickstart or visit https://docs.capivv.com/guides/ios`,
|
|
43
|
+
'AI_INTEGRATION_PROMPTS.md': `# AI Integration Prompts
|
|
44
|
+
|
|
45
|
+
Ready-to-use prompts for AI code generators are available at https://docs.capivv.com/guides/ai-prompts
|
|
46
|
+
|
|
47
|
+
Supported platforms: iOS (Swift), Android (Kotlin), Flutter, Web (React), Ionic/Capacitor
|
|
48
|
+
|
|
49
|
+
For each platform, the prompt covers:
|
|
50
|
+
1. SDK installation
|
|
51
|
+
2. Initialization with API key
|
|
52
|
+
3. User identification
|
|
53
|
+
4. Entitlement checking
|
|
54
|
+
5. Paywall display
|
|
55
|
+
6. Purchase processing
|
|
56
|
+
7. Sync on launch
|
|
57
|
+
|
|
58
|
+
Visit https://docs.capivv.com/guides/ai-prompts for the full prompts.`,
|
|
59
|
+
};
|
|
60
|
+
export function registerGuideResources(server) {
|
|
61
|
+
for (const guide of GUIDES) {
|
|
62
|
+
server.resource(guide.name, guide.uri, { mimeType: 'text/markdown' }, async (uri) => {
|
|
63
|
+
let content;
|
|
64
|
+
try {
|
|
65
|
+
const filePath = resolve(docsDir(), guide.file);
|
|
66
|
+
content = await readFile(filePath, 'utf-8');
|
|
67
|
+
}
|
|
68
|
+
catch {
|
|
69
|
+
content = FALLBACK[guide.file] ?? `Guide not found. Visit https://docs.capivv.com for documentation.`;
|
|
70
|
+
}
|
|
71
|
+
return {
|
|
72
|
+
contents: [
|
|
73
|
+
{
|
|
74
|
+
uri: uri.href,
|
|
75
|
+
text: content,
|
|
76
|
+
},
|
|
77
|
+
],
|
|
78
|
+
};
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
}
|
package/dist/resources/index.js
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
import { registerStatusResource } from './status.js';
|
|
2
2
|
import { registerRulesResource } from './rules.js';
|
|
3
3
|
import { registerConceptsResource } from './concepts.js';
|
|
4
|
+
import { registerQuickstartResource } from './quickstart.js';
|
|
5
|
+
import { registerGuideResources } from './guides.js';
|
|
4
6
|
export function registerAllResources(server, client) {
|
|
5
7
|
registerStatusResource(server, client);
|
|
6
8
|
registerRulesResource(server, client);
|
|
7
9
|
registerConceptsResource(server);
|
|
10
|
+
registerQuickstartResource(server);
|
|
11
|
+
registerGuideResources(server);
|
|
8
12
|
}
|