# MCP tools for personalized phrases

Read, create, update, and delete segment-based phrases through MCP, including map merging and draft behavior.

Available on the Grow, Scale, and Pro plans.

Phrases supply segment-specific text in supported RightMessage-rendered content, including widget questions, forms, offers, and campaign content replacements. A reference such as `{{ phrases.phr_example }}` uses the plural `phrases`. Adding that text to arbitrary website HTML does not make RightMessage scan and render the page as a Liquid template.

## MCP phrase access and fallbacks

Every operation accepts an optional string `project_id` and follows the [shared MCP authorization and project-selection rules](https://rightmessage.com/help/mcp-authorization-reference). An invalid ID, missing project, inaccessible project, or disabled MCP access returns an MCP error.

Reads use the draft configuration when available, otherwise the published configuration. Create, update, and delete save a draft, record a pre-change snapshot when the configuration has changed, and notify dashboard editors. They do not publish. [Publication tools](https://rightmessage.com/help/mcp-tools-publishing) control the live-site boundary.

At runtime, the phrase uses a mapped segment from its linked group, or its fallback when no mapped segment matches. A null or empty-string mapped value also falls back to `fallbackText`; it is not an intentional blank replacement. For a multi-select group, do not assume the map's property order establishes priority.

The examples below are illustrative and were not executed. Requests show the `name` and `arguments` passed to MCP `tools/call`. Responses show the decoded JSON payload rather than the MCP content envelope.

## `list-phrases`

Returns every phrase in the current configuration. There is no pagination or filtering.

| Argument     | Type   | Required | Meaning            |
| ------------ | ------ | -------- | ------------------ |
| `project_id` | string | No       | Public project ID. |

The response is an array. Each phrase has `id`, `fallbackText`, nullable `segmentGroupId`, and `map`, an object keyed by segment ID. Read responses can add `_name` companion fields for recognized resource IDs. No phrases returns `[]`.

```json
{"name":"list-phrases","arguments":{"project_id":"123456789"}}
```

```json
[{"id":"phr_example","fallbackText":"Welcome to WorkForge","segmentGroupId":null,"map":{}}]
```

This operation does not change the configuration.

## `get-phrase`

Returns one phrase, with the same fields and name enrichment as `list-phrases`.

| Argument     | Type   | Required | Meaning                                             |
| ------------ | ------ | -------- | --------------------------------------------------- |
| `project_id` | string | No       | Public project ID.                                  |
| `phrase_id`  | string | Yes      | Phrase ID returned by a read or creation operation. |

```json
{"name":"get-phrase","arguments":{"project_id":"123456789","phrase_id":"phr_example"}}
```

```json
{"id":"phr_example","fallbackText":"Welcome to WorkForge","segmentGroupId":null,"map":{}}
```

Missing input returns `phrase_id is required.` An unknown phrase returns `Phrase not found: phr_example`. This is a read, not a publication check.

## `create-phrase`

Adds a phrase to the draft.

| Argument           | Type   | Required | Meaning                                                                    |
| ------------------ | ------ | -------- | -------------------------------------------------------------------------- |
| `project_id`       | string | No       | Public project ID.                                                         |
| `fallback_text`    | string | Yes      | Text used when no mapped segment matches.                                  |
| `segment_group_id` | string | No       | Dimension to personalize by. Defaults to `null`.                           |
| `map`              | object | No       | Segment-ID keys with replacement text values. Defaults to an empty object. |

The tool accepts an open `map` object. Use segment-ID keys and string values, such as `{"seg_example":"Text for this segment"}`, not an array of conditions. Saving does not fully validate the map or prove that the supplied dimension and segment IDs exist. [Read the segment group](https://rightmessage.com/help/mcp-tools-segments) before saving.

```json
{"name":"create-phrase","arguments":{"project_id":"123456789","fallback_text":"Welcome to WorkForge","segment_group_id":"dim_example","map":{"seg_agency":"WorkForge for your agency"}}}
```

```json
{"id":"phr_example","fallbackText":"Welcome to WorkForge","segmentGroupId":"dim_example","map":{"seg_agency":"WorkForge for your agency"}}
```

The response uses stored camelCase keys, not the request's snake\_case keys. It does not include the read tools' name enrichment. Validation failures return `Validation error: ...`; other failures return `Operation failed: ...`.

## `update-phrase`

Changes supplied phrase fields. Omitted fields stay unchanged. Map entries merge by segment ID rather than replacing the complete map.

| Argument           | Type   | Required | Meaning                           |
| ------------------ | ------ | -------- | --------------------------------- |
| `project_id`       | string | No       | Public project ID.                |
| `phrase_id`        | string | Yes      | Existing phrase ID.               |
| `fallback_text`    | string | No       | New fallback text.                |
| `segment_group_id` | string | No       | New dimension ID.                 |
| `map`              | object | No       | Segment keys to add or overwrite. |

At least one editable field must be supplied. Top-level `null` values are treated as omitted, so `segment_group_id: null` does not clear the dimension.

The tool description advertises `null` for removing a map entry. The save path merges that key with a null value rather than deleting the key; the runtime then uses fallback text for that value. An empty `map: {}` does not clear existing entries either. Do not assume either request removes keys from a subsequent read.

```json
{"name":"update-phrase","arguments":{"project_id":"123456789","phrase_id":"phr_example","map":{"seg_agency":"Plan your agency work with WorkForge"}}}
```

```json
{"id":"phr_example","fallbackText":"Welcome to WorkForge","segmentGroupId":"dim_example","map":{"seg_agency":"Plan your agency work with WorkForge"}}
```

Updating can overwrite existing text. It is a destructive, idempotent draft operation. Missing input returns `phrase_id is required.` Empty updates return `No fields provided to update.` A missing phrase returns `Operation failed: Phrase not found: ...`.

## `delete-phrase`

Removes one phrase from the draft. It does not rewrite text fields that reference the phrase's ID.

| Argument     | Type   | Required | Meaning            |
| ------------ | ------ | -------- | ------------------ |
| `project_id` | string | No       | Public project ID. |
| `phrase_id`  | string | Yes      | Phrase to delete.  |

```json
{"name":"delete-phrase","arguments":{"project_id":"123456789","phrase_id":"phr_example"}}
```

```json
{"deleted":true,"phrase_id":"phr_example"}
```

This is destructive. References and the intended replacement need review before publication. Missing input returns `phrase_id is required.` An unknown phrase returns `Operation failed: Phrase not found: ...`. Configuration validation can also reject the save. The published site remains unchanged until publication.
