Skip to help content
RightMessage
MCP referenceReference

MCP tools for forms and form fields

MCP form and field arguments, field kinds, nested settings, response objects, index and reorder behavior, errors, and draft-only side effects.

Available on the Grow, Scale, and Pro plans.

Updated

View as Markdown

Use these MCP tools to create forms and manage their ordered fields. Forms and offers share ofr_ IDs. A stored item whose triggeredAction.type is link is an offer. Every other action type is a form. Offer tools cover link calls to action and performance reports for both forms and offers.

MCP form access and draft changes

Every tool accepts an optional string project_id and follows the shared MCP authorization and project-selection rules. There is no additional form-specific plan requirement for these calls. Provider actions still require a connected, entitled provider when visitors use the published form.

Reads use the draft if present, otherwise the published configuration. Mutations save a draft and a snapshot of the preceding configuration. No tool here publishes, creates a subscriber, applies a provider tag, or submits a form. Visitor-side actions happen after publication and visitor interaction. See publication tools to make the draft live.

Success examples show the JSON payload inside an MCP result. Errors are MCP error results, not REST status contracts. Shared errors include missing or invalid project selection, inaccessible projects, and unavailable MCP access. Mutations return Validation error: ... for configuration-schema failures and Operation failed: ... for other exceptions.

Examples use fictional WorkForge resources. They are illustrative and were not executed. Result excerpts are labeled where fields are omitted.

Form data and nested settings

Create and update inputs use is_enabled, parts.button_text, and parts.image_url. Results use isEnabled, parts.buttonText, and parts.imageUrl.

parts supports optional string properties title, description, button_text, and image_url. Text supports Liquid phrase references such as {{ phrases.phr_workdemo }}. New forms default to title Untitled Form, button text Submit, and null description and image. The internal name does not automatically become the visible title.

triggered_action supports optional type and settings. Its type is one of tag, list, automation, event, form, or contact. Creation defaults to form. The registered schema also accepts deprecated action, with type and settings; triggered_action takes precedence when both are supplied.

settings propertyInput typeReturned storage key and behavior
platformStringpartnerName, the connected provider name.
tag_idsArray of strings or numberstagIds. Used for tag and form. For a tag action, repair also splits comma/newline-separated entries and removes duplicates.
list_idsArray of strings or numberslistIds. Used for list.
automation_idsArray of strings or numbersautomationIds. Used for automation.
event_idsArray of strings or numberseventIds, the event names to fire. Used for event.
form_idsArray of strings or numbersformIds. Used for form; omission becomes [].
list_id, automation_idStringSingle-ID form of list_ids and automation_ids, stored as a one-item listIds or automationIds.
event_nameNonempty stringSingle-event form of event_ids, trimmed and stored as a one-item eventIds.
show_labelsBooleanformSettings.showLabels. New form actions default to true.
fieldsArray of field objectsReplaces the input field list. Save-time repair adds an email field and submit field whenever either is missing, including for [].
thanks_messageStringStored as thanksForConvertingText. When no nonempty redirect tree exists, repair creates a message node using this text, or Thank you! when blank/omitted.
redirect_urlStringBuilds redirectFunnel, a root with one redirect node, generated UUIDs, the supplied url, and open: false.

Every ID list is stored as trimmed strings, with integers turned into strings and blanks dropped. A list must be an array of strings or numbers, or the call fails with Operation failed: list_ids must be a list of IDs. (named for the key you sent). Send either the list or its single-ID form, not both: list_ids with list_id fails with Operation failed: Use list_ids or list_id, not both. On update-form, an ID list you send replaces the stored one.

Forms saved through MCP before October 27, 2026 stored list and automation IDs under singular listId and automationId keys, which visitors' submissions never read. The next save of the project folds them into listIds and automationIds. A form that is already live keeps its published behavior until you publish again.

Illustrative request that adds subscribers to a Mailchimp audience:

JSON
{"name":"create-form","arguments":{"name":"WorkForge newsletter","triggered_action":{"type":"list","settings":{"platform":"mailchimp","list_ids":["a1b2c3d4e5"]}}}}

A form result contains id, name, isEnabled, parts, and triggeredAction: {type, settings}. It can also contain existing configuration properties retained by an update. Stored fields use these names:

Field propertyType and meaning
displayTypeString. text, email, textarea, select, hidden, submit, or sg.
label, placeholderOptional strings.
widthNumber. Column span in the visitor form's six-column grid. 3 is half width and 6 is full width. Save-time repair caps widths at 6.
espFieldOptional string containing the provider field mapping.
requiredOptional boolean. Linked question fields explicitly default to false; ordinary fields can omit this stored key.
optionsFor select input, an array of objects with string label and value. Seeded email and submit fields instead contain an empty object.
valueOptional string, principally for hidden fields.
segmentGroupIdFor sg, an existing question raq_ ID or its dim_ ID.
questionDisplayOptional dropdown or radio, with dropdown as the linked-choice display default.

The field subresource tools translate display_type, esp_field, question_id, and question_display to those stored names. Within a whole form's settings.fields, only display_type, question_id, and question_display receive that translation. Use espField, not esp_field, in that nested array.

The field tools describe a 12-column grid and create-form-field initially defaults to 12, but save-time repair caps the stored width at 6. Pass width: 6 explicitly for a full-width field. Repair also fills missing options with {}, placeholder with "", and missing labels from the placeholder. The field mutation response can describe the pre-repair field and counts; use get-form to inspect the saved result.

create-form

Creates one draft form. Required argument name is a string. Optional arguments are project_id, boolean is_enabled defaulting to true, the parts, triggered_action, and deprecated action objects above, and fields.

Returns the complete new form. It does not attach the form to a flow or widget. If fields are omitted for a non-link action, the service seeds an email field and a submit field, each width 6. Repair also restores either missing field in a supplied list. Blank event_name fails with Operation failed: event_name must be a non-empty string. Invalid action or configuration values can return a validation error. Like the dashboard, MCP saves a form whose action has no destination IDs, such as the default form type with empty form_ids; its signups don't reach your email platform until you add one.

Ask for fields by kind

fields is an array of {kind, label?, required?} objects. The form asks for exactly those fields, in order, followed by the submit button. It replaces triggered_action.settings.fields.

kindField it adds
emailThe native email field that creates the contact. Always present and required; if you leave it out, it goes first.
nameOne full-name field.
first_and_last_nameA name field with first and last name.
first_name, last_name, companyA short text field with that default label.
phoneA phone number field.
websiteA URL field.
short_text, long_textA free-text or multi-line field. Needs a label, the question it asks.

Every kind except email is stored as an sg field linked to a library input question, so the answer is validated and kept in Responses. A library question of that kind with the same wording is reused when the form doesn't already link it; otherwise a new one is created in the same save. label defaults to the kind's name (at most 80 characters), and required defaults to false. A short_text labeled as a first name, last name, or company becomes that kind.

A form asks for at most 8 fields, email included. Errors include an unknown kind, a missing label on a free-text kind, the same kind twice (The form asks for phone more than once.), more than one way of asking for the name (Ask for the name once: name, first_and_last_name, or first_name and last_name.), and two text fields with the same label.

JSON
{"name":"create-form","arguments":{"name":"WorkForge consultation","fields":[{"kind":"name","required":true},{"kind":"email"},{"kind":"long_text","label":"What would you like help with?"}]}}

Illustrative request:

JSON
{"name":"create-form","arguments":{"name":"WorkForge guide","parts":{"title":"Get the WorkForge guide","button_text":"Send the guide"}}}

Illustrative result:

JSON
{"id":"ofr_workdemo","name":"WorkForge guide","isEnabled":true,"parts":{"title":"Get the WorkForge guide","description":null,"buttonText":"Send the guide","imageUrl":null},"triggeredAction":{"type":"form","settings":{"formSettings":{"showLabels":true},"formIds":[],"fields":[{"label":"Email address","placeholder":"Your email address","displayType":"email","width":6,"options":{}},{"displayType":"submit","width":6,"options":{},"placeholder":"","label":""}],"redirectFunnel":{"type":"root","child":[{"type":"message","content":"Thank you!"}]}}}}

This is a stored form definition, not evidence of a configured provider destination.

list-forms

