Skip to main content
Glama

Get a FoxForm form

foxform_get_form
Read-onlyIdempotent

Fetch a single form by ID, including its full question list, per-screen conditional logic and settings.

Args:

  • form_id (string): the form's ID (from foxform_list_forms)

  • response_format ('markdown' | 'json')

Returns { form, public_url }: the full form object (id, title, description, slug, status, theme, questions[], thank_you_message, timestamps, plus format and — when set — sections, chatbot_skin, chatbot_profile) plus public_url — the public link (https://forms.foxform.app/<slug>), which is live only when status is 'published'. Use public_url verbatim; never build the URL yourself (the public domain is forms.foxform.app, not foxform.app). Each screen in questions[] carries its own logic (branching / conditional display) and, for choice screens, choices[]/images[] with their points and value. The markdown output summarises every rule; use response_format 'json' to get the exact stored objects (that's the shape foxform_update_form expects back).

Form format (DEVF-296 / DEVF-322): pass format to choose how the form is presented.

  • 'single_question' (default): one screen at a time (classic).

  • 'single_page': every screen on one scrollable page. Optionally group screens into pages with sections: [{ id }] in order (the 'Section N' label comes from position; no editable title).

  • 'chatbot': an Instagram/WhatsApp DM-style conversation. Set chatbot_skin ('instagram' | 'whatsapp', default instagram) and chatbot_profile (all fields optional, each with a fallback). The question/branching engine is unchanged — only the presentation differs. These fields require the account's form-format feature to be enabled (live in production); when off the API ignores them and the form stays single_question.

End screen ('end'): title + description, an optional button (buttonEnabled false hides it; buttonText, buttonLink, buttonOpenNewTab) and an optional automatic redirect after submit: autoRedirect true + autoRedirectUrl (absolute http/https URL; the form link's query params such as utm_* are passed along and {{param}} tokens are filled from them) + autoRedirectDelay (seconds 0-10, default 3). The response is recorded before the redirect; respondents see a "Redirecting in N s" line with a "Go now" link.

CONDITIONAL LOGIC (branching), per screen — stored in questions[].logic:

logic.conditionalNavigationV2 = { enabled: true, groups: [ // groups are OR-joined; FIRST matching group wins { id: "grp-1", conditions: [ // conditions inside a group are AND-joined { id: "cond-1", left: "{{quer_testar}}", operator: "equal_to", right: "Ainda não" } ], then: { type: "specific_screen", targetScreenId: "s-motivos" } } ] }

  • then.type: 'next_screen' | 'previous_screen' | 'specific_screen' (needs targetScreenId = another screen's id) | 'end_form'. Add then.url (+ optional openNewTab) to redirect to an external URL instead.

  • operator: 'equal_to' | 'not_equal_to' | 'greater_than' | 'greater_or_equal_than' | 'less_than' | 'less_or_equal_than' | 'contains'.

  • left/right are EXPRESSION strings: a literal ("10", "Ainda não"), a variable ("{{score}}", "{{minha_var}}" = the screen's variableName), or arithmetic ("calc({{peso}}/(({{altura}}/100)*({{altura}}/100)))").

  • Comparing an ANSWER: use left: "{{<variableName of the deciding screen>}}" and right = the option's label OR its value (both match).

  • {{score}} is the running sum of points on the options picked so far (choices[].points, images[].points) — that is how score-based branching works.

  • A navigation group with no conditions NEVER matches. enabled: false stores the rules but disables them.

  • Screen-level conditional display uses the same group shape: logic.display = { enabled: true, groups: [...], showAfterSeconds?: n } (then is ignored — THEN means "show").

  • Other logic keys: logic.autoAdvance = { enabled, delaySeconds? }, logic.navigationBehavior = { onButtonClick?, onAutoAdvance?, targetScreenId? }.

  • logic.conditionalNavigation (legacy, pre-DEVF-161) is still read and migrated on load — don't author new rules with it.

Unknown fields are REJECTED (they used to be stored and silently ignored): logic as an array, or rules/branching/conditions/goto/jump/nextScreen anywhere, are not read by any renderer.

Input Schema

NameRequiredDescriptionDefault
form_idYesForm ID
response_formatNoOutput format: 'markdown' (human-readable) or 'json' (machine-readable)markdown

Schema Changelog

Changes observed during successful MCP inspections.

  1. First observed

TDQS

A3.9/5.0
Behavior4/5

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

Annotations already declare the read-only/idempotent/non-destructive profile, and the description adds genuinely non-obvious behavior: public_url is live only when status is 'published', the URL must be used verbatim because the public domain differs from the API domain, and markdown output only summarises rules while json returns exact stored objects. These are constraints the schema 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.

Conciseness2/5

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

The opening two paragraphs are front-loaded and earn their place, but the bulk of the text is authoring documentation for conditional logic (groups, operators, expression syntax, legacy keys) and format/section/chatbot/end-screen configuration that only matters to foxform_create_form / foxform_update_form. Statements like 'Unknown fields are REJECTED' are irrelevant to a tool with two fixed parameters, so the length is not justified for this operation.

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

Completeness4/5

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

With no output schema and a deeply nested return object, the description carries a real burden and mostly meets it: it enumerates the form object's fields, explains public_url liveness, and explains that each screen carries its own logic/choices. It is complete for calling the tool, though the deep-dive into logic authoring belongs to the write tools rather than to reading.

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; the description goes further by stating where form_id comes from and the practical difference between the two response_format values (markdown summarises, json is the exact round-trippable shape). That is real meaning beyond the enum labels.

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 ('Fetch a single form by ID') and immediately enumerates what is included (question list, per-screen conditional logic, settings), which distinguishes it from the analytics and list siblings. The return contract ({ form, public_url }) is stated up front.

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

Usage Guidelines3/5

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

It does route the agent usefully: form_id comes from foxform_list_forms, and response_format 'json' is the shape foxform_update_form expects back, implying the read-before-update workflow. But there is no explicit contrast with foxform_get_form_analytics or foxform_list_forms, and the instruction 'pass `format` to choose how the form is presented' describes an authoring parameter this read tool does not accept, which can mislead an agent about what it can do here.

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