-
Notifications
You must be signed in to change notification settings - Fork 2.8k
Description
Summary
Allow specifying HTTP headers for the MCP server for each run invocation, not only at initialization time. In multi-user or multi-tenant environments it’s often necessary to attach user-specific or session-specific headers (e.g., auth token, user-id, tenant-id) for each agent run.
Problem
Currently, the SDK supports configuring the MCP server client (URL, transport, static headers) at initialization. But if you need different headers per run (for example, different user tokens or metadata when the same agent is shared among users), there’s no direct hook to override or supply headers with each Runner.run() or Runner.run_streamed() invocation.
Proposed behaviour
-
Extend the Runner
run()andrun_streamed()methods to accept a new parameter (for examplemcp_headers: dict[str, str] | None) that allows specifying HTTP headers for the MCP server just for that run. -
Example usage:
result = await Runner.run( starting_agent=agent, input="Do something", run_config=run_config, mcp_headers={"Authorization": f"Bearer {user_token}", "X-User-Id": user_id} )
-
The SDK should merge default headers (set at MCP server/client init) and the per-run headers, with per-run headers taking precedence.
-
For streaming:
result = await Runner.run_streamed( starting_agent=agent, input="Another task", mcp_headers={"X-Tenant-Id": tenant_id} )
Benefits
- Supports multi-user / multi-tenant scenarios where many users share an agent or MCP connection but need per-request credentials or context headers.
- Avoids needing to recreate the MCP client for each user or each run just to change headers.
- Simplifies agent orchestration when per-run metadata (e.g., user-id, request id) must be sent to the MCP server for authorization, analytics, or routing.
Backward compatibility & notes
- If
mcp_headersis not provided, behaviour remains unchanged (use init‐level headers). - The new parameter is optional, so existing code continues working without change.
- Performance impact is minimal — just header injection per request.
Suggested API addition
class Runner:
@classmethod
async def run(
# existing parameters...
mcp_headers: dict[str, str] | None = None,
) -> RunResult:
...And similarly for run_streamed(...).