Skip to help content
RightMessage
MCP referenceReference

MCP tools for split tests

Create, inspect, update, start, complete, and delete split tests, including variant payloads and the publication boundary.

Available on the Grow, Scale, and Pro plans.

Updated

View as Markdown

Split-test tools manage test records for existing questions, offers, and flows. They do not create duplicate base resources. Starting a test changes its stored status immediately; publication deploys the active test to the website. Ending a test records the winner and can replace original content in the draft.

MCP split-test access and lifecycle

Every operation accepts an optional string project_id and follows the shared MCP authorization and project-selection rules. Invalid or inaccessible projects return errors.

split_test_pid is the public test ID returned as pid, not a resource ID or a made-up st_ identifier. Missing input, invalid IDs, and cross-project or unknown tests return errors.

The state sequence is draft → active → completed. Only draft tests can be edited or started. Only active tests can be ended. Completed tests cannot be restarted. Deleting an active test is prohibited.

Examples are illustrative and were not executed. Requests are tools/call parameters; responses are decoded payloads. Synthetic resource IDs assume that the corresponding resources already exist in WorkForge.

Variant payloads

variants is an array of variant objects. Control is implicit and should not be included. Common fields are:

FieldTypeMeaning
idstringNonempty variant identifier, distinct from control.
namestringNonempty display name.
weightnumberCreation requires 0–100; non-control weights must total at least 1 and less than 100.

The remaining weight is reserved for control. A supplied control object is removed during creation, and the remaining weights are redistributed. Don't copy the tool description's two-variant example with weights 50 and 50. Creation rejects that sum.

Question overrides

Question tests support one to three non-control variants, with unique IDs. Only one draft or active test may exist for a question.

  • text: optional nullable string overriding question text. Blank wording inherits control.
  • description: optional nullable string with the same inheritance behavior.
  • answers: optional nullable object keyed by an existing answer's segment ID. A value can be a label string or an object with label and imageUrl. Omitted, null, or empty-string values inherit control; promotion applies only nonempty label/image strings. Unknown segment keys do not create options.

Choice questions can vary question and answer wording. Input questions use text and description overrides. These payloads do not create new answer segments or change the underlying input type. buttonText is not a promoted question override.

Offer overrides

Offer variants can contain parts, an object with title, description, buttonText, and imageUrl string overrides. Omit a part to inherit it. Use intentional, nonempty values rather than null or empty patches.

A link-action offer can also contain link, a sparse object with only:

  • url: optional nonempty destination string.
  • open: optional boolean controlling whether it opens in a new tab.

Omitting link inherits the complete link. Within a supplied link, omitted fields inherit. Unknown link keys, null/empty link objects, malformed values, or link overrides on non-link offers are rejected. The create handler does not impose an offer-specific variant-count maximum.

Flow overrides

Flow creation accepts up to four variants. Every variant must include a complete funnelDefinition object with type: "root". It is a replacement tree, not a patch.

The tool advertises this as an open object rather than a separate recursively enumerated JSON schema. Preserve the complete valid flow node structure, including each node's type-specific fields and ordered child or branch arrays. The creation handler checks that the supplied root is a nonempty object/array with root type; that is not a guarantee that every nested node is runnable. Read the existing flow and use its validated node definitions rather than inferring a tree from these minimal root checks.

create-split-test

Creates a test record in draft status.

ArgumentTypeRequiredMeaning
project_idstringNoPublic project ID.
resource_typestringYesquestion, offer, or flow.
resource_idstringYesExisting resource ID.
variantsarray of objectsYesNonempty array using the payload rules above.
JSON
{"name":"create-split-test","arguments":{"project_id":"123456789","resource_type":"question","resource_id":"raq_example","variants":[{"id":"variant_b","name":"Direct question","weight":50,"text":"What would help your team most?"}]}}
JSON
{"pid":"987654321","resource_type":"question","resource_id":"raq_example","status":"draft","variants":[{"id":"variant_b","name":"Direct question","weight":50,"text":"What would help your team most?"}],"message":"Split test created in draft status. Use start-split-test to activate it."}

