Skip to content

Conversation

@jayhemnani9910
Copy link
Contributor

Summary

Some LLM clients incorrectly serialize booleans as strings ("false" instead of false in JSON). This causes FastMCP tools to receive
the string 'false' instead of Python False, making if param: checks evaluate incorrectly.

Root Cause

The existing pre_parse_json method was supposed to handle this via json.loads, but boolean values were being skipped because:

  1. json.loads("false") correctly returns Python False
  2. However, bool is a subclass of int in Python
  3. The skip condition isinstance(pre_parsed, str | int | float) matches booleans (since isinstance(False, int) is True)
  4. So the parsed boolean was discarded

Changes

  • Added explicit case-insensitive boolean string coercion in pre_parse_json method
  • Handles "true"/"false" strings (any case) → Python True/False
  • Processing happens before the generic JSON parsing logic
  • Only applies when parameter annotation is bool

Testing

  • Added 6 comprehensive test cases
  • All 39 func_metadata tests pass
  • All 329 FastMCP tests pass
  • Linter (ruff) passes
  • Type checker (pyright) passes

Related Issues

Fixes #1843

Some LLM clients incorrectly serialize booleans as strings ("false"
instead of false in JSON). The existing pre_parse_json method was
supposed to handle this via json.loads, but boolean values were being
skipped because bool is a subclass of int in Python, and the skip
condition isinstance(pre_parsed, str | int | float) matches booleans.

This fix adds explicit case-insensitive boolean string coercion before
the generic JSON parsing logic, properly converting "true"/"false"
strings to Python True/False when the parameter annotation is bool.

Fixes modelcontextprotocol#1843
Copilot AI review requested due to automatic review settings January 12, 2026 04:59
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR fixes an issue where LLM clients incorrectly serialize boolean values as strings (e.g., "false" instead of false in JSON), causing FastMCP tools to receive string values instead of Python booleans. This made if param: checks evaluate incorrectly since the string 'false' is truthy in Python.

Changes:

  • Added explicit case-insensitive boolean string coercion in the pre_parse_json method to convert "true"/"false" strings to Python True/False
  • Added 6 comprehensive test cases covering lowercase, case-insensitive, native booleans, non-boolean strings, runtime validation, and type-specific behavior
  • The fix is applied before generic JSON parsing to handle the edge case where json.loads("false") returns False, but isinstance(False, int) is True, causing the parsed boolean to be skipped

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
src/mcp/server/fastmcp/utilities/func_metadata.py Added boolean string coercion logic in pre_parse_json method to handle string "true"/"false" values for bool-annotated parameters
tests/server/fastmcp/test_func_metadata.py Added 6 comprehensive test functions validating boolean coercion for various cases including case-insensitivity, native booleans, non-boolean strings, runtime validation, and type specificity

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Function parameter coercion ("false" => False) failures in properly documented FastMCP tools?

1 participant