Lists the complete stored form objects, not compact summaries. The only argument is optional string project_id. It returns an array, or [] if no non-link items exist. No pagination or filtering arguments are registered.

This read has no draft or provider side effect. Shared access errors apply.

Illustrative request and result for an empty project:

JSON
{"name":"list-forms","arguments":{}}
JSON
[]

get-form

Returns one complete form, with resource-name annotations where a stored reference resolves. Arguments are optional string project_id and required string form_id.

Missing form_id returns form_id is required. A missing resource returns Form not found: ID. A link item returns an error directing the caller to get-offer. The read changes nothing.

Illustrative request and result excerpt:

JSON
{"name":"get-form","arguments":{"form_id":"ofr_workdemo"}}
JSON
{"id":"ofr_workdemo","id_name":"WorkForge guide","name":"WorkForge guide","isEnabled":true}

The full result also contains parts and triggeredAction, including all current fields.

update-form

Changes the existing draft item. Required string form_id selects the item. Optional arguments are project_id, name, is_enabled, parts, triggered_action, and deprecated action. At least one non-null update value is required. Top-level nulls do not clear values.

The tool returns the complete updated item. Omitted part properties and omitted action-setting keys stay unchanged. Supplied settings replace their matching keys, so fields replaces the entire field array and show_labels replaces the stored formSettings object. Changing action type does not clear the old settings automatically.

Changing thanks_message alone does not replace an existing nonempty redirectFunnel; repair only uses that message to populate an empty tree. Use redirect_url when the intended post-submit action is a redirect. After changing or removing fields, read the saved form because repair restores a missing email or submit field.

Missing ID returns form_id is required. No changes returns No fields provided to update. An unknown item returns Operation failed: Form not found: ID. This update handler does not enforce the non-link type check used by get-form; use the correct ID rather than relying on the tool name to protect an offer.

Illustrative request and result excerpt:

JSON
{"name":"update-form","arguments":{"form_id":"ofr_workdemo","parts":{"button_text":"Email my guide"}}}
JSON
{"id":"ofr_workdemo","name":"WorkForge guide","isEnabled":true,"parts":{"title":"Get the WorkForge guide","description":null,"buttonText":"Email my guide","imageUrl":null}}

The full result retains triggeredAction. No visitor sees this edit until publication.

duplicate-form

Copies a form into the draft with a new ofr_ ID. Arguments are optional string project_id, required string form_id, and optional string new_name. The name defaults to the original name plus (Copy).

Returns the complete copied form. Existing field definitions and provider destinations are copied. If an older form has no fields property, the copy receives the default email and submit fields. This tool neither duplicates a flow nor connects the copy to one.

Errors cover missing form_id, missing source, and a source with link action type. The latter directs the caller to duplicate-offer.

Illustrative request and result excerpt:

JSON
{"name":"duplicate-form","arguments":{"form_id":"ofr_workdemo","new_name":"WorkForge guide follow-up"}}
JSON
{"id":"ofr_copydemo","name":"WorkForge guide follow-up","isEnabled":true}

The full result includes the copied parts and triggeredAction.

delete-form

Deletes an item from the draft and clears offerId on referencing flow nodes. Arguments are optional string project_id and required string form_id. Returns deleted: true and the requested form_id.

A missing ID returns form_id is required. An unknown item returns Operation failed: Form not found: ID. This tool doesn't reject offer IDs. Supplying an offer ID can therefore delete that offer and clear its flow references.

Illustrative request and result:

JSON
{"name":"delete-form","arguments":{"form_id":"ofr_copydemo"}}
JSON
{"deleted":true,"form_id":"ofr_copydemo"}

This does not delete provider contacts or publish the removal.

create-form-field

Inserts a field just before the submit button, or at field_index. If there is no submit field, the default is the end of the list. Pass either kind or label with display_type.