Creation immediately stores the test record but does not start or publish it. Missing fields, unsupported resource types, invalid weights, excessive question/flow variants, duplicate open question tests, and invalid variant definitions return errors. Shared mutation failures use Validation error: ... or Operation failed: ....

list-split-tests

Lists stored tests, optionally filtered.

Arguments: optional project_id string; optional resource_type, resource_id, and status strings. Supported resource types are question, offer, and flow; normal status values are draft, active, and completed. For clarity, pair a resource ID with its type. The handler applies supplied filters independently.

JSON
{"name":"list-split-tests","arguments":{"project_id":"123456789","resource_type":"question","status":"draft"}}
JSON
[{"pid":"987654321","resource_type":"question","resource_id":"raq_example","status":"draft","variants":[{"id":"variant_b","name":"Direct question","weight":50,"text":"What would help your team most?"}],"started_at":null,"ended_at":null,"winner_id":null,"resource_name":"Business needs"}]

Each item contains pid, resource_type, resource_id, status, variants, started_at, ended_at, and winner_id; resolved resources can add resource_name. There are no pagination arguments. No matches returns []. This does not compute metrics or alter a test.

get-split-test

Reads one test, its original content, and optionally its metrics.

Arguments: optional project_id string; required split_test_pid string; optional include_metrics boolean, default true.

JSON
{"name":"get-split-test","arguments":{"project_id":"123456789","split_test_pid":"987654321","include_metrics":false}}

Illustrative response excerpt:

JSON
{"pid":"987654321","resource_type":"question","resource_id":"raq_example","status":"draft","snapshot":null,"original_content":{"text":"What does your team need?","description":"","buttonText":"Continue","options":[]}}

The full response includes test metadata and variants described under listing, plus snapshot. original_content for a question contains text, description, buttonText, and options, whose items contain segmentId, label, and imageUrl. Offer original content contains title, description, buttonText, and imageUrl; link-action offers also include url and openInNewTab. A flow does not receive the same top-level original-content expansion.

Original content uses draft-first configuration for draft tests and published configuration for active/completed tests. A completion snapshot, when present, contains created_at, original_content, and metrics; question snapshots also preserve related segment information.

Metrics are attached only for active/completed tests when requested. A metrics exception can leave the test readable with metrics: null and metrics_error. This operation changes neither test state nor configuration.

get-split-test-metrics

Retrieves performance for an active or completed test.

Arguments: optional project_id string and required split_test_pid string. There is no date-range or winner-selection argument.

JSON
{"name":"get-split-test-metrics","arguments":{"project_id":"123456789","split_test_pid":"987654321"}}

Illustrative offer-test response:

JSON
{"splitTestPid":"987654321","metrics":{"control":{"variantId":"control","variantName":"Control (original)","exposures":100,"conversions":12,"conversionRate":12},"variant_b":{"variantId":"variant_b","variantName":"Trial CTA","exposures":100,"conversions":15,"conversionRate":15}}}

The envelope contains splitTestPid and metrics, keyed by variant ID. Entries include variantId, resolved variantName, exposures, conversions, and percentage conversionRate.

Question entries also include confidenceInputs: {visitors, answered} and answerDistribution: {coverage, respondents, answers}. answers is keyed by segment ID with {count, share}. Coverage contains status (available or unavailable), nullable reason, and nullable from timestamp. respondents can be null when answer capture is unavailable. Do not substitute empty distributions for proven zero answers.

Flow responses add primaryMetric, either offerConversionRate when an arm includes offers or completionRate otherwise. Flow entries add completions, completionRate, offerConversions, offerConversionRate, avgDurationMs, dropoffs, and dropoffRate. Flow and question queries reject incomplete metric results. The older offer metric path can return zero control metrics after a backend exception, so zero values alone are not proof of a functioning data pipeline.

Draft tests return an error. The tool does not declare statistical significance, choose a winner, or change state. Inspect the sample size and coverage before making a decision.

update-split-test

