Python: Scope MCP headers to transport requests - #8039
Conversation
Keep provider header processing associated with the MCP tool that issued each request, including when HTTP clients are shared. Clean up request hooks on close and preserve redirect handling. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 4fca7430-5806-4fb4-a190-729e2473c5bb
There was a problem hiding this comment.
🟡 Changes recommended
Redirect chains can retain and expose previously injected headers when the provider’s key set changes.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
Scopes MCP provider headers per tool when sharing an HTTP client.
Changes:
- Adds a transport proxy and tool-specific request ownership.
- Manages hooks across close, reconnect, and redirects.
- Adds regression tests and guidance.
File summaries
| File | Description |
|---|---|
python/packages/core/agent_framework/_mcp.py |
Implements scoped header injection and cleanup. |
python/packages/core/tests/core/test_mcp.py |
Tests sharing, delegation, lifecycle, and redirects. |
python/packages/core/AGENTS.md |
Documents header-provider request scoping. |
Review details
- Files reviewed: 3/3 changed files
- Comments generated: 1
- Review effort level: Balanced
💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.
Remove previously injected provider headers before applying the latest set so redirected requests retain only current provider output. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 4fca7430-5806-4fb4-a190-729e2473c5bb
There was a problem hiding this comment.
MAF Automated Review — Iteration 1
Result: Findings reported
Scope: full PR (1 commit(s)): 9e90a73c3951
Model: gpt-5.6-sol-fast
Overview
The PR scopes shared-client header providers by tagging transport requests with a per-tool owner, delegates the underlying HTTP client surface, and removes and restores request hooks across normal close and reconnect. Owner checks, cross-origin stripping, and shared-client lifecycle tests provide strong coverage for ordinary request and redirect flows. A cancellation race remains: the caller can detach the authentication hook while the lifecycle owner is still performing transport teardown.
Reviewed the supplied pull-request change set across correctness, security/reliability, architecture, and failure behavior.
1 verified finding remained after source verification (1 medium) across 1 file. Details are attached to the affected lines below.
Affected areas: python/packages/core/agent_framework/_mcp.py
Keep the request hook attached while lifecycle-owner transport cleanup runs, including when the caller awaiting close is cancelled. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 4fca7430-5806-4fb4-a190-729e2473c5bb
Replace the shared request-hook list during cleanup so in-flight HTTPX hook iteration is not disrupted. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 4fca7430-5806-4fb4-a190-729e2473c5bb
Motivation & Context
When multiple MCP tools reuse the same HTTP client, provider output should remain associated with the transport request that initiated it. This keeps shared-client behavior deterministic while retaining the existing construction and connection model.
Description & Review Guide
header_providerrequest-hook processing to matching transport requests.httpx.AsyncClientwith consistent per-tool provider behavior. There are no public API changes.Related Issue
N/A — no public issue. Related PR #7892 adds static connect-time headers; this PR instead scopes existing
header_providerprocessing when an HTTP client is reused.Contribution Checklist
breaking changelabel (or add "[BREAKING]" to the title prefix, before or after any language prefix) — a workflow keeps the label and the title prefix in sync automatically.