ArgumentRequiredType and default
project_idNoString. Shared project selection.
form_idYesString. Must identify a non-link item.
field_indexNoNumber. The 0-based index the new field takes, from 0 up to the submit button's index. Defaults to just before the submit button. "Below the email field" is the email field's index plus 1.
kindWithout display_typename, first_and_last_name, first_name, last_name, phone, website, company, short_text, or long_text, as in create-form. Use label and required with it. A form keeps its one email field, so email is refused.
labelWith display_type, or for short_text and long_textString.
display_typeWithout kindString. One of the field types described above.
question_idFor sgString. Existing question or dimension ID.
question_displayNodropdown or radio. Applies only to sg.
widthNoNumber. Defaults to 12.
placeholder, esp_field, valueNoStrings. No stored default.
requiredNoBoolean. Defaults to false behavior; explicitly stored as false for sg when omitted.
optionsNoArray of {label, value} objects for select fields.

Returns form_id, zero-based field_index, the new field in stored naming, and total_fields. A kind call also returns kind. Missing form, link item, and invalid linked-question configuration return errors. question_id and question_display on a non-sg field are rejected. An unknown linked question returns Question not found: ID. Neither kind nor label with display_type returns Pass kind, or label and display_type. A field_index past the submit button returns an out-of-range error naming the allowed range. A kind the form already asks for, or a free-text field with a label it already uses, is refused; change that field with update-form-field instead.

Illustrative request and result for a form with the two default fields:

JSON
{"name":"create-form-field","arguments":{"form_id":"ofr_workdemo","label":"Company","display_type":"text","width":6,"esp_field":"company","required":false}}
JSON
{"form_id":"ofr_workdemo","field_index":1,"field":{"label":"Company","displayType":"text","width":6,"espField":"company","required":false},"total_fields":3}

update-form-field

Merges provided properties into one field. Required arguments are string form_id and numeric field_index. Optional project_id and all field properties from create-form-field are accepted. None of those optional properties receives a creation default during a normal update.

The index is zero-based and converted to an integer. The tool returns form_id, field_index, and the complete updated field. Updating options replaces that value. Omitted and null field properties stay unchanged. Changing display_type away from sg removes old question references unless they were explicitly supplied, in which case validation rejects the incompatible combination.

Errors include missing ID or index, a missing form, a link item, an out-of-range index, invalid question settings, and No field properties provided to update. Index errors distinguish an empty form from a form with a valid index range.

Illustrative request and result:

JSON
{"name":"update-form-field","arguments":{"form_id":"ofr_workdemo","field_index":1,"label":"Work email domain"}}
JSON
{"form_id":"ofr_workdemo","field_index":1,"field":{"label":"Work email domain","displayType":"text","width":6,"espField":"company","required":false,"options":{},"placeholder":""}}

delete-form-field

Removes a field and shifts later indexes down. Required arguments are string form_id and numeric field_index; project_id is optional. There is no stable field ID argument. The index is converted to an integer.

Returns form_id, the removed object as deleted_field, and the pre-repair remaining_fields count. Errors match the form lookup, type, and index errors described above. Save-time repair adds an email or submit field back if the deletion removed the last field of that type; the response count can therefore differ from get-form.

Illustrative request and result:

JSON
{"name":"delete-form-field","arguments":{"form_id":"ofr_workdemo","field_index":1}}
JSON
{"form_id":"ofr_workdemo","deleted_field":{"label":"Work email domain","displayType":"text","width":6,"espField":"company","required":false,"options":{},"placeholder":""},"remaining_fields":2}

move-form-field

Reorders a form's fields, like dragging a field in the form editor. Required arguments are string form_id, numeric field_index (the field to move), and numeric to_index (the 0-based index it ends up at; 0 makes it the first field). project_id is optional.

Any field, the email field included, can move anywhere before the submit button. The submit button never moves and always stays last; if it isn't last, the move puts it back at the end first. The tool returns form_id, from_index, the new field_index, the moved field, and total_fields.

Errors include field_index and to_index are required., an out-of-range field_index or to_index, The submit button always stays last; move the other fields instead., and a field already at to_index (nothing moved).

JSON
{"name":"move-form-field","arguments":{"form_id":"ofr_workdemo","field_index":1,"to_index":0}}
JSON
{"form_id":"ofr_workdemo","from_index":1,"field_index":0,"field":{"label":"Company","displayType":"text","width":6,"espField":"company","required":false},"total_fields":3}

All field mutations remain draft-only. Later calls must use the new indexes after an insertion, deletion, or move.

Still need a hand?

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

support@rightmessage.com