Skip to main content

MCP element reference: interactive elements in a bit

Every interactive element you can put in a bit over MCP: what it is for, the props it accepts, and a worked example. This page is generated from the rules Floxar's server applies, and every example on it was built by the server's own write path, so what you see is what a write accepts. The tools themselves are in authoring content.

How elements are written​

A new element takes two parts in the same add_bit or update_bit call:

  1. A line in bit_body that places it, carrying a key you choose in its anchor, as in the table below. Keys are 1 to 32 letters, digits, _ or -, and each is used once.
  2. An entry in elements with the same key, the element's type, its props and, for a check-list, radio button or dropdown, its items. Item lines carry their own keys.

The answer's minted_node_ids maps each key to the id Floxar created. At most 200 entries and items go in one call.

Markdown alone never creates an element: a line that only looks like one, without a matching elements entry, is refused with UNSUPPORTED_MARKDOWN_CONSTRUCT. When you update a bit, keep every element's anchor exactly as get_bit returned it; an element whose anchor you drop is refused with BIT_CONTENT_LOSS unless you list it in remove_node_ids. To change an existing element's props, send an elements entry with its id instead of a key.

TypeOn a stepPlaced in bit_body by
check-listCheckListItem[check-list: Before you ship](floxar-node:ship)
date-pickerDatePicker[date-picker: Delivery date](floxar-node:delivered)
dropdownDropdown[dropdown: Damage type](floxar-node:damage)
iframenot recorded[iframe](floxar-node:rates)
link-blockLinkBlock[link-block](floxar-node:portal)
link-inlineLinkInlineRead the [carrier guide](https://example.com/guide "floxar-node:guide") before you book.
radio-buttonRadioButton[radio-button: Within the refund window?](floxar-node:window)
searchable-fieldSearchableField[searchable-field: Carrier](floxar-node:carrier)
text-areaTextArea[text-area: Order number](floxar-node:order)
video-externalVideo![Packing a fragile item](https://example.com/packing.mp4 "floxar-node:demo")

Answering elements on a step​

A person answers in the app; an agent answers with submit_step_data, naming each element by its element_id and element_type. The value it sends: {value: <inner>}, inner by element_type: TextArea a string; DatePicker a string per config.picker_type (date YYYY-MM-DD, time HH

:SS
, datetime-local YYYY-MM-DDTHH
:SS
); Dropdown an option's value (its name when it has none); RadioButton an item's text; either may instead be the option's/item's id; CheckListItem a boolean; SearchableField an array of items from config.data; LinkInline / LinkBlock {clicked: boolean, url: config.url}; Video {played: boolean}.

check-list​

A list of items to tick. Each item is recorded on the trail as its own CheckListItem, and an item can be required. On a step and in submit_step_data it is CheckListItem.

Props (elements[].props):

PropTypeLimitsRequired
labelstring—no

Items (elements[].items, one per option, each with an id to edit it or a key to add it; text is the text shown):

PropTypeLimitsRequired
checkedboolean—no
requiredboolean—no
textstring—no

Example. The bit_body to send:

[check-list: Before you ship](floxar-node:ship)
- [ ] [Label printed](floxar-node:label)
- [ ] [Invoice enclosed](floxar-node:invoice)

with elements:

[
{
"items": [
{
"key": "label",
"required": true,
"text": "Label printed"
},
{
"key": "invoice",
"text": "Invoice enclosed"
}
],
"key": "ship",
"props": {
"label": "Before you ship"
},
"type": "check-list"
}
]

get_bit then returns the body with each key replaced by the id Floxar created:

[check-list: Before you ship](floxar-node:<id of ship>)
- [ ] [Label printed](floxar-node:<id of label>) *(required)*
- [ ] [Invoice enclosed](floxar-node:<id of invoice>)

and the step shows it as:

[check-list: Before you ship]
- [ ] Label printed *(required)*
- [ ] Invoice enclosed

date-picker​

A date, a time, or both, chosen by the person or agent running the step. On a step and in submit_step_data it is DatePicker.

Props (elements[].props):

PropTypeLimitsRequired
default_to_nowboolean—no
labelstring—no
picker_typeone of date, time, datetime-local—no
requiredboolean—no
seconds_precisionboolean—no

Example. The bit_body to send:

[date-picker: Delivery date](floxar-node:delivered)

with elements:

[
{
"key": "delivered",
"props": {
"label": "Delivery date",
"picker_type": "date",
"required": true
},
"type": "date-picker"
}
]

get_bit then returns the body with each key replaced by the id Floxar created:

[date-picker: Delivery date](floxar-node:<id of delivered>) (required)

and the step shows it as:

[date-picker: Delivery date] (required)

One choice from a list of options. Bit connections can depend on the option chosen. On a step and in submit_step_data it is Dropdown.

Props (elements[].props):

PropTypeLimitsRequired
labelstring—no
requiredboolean—no

Items (elements[].items, one per option, each with an id to edit it or a key to add it; name is the text shown):

PropTypeLimitsRequired
namestring—no
valuestring—no

Example. The bit_body to send:

[dropdown: Damage type](floxar-node:damage)
- [Crushed](floxar-node:crushed)
- [Wet](floxar-node:wet)
- [Missing items](floxar-node:missing)

with elements:

[
{
"items": [
{
"key": "crushed",
"name": "Crushed",
"value": "crushed"
},
{
"key": "wet",
"name": "Wet",
"value": "wet"
},
{
"key": "missing",
"name": "Missing items",
"value": "missing"
}
],
"key": "damage",
"props": {
"label": "Damage type",
"required": true
},
"type": "dropdown"
}
]

get_bit then returns the body with each key replaced by the id Floxar created:

[dropdown: Damage type](floxar-node:<id of damage>) (required)
- [Crushed](floxar-node:<id of crushed>)
- [Wet](floxar-node:<id of wet>)
- [Missing items](floxar-node:<id of missing>)

and the step shows it as:

[dropdown: Damage type] (required)
- Crushed
- Wet
- Missing items

iframe​

An embedded page shown in the step. It records nothing on the trail. It is not a step element: nothing is answered or recorded for it.

Props (elements[].props):

PropTypeLimitsRequired
heightnumber or stringor the same number as textno
urlstring—yes
urlDisplayOptionone of none, full, domain—no
widthnumber or stringor the same number as textno

Example. The bit_body to send:

[iframe](floxar-node:rates)

with elements:

[
{
"key": "rates",
"props": {
"height": 400,
"url": "https://example.com/rates"
},
"type": "iframe"
}
]

get_bit then returns the body with each key replaced by the id Floxar created:

[iframe](floxar-node:<id of rates>)

and the step shows it as:

[Embedded content](https://example.com/rates)

A link shown as a card with its title, description and image. Opening it is recorded as clicked. On a step and in submit_step_data it is LinkBlock.

Props (elements[].props):

PropTypeLimitsRequired
bitIdstring—no
custom_descriptionstring—no
custom_titlestring—no
is_no_descriptionboolean—no
is_no_iconboolean—no
is_no_imageboolean—no
is_no_linkboolean—no
urlstring—no

Example. The bit_body to send:

[link-block](floxar-node:portal)

with elements:

[
{
"key": "portal",
"props": {
"custom_title": "Carrier portal",
"url": "https://example.com/portal"
},
"type": "link-block"
}
]

get_bit then returns the body with each key replaced by the id Floxar created:

[link-block](floxar-node:<id of portal>)

and the step shows it as:

[Carrier portal](https://example.com/portal)

A link inside a sentence whose click is recorded on the trail. It sits in the text, not on a line of its own. On a step and in submit_step_data it is LinkInline.

Props (elements[].props):

PropTypeLimitsRequired
urlstring—yes

Example. The bit_body to send:

Read the [carrier guide](https://example.com/guide "floxar-node:guide") before you book.

with elements:

[
{
"key": "guide",
"props": {
"url": "https://example.com/guide"
},
"type": "link-inline"
}
]

get_bit then returns the body with each key replaced by the id Floxar created:

Read the [carrier guide](https://example.com/guide "floxar-node:<id of guide>") before you book.

and the step shows it as:

Read the [carrier guide](https://example.com/guide) before you book.

radio-button​

One choice from a group of options shown together. Bit connections can depend on the option chosen. On a step and in submit_step_data it is RadioButton.

Props (elements[].props):

PropTypeLimitsRequired
labelstring—no
requiredboolean—no

Items (elements[].items, one per option, each with an id to edit it or a key to add it; text is the text shown):

PropTypeLimitsRequired
checkedboolean—no
textstring—no

Example. The bit_body to send:

[radio-button: Within the refund window?](floxar-node:window)
- ( ) [Yes](floxar-node:yes)
- ( ) [No](floxar-node:no)

with elements:

[
{
"items": [
{
"key": "yes",
"text": "Yes"
},
{
"key": "no",
"text": "No"
}
],
"key": "window",
"props": {
"label": "Within the refund window?",
"required": true
},
"type": "radio-button"
}
]

get_bit then returns the body with each key replaced by the id Floxar created:

[radio-button: Within the refund window?](floxar-node:<id of window>) (required)
- ( ) [Yes](floxar-node:<id of yes>)
- ( ) [No](floxar-node:<id of no>)

and the step shows it as:

[radio-button: Within the refund window?] (required)
- ( ) Yes
- ( ) No

searchable-field​

A search box over a list of values you provide, for long lists such as products, carriers or locations. On a step and in submit_step_data it is SearchableField.

Props (elements[].props):

PropTypeLimitsRequired
dataarray of string or objectat most 5000 itemsno
labelstring—no
lengthinteger or string1 to 50; or the same number as textno
maxResultsinteger or string1 to 100; or the same number as textno
multiSelectResultsboolean—no
noResultsTextstring—no
paginationboolean—no
placeholderTextstring—no
requiredboolean—no
searchModeone of exact match, partial match, exact, partial—no

Example. The bit_body to send:

[searchable-field: Carrier](floxar-node:carrier)

with elements:

[
{
"key": "carrier",
"props": {
"data": [
"Parcel Express",
"Freight Line",
"Courier One"
],
"label": "Carrier",
"maxResults": 10,
"required": true,
"searchMode": "partial match"
},
"type": "searchable-field"
}
]

get_bit then returns the body with each key replaced by the id Floxar created:

[searchable-field: Carrier](floxar-node:<id of carrier>) (required)

and the step shows it as:

[searchable-field: Carrier] (required)

text-area​

Free text, from a short code to several paragraphs, with optional length limits and a pattern the answer must match. On a step and in submit_step_data it is TextArea.

Props (elements[].props):

PropTypeLimitsRequired
autoCompleteone of on, off—no
autoCorrectone of on, off or boolean—no
labelstring—no
lengthinteger or string1 to 5000; or the same number as textno
linesinteger or string1 to 100; or the same number as textno
maxLengthinteger or string1 to 5000; or the same number as textno
minLengthinteger or string0 to 5000; or the same number as textno
placeholderstring—no
requiredboolean—no
spellCheckboolean—no
validationMessagestring—no
validationModeone of enforced, warning—no
validationPatternstring—no
wrapone of soft, hard—no

Example. The bit_body to send:

[text-area: Order number](floxar-node:order)

with elements:

[
{
"key": "order",
"props": {
"label": "Order number",
"lines": 1,
"maxLength": 8,
"placeholder": "A-123456",
"required": true,
"validationMessage": "Use the form A-123456",
"validationMode": "enforced",
"validationPattern": "^A-[0-9]{6}$"
},
"type": "text-area"
}
]

get_bit then returns the body with each key replaced by the id Floxar created:

[text-area: Order number](floxar-node:<id of order>) (required)

and the step shows it as:

[text-area: Order number] (required)

video-external​

A video from an external address. Watching it is recorded as played. On a step and in submit_step_data it is Video.

Props (elements[].props):

PropTypeLimitsRequired
altTextstring—no
aspectRatiostring—no
maxWidthnumber or stringor the same number as textno
urlstring—yes
urlDisplayOptionone of none, full, domain—no

Example. The bit_body to send:

![Packing a fragile item](https://example.com/packing.mp4 "floxar-node:demo")

with elements:

[
{
"key": "demo",
"props": {
"altText": "Packing a fragile item",
"url": "https://example.com/packing.mp4"
},
"type": "video-external"
}
]

get_bit then returns the body with each key replaced by the id Floxar created:

![Packing a fragile item](https://example.com/packing.mp4 "floxar-node:<id of demo>")

and the step shows it as:

![Packing a fragile item](https://example.com/packing.mp4)

Last reviewed: 2026-10-06