Skip to content

[Bug] validate_tool_use_result_messages raises false positive when tool_use is not followed by tool_result #2960

Description

@Robin1987China

Bug Description

validate_tool_use_result_messages() in src/mcp/server/validation.py:83-87 raises a false ValueError when a tool_use block in the previous message is not followed by a tool_result block in the last message.

Spec Context

Per SEP-1577:

  • tool_result blocks MUST be preceded by a tool_use block ✅ (already checked)
  • There is no requirement that tool_use must be followed by tool_result

A plain text response after a tool_use is valid.

Reproduction

from mcp.types import SamplingMessage, TextContent, ToolUseContent
from mcp.server.validation import validate_tool_use_result_messages

msg1 = SamplingMessage(role="assistant", content=[
    TextContent(type="text", text="Hold on..."),
    ToolUseContent(type="tool_use", id="abc", name="search", input={"q": "test"}),
])
msg2 = SamplingMessage(role="user", content=[
    TextContent(type="text", text="Thanks, no results needed"),
])

validate_tool_use_result_messages([msg1, msg2])
# ValueError: ids of tool_result blocks and tool_use blocks from previous message do not match
# This is a false positive — msg2 has NO tool_result at all!

Root Cause

Line 83 runs the ID-matching check outside the if has_tool_results: block:

# L83 — runs unconditionally after the has_tool_results block
if has_previous_tool_use and previous_content:
    tool_use_ids = {c.id for c in previous_content if c.type == "tool_use"}
    tool_result_ids = {c.tool_use_id for c in last_content if c.type == "tool_result"}
    if tool_use_ids != tool_result_ids:  # tool_result_ids is empty → mismatch
        raise ValueError(...)

Fix (proposed)

Add has_tool_results to the condition:

if has_tool_results and has_previous_tool_use and previous_content:

AI Disclosure

Bug discovered with AI assistance (opencode).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions