# MCP tools for questions and answer options

MCP question and option schemas, input settings, returned config fields, replacement behavior, and deletion safeguards.

Available on the Grow, Scale, and Pro plans.

Use these MCP tools to create reusable questions and edit their answer options. Choice questions map answers to segments. Input questions collect typed values without a segment group. Adding a library question does not automatically insert it into a flow.

## MCP question access and draft changes

Every tool accepts an optional string `project_id` and follows the [shared MCP authorization and project-selection rules](https://rightmessage.com/help/mcp-authorization-reference). There is no additional question-specific plan requirement.

Reads prefer the draft over published configuration. Mutations save a snapshot of the preceding configuration, then validate and save a draft. They do not publish, collect an answer, or write to an email provider. Configuring identification or sync is not the same as performing it. [Publishing](https://rightmessage.com/help/mcp-tools-publishing) is separate.

An active A/B test locks its question's wording, options, display, behavior, and linked segment values or non-sync Auto-Segment rules. Updates and deletion that change those fields fail until the test ends. Sync mappings, internal names, and flow membership remain editable. This safeguard also applies when you edit an individual option.

Results shown here are JSON payloads within MCP responses. Shared errors cover project selection and access. Mutation exceptions become `Validation error: ...` for configuration-schema failures or `Operation failed: ...` otherwise. Examples are illustrative and were not executed. IDs belong to fictional WorkForge resources.

## Question arguments and returned names

The following fields are shared by `create-question` and `update-question`. A field is optional unless the tool section says otherwise.

| Input               | Type and behavior                                                                                                                          | Returned config key         |
| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------- |
| `text`              | String. Visitor-facing question text.                                                                                                      | `text`                      |
| `name`              | String. Internal name. Choice-question names are associated with the segment group in the UI.                                              | `name`                      |
| `description`       | String or null. Visitor-facing rich text.                                                                                                  | `description`               |
| `sync_to`           | `customField`, `variable`, or null. Input-answer destination.                                                                              | `syncTo`                    |
| `sync_to_field`     | String or null. Field or variable identifier.                                                                                              | `syncToField`               |
| `display_options`   | Object. Display settings, including boolean `hideLabels` for image answers.                                                                | `displayOptions`            |
| `segment_group_id`  | String `dim_` ID or null. Existing group for choices; no group for input questions.                                                        | `dimensionId`               |
| `display_type`      | `buttons`, `image`, `list`, `radio`, or `input`. Creation defaults to `buttons`.                                                           | `displayType`               |
| `input_type`        | `text`, `textarea`, `number`, `email`, `phone`, `name`, `address`, `country`, `url`, `date`, `rating`, `nps`, or null. Choices store null. | `inputType`                 |
| `randomize_options` | Boolean. Creation defaults to `false`.                                                                                                     | `isRandomizingOptionsOrder` |
| `input_settings`    | Object described below. Inner keys stay camelCase.                                                                                         | `inputSettings`             |
| `options`           | Array described below. Creation defaults to `[]`. Updates replace the array.                                                               | `options`                   |
| `other_option`      | Write-in settings described below.                                                                                                         | `otherOptions`              |

`list` means a dropdown. `radio` uses single-select radio controls or multi-select checkboxes, with an explicit Next button. In a bar widget, radio choices use a dropdown. Input questions use `display_type: "input"`, an `input_type`, no dimension, and empty `options`.

A stored question includes its `raq_` ID, text, dimension, display/input types, input settings, randomization flag, `otherOptions`, `options`, and `displayOptions`. Validation can add defaulted properties such as `isQuestion`. Reads add display annotations separately rather than replacing raw text.

### `input_settings`

These are config keys, not snake\_case aliases. The MCP schema accepts the object, and configuration validation checks nested properties. Optional keys have no tool-supplied value unless a default is stated here.

| Key                                          | Type and meaning                                                                                                                                                                                                                                              |
| -------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `placeholder`                                | String. Single-field placeholder, or the country question's empty option.                                                                                                                                                                                     |
| `validation`                                 | String retained by the configuration schema.                                                                                                                                                                                                                  |
| `required`                                   | Boolean. Set explicitly when optional answers are intended; current input behavior treats absence as required. Migrated questions can retain an explicit historical false.                                                                                    |
| `nextButtonLabel`, `skipButtonLabel`         | String or null. Null or absence inherits widget labels. Also supported for choice questions.                                                                                                                                                                  |
| `numberType`                                 | `plain`, `currency`, or `percentage`.                                                                                                                                                                                                                         |
| `currency`                                   | String, an ISO 4217 currency code.                                                                                                                                                                                                                            |
| `prefix`, `suffix`                           | Strings for number presentation.                                                                                                                                                                                                                              |
| `min`, `max`, `step`                         | Number or null. Slider bounds default to 0 and 100 when absent.                                                                                                                                                                                               |
| `display`                                    | `field` or `slider` for number input.                                                                                                                                                                                                                         |
| `defaultValue`                               | Number or null. Slider starting value; absence uses the midpoint.                                                                                                                                                                                             |
| `minLabel`, `maxLabel`                       | Strings.                                                                                                                                                                                                                                                      |
| `ratingMax`                                  | Integer from 3 through 10.                                                                                                                                                                                                                                    |
| `nameFormat`                                 | `first_last` or `full`.                                                                                                                                                                                                                                       |
| `defaultCountry`                             | String for the initial country setting.                                                                                                                                                                                                                       |
| `partLabels`                                 | Object of optional string keys `first`, `last`, `street`, `city`, `region`, `postcode`, `country`. No additional keys. Missing labels use English defaults. Full-name input has no label.                                                                     |
| `partPlaceholders`                           | Same keys as `partLabels`, plus `full`. String values. No additional keys. The address-country placeholder is its empty option.                                                                                                                               |
| `pinnedCountries`                            | Array of two-letter ISO country codes, in display order.                                                                                                                                                                                                      |
| `excludedCountries`                          | Array of two-letter ISO country codes to omit.                                                                                                                                                                                                                |
| `detectCountry`                              | Boolean for country input. Absence means true.                                                                                                                                                                                                                |
| `dateRange`                                  | `any`, `past`, or `future`. Absence means `any`. Past and future constraints include today.                                                                                                                                                                   |
| `dateRangeDays`                              | Integer from 1 through 36500. Bounds past or future choices by that many days. Absence means no day limit.                                                                                                                                                    |
| `mobileOnly`, `suggestTypoFixes`, `identify` | Booleans for the relevant phone or email control. Email can identify a visitor. Phone does not identify one.                                                                                                                                                  |
| `contactAction`                              | Object or null. If present, requires `type` and `settings`. Type is `contact`, `form`, `list`, or `tag`. Settings require string `partnerName`, with optional string arrays `formIds`, `listIds`, and `tagIds`. Additional keys are rejected in both objects. |
| `consent`                                    | Object with optional `disclosure` and `checkbox`. Disclosure requires boolean `enabled` and string `text`. Checkbox requires boolean `enabled` and string `label`. These objects reject additional keys.                                                      |
| `syncFieldMap`                               | Object mapping name parts `first`, `last`, `full`, or address parts `street`, `city`, `region`, `postcode`, `country` to string field IDs.                                                                                                                    |

Rating and NPS answers save numbers and advance on selection. A percentage slider displays `%`. Configuring `contactAction` does not connect the provider or grant its plan entitlement.

### `options` and `other_option`

A whole-question `options` entry supports `id`, `label`, `segment_id`, `image_url`, `conditions`, and `scores`. `label` is a string. Choice options need a valid mapped `segment_id`; although the tool description calls it optional, the stored option schema requires `segmentId`. Omitted `id` generates an `rqo_` ID. `image_url` becomes `imageUrl`.

`conditions` is a LogicDefinition object, defaulting to an empty object for whole-question writes. Its schema is covered by [condition tools](https://rightmessage.com/help/mcp-tools-conditions). `scores` is an array of `{score, amount}` entries. `score` is a nonempty string and `amount` is numeric. Whole-question writes discard malformed score entries and convert numeric amounts to JSON numbers. The individual option tools instead pass the supplied scores through to configuration validation.

`other_option` supports boolean `enabled`, string `label`, `input_type` of `text` or `textarea`, string `prompt`, string `placeholder`, and string or null `sync_to_custom_field`. Returned keys are `enabled`, `otherLabel`, `inputType`, `inputPrompt`, `inputPlaceholder`, and `syncToCustomField`. Disabled is the creation default. Config repair fills missing label/type/prompt/placeholder with `Other`, `textarea`, `Please share more`, and `""`, including when disabled. The current schema repair removes the obsolete `nextPrompt` field; follow-up Next text comes from `input_settings.nextButtonLabel`.

## `create-question`

Creates a question in the draft library. Required argument `text` is a nonempty string. All other arguments are optional fields from the shared tables, plus `project_id`.

Returns the complete new stored question. It does not create a dimension for a choice question. [Segment tools](https://rightmessage.com/help/mcp-tools-segments) can create the group first or create the group and linked question together.

Missing text returns `text is required.` Invalid input types, option mappings, nested settings, or previous-answer references can fail configuration validation. Creation does not prove that the question has a usable flow placement.

Illustrative request and result excerpt:

```json
{"name":"create-question","arguments":{"text":"How many people use WorkForge?","name":"Team size","display_type":"input","input_type":"number","input_settings":{"numberType":"plain","min":1,"required":true},"options":[]}}
```

```json
{"id":"raq_workdemo","text":"How many people use WorkForge?","name":"Team size","dimensionId":null,"displayType":"input","inputType":"number","inputSettings":{"numberType":"plain","min":1,"required":true},"isRandomizingOptionsOrder":false,"options":[],"displayOptions":{}}
```

The full result also includes `otherOptions` and schema-defaulted properties.

## `list-questions`

Returns all library questions with their complete raw config fields and display summaries. Its only argument is optional string `project_id`. There is no pagination.

Each returned object adds `textPreview`, `dimensionId`, `dimensionName`, `displayType`, `optionCount`, and `hasOther`. When available, `syncResolved` describes the linked dimension's sync field or the input question's field. `otherSyncFieldResolved` describes an enabled write-in field mapping. These are annotations, not mutation arguments.

No configuration or contact changes occur. Shared access errors apply. A project without questions returns `[]`.

Illustrative request and empty result:

```json
{"name":"list-questions","arguments":{}}
```

```json
[]
```

## `get-question`

Returns one complete question, with unmodified editable text, input settings, labels, and sync mappings. Arguments are optional string `project_id` and required string `question_id`.

Additional fields can include `textPreview`, `dimensionName`, per-option `segmentName` and `labelPreview`, `dimensionSyncResolved`, `syncToFieldResolved`, and `otherOptions.syncToCustomFieldResolved`. Resolved-name annotations such as `id_name` can also appear. These do not replace the raw fields.

Missing ID returns `question_id is required.` A missing question returns `Question not found: ID`. This read has no mutation side effect.

Illustrative request and result excerpt:

```json
{"name":"get-question","arguments":{"question_id":"raq_workdemo"}}
```

```json
{"id":"raq_workdemo","text":"How many people use WorkForge?","textPreview":"How many people use WorkForge?","displayType":"input","inputType":"number","inputSettings":{"numberType":"plain","min":1,"required":true},"options":[]}
```

## `update-question`

Updates a draft question. Required string `question_id` selects it. Optional arguments are `project_id` and the shared question fields. At least one update field must be supplied.

Returns the complete updated stored question. Omitted fields retain their values, but `input_settings`, `display_options`, `other_option`, and `options` replace their respective objects or arrays. They are not deep-merged. Existing option IDs survive only when included in the replacement array. Switching to a choice display type forces `inputType` to null.

Nullable `description`, `sync_to`, `sync_to_field`, `segment_group_id`, and `input_type` can be explicitly cleared. The handler ignores a null `input_settings` or `other_option`; an empty object supplies a replacement. An empty `options` array removes all options. Renaming a question does not rename its dimension or segment values.

Missing ID returns `question_id is required.` No update fields returns `No fields provided to update.` A missing question becomes `Operation failed: Question not found: ID`. Changing a referenced input type can fail previous-answer-condition validation if an existing operator no longer applies.

Illustrative request and result excerpt:

```json
{"name":"update-question","arguments":{"question_id":"raq_workdemo","input_settings":{"numberType":"plain","min":1,"required":false,"nextButtonLabel":"Continue"}}}
```

```json
{"id":"raq_workdemo","inputType":"number","inputSettings":{"numberType":"plain","min":1,"required":false,"nextButtonLabel":"Continue"}}
```

## `delete-question`

Removes the question and its options from the draft. Arguments are optional string `project_id` and required string `question_id`.

The underlying segment group is not deleted. Linked `sg` form fields referring to the question ID or its dimension ID are removed from forms. Previous-answer conditions block deletion and return a message listing the referencing resources. This tool does not promise a complete cascade through every flow reference.

Returns `{"deleted":true,"question_id":"ID"}`. Missing ID returns `question_id is required.` A missing question returns `Operation failed: Question not found: ID`. Other mutation-validation errors apply.

Illustrative request and result for an unreferenced question:

```json
{"name":"delete-question","arguments":{"question_id":"raq_workdemo"}}
```

```json
{"deleted":true,"question_id":"raq_workdemo"}
```

## `create-question-option`

Appends an answer option to a question. Required string arguments are `question_id` and `label`. Optional arguments are `project_id`, string `segment_id`, object `conditions`, and array `scores` of `{score: string, amount: number}`.

Although `segment_id` is optional in the advertised tool schema, a saved choice option requires its mapping. The individual tool initializes omitted `conditions` and `scores` as empty arrays before config validation. It returns the created option object with `id`, `label`, `conditions`, `scores`, and `segmentId` when provided. This returned object is the tool's constructed option, not an enriched question read.

Missing required identifiers or label return specific required-field errors. An unknown question returns `Operation failed: Question not found: ID`. Invalid option fields or conditions can fail configuration validation. No segment is created automatically.

Illustrative request and result:

```json
{"name":"create-question-option","arguments":{"question_id":"raq_rolequiz","label":"Operations","segment_id":"seg_opsdemo","conditions":{"and":[]},"scores":[{"score":"operations","amount":1}]}}
```

```json
{"id":"rqo_opsdemo","label":"Operations","conditions":{"and":[]},"scores":[{"score":"operations","amount":1}],"segmentId":"seg_opsdemo"}
```

## `update-question-option`

Finds an option across the project's questions and updates its supplied properties. Required string `option_id` identifies it; there is no `question_id` argument. Optional arguments are `project_id`, string `label`, string `segment_id`, object `conditions`, and array `scores` with the same entry schema as creation.

At least one nonempty label, nonempty segment ID, non-null conditions object, or non-null scores array is required. Empty strings and null do not clear the label or segment mapping. `conditions: {}` or `{"and":[]}` removes visibility constraints. `scores: []` clears scores. Supplied conditions and scores replace their complete values.

Returns the updated option object, not the parent question. Missing ID returns `option_id is required.` An empty update returns `At least one of label, segment_id, conditions, or scores must be provided.` An unknown option returns `Operation failed: Question option not found: ID`.

Illustrative request and result:

```json
{"name":"update-question-option","arguments":{"option_id":"rqo_opsdemo","label":"Operations team","scores":[]}}
```

```json
{"id":"rqo_opsdemo","label":"Operations team","conditions":{"and":[]},"scores":[],"segmentId":"seg_opsdemo"}
```

## `delete-question-option`

Removes one option from its parent question and reindexes the remaining options. Arguments are optional string `project_id` and required string `option_id`. There is no parent-question argument.

Returns `{"deleted":true,"option_id":"ID"}`. Missing ID returns `option_id is required.` An unknown option returns `Operation failed: Question option not found: ID`. Configuration-validation errors can also prevent saving.

The option's own mapping, conditions, and scores disappear with it. The underlying segment is not deleted. The change remains draft-only.

Illustrative request and result:

```json
{"name":"delete-question-option","arguments":{"option_id":"rqo_opsdemo"}}
```

```json
{"deleted":true,"option_id":"rqo_opsdemo"}
```
