Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 34 additions & 2 deletions .github/scripts/run_integration_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
)
PROFILES = (
"packaging",
"mcp-v1",
"core",
"providers",
"realtime",
Expand Down Expand Up @@ -78,7 +79,12 @@ def _any_llm_provider_extras(


def create_environment(
name: str, distribution: Path, *, extras: bool = False, optional_extra: str | None = None
name: str,
distribution: Path,
*,
extras: bool = False,
optional_extra: str | None = None,
additional_requirements: tuple[str, ...] = (),
) -> Path:
environment = WORKSPACE / name
venv_command = ["uv", "venv", "--clear", str(environment)]
Expand All @@ -88,7 +94,13 @@ def create_environment(
python = environment / ("Scripts/python.exe" if sys.platform == "win32" else "bin/python")
selected_extra = EXTRAS if extras else optional_extra
requirement = f"{distribution}[{selected_extra}]" if selected_extra else str(distribution)
requirements = [requirement, "pytest", "pytest-asyncio", "pytest-timeout"]
requirements = [
requirement,
"pytest",
"pytest-asyncio",
"pytest-timeout",
*additional_requirements,
]
external_providers_enabled = os.environ.get(
"OPENAI_AGENTS_INTEGRATION_EXTERNAL_PROVIDERS", ""
).lower() in {"1", "true", "yes"}
Expand Down Expand Up @@ -126,6 +138,7 @@ def run_suite(
*,
selection: str,
environment_kind: str,
additional_env: dict[str, str] | None = None,
) -> None:
child_env = dict(os.environ)
child_env.pop("PYTHONPATH", None)
Expand All @@ -147,6 +160,8 @@ def run_suite(
child_env["OPENAI_AGENTS_INTEGRATION_WHEEL"] = str(wheel)
child_env["OPENAI_AGENTS_INTEGRATION_SDIST"] = str(sdist)
child_env["OPENAI_AGENTS_INTEGRATION_ENVIRONMENT"] = environment_kind
if additional_env:
child_env.update(additional_env)
if environment_kind.startswith("extra-"):
child_env["OPENAI_AGENTS_INTEGRATION_EXTRA"] = environment_kind.removeprefix("extra-")
if not os.environ.get("OPENAI_AGENTS_INTEGRATION_ENABLE_TRACING"):
Expand Down Expand Up @@ -182,6 +197,23 @@ def main() -> None:
wheel, sdist = build_distributions()
print(f"[integration] wheel={wheel.name} sdist={sdist.name} profile={args.profile}")

if args.profile == "mcp-v1":
for mcp_version in ("1.19.0", "1.29.0"):
environment_kind = f"mcp-v1-{mcp_version}"
python = create_environment(
environment_kind,
wheel,
additional_requirements=(f"mcp=={mcp_version}",),
)
run_suite(
python,
wheel,
sdist,
selection="mcp_compat",
environment_kind=environment_kind,
additional_env={"OPENAI_AGENTS_INTEGRATION_MCP_VERSION": mcp_version},
)

if args.profile in {"packaging", "core", "hosted", "full", "release", "nightly", "manual"}:
python = create_environment("core", wheel)
selections = {
Expand Down
25 changes: 25 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,31 @@ jobs:
if: steps.changes.outputs.run != 'true'
run: echo "Skipping tests for non-code changes."

mcp-v1-compat:
runs-on: ubuntu-latest
env:
OPENAI_API_KEY: fake-for-tests
steps:
- name: Checkout repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1
- name: Detect code changes
id: changes
run: ./.github/scripts/detect-changes.sh code "${{ github.event.pull_request.base.sha || github.event.before }}" "${{ github.sha }}"
- name: Setup uv
if: steps.changes.outputs.run == 'true'
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # setup-uv v9.0.0; uv 0.11.14
with:
version: "0.11.14"
enable-cache: true
prune-cache: true
python-version: "3.12"
- name: Run packaged MCP v1 compatibility tests
if: steps.changes.outputs.run == 'true'
run: make integration-tests-mcp-v1
- name: Skip MCP v1 compatibility tests
if: steps.changes.outputs.run != 'true'
run: echo "Skipping MCP v1 compatibility tests for non-code changes."

tests-windows:
runs-on: windows-latest
env:
Expand Down
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,10 @@ integration-tests-manual:
integration-tests-packaging:
uv run python .github/scripts/run_integration_tests.py --profile packaging

.PHONY: integration-tests-mcp-v1
integration-tests-mcp-v1:
uv run python .github/scripts/run_integration_tests.py --profile mcp-v1

.PHONY: integration-tests-core
integration-tests-core:
uv run python .github/scripts/run_integration_tests.py --profile core
Expand Down
2 changes: 2 additions & 0 deletions examples/mcp/manager_example/README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# MCP Manager Example (FastAPI)

This repository example targets MCP Python SDK v2 and is intended to run with the repository's locked development environment. The Agents SDK client itself supports both MCP v1 and v2.

This example shows how to use `MCPServerManager` to keep MCP server lifecycle management in a single task inside a FastAPI app with the Streamable HTTP transport.

## Run the MCP server (Streamable HTTP)
Expand Down
14 changes: 7 additions & 7 deletions examples/mcp/manager_example/mcp_server.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,11 @@
import os

from mcp.server.fastmcp import FastMCP
from mcp.server.mcpserver import MCPServer
Comment thread
seratch marked this conversation as resolved.

STREAMABLE_HTTP_HOST = os.getenv("STREAMABLE_HTTP_HOST", "127.0.0.1")
STREAMABLE_HTTP_PORT = int(os.getenv("STREAMABLE_HTTP_PORT", "8000"))

mcp = FastMCP(
"FastAPI Example Server",
host=STREAMABLE_HTTP_HOST,
port=STREAMABLE_HTTP_PORT,
)
mcp = MCPServer("FastAPI Example Server")


@mcp.tool()
Expand All @@ -23,4 +19,8 @@ def echo(message: str) -> str:


if __name__ == "__main__":
mcp.run(transport="streamable-http")
mcp.run(
transport="streamable-http",
host=STREAMABLE_HTTP_HOST,
port=STREAMABLE_HTTP_PORT,
)
2 changes: 2 additions & 0 deletions examples/mcp/prompt_server/README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# MCP Prompt Server Example

This repository example targets MCP Python SDK v2 and is intended to run with the repository's locked development environment. The Agents SDK client itself supports both MCP v1 and v2.

This example uses a local MCP prompt server in [server.py](server.py).

Run the example via:
Expand Down
10 changes: 7 additions & 3 deletions examples/mcp/prompt_server/server.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import os

from mcp.server.fastmcp import FastMCP
from mcp.server.mcpserver import MCPServer

STREAMABLE_HTTP_HOST = os.getenv("STREAMABLE_HTTP_HOST", "127.0.0.1")
STREAMABLE_HTTP_PORT = int(os.getenv("STREAMABLE_HTTP_PORT", "18080"))

# Create server
mcp = FastMCP("Prompt Server", host=STREAMABLE_HTTP_HOST, port=STREAMABLE_HTTP_PORT)
mcp = MCPServer("Prompt Server")


# Instruction-generating prompts (user-controlled)
Expand Down Expand Up @@ -39,4 +39,8 @@ def generate_code_review_instructions(


if __name__ == "__main__":
mcp.run(transport="streamable-http")
mcp.run(
transport="streamable-http",
host=STREAMABLE_HTTP_HOST,
port=STREAMABLE_HTTP_PORT,
)
2 changes: 2 additions & 0 deletions examples/mcp/sse_example/README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# MCP SSE Example

This repository example targets MCP Python SDK v2 and is intended to run with the repository's locked development environment. The Agents SDK client itself supports both MCP v1 and v2.

This example uses a local SSE server in [server.py](server.py).

Run the example via:
Expand Down
6 changes: 3 additions & 3 deletions examples/mcp/sse_example/server.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import os
import random

from mcp.server.fastmcp import FastMCP
from mcp.server.mcpserver import MCPServer

SSE_HOST = os.getenv("SSE_HOST", "127.0.0.1")
SSE_PORT = int(os.getenv("SSE_PORT", "8000"))

# Create server
mcp = FastMCP("Echo Server", host=SSE_HOST, port=SSE_PORT)
mcp = MCPServer("Echo Server")


@mcp.tool()
Expand Down Expand Up @@ -39,4 +39,4 @@ def get_current_weather(city: str) -> str:


if __name__ == "__main__":
mcp.run(transport="sse")
mcp.run(transport="sse", host=SSE_HOST, port=SSE_PORT)
10 changes: 6 additions & 4 deletions examples/mcp/streamablehttp_custom_client_example/README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# Custom HTTP Client Factory Example

This repository example targets MCP Python SDK v2 and `httpx2`, and is intended to run with the repository's locked development environment. The Agents SDK client itself supports MCP v1 with `httpx` and MCP v2 with `httpx2`.

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
Expand All @@ -25,13 +27,13 @@ This example demonstrates how to use the new `httpx_client_factory` parameter in
### Basic Custom Client

```python
import httpx
import httpx2
from agents.mcp import MCPServerStreamableHttp

def create_custom_http_client() -> httpx.AsyncClient:
return httpx.AsyncClient(
def create_custom_http_client() -> httpx2.AsyncClient:
return httpx2.AsyncClient(
verify=False, # Disable SSL verification for testing
timeout=httpx.Timeout(60.0, read=120.0),
timeout=httpx2.Timeout(60.0, read=120.0),
headers={"X-Custom-Client": "my-app"},
)

Expand Down
14 changes: 7 additions & 7 deletions examples/mcp/streamablehttp_custom_client_example/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
import time
from typing import Any, cast

import httpx
import httpx2
Comment thread
seratch marked this conversation as resolved.

from agents import Agent, Runner, gen_trace_id, trace
from agents.mcp import MCPServer, MCPServerStreamableHttp
Expand All @@ -38,9 +38,9 @@ def _choose_port() -> int:

def create_custom_http_client(
headers: dict[str, str] | None = None,
timeout: httpx.Timeout | None = None,
auth: httpx.Auth | None = None,
) -> httpx.AsyncClient:
timeout: httpx2.Timeout | None = None,
auth: httpx2.Auth | None = None,
) -> httpx2.AsyncClient:
"""Create a custom HTTP client with specific configurations.

This function demonstrates how to configure:
Expand All @@ -55,14 +55,14 @@ def create_custom_http_client(
"User-Agent": "OpenAI-Agents-MCP/1.0",
}
if timeout is None:
timeout = httpx.Timeout(60.0, read=120.0)
timeout = httpx2.Timeout(60.0, read=120.0)
if auth is None:
auth = None
return httpx.AsyncClient(
return httpx2.AsyncClient(
# Disable SSL verification for testing (not recommended for production)
verify=False,
# Set custom timeout
timeout=httpx.Timeout(60.0, read=120.0),
timeout=httpx2.Timeout(60.0, read=120.0),
# Add custom headers that will be sent with every request
headers=headers,
)
Expand Down
10 changes: 7 additions & 3 deletions examples/mcp/streamablehttp_custom_client_example/server.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import os
import random

from mcp.server.fastmcp import FastMCP
from mcp.server.mcpserver import MCPServer

STREAMABLE_HTTP_HOST = os.getenv("STREAMABLE_HTTP_HOST", "127.0.0.1")
STREAMABLE_HTTP_PORT = int(os.getenv("STREAMABLE_HTTP_PORT", "18080"))

# Create server
mcp = FastMCP("Echo Server", host=STREAMABLE_HTTP_HOST, port=STREAMABLE_HTTP_PORT)
mcp = MCPServer("Echo Server")


@mcp.tool()
Expand All @@ -24,4 +24,8 @@ def get_secret_word() -> str:


if __name__ == "__main__":
mcp.run(transport="streamable-http")
mcp.run(
transport="streamable-http",
host=STREAMABLE_HTTP_HOST,
port=STREAMABLE_HTTP_PORT,
)
2 changes: 2 additions & 0 deletions examples/mcp/streamablehttp_example/README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# MCP Streamable HTTP Example

This repository example targets MCP Python SDK v2 and is intended to run with the repository's locked development environment. The Agents SDK client itself supports both MCP v1 and v2.

This example uses a local Streamable HTTP server in [server.py](server.py).

Run the example via:
Expand Down
10 changes: 7 additions & 3 deletions examples/mcp/streamablehttp_example/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@
import random

import requests
from mcp.server.fastmcp import FastMCP
from mcp.server.mcpserver import MCPServer

STREAMABLE_HTTP_HOST = os.getenv("STREAMABLE_HTTP_HOST", "127.0.0.1")
STREAMABLE_HTTP_PORT = int(os.getenv("STREAMABLE_HTTP_PORT", "18080"))

# Create server
mcp = FastMCP("Echo Server", host=STREAMABLE_HTTP_HOST, port=STREAMABLE_HTTP_PORT)
mcp = MCPServer("Echo Server")


@mcp.tool()
Expand Down Expand Up @@ -40,4 +40,8 @@ def get_current_weather(city: str) -> str:


if __name__ == "__main__":
mcp.run(transport="streamable-http")
mcp.run(
transport="streamable-http",
host=STREAMABLE_HTTP_HOST,
port=STREAMABLE_HTTP_PORT,
)
2 changes: 2 additions & 0 deletions examples/sandbox/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ These examples show how to run agents with an isolated workspace. Start with the

Most examples call a model through `Runner`, so set `OPENAI_API_KEY` in the repository-root `.env` file, in the example's `.env` file when it has one, or in your shell environment.

`sandbox_agent_with_tools.py` starts the repository's MCP v2 reference server and is intended to run with the locked development environment. The Agents SDK client itself supports both MCP v1 and v2.

## Small API examples

| Example | Run | What it shows |
Expand Down
4 changes: 2 additions & 2 deletions examples/sandbox/misc/reference_policy_mcp_server.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from mcp.server.fastmcp import FastMCP
from mcp.server.mcpserver import MCPServer

mcp = FastMCP("Reference Policy Server")
mcp = MCPServer("Reference Policy Server")


@mcp.tool()
Expand Down
2 changes: 1 addition & 1 deletion integration_tests/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Run the complete release-oriented matrix with:
export UV_DEFAULT_INDEX=https://pypi.org/simple
make integration-tests

`make integration-tests-release` runs the same release-safe matrix explicitly. `make integration-tests-nightly` also includes extended capability and transport checks, while `make integration-tests-manual` includes checks reserved for an intentionally configured manual run. Focused entry points are `make integration-tests-packaging`, `make integration-tests-core`, `make integration-tests-providers`, `make integration-tests-providers-external`, `make integration-tests-providers-all`, `make integration-tests-realtime`, `make integration-tests-voice`, `make integration-tests-hosted`, and `make integration-tests-extras`.
`make integration-tests-release` runs the same release-safe matrix explicitly. `make integration-tests-nightly` also includes extended capability and transport checks, while `make integration-tests-manual` includes checks reserved for an intentionally configured manual run. Focused entry points are `make integration-tests-packaging`, `make integration-tests-mcp-v1`, `make integration-tests-core`, `make integration-tests-providers`, `make integration-tests-providers-external`, `make integration-tests-providers-all`, `make integration-tests-realtime`, `make integration-tests-voice`, `make integration-tests-hosted`, and `make integration-tests-extras`. The MCP v1 profile installs the built wheel with both the supported v1 floor and latest tested v1 release in clean environments; the regular test job validates the locked MCP v2 dependency.

Invoke the repository-local `$integration-tests` skill to run the release profile with configured OpenRouter-backed provider checks. OpenRouter provides a single configured gateway for the standard multi-provider matrix; provider-specific direct connections are optional extensions selected explicitly. When a release review also requires runnable examples, run `$examples-auto-run` first and then `$integration-tests`.

Expand Down
Loading