-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Description
Agent Framework Bug Report: MCP CallToolResult._meta Field Not Respected
Summary
The Agent Framework library violates the official Model Context Protocol (MCP) specification by completely dropping the _meta field from CallToolResult responses. This prevents applications from accessing critical metadata such as token usage, cost information, and performance metrics that MCP servers can provide.
Bug Details
Location: agent_framework/_mcp.py in function _mcp_call_tool_result_to_ai_contents()
Issue: The function only processes the content field of CallToolResult objects and completely ignores the _meta field, which is part of the official MCP specification.
Impact:
- Loss of critical tool execution metadata (token usage, costs, performance metrics)
- Protocol compliance violation
- Prevents proper monitoring and cost tracking of MCP tool usage
- Breaks integration with compliant MCP servers that return metadata
Evidence from Official MCP Specification
1. Official Type Definition
From the official MCP Python SDK repository in src/mcp/types.py:
class CallToolResult(Result):
"""The server's response to a tool call."""
content: list[ContentBlock]
structuredContent: dict[str, Any] | None = None
isError: bool = False
# _meta field is inherited from Result base class
class Result(BaseModel):
"""Base class for JSON-RPC results."""
meta: dict[str, Any] | None = Field(alias="_meta", default=None)
"""
See [MCP specification](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/47339c03c143bb4ec01a26e721a1b8fe66634ebe/docs/specification/draft/basic/index.mdx#general-fields)
for notes on _meta usage.
"""
model_config = ConfigDict(extra="allow")2. Official Documentation
From the MCP Python SDK README.md (lines 387-417):
Advanced: Direct CallToolResult
For full control over tool responses including the
_metafield (for passing data to client applications without exposing it to the model), you can returnCallToolResultdirectly
3. Official Examples
From examples/snippets/servers/direct_call_tool_result.py:
@mcp.tool()
def advanced_tool() -> CallToolResult:
"""Return CallToolResult directly for full control including _meta field."""
return CallToolResult(
content=[TextContent(type="text", text="Response visible to the model")],
_meta={"hidden": "data for client applications only"},
)
@mcp.tool()
def validated_tool() -> Annotated[CallToolResult, ValidationModel]:
"""Return CallToolResult with structured output validation."""
return CallToolResult(
content=[TextContent(type="text", text="Validated response")],
structuredContent={"status": "success", "data": {"result": 42}},
_meta={"internal": "metadata"},
)4. Official Test Cases
From tests/server/test_lowlevel_output_validation.py:
async def call_tool_handler(name: str, arguments: dict[str, Any]) -> CallToolResult:
if name == "get_info":
return CallToolResult(
content=[TextContent(type="text", text="Results calculated")],
structuredContent={"status": "ok", "data": {"value": 42}},
_meta={"some": "metadata"},
)
# Test validates: assert result.meta == {"some": "metadata"}The Bug in Agent Framework
Current implementation in agent_framework/_mcp.py:
def _mcp_call_tool_result_to_ai_contents(result: Any) -> list[types.Content]:
"""Convert CallToolResult to AI content."""
if not hasattr(result, "content"):
raise ValueError("Result must have content field")
contents = []
for item in result.content:
# ... processes only content field
contents.append(converted_content)
return contents
# BUG: _meta field is completely dropped and never processed!Problem: The function:
- Only processes
result.content - Completely ignores
result._meta - Returns only converted content without metadata
- Violates the MCP specification
Expected Behavior
The Agent Framework should:
- Preserve the
_metafield fromCallToolResultresponses - Pass metadata through to the application layer
- Respect the MCP specification for protocol compliance
- Enable applications to access tool usage metrics, costs, and performance data
Proposed Solution
The _mcp_call_tool_result_to_ai_contents() function should be updated to:
- Extract and preserve the
_metafield fromCallToolResult - Return both content and metadata to the calling application
- Maintain protocol compliance with the official MCP specification
Possible approaches:
- Modify the return type to include metadata
- Add metadata to the agent response structure
- Provide a separate accessor for tool result metadata
- Follow the same pattern used by the official MCP Python SDK
Impact Assessment
Critical: This bug affects:
- ✅ Cost tracking: Token usage and API costs are lost
- ✅ Performance monitoring: Tool execution metrics are unavailable
- ✅ Protocol compliance: Violates official MCP specification
- ✅ Integration: Breaks compatibility with compliant MCP servers
- ✅ Debugging: Missing metadata prevents proper troubleshooting
Reproduction Steps
- Create an MCP server that returns
CallToolResultwith_metafield - Use Agent Framework to call the tool
- Observe that metadata is completely dropped from the response
- Compare with direct MCP client usage (metadata is preserved)
Environment
- Agent Framework Version: [Current installed version]
- MCP Python SDK Version: v1.21.2 (latest)
- Python Version: 3.12
- Platform: macOS
Additional Evidence
The MCP specification is widely implemented across multiple languages and frameworks:
- Official Go SDK includes
_metafield support - TypeScript implementations respect metadata
- Multiple third-party MCP implementations include metadata
References
- Official MCP Python SDK Repository
- MCP Specification Documentation
- MCP Protocol Introduction
- Official MCP Examples with _meta
Request: Please update Agent Framework to properly handle the _meta field in CallToolResult responses to ensure compliance with the official MCP specification and enable proper tool metadata access for applications.