feat(vwo): add VWO MCP for A/B testing and experiments#313
feat(vwo): add VWO MCP for A/B testing and experiments#313viniciusventura29 wants to merge 3 commits intomainfrom
Conversation
Implement comprehensive MCP for VWO with 22 tools covering: - Workspaces: list, get, create - Campaigns: list (with filtering), get, share link, update status - Goals: list, get, create, update - Variations: list - Sections: list - Feature Flags: list, create - Feature Flag Rules: list, create - Metric Reports: get report - Users, Websites, Drafts, Custom Widgets: list operations Authentication uses VWO API tokens (Bearer token header) with configurable default account ID. Client automatically unwraps _data responses and handles errors. Supports account ID override per tool call for multi-workspace operations. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
There was a problem hiding this comment.
10 issues found across 28 files
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="vwo/server/types/env.ts">
<violation number="1" location="vwo/server/types/env.ts:6">
P2: Tighten `accountId` validation: `z.string()` currently accepts empty or whitespace-only values, so invalid config can pass schema validation and break VWO requests later.</violation>
</file>
<file name="vwo/server/tools/features.ts">
<violation number="1" location="vwo/server/tools/features.ts:39">
P2: Enforce at least one goal in the schema; the current validator accepts `goals: []` even though the tool contract requires a metric.</violation>
</file>
<file name="vwo/server/tools/campaigns.ts">
<violation number="1" location="vwo/server/tools/campaigns.ts:112">
P2: Reject empty `ids` arrays in the update-status schema.</violation>
<violation number="2" location="vwo/server/tools/campaigns.ts:113">
P2: Constrain `status` to the documented VWO status values instead of accepting arbitrary strings.</violation>
</file>
<file name="vwo/README.md">
<violation number="1" location="vwo/README.md:10">
P2: This README step is incorrect for this repository: MCPs are deployed via automatic discovery, so telling contributors to update `deploy.json` sends them to a manual configuration path that should not exist.</violation>
</file>
<file name="vwo/server/tools/reports.ts">
<violation number="1" location="vwo/server/tools/reports.ts:17">
P2: Use a numeric schema for `reportId`; the current string schema rejects valid metric report IDs returned by VWO.</violation>
</file>
<file name="vwo/server/lib/env.ts">
<violation number="1" location="vwo/server/lib/env.ts:19">
P2: Trim and validate `accountId`; whitespace-only values currently bypass the guard and produce malformed VWO URLs.</violation>
</file>
<file name="vwo/server/tools/feature-rules.ts">
<violation number="1" location="vwo/server/tools/feature-rules.ts:16">
P2: Accept numeric environment/feature IDs here; the current schema rejects documented ID-based calls.</violation>
</file>
<file name="vwo/server/lib/vwo-client.ts">
<violation number="1" location="vwo/server/lib/vwo-client.ts:72">
P1: Wrap the update-goal payload in `goals`; the PATCH endpoint does not accept the raw object.</violation>
<violation number="2" location="vwo/server/lib/vwo-client.ts:72">
P1: Wrap the create-goal payload in the `goals` object expected by VWO.</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
| async createWorkspace(body: { name: string }): Promise<unknown> { | ||
| return this.request("/accounts", { | ||
| method: "POST", | ||
| body: JSON.stringify(body), |
There was a problem hiding this comment.
P1: Wrap the update-goal payload in goals; the PATCH endpoint does not accept the raw object.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At vwo/server/lib/vwo-client.ts, line 72:
<comment>Wrap the update-goal payload in `goals`; the PATCH endpoint does not accept the raw object.</comment>
<file context>
@@ -0,0 +1,288 @@
+ async createWorkspace(body: { name: string }): Promise<unknown> {
+ return this.request("/accounts", {
+ method: "POST",
+ body: JSON.stringify(body),
+ });
+ }
</file context>
| async createWorkspace(body: { name: string }): Promise<unknown> { | ||
| return this.request("/accounts", { | ||
| method: "POST", | ||
| body: JSON.stringify(body), |
There was a problem hiding this comment.
P1: Wrap the create-goal payload in the goals object expected by VWO.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At vwo/server/lib/vwo-client.ts, line 72:
<comment>Wrap the create-goal payload in the `goals` object expected by VWO.</comment>
<file context>
@@ -0,0 +1,288 @@
+ async createWorkspace(body: { name: string }): Promise<unknown> {
+ return this.request("/accounts", {
+ method: "POST",
+ body: JSON.stringify(body),
+ });
+ }
</file context>
| .string() | ||
| .optional() | ||
| .describe("Account ID override. Uses default if not provided."), | ||
| reportId: z.string().describe("Metric report ID"), |
There was a problem hiding this comment.
P2: Use a numeric schema for reportId; the current string schema rejects valid metric report IDs returned by VWO.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At vwo/server/tools/reports.ts, line 17:
<comment>Use a numeric schema for `reportId`; the current string schema rejects valid metric report IDs returned by VWO.</comment>
<file context>
@@ -0,0 +1,28 @@
+ .string()
+ .optional()
+ .describe("Account ID override. Uses default if not provided."),
+ reportId: z.string().describe("Metric report ID"),
+ }),
+ execute: async ({ context }) => {
</file context>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
1 issue found across 3 files (changes from recent commits).
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="vwo/server/lib/env.ts">
<violation number="1" location="vwo/server/lib/env.ts:5">
P2: Trim and validate the configured API token before returning it; the current code accepts whitespace-only or padded values and forwards them as the VWO auth header.</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
- Trim and validate apiToken and accountId to reject whitespace-only values - Add .min(1) to accountId in StateSchema - Use z.enum for campaign status instead of z.string - Add .min(1) to campaign ids array and feature goals array - Accept union of string | number for environmentId and featureId - Simplify README to remove incorrect deploy.json instruction - Update feature-rules client to accept string | number IDs Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
2 issues found across 7 files (changes from recent commits).
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="vwo/README.md">
<violation number="1" location="vwo/README.md:7">
P2: This instruction points users to the schema file instead of the MCP settings, so it can send them to the wrong place and encourages treating secrets as source code.</violation>
</file>
<file name="vwo/server/lib/env.ts">
<violation number="1" location="vwo/server/lib/env.ts:14">
P2: Trim the override before applying the fallback. As written, a whitespace-only `accountId` override suppresses the configured default and causes these tools to throw instead of using the default account.</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
|
|
||
| ## Getting Started | ||
|
|
||
| 1. Configure your MCP credentials in `server/types/env.ts` |
There was a problem hiding this comment.
P2: This instruction points users to the schema file instead of the MCP settings, so it can send them to the wrong place and encourages treating secrets as source code.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At vwo/README.md, line 7:
<comment>This instruction points users to the schema file instead of the MCP settings, so it can send them to the wrong place and encourages treating secrets as source code.</comment>
<file context>
@@ -4,10 +4,6 @@ Connect AI agents to VWO for A/B testing, experiment management, and optimizatio
## Getting Started
-1. Configure your MCP in `server/types/env.ts`
+1. Configure your MCP credentials in `server/types/env.ts`
2. Implement tools in `server/tools/`
-3. Rename `app.json.example` to `app.json` and customize
</file context>
| 1. Configure your MCP credentials in `server/types/env.ts` | |
| 1. Configure the VWO `StateSchema` in `server/types/env.ts`, then set `apiToken` and `accountId` in the MCP settings |
| } | ||
|
|
||
| export function getAccountId(env: Env, override?: string): string { | ||
| const id = (override || env.MESH_REQUEST_CONTEXT?.state?.accountId)?.trim(); |
There was a problem hiding this comment.
P2: Trim the override before applying the fallback. As written, a whitespace-only accountId override suppresses the configured default and causes these tools to throw instead of using the default account.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At vwo/server/lib/env.ts, line 14:
<comment>Trim the override before applying the fallback. As written, a whitespace-only `accountId` override suppresses the configured default and causes these tools to throw instead of using the default account.</comment>
<file context>
@@ -11,7 +11,7 @@ export function getApiToken(env: Env): string {
export function getAccountId(env: Env, override?: string): string {
- const id = override || env.MESH_REQUEST_CONTEXT?.state?.accountId;
+ const id = (override || env.MESH_REQUEST_CONTEXT?.state?.accountId)?.trim();
if (!id) {
throw new Error(
</file context>
| const id = (override || env.MESH_REQUEST_CONTEXT?.state?.accountId)?.trim(); | |
| const id = override?.trim() || env.MESH_REQUEST_CONTEXT?.state?.accountId?.trim(); |
Summary
Implement comprehensive VWO MCP with 22 tools for A/B testing campaign management, feature flags, and optimization experiment analysis.
Tools by Category:
Key Features:
_datawith error handling🤖 Generated with Claude Code
Summary by cubic
Adds a new
vwoMCP that integrates with VWO for A/B testing, feature flags, and experiment reporting. Ships 22 tools and a typedVWOClientwith state-based token auth (token sent viatokenheader), default account state, and automatic_dataunwrapping.New Features
vwoMCP with 22 tools: workspaces; campaigns (list/get/share/status); goals (list/get/create/update); variations/sections; features and rules (list/create); reports; users; websites; drafts; widgets.VWOClientwith query helpers and_dataunwrapping. DefaultaccountIdin state with per-tool override.Bug Fixes
apiTokenandaccountId; enforce.min(1)foraccountId.statusas enum; campaignidsand featuregoalsarrays require at least one item.string | numberforenvironmentIdandfeatureId.Written for commit 0533a17. Summary will update on new commits.