From 12a92b0900d9bf22bd72c1b301c639086ae9c927 Mon Sep 17 00:00:00 2001
From: Tony Deng
Date: Fri, 16 Oct 2026 21:40:37 +0000
Subject: [PATCH 1/5] fix: constrain Pydantic for the oldest MCP compatibility
test
---
.github/scripts/run_integration_tests.py | 6 +++-
tests/test_integration_runner.py | 44 ++++++++++++++++++++++++
2 files changed, 49 insertions(+), 1 deletion(-)
diff --git a/.github/scripts/run_integration_tests.py b/.github/scripts/run_integration_tests.py
index 90627d1386..2e2ed9be6d 100644
--- a/.github/scripts/run_integration_tests.py
+++ b/.github/scripts/run_integration_tests.py
@@ -488,10 +488,14 @@ def main() -> None:
if args.profile == "mcp-v1":
for mcp_version in ("1.19.0", "1.29.0"):
environment_kind = f"mcp-v1-{mcp_version}"
+ requirements = (f"mcp=={mcp_version}",)
+ if mcp_version == "1.19.0":
+ # MCP 1.19.0 imports eval_type_backport, removed in Pydantic 2.14.
+ requirements += ("pydantic<2.14",)
python = create_environment(
environment_kind,
wheel,
- additional_requirements=(f"mcp=={mcp_version}",),
+ additional_requirements=requirements,
)
run_suite(
python,
diff --git a/tests/test_integration_runner.py b/tests/test_integration_runner.py
index 9ce940aefa..bc3cf90c3e 100644
--- a/tests/test_integration_runner.py
+++ b/tests/test_integration_runner.py
@@ -582,6 +582,50 @@ def test_extra_collection_deselects_only_non_applicable_memory_backends(
assert deselected == [non_applicable]
+def test_mcp_v1_profile_isolates_legacy_pydantic_constraint(
+ monkeypatch: pytest.MonkeyPatch,
+ tmp_path: Path,
+) -> None:
+ namespace = runpy.run_path(str(RUNNER))
+ main = cast(Callable[[], None], namespace["main"])
+ created: list[tuple[str, tuple[str, ...]]] = []
+ suites: list[dict[str, Any]] = []
+
+ def fake_create_environment(
+ name: str,
+ distribution: Path,
+ *,
+ additional_requirements: tuple[str, ...] = (),
+ ) -> Path:
+ _ = distribution
+ created.append((name, additional_requirements))
+ return tmp_path / name / "python"
+
+ monkeypatch.setattr(sys, "argv", [str(RUNNER), "--profile", "mcp-v1"])
+ monkeypatch.setitem(
+ main.__globals__,
+ "build_distributions",
+ lambda: (tmp_path / "candidate.whl", tmp_path / "candidate.tar.gz"),
+ )
+ monkeypatch.setitem(main.__globals__, "create_environment", fake_create_environment)
+ monkeypatch.setitem(
+ main.__globals__, "run_suite", lambda *args, **kwargs: suites.append(kwargs)
+ )
+ monkeypatch.setattr(main.__globals__["shutil"], "rmtree", lambda *args, **kwargs: None)
+
+ main()
+
+ assert created == [
+ ("mcp-v1-1.19.0", ("mcp==1.19.0", "pydantic<2.14")),
+ ("mcp-v1-1.29.0", ("mcp==1.29.0",)),
+ ]
+ assert [suite["selection"] for suite in suites] == ["mcp_compat", "mcp_compat"]
+ assert [suite["additional_env"] for suite in suites] == [
+ {"OPENAI_AGENTS_INTEGRATION_MCP_VERSION": "1.19.0"},
+ {"OPENAI_AGENTS_INTEGRATION_MCP_VERSION": "1.29.0"},
+ ]
+
+
def test_packaging_profile_checks_dependency_present_contract_for_wheel_and_sdist(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
From ac9c46df6b902e04ceeab9250b280451d8ebbc0f Mon Sep 17 00:00:00 2001
From: td |
Date: Fri, 16 Oct 2026 15:03:04 -0700
Subject: [PATCH 2/5] fix: enforce MCP-compatible Pydantic in package metadata
---
.github/scripts/run_integration_tests.py | 6 +--
.../packaging/test_mcp_compat.py | 14 ++++++
pyproject.toml | 3 +-
tests/test_integration_runner.py | 44 -------------------
uv.lock | 2 +-
5 files changed, 18 insertions(+), 51 deletions(-)
diff --git a/.github/scripts/run_integration_tests.py b/.github/scripts/run_integration_tests.py
index 2e2ed9be6d..90627d1386 100644
--- a/.github/scripts/run_integration_tests.py
+++ b/.github/scripts/run_integration_tests.py
@@ -488,14 +488,10 @@ def main() -> None:
if args.profile == "mcp-v1":
for mcp_version in ("1.19.0", "1.29.0"):
environment_kind = f"mcp-v1-{mcp_version}"
- requirements = (f"mcp=={mcp_version}",)
- if mcp_version == "1.19.0":
- # MCP 1.19.0 imports eval_type_backport, removed in Pydantic 2.14.
- requirements += ("pydantic<2.14",)
python = create_environment(
environment_kind,
wheel,
- additional_requirements=requirements,
+ additional_requirements=(f"mcp=={mcp_version}",),
)
run_suite(
python,
diff --git a/integration_tests/packaging/test_mcp_compat.py b/integration_tests/packaging/test_mcp_compat.py
index 50ca59b358..2563271141 100644
--- a/integration_tests/packaging/test_mcp_compat.py
+++ b/integration_tests/packaging/test_mcp_compat.py
@@ -7,6 +7,7 @@
from unittest.mock import MagicMock, patch
import pytest
+from packaging.requirements import Requirement
from agents.mcp import MCPServerSse, MCPServerStdio, MCPServerStreamableHttp
@@ -15,6 +16,19 @@
LEGACY_SERVER_PATH = Path(__file__).with_name("mcp_legacy_server.py")
+def test_package_metadata_excludes_incompatible_pydantic() -> None:
+ requirements = [
+ Requirement(value) for value in importlib.metadata.requires("openai-agents") or []
+ ]
+ pydantic = next(requirement for requirement in requirements if requirement.name == "pydantic")
+
+ assert "2.12.2" in pydantic.specifier
+ assert "2.13.5" in pydantic.specifier
+ assert "2.14.0" not in pydantic.specifier
+ assert "2.14.1" not in pydantic.specifier
+ assert importlib.metadata.version("pydantic") in pydantic.specifier
+
+
@pytest.mark.asyncio
async def test_packaged_client_supports_mcp_v1() -> None:
expected_version = os.environ["OPENAI_AGENTS_INTEGRATION_MCP_VERSION"]
diff --git a/pyproject.toml b/pyproject.toml
index 2fda55bf0d..b261231caa 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -8,7 +8,8 @@ license = "MIT"
authors = [{ name = "OpenAI", email = "support@openai.com" }]
dependencies = [
"openai>=3.0.0,<4",
- "pydantic>=2.12.2, <3",
+ # MCP 1.19.0 imports eval_type_backport, removed in Pydantic 2.14.
+ "pydantic>=2.12.2, <2.14",
"griffelib>=2, <3",
"typing-extensions>=4.12.2, <5",
"requests>=2.0, <3",
diff --git a/tests/test_integration_runner.py b/tests/test_integration_runner.py
index bc3cf90c3e..9ce940aefa 100644
--- a/tests/test_integration_runner.py
+++ b/tests/test_integration_runner.py
@@ -582,50 +582,6 @@ def test_extra_collection_deselects_only_non_applicable_memory_backends(
assert deselected == [non_applicable]
-def test_mcp_v1_profile_isolates_legacy_pydantic_constraint(
- monkeypatch: pytest.MonkeyPatch,
- tmp_path: Path,
-) -> None:
- namespace = runpy.run_path(str(RUNNER))
- main = cast(Callable[[], None], namespace["main"])
- created: list[tuple[str, tuple[str, ...]]] = []
- suites: list[dict[str, Any]] = []
-
- def fake_create_environment(
- name: str,
- distribution: Path,
- *,
- additional_requirements: tuple[str, ...] = (),
- ) -> Path:
- _ = distribution
- created.append((name, additional_requirements))
- return tmp_path / name / "python"
-
- monkeypatch.setattr(sys, "argv", [str(RUNNER), "--profile", "mcp-v1"])
- monkeypatch.setitem(
- main.__globals__,
- "build_distributions",
- lambda: (tmp_path / "candidate.whl", tmp_path / "candidate.tar.gz"),
- )
- monkeypatch.setitem(main.__globals__, "create_environment", fake_create_environment)
- monkeypatch.setitem(
- main.__globals__, "run_suite", lambda *args, **kwargs: suites.append(kwargs)
- )
- monkeypatch.setattr(main.__globals__["shutil"], "rmtree", lambda *args, **kwargs: None)
-
- main()
-
- assert created == [
- ("mcp-v1-1.19.0", ("mcp==1.19.0", "pydantic<2.14")),
- ("mcp-v1-1.29.0", ("mcp==1.29.0",)),
- ]
- assert [suite["selection"] for suite in suites] == ["mcp_compat", "mcp_compat"]
- assert [suite["additional_env"] for suite in suites] == [
- {"OPENAI_AGENTS_INTEGRATION_MCP_VERSION": "1.19.0"},
- {"OPENAI_AGENTS_INTEGRATION_MCP_VERSION": "1.29.0"},
- ]
-
-
def test_packaging_profile_checks_dependency_present_contract_for_wheel_and_sdist(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
diff --git a/uv.lock b/uv.lock
index 412e6374dc..e2349fa146 100644
--- a/uv.lock
+++ b/uv.lock
@@ -2914,7 +2914,7 @@ requires-dist = [
{ name = "protobuf", marker = "extra == 'e2b'", specifier = ">=5.29.6,!=6.30.*,!=6.31.*,!=6.32.*,!=6.33.0.*,!=6.33.1.*,!=6.33.2.*,!=6.33.3.*,!=6.33.4.*" },
{ name = "protobuf", marker = "extra == 'modal'", specifier = ">=5.29.6,!=6.30.*,!=6.31.*,!=6.32.*,!=6.33.0.*,!=6.33.1.*,!=6.33.2.*,!=6.33.3.*,!=6.33.4.*" },
{ name = "protobuf", marker = "extra == 'temporal'", specifier = ">=5.29.6,!=6.30.*,!=6.31.*,!=6.32.*,!=6.33.0.*,!=6.33.1.*,!=6.33.2.*,!=6.33.3.*,!=6.33.4.*" },
- { name = "pydantic", specifier = ">=2.12.2,<3" },
+ { name = "pydantic", specifier = ">=2.12.2,<2.14" },
{ name = "pygments", marker = "python_full_version >= '3.11' and extra == 'any-llm'", specifier = ">=2.20.0" },
{ name = "pygments", marker = "extra == 'e2b'", specifier = ">=2.20.0" },
{ name = "pygments", marker = "extra == 'modal'", specifier = ">=2.20.0" },
From 69eef10bd4b26a49ed078b24987d44923f5fab17 Mon Sep 17 00:00:00 2001
From: td |
Date: Fri, 16 Oct 2026 15:52:59 -0700
Subject: [PATCH 3/5] fix: raise MCP minimum to 1.21.1 and retain current
Pydantic support
---
.github/scripts/run_integration_tests.py | 2 +-
integration_tests/packaging/test_mcp_compat.py | 11 ++++++++---
pyproject.toml | 5 ++---
uv.lock | 4 ++--
4 files changed, 13 insertions(+), 9 deletions(-)
diff --git a/.github/scripts/run_integration_tests.py b/.github/scripts/run_integration_tests.py
index 90627d1386..406c97b271 100644
--- a/.github/scripts/run_integration_tests.py
+++ b/.github/scripts/run_integration_tests.py
@@ -486,7 +486,7 @@ def main() -> None:
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"):
+ for mcp_version in ("1.21.1", "1.29.0"):
environment_kind = f"mcp-v1-{mcp_version}"
python = create_environment(
environment_kind,
diff --git a/integration_tests/packaging/test_mcp_compat.py b/integration_tests/packaging/test_mcp_compat.py
index 2563271141..92ee348283 100644
--- a/integration_tests/packaging/test_mcp_compat.py
+++ b/integration_tests/packaging/test_mcp_compat.py
@@ -16,7 +16,7 @@
LEGACY_SERVER_PATH = Path(__file__).with_name("mcp_legacy_server.py")
-def test_package_metadata_excludes_incompatible_pydantic() -> None:
+def test_package_metadata_requires_fixed_mcp_and_allows_current_pydantic() -> None:
requirements = [
Requirement(value) for value in importlib.metadata.requires("openai-agents") or []
]
@@ -24,8 +24,13 @@ def test_package_metadata_excludes_incompatible_pydantic() -> None:
assert "2.12.2" in pydantic.specifier
assert "2.13.5" in pydantic.specifier
- assert "2.14.0" not in pydantic.specifier
- assert "2.14.1" not in pydantic.specifier
+ assert "2.14.0" in pydantic.specifier
+ assert "2.14.1" in pydantic.specifier
+ mcp = next(requirement for requirement in requirements if requirement.name == "mcp")
+ assert "1.21.0" not in mcp.specifier
+ assert "1.21.1" in mcp.specifier
+ assert "1.29.0" in mcp.specifier
+ assert importlib.metadata.version("mcp") in mcp.specifier
assert importlib.metadata.version("pydantic") in pydantic.specifier
diff --git a/pyproject.toml b/pyproject.toml
index b261231caa..74945f70cd 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -8,13 +8,12 @@ license = "MIT"
authors = [{ name = "OpenAI", email = "support@openai.com" }]
dependencies = [
"openai>=3.0.0,<4",
- # MCP 1.19.0 imports eval_type_backport, removed in Pydantic 2.14.
- "pydantic>=2.12.2, <2.14",
+ "pydantic>=2.12.2, <3",
"griffelib>=2, <3",
"typing-extensions>=4.12.2, <5",
"requests>=2.0, <3",
"websockets>=15.0, <17",
- "mcp>=1.19.0, <3; python_version >= '3.10'",
+ "mcp>=1.21.1, <3; python_version >= '3.10'",
# Security floors for transitive runtime dependencies.
"httpx2>=2.12.0",
"pyjwt>=2.15.0",
diff --git a/uv.lock b/uv.lock
index e2349fa146..81ceadd3ac 100644
--- a/uv.lock
+++ b/uv.lock
@@ -2905,7 +2905,7 @@ requires-dist = [
{ name = "h2", marker = "extra == 'modal'", specifier = ">=4.4.1" },
{ name = "httpx2", specifier = ">=2.12.0" },
{ name = "litellm", marker = "extra == 'litellm'", specifier = ">=1.83.0" },
- { name = "mcp", marker = "python_full_version >= '3.10'", specifier = ">=1.19.0,<3" },
+ { name = "mcp", marker = "python_full_version >= '3.10'", specifier = ">=1.21.1,<3" },
{ name = "modal", marker = "extra == 'modal'", specifier = "==1.4.3" },
{ name = "numpy", marker = "python_full_version >= '3.10' and extra == 'voice'", specifier = ">=2.2.0,<3" },
{ name = "openai", specifier = ">=3.0.0,<4" },
@@ -2914,7 +2914,7 @@ requires-dist = [
{ name = "protobuf", marker = "extra == 'e2b'", specifier = ">=5.29.6,!=6.30.*,!=6.31.*,!=6.32.*,!=6.33.0.*,!=6.33.1.*,!=6.33.2.*,!=6.33.3.*,!=6.33.4.*" },
{ name = "protobuf", marker = "extra == 'modal'", specifier = ">=5.29.6,!=6.30.*,!=6.31.*,!=6.32.*,!=6.33.0.*,!=6.33.1.*,!=6.33.2.*,!=6.33.3.*,!=6.33.4.*" },
{ name = "protobuf", marker = "extra == 'temporal'", specifier = ">=5.29.6,!=6.30.*,!=6.31.*,!=6.32.*,!=6.33.0.*,!=6.33.1.*,!=6.33.2.*,!=6.33.3.*,!=6.33.4.*" },
- { name = "pydantic", specifier = ">=2.12.2,<2.14" },
+ { name = "pydantic", specifier = ">=2.12.2,<3" },
{ name = "pygments", marker = "python_full_version >= '3.11' and extra == 'any-llm'", specifier = ">=2.20.0" },
{ name = "pygments", marker = "extra == 'e2b'", specifier = ">=2.20.0" },
{ name = "pygments", marker = "extra == 'modal'", specifier = ">=2.20.0" },
From ecbf68c34af5b060682b124f5cd172d9e515886f Mon Sep 17 00:00:00 2001
From: td |
Date: Mon, 19 Oct 2026 09:23:50 -0700
Subject: [PATCH 4/5] fix: raise MCP minimum to 1.21.2 for the OAuth scope
hotfix
---
.github/scripts/run_integration_tests.py | 2 +-
integration_tests/packaging/test_mcp_compat.py | 4 ++--
pyproject.toml | 2 +-
uv.lock | 2 +-
4 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/.github/scripts/run_integration_tests.py b/.github/scripts/run_integration_tests.py
index 406c97b271..9062826d66 100644
--- a/.github/scripts/run_integration_tests.py
+++ b/.github/scripts/run_integration_tests.py
@@ -486,7 +486,7 @@ def main() -> None:
print(f"[integration] wheel={wheel.name} sdist={sdist.name} profile={args.profile}")
if args.profile == "mcp-v1":
- for mcp_version in ("1.21.1", "1.29.0"):
+ for mcp_version in ("1.21.2", "1.29.0"):
environment_kind = f"mcp-v1-{mcp_version}"
python = create_environment(
environment_kind,
diff --git a/integration_tests/packaging/test_mcp_compat.py b/integration_tests/packaging/test_mcp_compat.py
index 92ee348283..2bf5a8c42d 100644
--- a/integration_tests/packaging/test_mcp_compat.py
+++ b/integration_tests/packaging/test_mcp_compat.py
@@ -27,8 +27,8 @@ def test_package_metadata_requires_fixed_mcp_and_allows_current_pydantic() -> No
assert "2.14.0" in pydantic.specifier
assert "2.14.1" in pydantic.specifier
mcp = next(requirement for requirement in requirements if requirement.name == "mcp")
- assert "1.21.0" not in mcp.specifier
- assert "1.21.1" in mcp.specifier
+ assert "1.21.1" not in mcp.specifier
+ assert "1.21.2" in mcp.specifier
assert "1.29.0" in mcp.specifier
assert importlib.metadata.version("mcp") in mcp.specifier
assert importlib.metadata.version("pydantic") in pydantic.specifier
diff --git a/pyproject.toml b/pyproject.toml
index 74945f70cd..cabbce26bc 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -13,7 +13,7 @@ dependencies = [
"typing-extensions>=4.12.2, <5",
"requests>=2.0, <3",
"websockets>=15.0, <17",
- "mcp>=1.21.1, <3; python_version >= '3.10'",
+ "mcp>=1.21.2, <3; python_version >= '3.10'",
# Security floors for transitive runtime dependencies.
"httpx2>=2.12.0",
"pyjwt>=2.15.0",
diff --git a/uv.lock b/uv.lock
index 81ceadd3ac..90d4ea4dc0 100644
--- a/uv.lock
+++ b/uv.lock
@@ -2905,7 +2905,7 @@ requires-dist = [
{ name = "h2", marker = "extra == 'modal'", specifier = ">=4.4.1" },
{ name = "httpx2", specifier = ">=2.12.0" },
{ name = "litellm", marker = "extra == 'litellm'", specifier = ">=1.83.0" },
- { name = "mcp", marker = "python_full_version >= '3.10'", specifier = ">=1.21.1,<3" },
+ { name = "mcp", marker = "python_full_version >= '3.10'", specifier = ">=1.21.2,<3" },
{ name = "modal", marker = "extra == 'modal'", specifier = "==1.4.3" },
{ name = "numpy", marker = "python_full_version >= '3.10' and extra == 'voice'", specifier = ">=2.2.0,<3" },
{ name = "openai", specifier = ">=3.0.0,<4" },
From f22eb5591062b32eeb3bde09df09940a40c81c48 Mon Sep 17 00:00:00 2001
From: td |
Date: Mon, 19 Oct 2026 09:45:26 -0700
Subject: [PATCH 5/5] test: simplify MCP minimum coverage and document version
choice
---
.github/scripts/run_integration_tests.py | 1 +
.../packaging/test_mcp_compat.py | 19 -------------------
2 files changed, 1 insertion(+), 19 deletions(-)
diff --git a/.github/scripts/run_integration_tests.py b/.github/scripts/run_integration_tests.py
index 9062826d66..2e5513eb87 100644
--- a/.github/scripts/run_integration_tests.py
+++ b/.github/scripts/run_integration_tests.py
@@ -486,6 +486,7 @@ def main() -> None:
print(f"[integration] wheel={wheel.name} sdist={sdist.name} profile={args.profile}")
if args.profile == "mcp-v1":
+ # MCP 1.21.2 includes the Pydantic 2.14 import fix and the OAuth 401 scope hotfix.
for mcp_version in ("1.21.2", "1.29.0"):
environment_kind = f"mcp-v1-{mcp_version}"
python = create_environment(
diff --git a/integration_tests/packaging/test_mcp_compat.py b/integration_tests/packaging/test_mcp_compat.py
index 2bf5a8c42d..50ca59b358 100644
--- a/integration_tests/packaging/test_mcp_compat.py
+++ b/integration_tests/packaging/test_mcp_compat.py
@@ -7,7 +7,6 @@
from unittest.mock import MagicMock, patch
import pytest
-from packaging.requirements import Requirement
from agents.mcp import MCPServerSse, MCPServerStdio, MCPServerStreamableHttp
@@ -16,24 +15,6 @@
LEGACY_SERVER_PATH = Path(__file__).with_name("mcp_legacy_server.py")
-def test_package_metadata_requires_fixed_mcp_and_allows_current_pydantic() -> None:
- requirements = [
- Requirement(value) for value in importlib.metadata.requires("openai-agents") or []
- ]
- pydantic = next(requirement for requirement in requirements if requirement.name == "pydantic")
-
- assert "2.12.2" in pydantic.specifier
- assert "2.13.5" in pydantic.specifier
- assert "2.14.0" in pydantic.specifier
- assert "2.14.1" in pydantic.specifier
- mcp = next(requirement for requirement in requirements if requirement.name == "mcp")
- assert "1.21.1" not in mcp.specifier
- assert "1.21.2" in mcp.specifier
- assert "1.29.0" in mcp.specifier
- assert importlib.metadata.version("mcp") in mcp.specifier
- assert importlib.metadata.version("pydantic") in pydantic.specifier
-
-
@pytest.mark.asyncio
async def test_packaged_client_supports_mcp_v1() -> None:
expected_version = os.environ["OPENAI_AGENTS_INTEGRATION_MCP_VERSION"]
|