Replaces the stored variants of a draft test. It is not a per-variant merge.

Arguments: optional project_id string; required split_test_pid string; variants array of objects. Although the advertised schema does not mark variants required, the handler rejects a request without it because there are no other editable fields.

JSON
{"name":"update-split-test","arguments":{"project_id":"123456789","split_test_pid":"987654321","variants":[{"id":"variant_b","name":"Short question","weight":50,"text":"What do you need most?"}]}}
JSON
{"pid":"987654321","resource_type":"question","resource_id":"raq_example","status":"draft","variants":[{"id":"variant_b","name":"Short question","weight":50,"text":"What do you need most?"}]}

Include every variant you want to retain. This overwrites stored test data immediately, but does not publish it. Active/completed tests return a state error; absent update data returns No update fields provided. Pass variants to update. Model validation still applies to question and offer variants. The update handler does not repeat all of creation's weight and flow-root checks, so clients should retain the valid creation contract rather than relying on weaker update validation.

start-split-test

Changes a draft test to active and records started_at.

Arguments: optional project_id string and required split_test_pid string.

JSON
{"name":"start-split-test","arguments":{"project_id":"123456789","split_test_pid":"987654321"}}
JSON
{"pid":"987654321","resource_type":"question","resource_id":"raq_example","status":"active","started_at":"2026-10-13T12:00:00Z","message":"Split test is now active. Visitors will be randomly assigned to variants."}

This is a consequential activation, not a private preview. Variants become locked, and a subsequent configuration publication can include the active test. The handler itself does not compile or publish the snippet. The response's active message describes stored test state, not proof that new code reached visitors.

An active question test also locks changes to the question's wording, answers, display, behavior, linked segment values, and non-sync Auto-Segment rules. This applies to other mutation tools and configuration restores too. Sync mappings, internal names, and flow membership can still change. End the test before attempting a locked edit.

Only draft tests can start. Confirm the intended resource and variants, then use the publication tools when ready to deploy. Publication can include other pending configuration changes.

end-split-test

Completes an active test and declares control or a stored variant the winner.

Arguments: optional project_id string; required split_test_pid string and winner_id string. winner_id must be control or an existing variant ID.

JSON
{"name":"end-split-test","arguments":{"project_id":"123456789","split_test_pid":"987654321","winner_id":"control"}}
JSON
{"pid":"987654321","resource_type":"question","resource_id":"raq_example","status":"completed","winner_id":"control","ended_at":"2026-10-13T13:00:00Z","message":"Test ended. Control (original) wins — no changes made."}

Ending a test saves a completion snapshot and attempts to capture metrics. A metrics error leaves snapshot.metrics: null but does not by itself prevent completion. Test completion and promotion of a non-control winner either succeed together or fail together. A non-control winner overwrites supported question copy and answer wording, offer content and links, or the flow tree in the draft. Promoting a question's answer label can also change the corresponding segment name. Choosing control leaves original content unchanged but still completes the test record.

A winning variant replaces the prior editable content. The tool saves a configuration snapshot before promotion and notifies editors. It does not publish. Publish to deploy the winner and remove the running experiment from the served configuration. A completed test record alone does not prove that a previously published test has stopped running in browsers.

Wrong state, unknown winner, invalid ID, or invalid promotion returns an error. Review metrics and obtain a deliberate winner decision before calling it; the completion snapshot is not a guaranteed substitute for that review.

delete-split-test

Permanently deletes a draft or completed test record, including its stored completion snapshot.

Arguments: optional project_id string and required split_test_pid string.

JSON
{"name":"delete-split-test","arguments":{"project_id":"123456789","split_test_pid":"987654321"}}
JSON
{"deleted":true,"pid":"987654321"}

Active tests must be ended first. Deletion is immediate account-record removal, not a draft operation. Configuration undo cannot restore the test record, and deleting a completed test does not revert content already promoted or published. Missing/invalid IDs, unknown tests, and active-state deletion return errors.

Still need a hand?

Tell us what you’re trying to do and where you’re getting stuck.

support@rightmessage.com