splera-mcp 0.1.1 → 0.1.3

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 CHANGED
@@ -138,9 +138,13 @@ You've hit your plan's monthly experiment cap. Options: [upgrade](https://splera
138
138
  The SDK isn't reaching the page being tested. Verify the script tag is in place:
139
139
 
140
140
  ```html
141
- <script src="https://splera.app/sdk/splera.js" data-experiment-id="YOUR-EXPERIMENT-UUID" async></script>
141
+ <script src="https://splera.app/sdk/splera.js"
142
+ data-experiment="YOUR-EXPERIMENT-UUID"
143
+ data-api-url="https://splera.app"></script>
142
144
  ```
143
145
 
146
+ `data-api-url` is required: without it the SDK tracks nothing. If your experiment was created with splera-mcp 0.1.1, its install code was missing this attribute and used a callback form of `getVariant` that never runs. Re-copy the snippet from the experiment page on the dashboard.
147
+
144
148
  Also confirm the page is receiving real traffic. The dashboard shows live exposure counts at [splera.app/experiments/:id](https://splera.app).
145
149
 
146
150
  ### Agent doesn't use the Splera tool even when I ask
package/dist/config.d.ts CHANGED
@@ -17,4 +17,4 @@ export declare function loadConfig(): Config;
17
17
  * Pre-release / build metadata is NOT supported — we don't ship those for MCP.
18
18
  */
19
19
  export declare function isBelow(current: string, minimum: string): boolean;
20
- export declare const CURRENT_MCP_VERSION = "0.1.1";
20
+ export declare const CURRENT_MCP_VERSION = "0.1.3";
package/dist/config.js CHANGED
@@ -51,4 +51,4 @@ export function isBelow(current, minimum) {
51
51
  }
52
52
  return false;
53
53
  }
54
- export const CURRENT_MCP_VERSION = '0.1.1';
54
+ export const CURRENT_MCP_VERSION = '0.1.3';
@@ -0,0 +1,4 @@
1
+ export declare function buildInstallSnippet(experimentId: string, variants: {
2
+ id: string;
3
+ name: string;
4
+ }[], primaryEventName: string, decisionMode: string): string;
@@ -0,0 +1,32 @@
1
+ /**
2
+ * The install snippet create_experiment hands the agent. MUST match the web
3
+ * dashboard's `buildScriptTag` (packages/web/src/pages/experiments/lib/
4
+ * installPrompts.ts) — the SDK reads `data-experiment` + `data-api-url` from
5
+ * the tag and `getVariant(id, variantIds)` returns the variant synchronously.
6
+ * 0.1.1 shipped a callback form + no data-api-url, so nothing was tracked.
7
+ * Guarded by __tests__/installSnippet.test.ts.
8
+ */
9
+ const SDK_URL = 'https://splera.app/sdk/splera.js';
10
+ const API_URL = 'https://splera.app';
11
+ // Same rule as the web builder (Codex #23): code literals JSON-encoded, prose one line.
12
+ const inline = (s) => s.replace(/[\u0000-\u001f\u007f]+/g, ' ').trim();
13
+ export function buildInstallSnippet(experimentId, variants, primaryEventName, decisionMode) {
14
+ const branches = variants
15
+ .map((v, i) => {
16
+ const keyword = i === 0 ? 'if' : '} else if';
17
+ return ` ${keyword} (variant === ${JSON.stringify(v.id)}) {\n // Show ${inline(v.name)}`;
18
+ })
19
+ .join('\n');
20
+ return `<script src="${SDK_URL}"
21
+ data-experiment="${experimentId}"
22
+ data-api-url="${API_URL}"${decisionMode === 'bandit' ? '\n data-decision-mode="bandit"' : ''}></script>
23
+
24
+ <script>
25
+ const variant = Splera.getVariant("${experimentId}", ${JSON.stringify(variants.map((v) => v.id))});
26
+ ${branches}
27
+ }
28
+
29
+ // Call this when the conversion event happens:
30
+ Splera.track(${JSON.stringify(primaryEventName)});
31
+ </script>`;
32
+ }
@@ -1,4 +1,5 @@
1
1
  import { apiFetch, apiUrl } from '../apiClient.js';
2
+ import { buildInstallSnippet } from '../installSnippet.js';
2
3
  /**
3
4
  * Mirror of `packages/web/src/pages/experiments/lib/createExperiment.ts#variantId`.
4
5
  * Duplicated rather than imported because @splera/shared doesn't export it and
@@ -126,14 +127,10 @@ export const createExperimentTool = {
126
127
  `ID: ${exp.id}\n` +
127
128
  `Variants:\n${variantLines}\n` +
128
129
  `Primary metric: ${primaryMetric.event_name} (goal: ${primaryMetric.goal})\n\n` +
129
- `To activate, add this to your site's <head>:\n` +
130
- `<script src="https://splera.app/sdk/splera.js" data-experiment-id="${exp.id}" async></script>\n\n` +
131
- `Then wrap the element you want to vary:\n` +
132
- `Splera.getVariant('${exp.id}', (variant) => {\n` +
133
- ` if (variant === 'variant_b') document.querySelector('#cta').textContent = '${variants[1]?.name ?? 'Variant B'}';\n` +
134
- `});\n\n` +
135
- `Track conversions:\n` +
136
- `Splera.track('${primaryMetric.event_name}');\n\n` +
130
+ `Add this to the page (the first <script> in <head>, the second where the element renders),\n` +
131
+ `then put each variant's UI in its branch and move Splera.track() to the moment the conversion happens:\n\n` +
132
+ buildInstallSnippet(exp.id, variants, primaryMetric.event_name, body.decision_mode) +
133
+ `\n\nThe SDK is permanent: keep it installed after the test ends.\n\n` +
137
134
  `View live results: ${resultsUrl}`;
138
135
  // Structured JSON block. CRITICAL: agents parse this, not the prose.
139
136
  // `apiUrl` from config isn't substituted into results_url because the
@@ -152,6 +149,7 @@ export const createExperimentTool = {
152
149
  goal: primaryMetric.goal,
153
150
  },
154
151
  sdk_script_url: 'https://splera.app/sdk/splera.js',
152
+ install_snippet: buildInstallSnippet(exp.id, variants, primaryMetric.event_name, body.decision_mode),
155
153
  results_url: resultsUrl,
156
154
  api_url: apiUrl,
157
155
  };
@@ -44,10 +44,13 @@ export const shipWinnerTool = {
44
44
  `Guard window: ${exp.guard_window_days} days (until ${guardWindowEndsDate}).\n` +
45
45
  ` - Use get_results to monitor for degradation.\n` +
46
46
  ` - If the live rate drops below baseline past the alert threshold, you'll get an email alert.\n` +
47
- ` - Rollback is manual only (dashboard): ${resultsUrl}\n\n` +
48
- `Next step (optional): when you're confident the winner is stable, hardcode it\n` +
49
- `into your codebase and remove the Splera script tag. The dashboard will walk\n` +
50
- `you through it.`;
47
+ ` - Roll back in one click from the dashboard: ${resultsUrl}\n` +
48
+ ` - On Pro, turn on auto-rollback in Settings to roll back automatically on a drop.\n\n` +
49
+ `Keep the Splera <script> tag installed: it is how this ship (and any rollback)\n` +
50
+ `reaches the site, and it runs future experiments.\n\n` +
51
+ `Next step (optional): once the winner is stable, hardcode it and remove only this\n` +
52
+ `experiment's getVariant branches and track() calls. The dashboard's Finalize step\n` +
53
+ `walks you through it.`;
51
54
  // Flatten to the spec's ShipResponse shape in the JSON block.
52
55
  const shipResponse = {
53
56
  winning_variant_id: exp.winning_variant_id,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "splera-mcp",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "mcpName": "io.github.sohaibt/splera",
5
5
  "description": "Model Context Protocol (MCP) server for Splera — A/B testing for vibe coders. Create experiments, check results, and ship winners directly from your AI coding agent.",
6
6
  "type": "module",