# MCP tools for condition discovery and validation

Discover condition sources and exact fields, paginate the catalog, and validate audience rules without changing your project.

Available on the Grow, Scale, and Pro plans.

Use these MCP tools to find condition fields and validate rules for segment signals, flow branches, question options, and widget visibility. They do not evaluate a real visitor or save a rule.

## MCP condition access and validation results

Both tools accept an optional string `project_id` and follow the [shared MCP authorization and project-selection rules](https://rightmessage.com/help/mcp-authorization-reference). There is no extra condition-specific plan gate. A catalog entry does not grant access to the provider or product feature that uses it.

Project context comes from draft configuration when available, otherwise published configuration. The tools return JSON payloads inside MCP responses. Project-selection and authorization failures are MCP errors. An invalid condition normally returns a successful tool result with `valid: false`, not an MCP transport error.

All examples are illustrative and were not executed. WorkForge IDs and `example.com` values are fictional.

## `list-condition-sources`

Returns static condition definitions plus project-specific segment, input-answer, and provider sources.

| Argument     | Required | Type, default, and limits                                                                                                                                            |
| ------------ | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `project_id` | No       | String. Shared project selection.                                                                                                                                    |
| `source`     | No       | String. Exact source name, case-sensitive.                                                                                                                           |
| `search`     | No       | String. Case-insensitive match against source names, source labels, type names, question IDs and labels, and segment names. Leading and trailing spaces are trimmed. |
| `compact`    | No       | Boolean, default `false`. Removes examples and defaults to 20 entries.                                                                                               |
| `limit`      | No       | Integer from `1` through `100`. Default 20 in compact mode, otherwise all matching entries.                                                                          |
| `offset`     | No       | Integer at least `0`, default `0`. Counts matching type or question entries, not source objects.                                                                     |

Without filters or pagination arguments, the result contains `sources`, `logic_definition_schema`, and `signal_schema`. Each ordinary source has `name`, `label`, optional `description`, and `types`. Each type has `value`, `label`, `operators`, and `fields`. Dynamic segment types also have `available_segments: [{id, name}]`.

Field definitions have `name` and, where applicable, `type`, `description`, `required`, `required_when`, and enum `values`. A missing `required` flag is not a guarantee that the runtime can use an omitted field; descriptions contain additional conditional requirements.

The `answers` source differs. It has source-level `fields` and a `questions` array. Each question entry contains `questionId`, `label`, `inputType`, and its valid `operators`.

`logic_definition_schema` contains a description and, outside compact mode, `example_simple` and `example_complex`. `signal_schema` contains a description, `weight_values: ["weak", "moderate", "strong"]`, and, outside compact mode, an example.

Any filter, compact mode, explicit limit, or positive offset adds `total` and `next`. `total` counts matching type/question entries before pagination. `next` is the next offset or null. A source can span several pages. Sources without entries on the current page are omitted. An unknown source or unmatched search returns an empty `sources` array rather than an error. Following `next` requires the same filters.

This read does not save configuration or contact a visitor. Shared access errors apply.

Illustrative request:

```json
{"name":"list-condition-sources","arguments":{"source":"pageviews","search":"First-time","compact":true,"limit":1}}
```

Illustrative result:

```json
{"sources":[{"name":"pageviews","label":"On-Site Behavior","types":[{"value":"newvisitor","label":"First-time visitor","operators":[],"fields":[]}]}],"logic_definition_schema":{"description":"Conditions use nested AND/OR logic. Top-level has \"or\" array of groups, each group has \"and\" array of conditions. For simple conditions, use just {\"and\": [...]} ."},"signal_schema":{"description":"Signals are automatic segment detection rules on dimensions. Each signal links a condition to a specific segment.","weight_values":["weak","moderate","strong"]},"total":1,"next":null}
```

Descriptive strings in this illustrative result are explanatory, not values to compare in client code.

### Logic structure

A simple definition is `{"and":[condition]}`. Alternatives use `{"or":[{"and":[condition]}, {"and":[anotherCondition]}]}`. Groups can nest and use `{"not":group}`. The validator accepts empty `and` and `or` arrays, but they aren't interchangeable. For widget visibility, empty AND matches all and empty OR matches none.

Most leaves contain `$source`, `$type`, and source-specific arguments. `answers` leaves contain `$source: "answers"`, `questionId`, `operator`, and optional `value`, with no `$type`.

A signal wraps a definition in `{indicates, weight, definition}`. `indicates` is a segment ID. Signal creation belongs to [segment tools](https://rightmessage.com/help/mcp-tools-segments). The validator accepts the definition, not that outer signal object. Campaign `changes.segment_ids` is a separate campaign input format, not a LogicDefinition argument.

### Operator sets

The following names are exact strings:

- String comparisons: `equals`, `does not equal`, `contains`, `does not contain`, `starts with`, `ends with`, `glob`, `is set`, `is not set`.
- Inclusion comparisons: `include any`, `do not include any`, `is set`, `is not set`.
- Mathematical comparisons: `equals`, `does not equal`, `gt`, `lt`, `gte`, `lte`.
- Count comparisons in `occurrenceOperator`: `equals`, `gte`, `lte`, `gt`, `lt`.

An empty operators list denotes a source that does not use a comparison operator, or one that uses a differently named comparison field.

### Static sources and fields

| Source and type                                                                                                                                                        | Operators and leaf fields                                                                                                                                                                                                                                                                                                                                                              |
| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `pageviews` / `landingpage`                                                                                                                                            | String comparisons. String `value`, a pathname beginning with `/`, without domain, query, or hash.                                                                                                                                                                                                                                                                                     |
| `pageviews` / `path`                                                                                                                                                   | String comparisons plus `matches pattern`. String pathname `value`; `occurrence`: `last`, `penultimate`, `any`, or `not_any`; `timeframe`: `ever`, `within`, or `outside`. For `any`, add numeric `occurrenceCount` and `occurrenceOperator`. For `within` or `outside`, add numeric `duration` and `unit`: `week`, `day`, or `hour`. `matches pattern` requires `occurrence: "last"`. |
| `pageviews` / `domain`                                                                                                                                                 | String comparisons plus `matches pattern`. String `value`. Pattern matching ignores `www.`, otherwise matches the domain exactly. Blank or `*` means any domain.                                                                                                                                                                                                                       |
| `pageviews` / `newvisitor`                                                                                                                                             | No other fields.                                                                                                                                                                                                                                                                                                                                                                       |
| `pageviews` / `returningvisitor`                                                                                                                                       | `timeframe`: `ever`, `within`, or `outside`; numeric `duration` and `unit` for a bounded window.                                                                                                                                                                                                                                                                                       |
| `pageviews` / `pageCount`                                                                                                                                              | `scope`: `any` by default, or `filtered`. Filtered scope adds string `operator` and path `value`. Numeric `occurrenceCount`; `occurrenceOperator` defaults to `gte`. Optional `timeframe`, `duration`, and `unit` as above.                                                                                                                                                            |
| `pageviews` / `sessionCount`                                                                                                                                           | Numeric `occurrenceCount`, and `occurrenceOperator` defaulting to `gte`. This source defines a session as pageviews separated by no gap longer than one hour.                                                                                                                                                                                                                          |
| `pageviews` / `visitorAge`                                                                                                                                             | `occurrenceOperator`, numeric `duration`, and `unit`: `week`, `day`, or `hour`.                                                                                                                                                                                                                                                                                                        |
| `utm` / `utm_source`, `utm_medium`, `utm_campaign`, `utm_term`, `utm_content`                                                                                          | String comparisons, string `value`, and `occurrence`: `last touch`, `last`, `first touch`, `first`, or `any`. Presence operators need no value.                                                                                                                                                                                                                                        |
| `query` / `custom`                                                                                                                                                     | Same string operators and occurrence choices as UTM, plus required string `query`, the parameter name.                                                                                                                                                                                                                                                                                 |
| `referrer` / `direct`, `referral`                                                                                                                                      | No additional fields.                                                                                                                                                                                                                                                                                                                                                                  |
| `referrer` / `domain`                                                                                                                                                  | Required string `domain` without scheme. No comparison operator.                                                                                                                                                                                                                                                                                                                       |
| `referrer` / `custom`                                                                                                                                                  | String comparisons and string URL `value`.                                                                                                                                                                                                                                                                                                                                             |
| `location` / `country`                                                                                                                                                 | Inclusion comparisons and string-array `value` of country codes.                                                                                                                                                                                                                                                                                                                       |
| `location` / `city`                                                                                                                                                    | String comparisons and string `value`.                                                                                                                                                                                                                                                                                                                                                 |
| `device` / `os`                                                                                                                                                        | Inclusion comparisons and string-array `value`. Catalog names are `iOS`, `Android`, `Windows`, `MacOS`, and `Linux`.                                                                                                                                                                                                                                                                   |
| `device` / `browser`                                                                                                                                                   | Inclusion comparisons and string-array `value`. Catalog names are `Chrome`, `Firefox`, `Safari`, `Edge`, and `Opera`.                                                                                                                                                                                                                                                                  |
| `date` / `date`                                                                                                                                                        | `between`, `equals`, `before`, or `after`; string date `value` in `YYYY-MM-DD`. `between` also needs string `dateEnd`.                                                                                                                                                                                                                                                                 |
| `date` / `weekday`, `month`                                                                                                                                            | Inclusion comparisons and string-array `value`, using English day or month names.                                                                                                                                                                                                                                                                                                      |
| `jsdata` / `windowVariable`, `cookie`, `localStorage`                                                                                                                  | String comparisons, required string `variable`, and string `value`. `variable` is the window path, cookie name, or storage key.                                                                                                                                                                                                                                                        |
| `scores` / `score`                                                                                                                                                     | Mathematical comparisons, required string `score`, and numeric `value`.                                                                                                                                                                                                                                                                                                                |
| `scores` / `variable`                                                                                                                                                  | Mathematical comparisons, required string `variable`, and string `value` in the catalog.                                                                                                                                                                                                                                                                                               |
| `scores` / `inputQuestion`                                                                                                                                             | Mathematical comparisons, required string `inputQuestion`, and string `value` in the catalog.                                                                                                                                                                                                                                                                                          |
| `rightmessage` / `widget`                                                                                                                                              | Inclusion comparisons and string-array `value` of widget IDs.                                                                                                                                                                                                                                                                                                                          |
| `rightmessage` / `question`                                                                                                                                            | Inclusion comparisons and string-array `questionId` of `raq_` or `dim_` IDs. Optional `scope: "pageview"`.                                                                                                                                                                                                                                                                             |
| `wordpress` / `current-pageId`, `current-postId`, `current-taxonomy-post_tag`, `current-taxonomy-category`, `favorite-taxonomy-post_tag`, `favorite-taxonomy-category` | Inclusion comparisons and string-array `value` of the corresponding WordPress IDs.                                                                                                                                                                                                                                                                                                     |

For current-page `matches pattern`, one leading or trailing slash is ignored and `*` is a wildcard. `/` means the homepage, `/blog` means that exact path, and `/blog/*` means paths beneath it. UTM and query values use readable strings; callers do not need to pre-encode spaces.

### Project-specific sources

For `segments`, `$type` is an existing dimension ID. `segmentId` is an array of segment IDs. Inclusion operators apply. The catalog supplies the real IDs and names through `available_segments`.

The provider source uses the active provider's name, not a generic `esp` string. Available types depend on provider capabilities:

| Provider type                 | Fields and operators                                                                                                        |
| ----------------------------- | --------------------------------------------------------------------------------------------------------------------------- |
| `isAnonymous`, `isSubscriber` | No fields or operators.                                                                                                     |
| `tags`                        | Inclusion operators and `tagIds` string array.                                                                              |
| `customField`                 | Required `customFieldId` string, string operators, optional `value` for presence checks and a string value for comparisons. |
| `lists`                       | Inclusion operators and `listIds` string array. Only exposed if the provider can query lists.                               |
| `eventHistory`                | Required string `eventName`; `has_fired`, `has_not_fired`, `gte`, `lt`, or `equals`. Numeric `count` for count comparisons. |
| `purchaseHistory`             | Inclusion operators. String-array `productIds` for include and exclude comparisons.                                         |
| `totalRevenue`                | Mathematical operators and required numeric `value`. Exposed only when supported.                                           |

Without a connected integration, `espplaceholder` exposes only `isAnonymous` and `isSubscriber`. It does not supply provider fields or tags. Connected profile conditions depend on visitor identification; catalog discovery does not identify anyone.

### Previous input answers

The `answers` source lists only existing input questions. Every input type accepts `has answered` and `has not answered`. Additional operators depend on the question's `inputType`:

| Input type                | Additional operators                                                                                                    |
| ------------------------- | ----------------------------------------------------------------------------------------------------------------------- |
| `number`, `rating`, `nps` | `equals`, `does not equal`, `greater than`, `greater than or equal to`, `less than`, `less than or equal to`, `between` |
| `date`                    | `before`, `after`, `on`, `between`, `in the past`, `in the future`, `within the next days`, `within the last days`      |
| `country`                 | `is`, `is not`, `is any of`                                                                                             |
| `phone`                   | `country is`, `country is not`, `country is any of`                                                                     |
| `email`                   | `domain is`, `domain is not`, `domain is any of`, `domain ends with`, `is a business email`, `is a personal email`      |
| `address`                 | `country is`, `country is not`, `country is any of`, `region equals`, `city equals`, `postal code starts with`          |
| `name`                    | `first name equals`, `first name contains`, `has last name`, `has no last name`                                         |
| `url`                     | `equals`, `contains`, `starts with`, `is empty`, `is not empty`, `domain is`, `domain ends with`                        |
| `text`, `textarea`        | `equals`, `contains`, `starts with`, `is empty`, `is not empty`                                                         |

Presence, empty-value, business/personal-email, last-name-presence, and past/future operators reject a supplied `value`. Numeric comparisons require finite JSON numbers. Country comparisons require uppercase two-letter codes. Dates require real `YYYY-MM-DD` calendar dates. Domain targets must be hostnames of at most 253 characters, not URLs or email addresses. Name and address text targets cannot be blank.

Any-of operators need a nonempty array. `between` needs exactly two values in ascending order and is inclusive. Relative-day comparisons need a nonnegative integer no greater than `9007199254740991`. They include today and the endpoint in the visitor's local calendar. `in the past` and `in the future` exclude today.

Missing answers or missing answer parts fail ordinary comparisons. Only `has not answered` matches a missing answer. `is empty` can match an explicitly stored empty string.

## `validate-condition`

Checks one LogicDefinition against the current project's known sources, dimensions, and input questions.

| Argument                       | Required | Type and default                                                                                 |
| ------------------------------ | -------- | ------------------------------------------------------------------------------------------------ |
| `project_id`                   | No       | String. Shared project selection.                                                                |
| `condition`                    | Yes      | Nonempty object containing `and`, `or`, or `not` logic.                                          |
| `allow_legacy_pageview_values` | No       | Boolean, default `false`. Only literal `true` relaxes pathname checks for existing stored rules. |

Returns exactly `{"valid":true}` when no issues are found, or `{"valid":false,"errors":["..."]}`. Errors identify paths such as `and[0]` or `or[1].and[0]`.

Checks include group structure, missing `$source`, unknown source/type, unknown segment dimension, invalid supplied operators, and selected required fields. It checks query names, browser-data variable names, referrer domains, score identifiers, provider custom-field identifiers, tag/list arrays, event names, revenue values, and `dateEnd` for a date range. Input-answer rules receive the stricter type-specific checks above, including rejection of extra keys.

New `pageviews/path` and `pageviews/landingpage` values must begin with `/` and contain no query or hash. The legacy flag skips that pathname restriction for an existing stored rule. It does not make `matches pattern` valid for historical occurrences; that operator still requires `occurrence: "last"`.

This is a rule-shape check, not a full runtime simulation. In particular, it does not validate every catalog requirement, resolve every segment ID or provider value, fetch a contact, or guarantee that a provider implements a type merely because validation passed. A bare leaf is not the accepted top-level validation format, even though widget visibility can store one. Wrapping the leaf in `and` validates its fields without saving it.

An empty object returns `valid: false` with `Condition must be a non-empty object with "and" or "or" keys.` Shared authorization failures remain MCP errors. No rule is normalized or saved by this tool.

Illustrative request and result:

```json
{"name":"validate-condition","arguments":{"condition":{"and":[{"$source":"query","$type":"custom","query":"plan","operator":"equals","value":"team","occurrence":"last"}]}}}
```

```json
{"valid":true}
```

Illustrative invalid request and result:

```json
{"name":"validate-condition","arguments":{"condition":{"and":[{"$source":"pageviews","$type":"path","operator":"equals","value":"https://example.com/pricing","occurrence":"last"}]}}}
```

```json
{"valid":false,"errors":["and[0]: pageviews/path \"value\" must be a pathname beginning with \"/\" and must not include a domain, query string, or hash (for example, \"/pricing\")."]}
```
