@@ -2267,6 +2267,109 @@ if __name__ == "__main__":
22672267_ Full example: [ examples/snippets/clients/streamable_basic.py] ( https://github.com/modelcontextprotocol/python-sdk/blob/main/examples/snippets/clients/streamable_basic.py ) _
22682268<!-- /snippet-source -->
22692269
2270+ ### Per-Request HTTP Headers
2271+
2272+ When using HTTP transports, you can pass custom headers on a per-request basis. This enables various use cases such as request tracing, authentication context, A/B testing, debugging flags, and more while maintaining a single persistent connection:
2273+
2274+ <!-- snippet-source examples/snippets/clients/per_request_headers_example.py -->
2275+ ``` python
2276+ """
2277+ Example demonstrating per-request headers functionality for MCP client.
2278+
2279+ Shows how to use the extra_headers parameter to send different HTTP headers
2280+ with each request, enabling use cases like per-user authentication, request
2281+ tracing, A/B testing, and multi-tenant applications.
2282+ """
2283+
2284+ import asyncio
2285+
2286+ from mcp import ClientSession
2287+ from mcp.client.streamable_http import streamablehttp_client
2288+
2289+
2290+ async def main ():
2291+ """ Demonstrate per-request headers functionality."""
2292+
2293+ # Connection-level headers (static for the entire session)
2294+ connection_headers = {" Authorization" : " Bearer org-level-token" , " X-Org-ID" : " org-123" }
2295+
2296+ async with streamablehttp_client(" https://mcp.example.com/mcp" , headers = connection_headers) as (
2297+ read_stream,
2298+ write_stream,
2299+ _,
2300+ ):
2301+ async with ClientSession(read_stream, write_stream) as session:
2302+ await session.initialize()
2303+
2304+ # Example 1: Request tracing
2305+ tracing_headers = {
2306+ " X-Request-ID" : " req-12345" ,
2307+ " X-Trace-ID" : " trace-abc-456" ,
2308+ }
2309+ result = await session.call_tool(" process_data" , {" type" : " analytics" }, extra_headers = tracing_headers)
2310+ print (f " Traced request result: { result} " )
2311+
2312+ # Example 2: User-specific authentication
2313+ user_headers = {
2314+ " X-User-ID" : " alice" ,
2315+ " X-Auth-Token" : " user-token-12345" ,
2316+ }
2317+ result = await session.call_tool(" get_user_data" , {" fields" : [" profile" ]}, extra_headers = user_headers)
2318+ print (f " User-specific result: { result} " )
2319+
2320+ # Example 3: A/B testing
2321+ experiment_headers = {
2322+ " X-Experiment-ID" : " new-ui-test" ,
2323+ " X-Variant" : " variant-b" ,
2324+ }
2325+ result = await session.call_tool(
2326+ " get_recommendations" , {" user_id" : " user123" }, extra_headers = experiment_headers
2327+ )
2328+ print (f " A/B test result: { result} " )
2329+
2330+ # Example 4: Override connection-level headers
2331+ override_headers = {
2332+ " Authorization" : " Bearer user-specific-token" , # Overrides connection-level
2333+ " X-Special-Permission" : " admin" ,
2334+ }
2335+ result = await session.call_tool(" admin_operation" , {" operation" : " reset" }, extra_headers = override_headers)
2336+ print (f " Admin operation result: { result} " )
2337+
2338+ # Example 5: Works with all ClientSession methods
2339+ await session.list_resources(extra_headers = {" X-Resource-Filter" : " public" })
2340+ await session.get_prompt(" template" , extra_headers = {" X-Context" : " help" })
2341+ await session.set_logging_level(" debug" , extra_headers = {" X-Debug-Session" : " true" })
2342+
2343+
2344+ if __name__ == " __main__" :
2345+ print (" MCP Client Per-Request Headers Example" )
2346+ print (" =" * 50 )
2347+
2348+ try :
2349+ asyncio.run(main())
2350+ except Exception as e:
2351+ print (f " Example requires a running MCP server. Error: { e} " )
2352+ print (" \n This example demonstrates the API usage patterns." )
2353+ ```
2354+
2355+ _ Full example: [ examples/snippets/clients/per_request_headers_example.py] ( https://github.com/modelcontextprotocol/python-sdk/blob/main/examples/snippets/clients/per_request_headers_example.py ) _
2356+ <!-- /snippet-source -->
2357+
2358+ The ` extra_headers ` parameter is available for all ` ClientSession ` methods that make server requests:
2359+
2360+ - ` call_tool() `
2361+ - ` get_prompt() `
2362+ - ` read_resource() `
2363+ - ` list_tools() `
2364+ - ` list_prompts() `
2365+ - ` list_resources() `
2366+ - ` list_resource_templates() `
2367+ - ` subscribe() `
2368+ - ` unsubscribe() `
2369+ - ` set_logging_level() `
2370+
2371+ Per-request headers are merged with the transport's default headers, with per-request headers taking precedence for duplicate keys.
2372+
22702373### Client Display Utilities
22712374
22722375When building MCP clients, the SDK provides utilities to help display human-readable names for tools, resources, and prompts:
0 commit comments