Skip to main content
Glama

Publish a form

publish_form

Call this to put 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. When save_form_draft is listed, use it instead to prepare 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. Call 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.

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. 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. password, file, autocomplete, optionsFrom and custom types are refused.

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

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

  • 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

TableJSON 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.
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

TableJSON 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. 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"
      +]
  2. First observed

TDQS

A4.7/5.0
Behavior5/5

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

Annotations give a basic mutation profile (readOnlyHint=false, idempotentHint=false, openWorldHint=true), but the description goes far beyond them: the full return payload, the unauthenticated path that returns claim_url/expires_at/terms_url and implicitly accepts Terms for the user, first-call agent_key issuance, and the 7-day claim deadline. It also documents error behaviour (fix every listed path and call again) and credential handling, which annotations cannot express.

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

Conciseness3/5

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

Front-loaded and dense, but bloated for its purpose: an output schema exists, yet the description still enumerates every returned key (form_id, version, endpoint, hosted_url, embed_snippet, iframe_snippet, react_snippet, vue_snippet, dashboard_url, warnings), and the minimal definition example is duplicated verbatim in the definition parameter's schema description. The embedded Rules block is valuable but pushes the text well past what a front-loaded summary needs.

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 complex, irreversible publish with a nested definition payload, the description covers the creation branches, the full validation ruleset, credential and key handling, the claim_url handoff to the user, and error recovery. With the output schema present it need not explain return values further, so nothing an agent needs to call this 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 description coverage is 100%, so the baseline would be 3, but the description adds genuine semantics: the create-vs-version branch on form_id, the carry-over rule for allow_another_response, and the fallback that a materially invalid definition gets refused (password/file/autocomplete types, 32 KB / 100 field caps). The email/redirect_url caveats are largely mirrored in the schema, which keeps this from a 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 (publish) plus the resource and the exact branching semantics: without form_id it creates a new form, with form_id it publishes a new version. It also contrasts itself with a named alternative (save_form_draft), so an agent can separate it from siblings like update_form_settings or list_forms 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?

Explicit when-to-use ("put a form live", "when the user needs a working form... without writing a backend") and explicit when-not with a named alternative ("When save_form_draft is listed, use it instead to prepare changes to a live form without going live"). Preconditions (account key vs no key) and the new-form-vs-new-version branch are spelled out.

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