Skip to content

fix: boolean false values dropped in form submissions#3776

Merged
jlowin merged 2 commits intomainfrom
fix/form-boolean-false
Apr 7, 2026
Merged

fix: boolean false values dropped in form submissions#3776
jlowin merged 2 commits intomainfrom
fix/form-boolean-false

Conversation

@jlowin
Copy link
Copy Markdown
Member

@jlowin jlowin commented Apr 7, 2026

HTML checkboxes don't send a value when unchecked, so Prefab UI forms omit boolean fields entirely from the submitted data. This caused submit_form to fail with a "Missing required argument" error even when the boolean field had a Pydantic default.

Two fixes:

In form.py, the submit_form tool now backfills missing boolean fields with their model defaults (or False) before Pydantic validation. The data parameter also defaults to None so the tool doesn't reject an empty argument dict outright.

In apps_dev.py, the dev server's form handler now parses "true"/"false" strings into actual booleans instead of dropping them during the empty-string filter.

class NoteForm(BaseModel):
    title: str
    content: str
    archived: bool = False  # unchecked checkbox now correctly submits as False

mcp.add_provider(FormInput(model=NoteForm))

Closes #3769

@marvin-context-protocol marvin-context-protocol Bot added bug Something isn't working. Reports of errors, unexpected behavior, or broken functionality. contrib Related to community contributions in src/contrib/ directory. cli Related to FastMCP CLI commands (run, dev, install) or CLI functionality. labels Apr 7, 2026
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 87ba54d7ae

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/fastmcp/cli/apps_dev.py Outdated
Comment on lines +1454 to +1455
if stripped.lower() in ("true", "false"):
v = stripped.lower() == "true"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Avoid coercing every "true"/"false" string to bool

In api_launch form mode, this unconditional conversion changes any user-entered "true"/"false" string into a boolean before tool validation, even when the target parameter is typed as str. That creates a regression for string inputs (for example a str field set to "false" now arrives as False and fails Pydantic string validation), so boolean parsing should be gated by the argument schema/type instead of applied globally.

Useful? React with 👍 / 👎.

Comment thread src/fastmcp/apps/form.py
Comment on lines +71 to +74
if field_info.default is not pydantic.fields.PydanticUndefined:
data[name] = field_info.default
else:
data[name] = False
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Respect default_factory when backfilling boolean defaults

_backfill_boolean_defaults says it backfills from model defaults, but this branch only checks field_info.default; for boolean fields declared with Field(default_factory=...), default is PydanticUndefined, so missing input is forced to False instead of using the configured factory value. That silently overrides model behavior for omitted checkbox fields and can invert defaults in production forms.

Useful? React with 👍 / 👎.

@marvin-context-protocol
Copy link
Copy Markdown
Contributor

marvin-context-protocol Bot commented Apr 7, 2026

Test Failure Analysis

Summary: One test timed out on Windows Python 3.10 — test_run_mcp_config in tests/cli/test_run.py — but this failure is unrelated to the PR's changes.

Root Cause: The failing test spawns a Python subprocess via stdio transport (an MCP proxy server), which can be slow to start on Windows. The unit test timeout is 5 seconds, which is occasionally not enough for subprocess startup + FastMCP import on Windows CI runners. All other platforms (Ubuntu Python 3.10 and 3.13) passed.

Suggested Solution: This appears to be pre-existing Windows flakiness in test_run_mcp_config, not caused by this PR. The PR only touches form.py, apps_dev.py, and test_form.py — none of which are in the code path exercised by the failing test. A re-run of the workflow should pass.

Note: This comment has been updated after re-analysis of workflow run 24086992468 — same failure, same root cause.

Detailed Analysis

Failing test: tests/cli/test_run.py::TestMCPConfig::test_run_mcp_config on Tests: Python 3.10 on windows-latest

Timeout log excerpt:

tests\cli\test_run.py ........+++++++++++++++++++++++++++++++++++ Timeout +++++++++++++++++++++++++++++++++++

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Captured stderr ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
DEBUG    Inferred transport: <MCPConfigTransport(...)>
DEBUG    Inferred transport: <FastMCPTransport(server='FastMCP Proxy-fc41')>
DEBUG    [Client-1903] called list_tools
DEBUG    [FastMCPProxy-fc41] Handler called: list_tools
DEBUG    Stdio transport connected
~~~~~~~~~~~~~~~~~~~~~ Stack of AnyIO worker thread ~~~~~~~~~~~~~~~~~~~~~
  ... waiting on queue.get() ...

What the test does: Creates an MCPConfig pointing to a temp Python script, wraps it in a FastMCP proxy server, and calls list_tools(). The transport connects via stdio to a spawned python subprocess. The subprocess connects (Stdio transport connected) but the 5s timeout fires before list_tools returns.

Why it's unrelated to this PR: The PR diff only touches:

  • src/fastmcp/apps/form.py — form submission logic
  • tests/apps/test_form.py — form tests

None of these are in the proxy, transport, or MCP config code paths.

Other passing jobs:

  • ✅ Tests: Python 3.10 on ubuntu-latest
  • ✅ Tests: Python 3.13 on ubuntu-latest
  • ✅ Integration tests
  • ✅ MCP conformance tests
  • ✅ Tests with lowest-direct dependencies
Related Files
  • tests/cli/test_run.py:104TestMCPConfig::test_run_mcp_config — the timed-out test; spawns a Python subprocess via stdio
  • src/fastmcp/apps/form.py — PR change (unrelated to failure)

@jlowin jlowin merged commit 8ee81b3 into main Apr 7, 2026
13 of 14 checks passed
@jlowin jlowin deleted the fix/form-boolean-false branch April 7, 2026 15:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working. Reports of errors, unexpected behavior, or broken functionality. cli Related to FastMCP CLI commands (run, dev, install) or CLI functionality. contrib Related to community contributions in src/contrib/ directory.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Unable to submit boolean false via fastmcp dev apps form

1 participant