Skip to content

Commit 794db74

Browse files
committed
fix(server): serialize non-finite floats as null in text content blocks to ensure valid RFC 8259 JSON
1 parent d2290ca commit 794db74

4 files changed

Lines changed: 25 additions & 3 deletions

File tree

src/mcp/server/mcpserver/prompts/base.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,9 @@ async def render(
203203
elif isinstance(msg, str | ContentBlock | Image | Audio): # bare content is one user message
204204
messages.append(UserMessage(msg))
205205
else: # pragma: no cover
206-
content = pydantic_core.to_json(msg, fallback=str, indent=2).decode()
206+
content = pydantic_core.to_json(
207+
msg, fallback=str, indent=2, inf_nan_mode="null"
208+
).decode()
207209
messages.append(Message(role="user", content=content))
208210

209211
return messages

src/mcp/server/mcpserver/resources/types.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,9 @@ async def read(self) -> str | bytes:
100100
elif isinstance(result, str):
101101
return result
102102
else:
103-
return pydantic_core.to_json(result, fallback=str, indent=2).decode()
103+
return pydantic_core.to_json(
104+
result, fallback=str, indent=2, inf_nan_mode="null"
105+
).decode()
104106

105107
@classmethod
106108
def from_function(

src/mcp/server/mcpserver/utilities/func_metadata.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -666,6 +666,8 @@ def _convert_to_content(result: Any) -> list[ContentBlock]:
666666
)
667667

668668
if not isinstance(result, str):
669-
result = pydantic_core.to_json(result, fallback=str, indent=2).decode()
669+
result = pydantic_core.to_json(
670+
result, fallback=str, indent=2, inf_nan_mode="null"
671+
).decode()
670672

671673
return [TextContent(type="text", text=result)]

tests/server/mcpserver/test_func_metadata.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1520,3 +1520,19 @@ def fn() -> StepA | StepB: ... # pragma: no branch
15201520

15211521
meta = func_metadata(fn)
15221522
assert meta.output_schema is None
1523+
1524+
1525+
def test_convert_to_content_non_finite_floats():
1526+
import json
1527+
import math
1528+
from mcp.server.mcpserver.utilities.func_metadata import _convert_to_content
1529+
1530+
result = {"mean": 1.5, "stddev": math.nan, "max": math.inf, "min": -math.inf}
1531+
content = _convert_to_content(result)
1532+
assert len(content) == 1
1533+
assert content[0].type == "text"
1534+
text = content[0].text
1535+
# Must be valid RFC 8259 JSON parseable by standard JSON parsers
1536+
parsed = json.loads(text)
1537+
assert parsed == {"mean": 1.5, "stddev": None, "max": None, "min": None}
1538+

0 commit comments

Comments
 (0)