Python: Preserve bounded MCP Host payload metadata - #8128
Conversation
Code Coverage OverviewLanguages: Python Python / code-coverage/pythonThe overall line coverage in commit 57db79e in the Show a line coverage summary of the most covered files.
Updated |
There was a problem hiding this comment.
🟡 Changes recommended
Oversized errors lose metadata, custom function parsers discard markers, and error capture is not limited to generated calls.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
Adds bounded, Host-only MCP result metadata capture while preserving model-facing output.
Changes:
- Adds scoped, size-limited Host payload markers.
- Preserves markers through task and error paths.
- Adds payload, transport, and compatibility tests.
File summaries
| File | Description |
|---|---|
python/packages/core/agent_framework/_mcp.py |
Implements MCP Host payload capture and propagation. |
python/packages/core/agent_framework/_tools.py |
Transfers exception metadata into function results. |
python/packages/core/tests/core/test_mcp.py |
Adds MCP payload regression coverage. |
Review details
Suppressed comments (2)
python/packages/core/agent_framework/_mcp.py:2619
- The legacy/fallback error path also captures a complete Host payload for direct
call_tool_as_task()calls even thoughpreserve_host_payloadis false. Apply the generated-call guard here as well so fallback behavior remains scoped consistently.
_mcp_tool_result_host_payload(
fallback_result,
max_size_bytes=self.max_host_payload_size_bytes,
),
python/packages/core/agent_framework/_mcp.py:2836
- Completed-task errors likewise serialize and retain the Host payload when the public direct task API requested no preservation. Gate this capture on
preserve_host_payloadto keep all task paths generated-call-only.
_mcp_tool_result_host_payload(
payload,
max_size_bytes=self.max_host_payload_size_bytes,
),
- Files reviewed: 3/3 changed files
- Comments generated: 4
- Review effort level: Balanced
💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.
There was a problem hiding this comment.
MAF Automated Review — Iteration 1
Result: Findings reported
Scope: full PR (1 commit(s)): 5aebc2d700f4
Model: gpt-5.6-sol-fast
Overview
The PR cleanly scopes successful Host-payload capture to generated MCP functions, uses early and final serialization-size guards, and covers normal, error, fallback, and completed-task paths with targeted tests. The residual risks are that the per-result cap is not an aggregate bound, raw _meta can bypass it, oversized errors lose metadata, required-task dispatch bypasses public overrides, and an empty custom parser result changes the model-facing projection.
Reviewed the supplied pull-request change set across correctness, security/reliability, architecture, and failure behavior.
5 verified findings remained after source verification (5 medium) across 1 file. Details are attached to the affected lines below.
Affected areas: python/packages/core/agent_framework/_mcp.py
5aebc2d to
1fcacea
Compare
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
1fcacea to
57db79e
Compare
There was a problem hiding this comment.
MAF Automated Review — Iteration 2
Result: Findings reported
Scope: full PR (1 commit(s)): 57db79e933bd
Model: gpt-5.6-sol-fast
Overview
The PR separates complete MCP Host payloads from model-facing projections with a context-local capture, a function-result carrier, per-result serialization limits, and broad streaming, error, middleware, and task-path tests. Its strongest guards are the finally-scoped capture reset, exact post-serialization checks, and an aggregate request budget for complete payloads. Residual risks remain where server metadata crosses the security-label boundary, bypasses the aggregate budget, makes approval state non-durable, and is lost when result parsing fails.
Reviewed the supplied pull-request change set across correctness, security/reliability, architecture, and failure behavior.
4 verified findings remained after source verification (3 high, 1 medium) across 2 files. Details are attached to the affected lines below.
Affected areas: python/packages/core/agent_framework/_mcp.py, python/packages/core/agent_framework/_tools.py
Motivation & Context
Generated MCP
FunctionToolcalls need to retain the completeCallToolResultfor Host transports even when the model-facing parser intentionally projects only a bounded summary. Without a core-owned capture contract, fields such asstructuredContentare unavailable to downstream transports and persisted history after tool execution.This is layer 1 (the bottom layer) of the split replacement for #7971. It establishes only the core MCP Host-payload capture contract and remains orthogonal to #7897: it does not change which MCP content the model sees, or its ordering, preference, or deduplication.
Description & Review Guide
ContextVar, attach one JSON-safe complete result under a private core marker after built-in or custom parsing, preserve_metaon every model-facing item, and carry the marker through generic function-error conversion. Normal, long-running fallback, completed-task, and MCP error paths share the contract. A configurable per-result size cap rejects oversized payloads before full-copy materialization and retains an exact final serialization guard;Nonedisables the cap. The option is keyword-only onMCPToolafter all existing positional parameters and is forwarded by every concrete transport.call_tool()custom-parser return shapes, model-visible content, transport subclass behavior, or header-provider behavior. Oversized Host payloads are omitted while bounded model projections and_metaremain intact.Related Issue
Part of #7959.
This draft is the core-only first layer replacing the broader open source PR #7971. Draft #7897 addresses model-facing MCP content selection and is intentionally independent from this Host-only metadata contract.
Contribution Checklist
breaking changelabel (or add "[BREAKING]" to the title prefix, before or after any language prefix) — a workflow keeps the label and title prefix in sync automatically.