Skip to main content
Glama

Publish a form

publish_form
Destructive

Puts a form live on Formhaus Cloud: without form_id it creates a new form, with form_id it publishes a new version of that form. With form_id the new version replaces the live version of that form. save_form_draft, when listed, prepares changes to a live form without going live. Returns form_id, version, endpoint (POST URL for submissions), hosted_url, embed_snippet, iframe_snippet, react_snippet, vue_snippet, dashboard_url and warnings. Without an account key it also returns claim_url, expires_at and terms_url (publishing accepts these Terms for the user), and on the first call without any key agent_key and agent_key_notice. Use it when the user needs a working form (contact, waitlist, signup, survey, feedback) without writing a backend. A new version keeps form_id, endpoint and links. allow_another_response: true shows a "Submit another response" button on the success screen of the hosted page and embed; a new form starts with false, and a new version keeps the current value unless you send it. folder (account keys only): a folder id or name from list_forms; a new form goes into it and a new version moves the form into it.

Minimal valid definition: {"id":"waitlist","title":"Join the waitlist","submit":{"label":"Join"},"fields":[{"key":"email","type":"email","label":"Email","validation":{"required":true}}]}

Rules:

  • Top level needs id, title and submit {"label": "..."}.

  • Each field needs key, type and label; a hidden field may omit label. Use "fields" for one step, or "steps" (each with id, title and fields) for several, never both.

  • Types: text, email, phone, number, textarea, select, multiselect, radio, checkbox, switch, date, datetime, scale, rating, file. A form has at most 5 file fields; each file is up to 10 MB and must be PDF, PNG, JPEG, WebP, GIF, TXT, CSV, DOCX or XLSX. password, autocomplete, optionsFrom and custom types are refused.

  • select, multiselect and radio need "options": [{"value": "a", "label": "A"}].

  • scale shows numbered points from validation.min (0 or 1, default 1) to validation.max (default 5); rating shows 1 to validation.max stars (default 5). Both take 2 to 11 points and store a whole number. Up to 3 "options" whose value is a point, such as {"value": "10", "label": "Extremely likely"}, label that point. NPS is a scale from 0 to 10. Set "formatVersion": "1.3" when a form uses scale or rating.

  • radio and multiselect options may have "image": an https: or data:image/ URL shown with the label. Other URLs do not show. "columns" (1 to 4) sets the picture cards per row.

  • A section with "layout": "matrix" (the only layout value) shows its radio and multiselect fields as rows with shared columns; give every row the same options. A step or section may have no fields, as a welcome or statement screen.

  • "validation": {"required": true, "minLength": 2, "maxLength": 200, "min": 0, "max": 10, "pattern": "^[a-z]+$"}.

  • Format 1.5 ("formatVersion": "1.5") adds three features. {{key}} in a step or section title or description, or in a field label, helperText, placeholder or group itemLabel, shows the answer of an earlier field, such as "label": "Why did {{name}} join?". A multiselect option with "exclusive": true, such as "None of these", is the only answer when picked; put it last. "autocomplete" takes an HTML autofill token such as "given-name", "email" or "off". Hosted forms refuse cc-* and current-password tokens.

  • At most 32 KB and 100 fields.

  • JSON Schema: https://formhaus.dev/schema/form-definition.json

Store agent_key in .env as FORMHAUS_API_KEY, never in browser code; the MCP client must send it as Authorization: Bearer <agent_key>. Give claim_url to the user: they must open it within 7 days to keep the form. The text of the result has hosted_url, endpoint, embed_snippet and, when issued, agent_key and claim_url; every field is in structuredContent. On error, fix every listed path and call again.

Input Schema

