Repository navigation
feat(mcp): run on mcp 1 and mcp 2, so a trainer can install vLLM 0.30 and later - #357
earakely-scale wants to merge 4 commits into
Conversation
… and later vLLM 0.30 and later require mcp>=2, and agent-env and its protocol package pinned mcp<2, so a trainer with agent-env installed was held to vLLM 0.29. - The pins widen to mcp>=1.25,<3 (fastmcp <5). The gateway's image keeps its own mcp<2, since it serves on mcp 1's FastMCP. uv.lock stays on mcp 1: the openenv extra's fastmcp 3 needs it. - agentenv_protocol.mcp_compat holds what differs: the high-level server (FastMCP, or MCPServer holding mcp 1's serving settings), a client session (httpx2 and two streams on mcp 2), the low-level server's handlers, an mcp type's field under either spelling, and a crash's text in a tool's error, which mcp 2 keeps on the server. - The protocol's FastMCP app, its tools/list filter per role (middleware on mcp 2), the peer-agents server and the computer conformance probe use it, and so do agent-env's MCP clients and the example verifiers. agent-env no longer declares mcp itself; it arrives with the protocol package. - The tests run on both versions, and a unit-mcp2 job runs the unit tier on mcp 2.3 and fastmcp 4, in two passes, since fastmcp 4 adds mcp 1's camel-case attributes to mcp's types once imported. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…mcp2's venv on PATH client_session built a plain httpx client when no timeout was given, so the env provider's tool listing, the legacy reset and the example verifiers lost mcp's 30 s and 300 s timeouts for httpx's 5 s default. It now builds the client with mcp's own create_mcp_http_client on both versions, and a test checks the defaults and an explicit timeout. The generated-CLI tests run their script on python3 from PATH, which the unit-mcp2 job didn't point at its venv, as the unit job does. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…they import A test added on main that imports the gateway server broke the job's fixed --ignore list. .github/scripts/mcp2_test_split.py now finds the tests that import the gateway server, directly or through a test module that does, and the protocol tests that import fastmcp, so a new one is placed on its own. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
| app = mcp_compat.deployed_server(card.name, host=os.environ.get("MCP_HOST", "0.0.0.0"), | ||
| port=int(os.environ.get("MCP_PORT", "18765")), **fastmcp_kwargs) |
There was a problem hiding this comment.
create_fastmcp_app() now raises TypeError when callers supply host or port through fastmcp_kwargs, because those keywords are also passed explicitly. Previously, it accepted those settings and then replaced them with MCP_HOST and MCP_PORT.
On mcp 2, supplying transport_security also fails because deployed_server() passes it twice. Merge the settings before calling these helpers so existing arguments do not stop the app from starting.
Prompt To Fix With AI
This is a comment left during a code review.
Path: packages/agentenv-protocol/src/agentenv_protocol/agent_env_environment.py
Line: 467-468
Comment:
**Server settings stop startup**
`create_fastmcp_app()` now raises `TypeError` when callers supply `host` or `port` through `fastmcp_kwargs`, because those keywords are also passed explicitly. Previously, it accepted those settings and then replaced them with `MCP_HOST` and `MCP_PORT`.
On mcp 2, supplying `transport_security` also fails because `deployed_server()` passes it twice. Merge the settings before calling these helpers so existing arguments do not stop the app from starting.
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.|
Parked as a draft until OpenEnv ships FastMCP 4 (openenv/OpenEnv#1304). The TRL route through OpenEnv needs OpenEnv in the trainer, and OpenEnv 0.10 requires mcp 1. So this PR doesn't unblock vLLM 0.30+ for that route yet, and the first TRL runs can use vLLM 0.29. Merging now would mean carrying the compat layer and Once #1304 is released, we'll decide between this dual support and mcp 2 only, with the OpenEnv check done in the same change. The branch is kept: CI was green apart from 🤖 Generated with Claude Code |
What and why
vLLM 0.30 and later require
mcp>=2. agent-env and its protocol package pinnedmcp<2, so a trainer with agent-env installed was held to vLLM 0.29. TRL 1.16 allows vLLM 0.22–0.31, and its minimum keeps rising. On the current release,agentenv-frameworkwithtrl[vllm]andvllm>=0.30has no solution; on this branch it resolves on Linux to TRL 1.16, vLLM 0.31 and mcp 2.3.0.Pins
mcp>=1.25,<3, and the protocol's fastmcp extra<5.mcp<2, since it serves on mcp 1's FastMCP. That code is container-only and unchanged.uv.lockstays on mcp 1: theopenenvextra's fastmcp 3 needs it, until OpenEnv moves to FastMCP 4.mcpitself. Nothing outside the gateway imports it directly any more, sotest_runtime_dependencies_are_importedflagged it; it arrives withagentenv-framework-protocol[computer].agentenv_protocol.mcp_compatholds what differs between the versions:server(name, **settings)builds mcp 1'sFastMCP, or mcp 2'sMCPServerholding the serving settings (path, host, port, transport security) that mcp 2 takes atstreamable_http_app()andrun()instead.client_session(url, headers=, timeout=)opens an initializedClientSession. mcp 2's client takes anhttpx2client and yields two streams, where mcp 1's tookhttpxand yielded three.low_level_server(...)registers a low-level server's handlers: by decorator on mcp 1, by constructor on mcp 2.field(result, "isError")reads an mcp type's field. mcp 2 spells the attributes in snake case only.with_crash_text(error)restores a tool crash's text on mcp 2. mcp 2 reports "Error executing tool x" alone and keeps the exception's text on the server; mcp 1 sends "Error executing tool x: ". An env's errors now read the same on either version, and the crash is still logged on the server.Where it's used
create_fastmcp_appandserve();tools/listfilter, which on mcp 2 runs inMCPServer's middleware, since mcp 2 has no request context outside a handler;env_outcome_verifierruns a bundle'sverify.pyin agent-env's process, so verifiers see the trainer's mcp. The README tells verifier authors to useclient_sessionandfield.Tests
importorskip("mcp.server.fastmcp").tests/mcp_versions.py(andtst/util/mcp_versions.py) give an in-memory or HTTP session whose results read by mcp 1's attribute names on either version.mcp-session-idresponse header, or speak JSON-RPC directly.CI:
unit-mcp2runs the unit tier on mcp 2.3 and fastmcp 4. It installs every extra butopenenv, plus thedevtest tools read frompyproject.toml.fastmcp4 adds mcp 1's camel-case attributes to mcp's types process-wide (fastmcp/_compat.py). In one process that hides exactly the reads this job exists to catch: run alone, 17 conformance tests failed that passed in the full suite. So the tests that import fastmcp run in a second pass.openenvtests;openenv's included. Theunitjob runs them.Not in this PR: porting the gateway itself to
MCPServer. Its container keeps mcp 1, and trainers don't need it.How it was tested
pytest tst/unit packages/agentenv-protocol/tests -n 10: 10,949 passed, 1 failed.submit_runs_test::test_a_first_ctrl_c_lets_the_runner_finish_stopping, a Ctrl-C timing test that passes 3 of 3 alone and doesn't touch mcp. The run before passed all 10,950.unit-mcp2passes exactly as the workflow runs them: 9,861 passed, then 56 passed.tst/integration/env/envs/server_env_local_test.py, which drives the Episode API, passes 5 of 5.uv pip compileof agent-env withtrl[vllm]andvllm>=0.30for x86_64 Linux and Python 3.12 resolves to TRL 1.16.0, vLLM 0.31.0 and mcp 2.3.0. On 0.9.1367 it has no solution.ruff checkanduv lock --checkpass.🤖 Generated with Claude Code
Fix the duplicate settings arguments before merging so existing SDK callers can still build their environment apps.
Fix with agent prompt
Summary
Adds shared helpers so the protocol SDK and framework clients can run on mcp 1 or mcp 2.
Diagram
%%{init: {'theme': 'neutral'}}%% flowchart LR App[Environment app] --> Compat[mcp_compat] Clients[Framework clients] --> Compat Compat --> MCP1[mcp 1] Compat --> MCP2[mcp 2] Gateway[Gateway image] --> MCP1Reviews (3) · Last reviewed commit: "ci(mcp): find the unit-mcp2 job's left-o..." · Reviewed by Greptile