@capivv/mcp-server 0.5.47 → 0.5.49

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 CHANGED
@@ -54,6 +54,30 @@ export declare class CapivvClient {
54
54
  * "store says zero territories" from "this product type isn't read-
55
55
  * supported yet."
56
56
  */
57
+ /**
58
+ * V0.5.49 — issue #18 follow-up. What-if Bayesian posterior with
59
+ * caller-provided overrides. Doesn't mutate the experiment's
60
+ * stored pre_registration.
61
+ */
62
+ getExperimentPosterior(input: {
63
+ experiment_id: string;
64
+ decision_threshold_pct?: number;
65
+ prior_alpha?: number;
66
+ prior_beta?: number;
67
+ }): Promise<unknown>;
68
+ /**
69
+ * V0.5.48 — issue #18 Primitive 3 follow-up. Upload the Apple
70
+ * promotional-offer signing key. Distinct from the ASC API key
71
+ * the customer set via the dashboard's Apple integration flow —
72
+ * promotional offers use a separate .p8 generated under
73
+ * Users and Access → Keys → In-App Purchase.
74
+ */
75
+ setApplePromotionalOfferKey(input: {
76
+ key_id: string;
77
+ private_key: string;
78
+ }): Promise<{
79
+ ok: boolean;
80
+ }>;
57
81
  listStorePrices(productId: string): Promise<{
58
82
  product_id: string;
59
83
  apple_store_product_id?: string;
package/dist/client.js CHANGED
@@ -151,6 +151,35 @@ export class CapivvClient {
151
151
  * "store says zero territories" from "this product type isn't read-
152
152
  * supported yet."
153
153
  */
154
+ /**
155
+ * V0.5.49 — issue #18 follow-up. What-if Bayesian posterior with
156
+ * caller-provided overrides. Doesn't mutate the experiment's
157
+ * stored pre_registration.
158
+ */
159
+ async getExperimentPosterior(input) {
160
+ const params = new URLSearchParams();
161
+ if (input.decision_threshold_pct !== undefined) {
162
+ params.set('decision_threshold_pct', String(input.decision_threshold_pct));
163
+ }
164
+ if (input.prior_alpha !== undefined) {
165
+ params.set('prior_alpha', String(input.prior_alpha));
166
+ }
167
+ if (input.prior_beta !== undefined) {
168
+ params.set('prior_beta', String(input.prior_beta));
169
+ }
170
+ const qs = params.toString() ? `?${params.toString()}` : '';
171
+ return this.get(`/dashboard/experiments/${encodeURIComponent(input.experiment_id)}/posterior${qs}`);
172
+ }
173
+ /**
174
+ * V0.5.48 — issue #18 Primitive 3 follow-up. Upload the Apple
175
+ * promotional-offer signing key. Distinct from the ASC API key
176
+ * the customer set via the dashboard's Apple integration flow —
177
+ * promotional offers use a separate .p8 generated under
178
+ * Users and Access → Keys → In-App Purchase.
179
+ */
180
+ async setApplePromotionalOfferKey(input) {
181
+ return this.post(`/dashboard/integrations/apple/promotional-offer-key`, input);
182
+ }
154
183
  async listStorePrices(productId) {
155
184
  return this.get(`/dashboard/products/${encodeURIComponent(productId)}/store-prices`);
156
185
  }
@@ -0,0 +1,22 @@
1
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import type { CapivvClient } from '../client.js';
3
+ /**
4
+ * V0.5.49 — focused Bayesian posterior endpoint. Issue #18 follow-up.
5
+ *
6
+ * `capivv_get_experiment_summary` returns the posterior computed
7
+ * against the experiment's stored pre-registration block. This tool
8
+ * lets the agent (or operator doing what-if analysis) override the
9
+ * decision threshold + Beta priors WITHOUT mutating the experiment's
10
+ * stored pre_registration.
11
+ *
12
+ * Example usage:
13
+ * "What would the ship/wait recommendation be at a 10pp threshold
14
+ * instead of our pre-registered 5pp?"
15
+ * "What if we use a tighter Beta(10, 90) prior reflecting our
16
+ * history of ~10% conversion?"
17
+ *
18
+ * Returns the same PosteriorSummary shape as
19
+ * `capivv_get_experiment_summary.posterior_summary`, plus the
20
+ * (control, challenger) variant ids used in the comparison.
21
+ */
22
+ export declare function registerGetExperimentPosteriorTool(server: McpServer, client: CapivvClient): void;
@@ -0,0 +1,43 @@
1
+ import { z } from 'zod';
2
+ /**
3
+ * V0.5.49 — focused Bayesian posterior endpoint. Issue #18 follow-up.
4
+ *
5
+ * `capivv_get_experiment_summary` returns the posterior computed
6
+ * against the experiment's stored pre-registration block. This tool
7
+ * lets the agent (or operator doing what-if analysis) override the
8
+ * decision threshold + Beta priors WITHOUT mutating the experiment's
9
+ * stored pre_registration.
10
+ *
11
+ * Example usage:
12
+ * "What would the ship/wait recommendation be at a 10pp threshold
13
+ * instead of our pre-registered 5pp?"
14
+ * "What if we use a tighter Beta(10, 90) prior reflecting our
15
+ * history of ~10% conversion?"
16
+ *
17
+ * Returns the same PosteriorSummary shape as
18
+ * `capivv_get_experiment_summary.posterior_summary`, plus the
19
+ * (control, challenger) variant ids used in the comparison.
20
+ */
21
+ export function registerGetExperimentPosteriorTool(server, client) {
22
+ server.tool('capivv_get_experiment_posterior', "Compute the Bayesian posterior summary for an experiment with caller-provided decision threshold + Beta priors. Does NOT mutate the experiment's stored pre_registration. Use for what-if analysis; use capivv_get_experiment_summary for the official numbers.", {
23
+ experiment_id: z.string().uuid().describe('The experiment to analyze'),
24
+ decision_threshold_pct: z
25
+ .number()
26
+ .min(0)
27
+ .optional()
28
+ .describe('The minimum lift in percentage points to count as "worth shipping." Drives prob_uplift_exceeds_threshold. Default 0 (any positive lift counts).'),
29
+ prior_alpha: z
30
+ .number()
31
+ .positive()
32
+ .optional()
33
+ .describe('Beta prior α₀. Default 1 (uniform). Use a larger value to encode prior conversions you\'ve seen (e.g. prior_alpha=10 with prior_beta=190 encodes "we\'ve seen ~5% conversion in 200 prior observations").'),
34
+ prior_beta: z
35
+ .number()
36
+ .positive()
37
+ .optional()
38
+ .describe('Beta prior β₀. Default 1 (uniform).'),
39
+ }, async (args) => {
40
+ const result = await client.getExperimentPosterior(args);
41
+ return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
42
+ });
43
+ }
@@ -49,9 +49,11 @@ import { registerCreateExperimentTool } from './create-experiment.js';
49
49
  import { registerUpdateExperimentTool } from './update-experiment.js';
50
50
  import { registerUpdateVariantTool } from './update-variant.js';
51
51
  import { registerListStorePricesTool } from './list-store-prices.js';
52
+ import { registerSetApplePromotionalOfferKeyTool } from './set-apple-promotional-offer-key.js';
52
53
  import { registerStartExperimentTool } from './start-experiment.js';
53
54
  import { registerStopExperimentTool } from './stop-experiment.js';
54
55
  import { registerGetExperimentSummaryTool } from './get-experiment-summary.js';
56
+ import { registerGetExperimentPosteriorTool } from './get-experiment-posterior.js';
55
57
  import { registerUpdateAppTool } from './update-app.js';
56
58
  import { registerDeleteAppTool } from './delete-app.js';
57
59
  import { registerArchiveAppTool } from './archive-app.js';
@@ -165,9 +167,11 @@ export function registerAllTools(server, client) {
165
167
  registerUpdateExperimentTool(server, client);
166
168
  registerUpdateVariantTool(server, client);
167
169
  registerListStorePricesTool(server, client);
170
+ registerSetApplePromotionalOfferKeyTool(server, client);
168
171
  registerStartExperimentTool(server, client);
169
172
  registerStopExperimentTool(server, client);
170
173
  registerGetExperimentSummaryTool(server, client);
174
+ registerGetExperimentPosteriorTool(server, client);
171
175
  // Apps gap-fillers (V8 Phase B.6)
172
176
  registerUpdateAppTool(server, client);
173
177
  registerDeleteAppTool(server, client);
@@ -0,0 +1,25 @@
1
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import type { CapivvClient } from '../client.js';
3
+ /**
4
+ * V0.5.48 — issue #18 Primitive 3 follow-up. Upload the Apple
5
+ * promotional-offer signing key so capivv can issue signed offer
6
+ * payloads for pricing-A/B experiments without per-arm SKU explosion
7
+ * (the v0.5.44 Primitive 3 surface).
8
+ *
9
+ * Customer flow:
10
+ * 1. App Store Connect → Users and Access → Keys → In-App Purchase.
11
+ * 2. Generate a new "Subscription Key" (this is the .p8 file).
12
+ * 3. Note the Key ID shown next to it.
13
+ * 4. Open the .p8 file, copy the full contents including the
14
+ * BEGIN PRIVATE KEY / END PRIVATE KEY lines.
15
+ * 5. Call this tool with key_id + private_key.
16
+ *
17
+ * The backend probe-parses the key with a dummy sign call before
18
+ * persisting, so a paste error returns a clear error here rather
19
+ * than failing 24h later when the SDK first asks for a signature.
20
+ *
21
+ * Distinct from the ASC API key set via capivv_connect_apple_integration —
22
+ * Apple scopes signing authority separately so loss of one doesn't
23
+ * compromise the other.
24
+ */
25
+ export declare function registerSetApplePromotionalOfferKeyTool(server: McpServer, client: CapivvClient): void;
@@ -0,0 +1,38 @@
1
+ import { z } from 'zod';
2
+ /**
3
+ * V0.5.48 — issue #18 Primitive 3 follow-up. Upload the Apple
4
+ * promotional-offer signing key so capivv can issue signed offer
5
+ * payloads for pricing-A/B experiments without per-arm SKU explosion
6
+ * (the v0.5.44 Primitive 3 surface).
7
+ *
8
+ * Customer flow:
9
+ * 1. App Store Connect → Users and Access → Keys → In-App Purchase.
10
+ * 2. Generate a new "Subscription Key" (this is the .p8 file).
11
+ * 3. Note the Key ID shown next to it.
12
+ * 4. Open the .p8 file, copy the full contents including the
13
+ * BEGIN PRIVATE KEY / END PRIVATE KEY lines.
14
+ * 5. Call this tool with key_id + private_key.
15
+ *
16
+ * The backend probe-parses the key with a dummy sign call before
17
+ * persisting, so a paste error returns a clear error here rather
18
+ * than failing 24h later when the SDK first asks for a signature.
19
+ *
20
+ * Distinct from the ASC API key set via capivv_connect_apple_integration —
21
+ * Apple scopes signing authority separately so loss of one doesn't
22
+ * compromise the other.
23
+ */
24
+ export function registerSetApplePromotionalOfferKeyTool(server, client) {
25
+ server.tool('capivv_set_apple_promotional_offer_key', "Upload Apple's promotional-offer signing key (.p8) so capivv can sign per-cohort promotional offers for pricing-A/B experiments (variant.config.promotional_offer_config). Distinct from the ASC API key — generated separately in App Store Connect under Users and Access → Keys → In-App Purchase.", {
26
+ key_id: z
27
+ .string()
28
+ .min(1)
29
+ .describe('The Key ID Apple shows next to the generated .p8 file (e.g. "ABC123XYZ"). NOT the same as the ASC API Key ID — separate value.'),
30
+ private_key: z
31
+ .string()
32
+ .min(1)
33
+ .describe('Full contents of the .p8 file Apple generated, including the "-----BEGIN PRIVATE KEY-----" and "-----END PRIVATE KEY-----" lines. The backend probe-parses this before persisting.'),
34
+ }, async (input) => {
35
+ const result = await client.setApplePromotionalOfferKey(input);
36
+ return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
37
+ });
38
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@capivv/mcp-server",
3
- "version": "0.5.47",
3
+ "version": "0.5.49",
4
4
  "description": "MCP server for managing Capivv subscription platform via AI assistants",
5
5
  "type": "module",
6
6
  "bin": {