Documentation
¶
Overview ¶
Package gomukit provides prebuilt, parameterized, interactive HTML widgets for MCP Apps (the official Model Context Protocol UI extension, io.modelcontextprotocol/ui). Widgets render as fully self-contained HTML documents — inline CSS, inline JavaScript, no external references — ready to serve as ui:// template resources from any Go MCP server.
The core packages are SDK-agnostic; package gosdk adapts widgets to the official modelcontextprotocol/go-sdk.
Index ¶
- func RowsOf(slice any) ([]map[string]any, error)
- type AcceptSpec
- type Action
- type ActionKind
- type ActionVariant
- type Align
- type ArgSource
- type BadgeVariant
- type Brand
- type Calendar
- type CancelSpec
- type Card
- type CardContent
- type CardFooter
- type CardHeader
- type CardList
- type CardTemplate
- type Choice
- type ChoiceLayout
- type ChoiceOption
- type ChoiceSubmit
- type Column
- func ActionsColumn(actions ...Action) Column
- func Badge(key, label string, variants map[string]BadgeVariant) Column
- func Date(key, label string, format ...string) Column
- func Link(hrefKey, label string) Column
- func Number(key, label string, format ...string) Column
- func Text(key, label string) Column
- type ColumnType
- type Confirm
- type DateMode
- type DatePicker
- type DatePreset
- type DateSpan
- type DateSubmit
- type DescriptionItem
- type Descriptions
- type Effect
- type EmptyState
- type Field
- type FieldType
- type Form
- type Input
- type InputType
- type LinkSpec
- type Menu
- type MenuItem
- type Option
- type RejectSpec
- type SelectionConfig
- type SortSpec
- type SubmitSpec
- type Table
- type Validation
- type WeekStart
- type Widget
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
Types ¶
type AcceptSpec ¶
type AcceptSpec struct {
// Tool is the MCP tool called when the reader accepts (required).
Tool string
// Label defaults to "Confirm".
Label string
// Args maps tool argument names to their sources. Static and FromRow
// apply; FromSelection does not — a confirmation has no selection.
// Ignored when ChatPrompt is set.
Args map[string]ArgSource
// ChatPrompt, when set, makes accepting post this text as a user message
// (ui/message) instead of calling Tool directly, for hosts that answer a
// view-initiated call without opening the widget behind it. Write it as
// the request a user would type; the model then makes the call.
//
// Named apart from Confirm.Prompt, which is the question put to the
// reader rather than a message sent on their behalf.
ChatPrompt string
// Variant overrides the button styling derived from Severity.
Variant ActionVariant
// SuccessMessage is shown in place of the buttons once the call succeeds.
// Defaults to the tool result's own text.
SuccessMessage string
}
AcceptSpec configures the confirming call.
type Action ¶
type Action struct {
Label string
// Kind defaults to ActionTool.
Kind ActionKind
// Tool is the MCP tool name to call (Kind == ActionTool).
Tool string
// Args maps tool argument names to their sources. Ignored when Prompt is
// set — the model chooses the arguments there.
Args map[string]ArgSource
// Prompt, when set, makes the action ask the host to post this text as a
// user message (ui/message) instead of calling Tool itself. Write it as
// the request a user would type; the model reads it and decides which
// tool answers, so Tool documents what the action opens.
//
// The text is fixed: it carries no row values, because the model works
// out which record is meant from the conversation. Only tool actions may
// set it — a link action already navigates on its own.
Prompt string
// HrefKey is the row field holding the URL (Kind == ActionLink).
HrefKey string
// Confirm, when set, requires a second confirming click showing this
// text before the action fires. (Rendered inline: native confirm()
// dialogs are silently disabled in sandboxed MCP Apps iframes.)
Confirm string
Variant ActionVariant
}
Action is a user-triggerable operation on a widget: a per-row button, a bulk action over selected rows, or a link.
A tool action normally calls Tool and lets the widget handle the result — re-rendering from returned rows, or reporting the outcome. When the tool answers with a widget of its own instead (an edit form, a detail view), the host is the one that must open it, and a host that runs a view-initiated call out of band opens nothing. Prompt routes such an action through the chat for those hosts: see its documentation below.
type ActionKind ¶
type ActionKind string
ActionKind selects what an Action does when triggered.
const ( // ActionTool calls an MCP tool (the zero-value default). ActionTool ActionKind = "tool" // ActionLink asks the host to open a URL taken from the row. ActionLink ActionKind = "link" )
type ActionVariant ¶
type ActionVariant string
ActionVariant selects button styling.
const ( VariantDefault ActionVariant = "" VariantPrimary ActionVariant = "primary" VariantDanger ActionVariant = "danger" )
type ArgSource ¶
type ArgSource struct {
// contains filtered or unexported fields
}
ArgSource declares where a tool-call argument value comes from when an action fires. Construct with Static, FromRow, or FromSelection.
func FromSelection ¶
FromSelection collects the values of field across all selected rows (bulk actions).
func (ArgSource) MarshalJSON ¶
MarshalJSON emits {"static": v} | {"row": "field"} | {"selection": "field"}.
type BadgeVariant ¶
type BadgeVariant string
BadgeVariant colors a badge cell value.
const ( BadgeNeutral BadgeVariant = "neutral" BadgeInfo BadgeVariant = "info" BadgeSuccess BadgeVariant = "success" BadgeWarning BadgeVariant = "warning" BadgeDanger BadgeVariant = "danger" )
type Brand ¶
type Brand struct {
// Name is the application name shown next to the logo. Required unless a
// logo is set.
Name string
// URL is an optional http(s) link opened through the host (ui/openLink);
// it makes the whole brand clickable.
URL string
// LogoSVG is inline <svg> markup. It is author-trusted input, checked
// only against script-bearing and resource-loading constructs.
LogoSVG string
// LogoDataURI is a "data:image/...;base64,..." alternative to LogoSVG.
LogoDataURI string
// LogoAlt is the alt text for LogoDataURI. Defaults to Name.
LogoAlt string
}
Brand identifies the application a widget belongs to: an optional logo, a name, and an optional link. It renders at the top left of the widget chrome, before the title, and is shared by pointer across widgets.
Documents must stay self-contained, so a logo is never a URL: supply either inline SVG markup (LogoSVG, recommended — it needs nothing from the host's CSP) or a base64 data URI (LogoDataURI, which renders as an <img> and therefore depends on the host allowing img-src data:).
type Calendar ¶
type Calendar struct {
// Min is the earliest selectable date, as "YYYY-MM-DD". Days before it
// are shown but cannot be picked, and the grid will not travel past the
// month holding it.
Min string
// Max is the latest selectable date, as "YYYY-MM-DD".
Max string
// Disabled lists individual days that cannot be picked ("YYYY-MM-DD") —
// holidays, sold-out days, days already booked. In a range calendar a
// span may not straddle one.
Disabled []string
// DisableWeekends blocks every Saturday and Sunday. It is about the days
// themselves, not about where the week starts: WeekStartSaturday still
// blocks the same two days.
DisableWeekends bool
// Months is how many months are shown at once. Defaults to 1 for a single
// date and 2 for a range, which is what makes a span across a month
// boundary one gesture rather than two. Maximum 4. They sit side by side
// where the widget has room and wrap under each other where it has not —
// every month asked for stays on screen, narrow chat pane or not.
Months int
// WeekNumbers adds a leading column of ISO 8601 week numbers.
WeekNumbers bool
// MonthDropdowns replaces the month caption with month and year
// dropdowns, so a date years away is two presses rather than a hundred.
// Use it for dates of birth and anything else far from today.
MonthDropdowns bool
// FromYear and ToYear bound the year dropdown. They default to the years
// of Min and Max, and — where those are unset — to 100 years before and
// 10 years after the year the document is rendered in.
FromYear, ToYear int
// WeekStart overrides the first day of the week. Defaults to the host
// locale's own first day.
WeekStart WeekStart
// StartOn is the month the grid opens on while nothing is selected, as
// "YYYY-MM-DD" (the day itself is ignored). Defaults to the month holding
// the selection, or the reader's current month clamped into Min/Max.
StartOn string
// Presets are named shortcuts listed beside the grid.
Presets []DatePreset
}
Calendar configures the date grid: which days may be picked, how many months are on show, and how the reader travels between them. It is a shared building block rather than a widget — the DatePicker widget renders one inline, and a Form's FDate and FDateRange fields render one in a popover — so the same configuration means the same grid in both places.
The zero value is a one-month grid with every day selectable, which is what most fields want.
type CancelSpec ¶
type CancelSpec struct {
// Label defaults to "Cancel".
Label string
}
CancelSpec adds a reset button to the form.
type Card ¶
type Card struct {
// URI is the widget's ui:// resource URI (required).
URI string
// Title is shown in the toolbar and the document title.
Title string
// Template describes the card content (required).
Template CardTemplate
// RowsKey is the structuredContent key holding the rows array; the card
// renders rows[0]. Defaults to "rows".
RowsKey string
// RowID is the record field used for FromRow action args. Defaults to
// "id".
RowID string
// Empty configures the message shown when no record is present.
Empty EmptyState
// InitialData is an optional structuredContent-shaped snapshot baked into
// the document as a JSON island.
InitialData map[string]any
// LoadTool, when set, names a read tool the runtime calls once on load to
// hydrate the card from fresh data, replacing InitialData. It must return
// the record under RowsKey.
LoadTool string
// LoadArgs are optional static arguments passed to LoadTool.
LoadArgs map[string]any
// Brand renders the application logo/name on the widget.
Brand *Brand
// Theme overrides gomukit design tokens for this widget.
Theme *theme.Theme
// UI overrides resource _meta.ui (CSP, permissions, prefersBorder).
UI *uispec.ResourceUIMeta
}
Card renders a single record as a card. The record is the first element of the rows array delivered at runtime under RowsKey (the same contract as Table and CardList), or baked into the document via InitialData.
func (*Card) Descriptor ¶
func (c *Card) Descriptor() uispec.ResourceDescriptor
Descriptor implements Widget.
type CardContent ¶
type CardContent struct {
// TextKey is a row field rendered as a paragraph of body text.
TextKey string
// Text is fixed body prose, used instead of TextKey.
Text string
// Items are the label/value detail rows.
Items Descriptions
}
CardContent is the card's body section: prose, a label/value detail list, or both. The list is the shared Descriptions block, so a card's fields render and format exactly like a confirmation's details.
type CardFooter ¶
type CardFooter struct {
TextKey string
Text string
// (they belong to CardList bulk actions).
Actions []Action
}
CardFooter is the card's bottom section: a note, and the buttons that act on the record.
type CardHeader ¶
type CardHeader struct {
// TitleKey is the row field shown as the card title (required).
TitleKey string
// DescriptionKey is a row field shown under the title.
DescriptionKey string
// Description is fixed text shown under the title, used instead of
// DescriptionKey.
Description string
// Badge is a status badge for the header's action slot. Construct it with
// the Badge column constructor; it is present when its Key is set, and
// must be a badge column.
Badge Column
// Action is a button for the header's action slot, used instead of Badge.
// FromSelection args are invalid here (they belong to CardList bulk
// actions).
Action *Action
}
CardHeader is the card's top section: the title, an optional description under it, and a single action slot at the end of the header line holding either a status badge or a button — not both, the way one slot works.
type CardList ¶
type CardList struct {
// URI is the widget's ui:// resource URI (required).
URI string
// Title is shown in the toolbar and the document title.
Title string
// Template describes how each record renders as a card (required).
Template CardTemplate
// RowsKey is the structuredContent key holding the rows array. Defaults
// to "rows".
RowsKey string
// RowID uniquely identifies a record, used for selection and
// FromRow/FromSelection args. Defaults to "id".
RowID string
// PageSize enables client-side pagination when > 0.
PageSize int
// PageSizes offers alternative page sizes in a dropdown on the pagination
// bar. Entries must be > 0 and PageSize must be set; PageSize is added to
// the list if it is not among them. Empty renders no chooser.
PageSizes []int
// LoadMore turns the carousel into a growing strip instead of a paged one:
// it starts at PageSize records and appends the next PageSize each time
// the reader activates the "Load more" tile at the end of the strip, which
// replaces the prev/next pagination bar. Records already scrolled past stay
// where they are, so the strip reads as one continuous run.
//
// Requires PageSize > 0, and cannot be combined with PageSizes: the page
// size chooser lives on the bar this removes.
LoadMore bool
// DefaultSort pre-sorts records on load.
DefaultSort *SortSpec
// Filterable adds a client-side text filter box.
Filterable bool
// Selection enables per-card checkboxes and bulk actions.
Selection *SelectionConfig
// Empty configures the no-data message.
Empty EmptyState
// InitialData is an optional structuredContent-shaped snapshot baked into
// the document as a JSON island.
InitialData map[string]any
// LoadTool, when set, names a read tool the runtime calls once on load to
// hydrate the list from fresh data, replacing InitialData. It must return
// the records under RowsKey.
LoadTool string
// LoadArgs are optional static arguments passed to LoadTool.
LoadArgs map[string]any
// Brand renders the application logo/name on the widget.
Brand *Brand
// Theme overrides gomukit design tokens for this widget.
Theme *theme.Theme
// UI overrides resource _meta.ui (CSP, permissions, prefersBorder).
UI *uispec.ResourceUIMeta
}
CardList renders a collection of records as cards in a responsive grid, with client-side filter, sort, pagination, selection with bulk actions, and per-card actions — the same runtime machinery as Table, laid out as cards instead of table rows.
func (*CardList) Descriptor ¶
func (l *CardList) Descriptor() uispec.ResourceDescriptor
Descriptor implements Widget.
func (*CardList) Document ¶
Document implements Widget. The shell contains the list chrome (toolbar, filter, sort, selection, pagination); the cards themselves are rendered by the embedded runtime from tool-result data and the optional snapshot.
type CardTemplate ¶
type CardTemplate struct {
// Header is the top section (required: it holds the title).
Header CardHeader
// Content is the card body.
Content CardContent
Footer CardFooter
}
CardTemplate describes how one record renders as a card. It is shared by the single-record Card widget and the CardList collection widget, and is built from three sections that always render in the same order:
Header — what the record is: title, description, and one slot at the
end of the line for a status badge or a button.
Content — the record itself: a paragraph of prose and/or a label/value
detail list (typed and Intl-formatted like table cells).
Footer — what can be done with it: a note and a row of action buttons.
Only Header is required; a section with nothing in it is not rendered at all, so a bare title-and-actions card carries no empty chrome.
type Choice ¶
type Choice struct {
// URI is the widget's ui:// resource URI (required).
URI string
// Title is shown in the toolbar and the document title.
Title string
// Prompt is the headline question, e.g. "How should we ship this?"
// (required).
Prompt string
// Body is supporting prose under the prompt.
Body string
// Layout places the description block. Defaults to ChoiceAuto.
Layout ChoiceLayout
// Multiple lets the reader pick more than one option. Without it the
// options are radios and exactly one can be chosen.
Multiple bool
// Min is the fewest options a multiple choice accepts. Defaults to 1 —
// submitting nothing is not a choice. Ignored unless Multiple.
Min int
// Max is the most a multiple choice accepts; 0 means no limit. Once Max
// options are ticked the rest disable, so the limit is visible rather
// than only enforced. Ignored unless Multiple.
Max int
// Options are the candidates, in reading order. May be empty when they
// arrive at runtime under OptionsKey.
Options []ChoiceOption
// Details describes the record the question is about, read from rows[0].
// It sits under the prompt, above the options.
Details Descriptions
// Submit configures the call the decision makes (required).
Submit ChoiceSubmit
// Cancel configures the declining button. Nil renders no such button,
// leaving the host's own affordances as the only way out.
Cancel *RejectSpec
// RowsKey is the structuredContent key holding the context record; the
// widget reads rows[0]. Defaults to "rows".
RowsKey string
// OptionsKey is the structuredContent key holding the option array.
// Defaults to "options".
OptionsKey string
// RowID is the record field used for FromRow args. Defaults to "id".
RowID string
// InitialData is an optional structuredContent-shaped snapshot baked into
// the document as a JSON island.
InitialData map[string]any
// LoadTool, when set, names a read tool the runtime calls once on load to
// fetch the options and the record fresh, replacing InitialData. Use it
// when what is on offer can change between registration and the question.
LoadTool string
// LoadArgs are optional static arguments passed to LoadTool.
LoadArgs map[string]any
// Brand renders the application logo/name on the widget.
Brand *Brand
// Theme overrides gomukit design tokens for this widget.
Theme *theme.Theme
// UI overrides resource _meta.ui (CSP, permissions, prefersBorder).
UI *uispec.ResourceUIMeta
}
Choice asks the reader to pick — one option or several — and then to submit. Nothing happens until they do: picking is local, and only the submit button calls a tool.
It is the deliberating counterpart to Confirm. Confirm asks a yes/no question about one operation; Choice asks which operation, and gives every candidate room to argue for itself: a summary in the list, and a description block with prose, bullets and a typed detail list. Where that block sits is a matter of width — see ChoiceLayout.
Options are authored here, arrive at runtime under OptionsKey, or both: a runtime list replaces the authored one wholesale, the same contract Confirm uses for effects. The record the question is about (Details, and FromRow submit arguments) arrives under RowsKey as rows[0].
The decision is final. Once the submit call succeeds, or the reader cancels, the controls are gone; a failed submit re-arms so a transient error can be retried.
func (*Choice) Descriptor ¶
func (c *Choice) Descriptor() uispec.ResourceDescriptor
Descriptor implements Widget.
type ChoiceLayout ¶
type ChoiceLayout string
ChoiceLayout places the block that describes an option.
The layout is about width, not about taste: a widget with room for two columns reads better with the description beside the options, and the same widget in a narrow chat pane reads better with it underneath. ChoiceAuto picks per width at runtime; the other two settle it for good.
const ( // ChoiceAuto shows the description beside the options while the widget is // wide enough for two columns and under the selected option when it is // not. It is the default, and the right answer unless the content says // otherwise. ChoiceAuto ChoiceLayout = "" // ChoiceSplit always shows the description in a side panel. ChoiceSplit ChoiceLayout = "split" // ChoiceStacked always shows the description under its own option. ChoiceStacked ChoiceLayout = "stacked" )
type ChoiceOption ¶
type ChoiceOption struct {
// Value is what the submit call sends for this option (required, unique).
Value string
// Label is the option's name in the list. Defaults to Value.
Label string
// Summary is a single supporting line under the label, shown in the list
// whether or not the option is selected.
Summary string
// Body is prose about the option, shown in the description block.
Body string
// Bullets are short points about the option, listed under Body.
Bullets []string
// Details is a label/value list about the option, shown under Bullets.
// Items with a Key read Data; items with Text are fixed.
Details Descriptions
// Data is the option's record, the source for Key detail items.
Data map[string]any
// Badge is optional short text beside the label — "recommended",
// "cheapest".
Badge string
// BadgeVariant colors the badge. Defaults to BadgeNeutral.
BadgeVariant BadgeVariant
// Default preselects the option. A single choice takes at most one.
Default bool
// Disabled renders the option unselectable — on offer, but not now.
Disabled bool
}
ChoiceOption is one candidate. Label and Summary are what the list shows; Body, Bullets and Details are the case for it, shown in the description block once it is the option in hand.
Details items typed with a Key read their value from Data — the option's own record — so an option can carry facts that are formatted for the host's locale rather than pre-rendered into strings.
type ChoiceSubmit ¶
type ChoiceSubmit struct {
// Tool is the MCP tool called on submit (required).
Tool string
// Label defaults to "Continue".
Label string
// ValueArg is the tool argument carrying the decision: the chosen option's
// Value, or the array of chosen values in a multiple choice. Defaults to
// "choice".
ValueArg string
// Args maps further tool argument names to their sources. Static and
// FromRow apply; FromSelection does not — a choice has no row selection.
// Ignored when ChatPrompt is set.
Args map[string]ArgSource
// ChatPrompt, when set, makes submitting post a user message (ui/message)
// instead of calling Tool directly, for hosts that answer a view-initiated
// call without opening the widget behind it. The reader's decision is
// appended to this text, since a choice's whole output is what they picked
// and ValueArg has no counterpart in a chat turn.
//
// Named apart from Choice.Prompt, which is the question put to the reader
// rather than a message sent on their behalf.
ChatPrompt string
// Variant overrides the submit button styling (VariantPrimary).
Variant ActionVariant
// SuccessMessage is shown in place of the controls once the call succeeds.
// Defaults to the tool result's own text.
SuccessMessage string
}
ChoiceSubmit configures the call a Choice makes once the reader submits.
type Column ¶
type Column struct {
// Key is the row field this column displays (unused for ColActions).
Key string
Label string
// Type defaults to ColText.
Type ColumnType
// Sortable overrides the default (text/number/date sortable, others not).
Sortable *bool
Align Align
// Format refines rendering, interpreted by the runtime via Intl:
// numbers: "int" | "decimal:<digits>" | "percent" | "currency:<code>";
// dates: "date" | "datetime" | "time" | "relative".
Format string
// Badge maps cell values to badge variants (ColBadge).
Badge map[string]BadgeVariant
// Link configures ColLink columns.
Link *LinkSpec
// Actions renders per-row action buttons (ColActions).
Actions []Action
// Width is a CSS width for the column (e.g. "12rem", "20%").
Width string
}
Column defines one table column.
func ActionsColumn ¶
ActionsColumn returns a per-row actions column.
func Badge ¶
func Badge(key, label string, variants map[string]BadgeVariant) Column
Badge returns a badge column mapping values to variants.
func Date ¶
Date returns a date column with an optional format ("date", "datetime", "time", "relative").
type ColumnType ¶
type ColumnType string
ColumnType selects how a column renders its cells.
const ( ColText ColumnType = "text" // the zero-value default ColNumber ColumnType = "number" ColDate ColumnType = "date" ColBadge ColumnType = "badge" ColLink ColumnType = "link" ColActions ColumnType = "actions" )
type Confirm ¶
type Confirm struct {
// URI is the widget's ui:// resource URI (required).
URI string
// Title is shown in the toolbar and the document title.
Title string
// Prompt is the headline question, e.g. "Delete Ada Lovelace?"
// (required).
Prompt string
// Body is supporting prose under the prompt.
Body string
// Severity colors the widget: BadgeInfo (the default), BadgeWarning or
// BadgeDanger. It also picks the accept button's variant unless
// Accept.Variant says otherwise.
Severity BadgeVariant
// Details describes the record the operation targets, read from rows[0].
Details Descriptions
// Effects are the side effects known at registration time. Any effects
// delivered under EffectsKey at runtime replace this list wholesale.
Effects []Effect
// Acknowledge, when set, is the label of a checkbox the reader must tick
// before the accept button enables ("I understand this cannot be undone").
Acknowledge string
// TypeToConfirm, when set, is a phrase the reader must type exactly
// before the accept button enables — the record's name, usually.
TypeToConfirm string
// Accept configures the confirming call (required).
Accept AcceptSpec
// Reject configures the declining button. Nil renders no such button,
// leaving the host's own affordances as the only way out.
Reject *RejectSpec
// RowsKey is the structuredContent key holding the record array; the
// widget reads rows[0]. Defaults to "rows".
RowsKey string
// EffectsKey is the structuredContent key holding the side-effect array.
// Defaults to "effects".
EffectsKey string
// RowID is the record field used for FromRow args. Defaults to "id".
RowID string
// InitialData is an optional structuredContent-shaped snapshot baked into
// the document as a JSON island.
InitialData map[string]any
// LoadTool, when set, names a read tool the runtime calls once on load to
// fetch the record and effects fresh, replacing InitialData. Use it when
// the consequences must be current at decision time rather than at render
// time.
LoadTool string
// LoadArgs are optional static arguments passed to LoadTool.
LoadArgs map[string]any
// Brand renders the application logo/name on the widget.
Brand *Brand
// Theme overrides gomukit design tokens for this widget.
Theme *theme.Theme
// UI overrides resource _meta.ui (CSP, permissions, prefersBorder).
UI *uispec.ResourceUIMeta
}
Confirm is an approval widget: it states an operation, shows the record it targets and the side effects it will have, and offers exactly two outcomes — accept, which calls a tool, or reject, which does not.
It is the long form of Action.Confirm. That one re-labels a button for a second click and has room for a few words; this one is a view of its own, for operations whose consequences the reader has to weigh before deciding.
The prompt, the effects a server can name up front, and the guards are authored here. Everything that depends on the particular call arrives at runtime in structuredContent: the record under RowsKey (the widget shows rows[0], same contract as Card) and the side effects under EffectsKey, which replace the authored ones.
A decision is final: once the reader accepts and the tool succeeds, or rejects, the buttons are gone. A failed accept is the exception — the widget re-arms so a transient error can be retried.
func (*Confirm) Descriptor ¶
func (c *Confirm) Descriptor() uispec.ResourceDescriptor
Descriptor implements Widget.
type DateMode ¶
type DateMode string
DateMode selects what a calendar picks: one date, or the span between two.
type DatePicker ¶
type DatePicker struct {
// URI is the widget's ui:// resource URI (required).
URI string
// Title is shown in the toolbar and the document title.
Title string
// Prompt is the headline question, e.g. "When should we deliver?"
// (required).
Prompt string
// Body is supporting prose under the prompt.
Body string
// Mode picks one date (the default) or a span.
Mode DateMode
// Calendar configures the grid. Nil is the zero value: one month for a
// single date, two for a range, every day selectable.
Calendar *Calendar
// Default preselects a date ("YYYY-MM-DD"). In a range picker it is the
// start, and DefaultEnd is the end.
Default string
// DefaultEnd preselects the end of the span (DateRange only).
DefaultEnd string
// Details describes the record the question is about, read from rows[0].
// It sits under the prompt, above the calendar.
Details Descriptions
// Submit configures the call the decision makes (required).
Submit DateSubmit
// Cancel configures the declining button. Nil renders no such button,
// leaving the host's own affordances as the only way out.
Cancel *RejectSpec
// ValueKey is the structuredContent key holding the runtime selection and
// any runtime bounds. Defaults to "value". See docs/widgets.md for the
// shape; briefly, a "YYYY-MM-DD" string, or an object with start, end,
// min, max and disabled.
ValueKey string
// RowsKey is the structuredContent key holding the context record; the
// widget reads rows[0]. Defaults to "rows".
RowsKey string
// RowID is the record field used for FromRow args. Defaults to "id".
RowID string
// InitialData is an optional structuredContent-shaped snapshot baked into
// the document as a JSON island.
InitialData map[string]any
// LoadTool, when set, names a read tool the runtime calls once on load to
// fetch the selection and bounds fresh, replacing InitialData. Use it when
// what is still free to book can change between registration and the
// question.
LoadTool string
// LoadArgs are optional static arguments passed to LoadTool.
LoadArgs map[string]any
// Brand renders the application logo/name on the widget.
Brand *Brand
// Theme overrides gomukit design tokens for this widget.
Theme *theme.Theme
// UI overrides resource _meta.ui (CSP, permissions, prefersBorder).
UI *uispec.ResourceUIMeta
}
DatePicker asks the reader for a date, or for the span between two, and then to submit it. Nothing happens until they do: picking is local, and only the submit button calls a tool.
It is the standalone form of the same grid a Form's FDate and FDateRange fields render in a popover. Use the widget when the date is the whole question — "when should this ship?", "which nights?" — and the field when it is one answer among several. The grid is configured identically either way: see Calendar for bounds, blocked days, presets and month travel.
The calendar is inline rather than behind a trigger: the widget is a view of its own, and a view whose only job is a calendar should not ask to be opened.
What the reader picks travels as plain "YYYY-MM-DD" strings: Submit.ValueArg carries the date, and in a range picker Submit.EndArg carries the end.
The decision is final. Once the submit call succeeds, or the reader cancels, the controls are gone; a failed submit re-arms so a transient error can be retried.
func (*DatePicker) Descriptor ¶
func (d *DatePicker) Descriptor() uispec.ResourceDescriptor
Descriptor implements Widget.
func (*DatePicker) Document ¶
func (d *DatePicker) Document() (string, error)
Document implements Widget. The question and the buttons are authored, so they are rendered here; the grid is not. Which days a month holds, which of them are still free, and what the reader has picked are all runtime state — and the month names come from the host's locale, which is not known until the handshake — so the calendar is an empty host the runtime fills.
func (*DatePicker) ToolMeta ¶
func (d *DatePicker) ToolMeta() map[string]any
ToolMeta implements Widget.
type DatePreset ¶
type DatePreset struct {
// Label names the shortcut, e.g. "Last 7 days" (required).
Label string
// Span is a window relative to the reader's today, resolved at runtime in
// the host's time zone.
Span DateSpan
// Start and End are a fixed window, as "YYYY-MM-DD" — a quarter that has
// closed, a campaign that ran. In a single-date calendar only Start is
// used; End is not allowed.
Start, End string
}
DatePreset is a named shortcut listed beside the grid: one press picks a whole window instead of two dates. Exactly one of Span and Start/End says which window.
type DateSpan ¶
type DateSpan string
DateSpan names a window relative to the reader's today. A server cannot name those dates at registration time — "the last 7 days" is a different week by the time the widget is read, and "today" depends on the reader's time zone rather than the server's — so a span travels as the name of a rule and the runtime resolves it against the host's clock.
const ( SpanToday DateSpan = "today" SpanYesterday DateSpan = "yesterday" SpanTomorrow DateSpan = "tomorrow" SpanLast7Days DateSpan = "last-7-days" SpanLast30Days DateSpan = "last-30-days" SpanLast90Days DateSpan = "last-90-days" SpanNext7Days DateSpan = "next-7-days" SpanNext30Days DateSpan = "next-30-days" SpanThisWeek DateSpan = "this-week" SpanLastWeek DateSpan = "last-week" SpanThisMonth DateSpan = "this-month" SpanLastMonth DateSpan = "last-month" SpanThisYear DateSpan = "this-year" // SpanYearToDate runs from 1 January to today, where SpanThisYear runs to // 31 December. SpanYearToDate DateSpan = "year-to-date" )
type DateSubmit ¶
type DateSubmit struct {
// Tool is the MCP tool called on submit (required).
Tool string
// Label defaults to "Continue".
Label string
// ValueArg is the tool argument carrying the picked date, as
// "YYYY-MM-DD". Defaults to "date" for a single date and "start" for a
// range.
ValueArg string
// EndArg is the tool argument carrying the end of the span. Defaults to
// "end". DateRange only.
EndArg string
// Args maps further tool argument names to their sources. Static and
// FromRow apply; FromSelection does not — a date has no row selection.
// Ignored when ChatPrompt is set.
Args map[string]ArgSource
// ChatPrompt, when set, makes submitting post a user message (ui/message)
// instead of calling Tool directly, for hosts that answer a view-initiated
// call without opening the widget behind it. The picked date is appended
// to this text, since a picker's whole output is that date and ValueArg
// has no counterpart in a chat turn.
//
// Named apart from DatePicker.Prompt, which is the question put to the
// reader rather than a message sent on their behalf.
ChatPrompt string
// Variant overrides the submit button styling (VariantPrimary).
Variant ActionVariant
// SuccessMessage is shown in place of the controls once the call succeeds.
// Defaults to the tool result's own text.
SuccessMessage string
}
DateSubmit configures the call a DatePicker makes once the reader submits.
type DescriptionItem ¶
type DescriptionItem struct {
// Label names the value (required).
Label string
// Key is the record field holding the value. On an Input item it is the
// prefill source instead: the control opens on that field's value.
Key string
// Text is a fixed value, used instead of Key.
Text string
// Input makes this item a question: the value cell renders a control, and
// what the reader puts in it travels with the widget's call. Only the
// widgets that own a call accept one — DatePicker.Details and a card's
// Content.Items; a Confirm's or a Choice's details are read-only.
Input *Input
// Type selects rendering: ColText (default), ColNumber, ColDate, ColBadge
// or ColLink. Fixed-text items are always text.
Type ColumnType
// Format refines number and date rendering, exactly as Column.Format.
Format string
// Badge maps values to badge variants (ColBadge).
Badge map[string]BadgeVariant
// Link configures a ColLink item; its URL comes from the record.
Link *LinkSpec
// Align positions the value within its cell.
Align Align
}
DescriptionItem is one label/value pair. The value is either read from the record at runtime (Key) or authored here as fixed text (Text) — exactly one of the two. A Key value is typed and Intl-formatted by the runtime, using the same types, formats and host locale as a table cell.
An item can also ask rather than state: set Input and the value cell holds a control the reader fills in, whose value travels with the widget's own call. See Input.
type Descriptions ¶
type Descriptions struct {
// Items are the entries, in reading order (at least one to render).
Items []DescriptionItem
}
Descriptions is a label/value detail list — the block a widget uses to spell out what a record is before the reader acts on it. It is a shared building block, not a widget: it has no URI and no Document, and is embedded by value the way CardTemplate is.
There are no layout controls. The items lay themselves out in as many columns as the widget's own width allows and collapse to one in a narrow chat pane, so the same document reads in either.
type Effect ¶
type Effect struct {
// Text states the consequence, e.g. "Deletes the audit trail" (required).
Text string
// Detail is a secondary line qualifying it.
Detail string
// Value is a magnitude shown at the end of the row, e.g. "12 records".
Value string
// Severity colors the row: BadgeNeutral (the default), BadgeInfo,
// BadgeSuccess, BadgeWarning or BadgeDanger.
Severity BadgeVariant
}
Effect is one consequence of the operation, listed so the reader can weigh it before accepting.
type EmptyState ¶
type EmptyState struct {
Title string `json:"title,omitempty"`
Body string `json:"body,omitempty"`
}
EmptyState configures the message shown when a widget has no data.
type Field ¶
type Field struct {
// Name is the tool-call argument name (required, unique).
Name string
Label string
// Description renders as help text under the control.
Description string
Placeholder string
// Type defaults to FText.
Type FieldType
// Required marks the field as mandatory.
Required bool
// Default is the initial value: string-like for most fields, bool for
// FCheckbox, []string for FMultiSelect, and []string{start, end} for
// FDateRange.
Default any
// Options are required for FSelect and FMultiSelect.
Options []Option
// Validation adds client-side constraints. Date fields take their bounds
// from Calendar instead.
Validation *Validation
// Rows sets the textarea height (FTextarea).
Rows int
// Calendar configures the grid an FDate or FDateRange field opens, exactly
// as it configures the standalone DatePicker widget: bounds, blocked days,
// presets, month travel. Nil is the zero value — one month for a date, two
// for a range, every day selectable.
Calendar *Calendar
// EndName is the tool-call argument carrying a range's end date
// (FDateRange only). Defaults to Name + "_end". It shares the field's
// namespace, so it must not collide with another field's Name.
EndName string
}
Field defines one form field.
type FieldType ¶
type FieldType string
FieldType selects the control a Field renders.
const ( FText FieldType = "text" // the zero-value default FTextarea FieldType = "textarea" FNumber FieldType = "number" FCheckbox FieldType = "checkbox" FSelect FieldType = "select" FMultiSelect FieldType = "multiselect" FDate FieldType = "date" FDateRange FieldType = "daterange" FTime FieldType = "time" FHidden FieldType = "hidden" FReadonly FieldType = "readonly" )
type Form ¶
type Form struct {
// URI is the widget's ui:// resource URI (required).
URI string
// Title is shown above the form and as the document title.
Title string
// Fields defines the form fields (required, non-empty).
Fields []Field
// Submit configures the submit tool call (required).
Submit SubmitSpec
// Cancel, when set, adds a reset button.
Cancel *CancelSpec
// PrefillKey is the structuredContent key holding {"field": value}
// prefill data. Defaults to "values".
PrefillKey string
// ErrorsKey is the structuredContent key holding {"field": "message"}
// validation errors. Defaults to "errors".
ErrorsKey string
// InitialData is an optional structuredContent-shaped snapshot baked
// into the document (e.g. {"values": {...}} for a pre-filled edit form).
InitialData map[string]any
// LoadTool, when set, names a read tool the runtime calls once on load
// (after the host handshake) to hydrate the form's prefill from fresh
// data, replacing the baked InitialData snapshot. The tool must return
// the prefill values under PrefillKey in its structuredContent.
LoadTool string
// LoadArgs are optional static arguments passed to LoadTool.
LoadArgs map[string]any
// Brand renders the application logo/name on the widget.
Brand *Brand
// Theme overrides gomukit design tokens for this widget.
Theme *theme.Theme
// UI overrides resource _meta.ui.
UI *uispec.ResourceUIMeta
}
Form is a create/edit form widget: typed fields with client-side validation, submit as an MCP tool call, and server-side field errors mapped back inline.
For edit forms, prefill values arrive at runtime in the tool result's structuredContent under PrefillKey; the submit call's response may return field errors under ErrorsKey ({"field": "message"}).
func (*Form) Descriptor ¶
func (f *Form) Descriptor() uispec.ResourceDescriptor
Descriptor implements Widget.
type Input ¶ added in v0.7.1
type Input struct {
// Name is the tool argument the value travels in (required, unique within
// the block, and distinct from every other argument the widget's call
// builds).
Name string
// Type defaults to InputText.
Type InputType
// Placeholder is the empty-state text. On an InputSelect it is what the
// dropdown reads before a choice is made.
Placeholder string
// Required blocks the widget's call until the control is filled in.
Required bool
// Default is the value the control opens on: string-like for text, number
// and select, bool for InputCheckbox. The item's Key wins over it when the
// record carries that field.
Default any
// Options are the choices of an InputSelect (required for it, invalid
// otherwise).
Options []Option
// Validation adds client-side constraints, exactly as on a form Field.
// Only Message applies to a select or a checkbox; the rest constrain text
// length, number bounds and step.
Validation *Validation
}
Input is the control an editable DescriptionItem renders in place of a value. What the reader puts in it is collected at call time and merged into the arguments of the widget's own call: a DatePicker's submit, alongside the picked date, or the action buttons of the card the item sits in.
It is the short form of a Form field, for the question a widget asks in passing — "how many?", "which warehouse?" — rather than a form of its own. A whole set of fields with their own submit button is still a Form.
type InputType ¶ added in v0.7.1
type InputType string
InputType selects the control an editable DescriptionItem renders.
type LinkSpec ¶
type LinkSpec struct {
HrefKey string `json:"hrefKey"`
TextKey string `json:"textKey,omitempty"`
Text string `json:"text,omitempty"`
}
LinkSpec configures a link column. The URL comes from HrefKey; the link text comes from TextKey, or the fixed Text, or the URL itself.
type Menu ¶
type Menu struct {
// URI is the widget's ui:// resource URI (required).
URI string
// Title is shown in the toolbar and the document title.
Title string
// Intro is optional lead text shown above the tiles.
Intro string
// Items are the menu entries (at least one is required).
Items []MenuItem
// Brand renders the application logo/name on the widget.
Brand *Brand
// Theme overrides gomukit design tokens for this widget.
Theme *theme.Theme
// UI overrides resource _meta.ui (CSP, permissions, prefersBorder).
UI *uispec.ResourceUIMeta
}
Menu renders a launcher: a grid of tiles, one per MCP tool the application exposes with a UI. Choosing a tile calls that tool, and the host opens the widget bound to it — so a Menu is the entry point an app hands the user before any particular record is in view.
Unlike the data widgets, a Menu is fully authored at registration time: the tiles are server-rendered from Items and the document needs nothing from the runtime data contract.
func (*Menu) Descriptor ¶
func (m *Menu) Descriptor() uispec.ResourceDescriptor
Descriptor implements Widget.
type MenuItem ¶
type MenuItem struct {
// Tool is the MCP tool called when the item is chosen (required). With
// Prompt set the call is the model's to make, so Tool documents what the
// item opens and still supplies the default Label.
Tool string
// Args are static arguments passed to Tool. Menu items carry no record,
// so unlike Action args these are fixed values, not row lookups. Ignored
// when Prompt is set — the model chooses the arguments there.
Args map[string]any
// Prompt, when set, makes the item ask the host to post this text as a
// user message (ui/message) instead of calling Tool itself. Write it as
// the request a user would type: the model reads it and decides which
// tool answers, so name what the item opens rather than the tool.
Prompt string
// Label is the tile heading. Defaults to Tool.
Label string
// Description is the supporting line under the label.
Description string
// IconSVG is inline <svg> markup shown above the label. Documents stay
// self-contained, so an icon is never a URL. It is author-trusted input,
// checked only against script-bearing and resource-loading constructs.
IconSVG string
// Badge is optional short text shown in the tile's top right — a category
// or state marker such as "read" or "beta".
Badge string
// BadgeVariant colors the badge. Defaults to BadgeNeutral.
BadgeVariant BadgeVariant
}
MenuItem is one entry in a Menu: a tool the user can start from the menu tile grid. Choosing it calls Tool with Args; the host answers by opening that tool's own widget, so a menu item is navigation rather than an action with a result of its own.
That relies on the host opening the widget bound to a view-initiated tools/call. A host that instead runs such a call out of band answers it without opening anything, and the tile looks inert. Prompt switches the item to the chat path for those hosts: the host posts the text as a user turn, the model calls the tool, and the widget arrives as that call's result.
type RejectSpec ¶
type RejectSpec struct {
// Label defaults to "Cancel".
Label string
// Tool is an optional MCP tool called when the reader declines. Without
// it, declining is a local outcome the server never hears about — set it
// when the operation needs an explicit "no".
Tool string
// Args maps tool argument names to their sources (Static and FromRow).
Args map[string]ArgSource
// Message is shown in place of the buttons once the reader declines.
// Defaults to "Cancelled."
Message string
}
RejectSpec configures the declining button.
type SelectionConfig ¶
type SelectionConfig struct {
// Bulk actions appear in the toolbar while rows are selected.
// FromSelection args resolve across all selected rows.
Bulk []Action
}
SelectionConfig enables row selection.
type SubmitSpec ¶
type SubmitSpec struct {
// Tool is the MCP tool called with {field: value, ...} merged over
// StaticArgs (required).
Tool string
// Label defaults to "Submit".
Label string
// StaticArgs are fixed arguments merged under the field values.
StaticArgs map[string]any
// SuccessMessage is shown after a successful submit.
SuccessMessage string
}
SubmitSpec configures form submission.
type Table ¶
type Table struct {
// URI is the widget's ui:// resource URI (required).
URI string
// Title is shown in the toolbar and the document title.
Title string
// Columns defines the table's columns (required, non-empty).
Columns []Column
// RowsKey is the structuredContent key holding the rows array.
// Defaults to "rows".
RowsKey string
// RowID is the row field that uniquely identifies a row, used for
// selection and FromRow/FromSelection args. Defaults to "id".
RowID string
// PageSize enables client-side pagination when > 0.
PageSize int
// PageSizes offers alternative page sizes in a dropdown on the pagination
// bar. Entries must be > 0 and PageSize must be set; PageSize is added to
// the list if it is not among them. Empty renders no chooser.
PageSizes []int
// DefaultSort pre-sorts rows on load.
DefaultSort *SortSpec
// Filterable adds a client-side text filter box.
Filterable bool
// Selection enables row checkboxes and bulk actions.
Selection *SelectionConfig
// Empty configures the no-data message.
Empty EmptyState
// InitialData is an optional structuredContent-shaped snapshot baked
// into the document as a JSON island.
InitialData map[string]any
// LoadTool, when set, names a read tool the runtime calls once on load
// (after the host handshake) to hydrate the table from fresh data,
// replacing the baked InitialData snapshot. This keeps a reloaded widget
// current instead of reverting to the state frozen at render time. The
// tool must return the rows under RowsKey in its structuredContent.
LoadTool string
// LoadArgs are optional static arguments passed to LoadTool.
LoadArgs map[string]any
// Brand renders the application logo/name on the widget.
Brand *Brand
// Theme overrides gomukit design tokens for this widget.
Theme *theme.Theme
// UI overrides resource _meta.ui (CSP, permissions, prefersBorder).
UI *uispec.ResourceUIMeta
}
Table is an interactive data table widget: typed columns, client-side sort/filter/pagination, row selection with bulk actions, and per-row actions that call MCP tools.
Rows are string-keyed JSON objects delivered at runtime in the tool result's structuredContent (under RowsKey); the embedded runtime renders them. InitialData optionally bakes a snapshot into the document for instant first paint.
func (*Table) Descriptor ¶
func (t *Table) Descriptor() uispec.ResourceDescriptor
Descriptor implements Widget.
type Validation ¶
type Validation struct {
// Pattern is a regular expression the value must match (HTML pattern
// attribute semantics).
Pattern string
// Min/Max/Step constrain number, date, and time fields.
Min *float64
Max *float64
Step *float64
// MinLen/MaxLen constrain text lengths.
MinLen *int
MaxLen *int
// Message overrides the browser's validation message.
Message string
}
Validation declares client-side constraints, rendered as native HTML validation attributes and enforced before submit.
type WeekStart ¶
type WeekStart string
WeekStart is the day a calendar's week begins on.
const ( // WeekStartLocale takes the first day from the host's locale — Monday in // most of the world, Sunday in the US, Saturday in much of the Middle // East. It is the default, and the right answer unless a domain says // otherwise (a Monday-to-Sunday shift roster, say). WeekStartLocale WeekStart = "" WeekStartMonday WeekStart = "monday" WeekStartSunday WeekStart = "sunday" // WeekStartSaturday is the first day in much of the Middle East. WeekStartSaturday WeekStart = "saturday" )
type Widget ¶
type Widget interface {
// Document renders the complete self-contained HTML document.
Document() (string, error)
// Descriptor returns registration data for the template resource.
Descriptor() uispec.ResourceDescriptor
// ToolMeta returns the _meta map linking a tool to this widget:
// {"ui": {"resourceUri": ...}}.
ToolMeta() map[string]any
// Validate checks the widget configuration.
Validate() error
}
Widget is a renderable MCP Apps UI template. The widget's ui:// URI is available as Descriptor().URI.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
examples
|
|
|
demo
command
Command demo is a runnable MCP server showcasing gomukit widgets: a user table with row/bulk actions, the same users as a card grid, an edit form with server-side validation, a confirmation, and a date picker whose selectable window is computed per call.
|
Command demo is a runnable MCP server showcasing gomukit widgets: a user table with row/bulk actions, the same users as a card grid, an edit form with server-side validation, a confirmation, and a date picker whose selectable window is computed per call. |
|
harness
command
Command harness serves a fake MCP Apps host for manually smoke-testing gomukit widgets without a real host.
|
Command harness serves a fake MCP Apps host for manually smoke-testing gomukit widgets without a real host. |
|
preview
command
Command preview is a runnable MCP server built for inspecting gomukit: it exposes every widget the library renders as real MCP tools and ui:// resources, so an MCP Apps capable inspector drives them over the wire instead of through a fake host page.
|
Command preview is a runnable MCP server built for inspecting gomukit: it exposes every widget the library renders as real MCP tools and ui:// resources, so an MCP Apps capable inspector drives them over the wire instead of through a fake host page. |
|
Package gosdk adapts gomukit widgets to the official Go MCP SDK (github.com/modelcontextprotocol/go-sdk).
|
Package gosdk adapts gomukit widgets to the official Go MCP SDK (github.com/modelcontextprotocol/go-sdk). |
|
internal
|
|
|
assets
Package assets embeds the compiled gomukit runtime (JavaScript) and stylesheet.
|
Package assets embeds the compiled gomukit runtime (JavaScript) and stylesheet. |
|
htmlx
Package htmlx assembles complete, self-contained MCP Apps HTML documents: inline stylesheet, widget shell markup, JSON data islands, and the inline runtime bundle.
|
Package htmlx assembles complete, self-contained MCP Apps HTML documents: inline stylesheet, widget shell markup, JSON data islands, and the inline runtime bundle. |
|
Package theme provides global styling overrides for gomukit widgets.
|
Package theme provides global styling overrides for gomukit widgets. |
|
Package uispec defines constants and _meta types for the MCP Apps extension (io.modelcontextprotocol/ui), spec version 2026-01-26.
|
Package uispec defines constants and _meta types for the MCP Apps extension (io.modelcontextprotocol/ui), spec version 2026-01-26. |