-
Notifications
You must be signed in to change notification settings - Fork 2.6k
feat: #1829 add httpx_client_factory to MCPServerStreamableHttp initialization options #1833
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
seratch
merged 5 commits into
openai:main
from
jjcampana:feat/mcp_add_custom_http_client
Oct 1, 2025
+490
−12
Merged
Changes from 3 commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
62 changes: 62 additions & 0 deletions
62
examples/mcp/streamablehttp_custom_client_example/README.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
# Custom HTTP Client Factory Example | ||
|
||
This example demonstrates how to use the new `httpx_client_factory` parameter in `MCPServerStreamableHttp` to configure custom HTTP client behavior for MCP StreamableHTTP connections. | ||
|
||
## Features Demonstrated | ||
|
||
- **Custom SSL Configuration**: Configure SSL certificates and verification settings | ||
- **Custom Headers**: Add custom headers to all HTTP requests | ||
- **Custom Timeouts**: Set custom timeout values for requests | ||
- **Proxy Configuration**: Configure HTTP proxy settings | ||
- **Custom Retry Logic**: Set up custom retry behavior (through httpx configuration) | ||
|
||
## Running the Example | ||
|
||
1. Make sure you have `uv` installed: https://docs.astral.sh/uv/getting-started/installation/ | ||
|
||
2. Run the example: | ||
```bash | ||
cd examples/mcp/streamablehttp_custom_client_example | ||
uv run main.py | ||
``` | ||
|
||
## Code Examples | ||
|
||
### Basic Custom Client | ||
|
||
```python | ||
import httpx | ||
from agents.mcp import MCPServerStreamableHttp | ||
|
||
def create_custom_http_client() -> httpx.AsyncClient: | ||
return httpx.AsyncClient( | ||
verify=False, # Disable SSL verification for testing | ||
timeout=httpx.Timeout(60.0, read=120.0), | ||
headers={"X-Custom-Client": "my-app"}, | ||
) | ||
|
||
async with MCPServerStreamableHttp( | ||
name="Custom Client Server", | ||
params={ | ||
"url": "http://localhost:8000/mcp", | ||
"httpx_client_factory": create_custom_http_client, | ||
}, | ||
) as server: | ||
# Use the server... | ||
``` | ||
|
||
## Use Cases | ||
|
||
- **Corporate Networks**: Configure proxy settings for corporate environments | ||
- **SSL/TLS Requirements**: Use custom SSL certificates for secure connections | ||
- **Custom Authentication**: Add custom headers for API authentication | ||
- **Network Optimization**: Configure timeouts and connection pooling | ||
- **Debugging**: Disable SSL verification for development environments | ||
|
||
## Benefits | ||
|
||
- **Flexibility**: Configure HTTP client behavior to match your network requirements | ||
- **Security**: Use custom SSL certificates and authentication methods | ||
- **Performance**: Optimize timeouts and connection settings for your use case | ||
- **Compatibility**: Work with corporate proxies and network restrictions | ||
|
116 changes: 116 additions & 0 deletions
116
examples/mcp/streamablehttp_custom_client_example/main.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
"""Example demonstrating custom httpx_client_factory for MCPServerStreamableHttp. | ||
|
||
This example shows how to configure custom HTTP client behavior for MCP StreamableHTTP | ||
connections, including SSL certificates, proxy settings, and custom timeouts. | ||
""" | ||
|
||
import asyncio | ||
import os | ||
import shutil | ||
import subprocess | ||
import time | ||
from typing import Any | ||
|
||
import httpx | ||
|
||
from agents import Agent, Runner, gen_trace_id, trace | ||
from agents.mcp import MCPServer, MCPServerStreamableHttp | ||
from agents.model_settings import ModelSettings | ||
|
||
|
||
def create_custom_http_client( | ||
headers: dict[str, str] | None = None, | ||
timeout: httpx.Timeout | None = None, | ||
auth: httpx.Auth | None = None, | ||
) -> httpx.AsyncClient: | ||
"""Create a custom HTTP client with specific configurations. | ||
|
||
This function demonstrates how to configure: | ||
- Custom SSL verification settings | ||
- Custom timeouts | ||
- Custom headers | ||
- Proxy settings (commented out) | ||
""" | ||
if headers is None: | ||
headers = { | ||
"X-Custom-Client": "agents-mcp-example", | ||
"User-Agent": "OpenAI-Agents-MCP/1.0", | ||
} | ||
if timeout is None: | ||
timeout = httpx.Timeout(60.0, read=120.0) | ||
if auth is None: | ||
auth = None | ||
return httpx.AsyncClient( | ||
# Disable SSL verification for testing (not recommended for production) | ||
verify=False, | ||
# Set custom timeout | ||
timeout=httpx.Timeout(60.0, read=120.0), | ||
# Add custom headers that will be sent with every request | ||
headers=headers, | ||
) | ||
|
||
|
||
async def run_with_custom_client(mcp_server: MCPServer): | ||
"""Run the agent with a custom HTTP client configuration.""" | ||
agent = Agent( | ||
name="Assistant", | ||
instructions="Use the tools to answer the questions.", | ||
mcp_servers=[mcp_server], | ||
model_settings=ModelSettings(tool_choice="required"), | ||
) | ||
|
||
# Use the `add` tool to add two numbers | ||
message = "Add these numbers: 7 and 22." | ||
print(f"Running: {message}") | ||
result = await Runner.run(starting_agent=agent, input=message) | ||
print(result.final_output) | ||
|
||
|
||
async def main(): | ||
"""Main function demonstrating different HTTP client configurations.""" | ||
|
||
print("=== Example: Custom HTTP Client with SSL disabled and custom headers ===") | ||
async with MCPServerStreamableHttp( | ||
name="Streamable HTTP with Custom Client", | ||
params={ | ||
"url": "http://localhost:8000/mcp", | ||
"httpx_client_factory": create_custom_http_client, | ||
}, | ||
) as server: | ||
trace_id = gen_trace_id() | ||
with trace(workflow_name="Custom HTTP Client Example", trace_id=trace_id): | ||
print(f"View trace: https://platform.openai.com/logs/trace?trace_id={trace_id}\n") | ||
await run_with_custom_client(server) | ||
|
||
|
||
if __name__ == "__main__": | ||
# Let's make sure the user has uv installed | ||
if not shutil.which("uv"): | ||
raise RuntimeError( | ||
"uv is not installed. Please install it: https://docs.astral.sh/uv/getting-started/installation/" | ||
) | ||
|
||
# We'll run the Streamable HTTP server in a subprocess. Usually this would be a remote server, but for this | ||
# demo, we'll run it locally at http://localhost:8000/mcp | ||
process: subprocess.Popen[Any] | None = None | ||
try: | ||
this_dir = os.path.dirname(os.path.abspath(__file__)) | ||
server_file = os.path.join(this_dir, "server.py") | ||
|
||
print("Starting Streamable HTTP server at http://localhost:8000/mcp ...") | ||
|
||
# Run `uv run server.py` to start the Streamable HTTP server | ||
process = subprocess.Popen(["uv", "run", server_file]) | ||
# Give it 3 seconds to start | ||
time.sleep(3) | ||
|
||
print("Streamable HTTP server started. Running example...\n\n") | ||
except Exception as e: | ||
print(f"Error starting Streamable HTTP server: {e}") | ||
exit(1) | ||
|
||
try: | ||
asyncio.run(main()) | ||
finally: | ||
if process: | ||
process.terminate() |
23 changes: 23 additions & 0 deletions
23
examples/mcp/streamablehttp_custom_client_example/server.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import random | ||
|
||
from mcp.server.fastmcp import FastMCP | ||
|
||
# Create server | ||
mcp = FastMCP("Echo Server") | ||
|
||
|
||
@mcp.tool() | ||
def add(a: int, b: int) -> int: | ||
"""Add two numbers""" | ||
print(f"[debug-server] add({a}, {b})") | ||
return a + b | ||
|
||
|
||
@mcp.tool() | ||
def get_secret_word() -> str: | ||
print("[debug-server] get_secret_word()") | ||
return random.choice(["apple", "banana", "cherry"]) | ||
|
||
|
||
if __name__ == "__main__": | ||
mcp.run(transport="streamable-http") |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.