NameRequiredDescriptionDefault
emailNoOnly for a new form published without an account key: the user's email. Formhaus emails them claim_url (at most one email per address per hour, no form content). Ignored with a warning otherwise.
folderNoAccount keys only: a folder id or name from the folders that list_forms returns. A new form goes into that folder; with form_id the form moves into it. Empty string takes the form out of its folder. Omit to leave the form where it is.
form_idNoThe 10-character form_id of an existing form to publish a new version of it. Requires an account key (fh_live_...) of the form's account or the agent key (fh_agent_...) that created the form. Omit to create a new form.
definitionYesThe Formhaus form definition: a JSON object, or a string containing that JSON. Minimal example: {"id":"waitlist","title":"Join the waitlist","submit":{"label":"Join"},"fields":[{"key":"email","type":"email","label":"Email","validation":{"required":true}}]}
redirect_urlNohttp(s) URL the hosted page and embed open after a successful submission instead of the success message. Empty string removes it. Ignored with a warning for unclaimed forms.
success_messageNoText shown after a successful submission on the hosted page and embed. Up to 500 characters.
allow_another_responseNotrue shows a Submit another response button on the success screen of the hosted page and embed. false hides it. A new form starts with false; a new version keeps the current value when omitted. No effect while redirect_url is set.

Output Schema

NameRequiredDescriptionDefault
form_idYes
versionYes
endpointYes
warningsYes
agent_keyNo
claim_urlNo
terms_urlNo
expires_atNo
hosted_urlYes
vue_snippetYes
form_versionYes
dashboard_urlYes
embed_snippetYes
react_snippetYes
iframe_snippetYes
agent_key_noticeNo

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed1 schema field changed
    • addedInput schema / properties / folder
      Added value: +{
      +  "description": "Account keys only: a folder id or name from the folders that list_forms returns. A new form goes into that folder; with form_id the form moves into it. Empty string takes the form out of its folder. Omit to leave the form where it is.",
      +  "type": [
      +    "null",
      +    "string"
      +  ]
      +}
  2. Changed2 schema fields changed
    • addedOutput schema / properties / iframe_snippet
      Added value: +{
      +  "type": "string"
      +}
    • changedOutput schema / required
      Previous value: -[
      -  "form_id",
      -  "version",
      -  "form_version",
      -  "endpoint",
      -  "hosted_url",
      -  "embed_snippet",
      -  "react_snippet",
      -  "vue_snippet",
      -  "dashboard_url",
      -  "warnings"
      -]New value: +[
      +  "form_id",
      +  "version",
      +  "form_version",
      +  "endpoint",
      +  "hosted_url",
      +  "embed_snippet",
      +  "iframe_snippet",
      +  "react_snippet",
      +  "vue_snippet",
      +  "dashboard_url",
      +  "warnings"
      +]
  3. First observed

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes well beyond annotations: it discloses that a new version replaces the live version (consistent with destructiveHint=true), enumerates the return payload, explains the no-account-key claim flow (claim_url, expires_at, terms_url, 7-day window), agent_key issuance and storage requirement, and error recovery ('fix every listed path and call again'). This is substantial behavioral context that annotations alone do not provide.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Dense but front-loaded: the core create-vs-publish rule is the first sentence, and the long format-rules section is largely necessary for the complex definition parameter. Some redundancy exists where allow_another_response and folder are re-explained after already appearing in the schema, keeping it from a 5.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a high-complexity, 7-parameter mutation tool this is thorough: authentication, key storage, claim lifecycle, output fields, format-version rules, size limits, and error behavior are all covered. An output schema exists so return-value detail is bonus rather than a requirement, and nothing needed to call correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds real meaning: allow_another_response new-form-vs-new-version defaults, folder behavior for new vs. existing forms, and an extensive specification of the definition format (types, validation, layout, formatVersion, exclusivity, limits). It restates some schema params, which caps it below 5.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource and immediately splits the two behaviors: 'without form_id it creates a new form, with form_id it publishes a new version of that form.' It names the sibling tool save_form_draft and the relationship to it, so an agent can distinguish this from get_submissions, list_forms, and update_form_settings without opening a schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit when-to-use ('when the user needs a working form... without writing a backend') with concrete examples, and names the alternative (save_form_draft) that prepares changes without going live. The condition separating create vs. new-version is also stated up front.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.

Resources