Skip to content

fix(e2e): unbreak trtllm lanes broken by mcp 2.0.0a1 - #1675

Merged
slin1237 merged 1 commit into
mainfrom
fix/e2e-mcp-constraint
Jun 11, 2026
Merged

slin1237 merged 1 commit into
mainfrom
fix/e2e-mcp-constraint

Conversation

@slin1237

@slin1237 slin1237 commented Jun 11, 2026 •

Copy link
Copy Markdown
Member

Summary

Every trtllm e2e job has been failing at the model-download step (before any test runs) since the TensorRT-LLM 1.3.0rc18 bump (#1663):

File ".../e2e_test/infra/__init__.py", line 44, in <module>
    from .mock_mcp import ...
File ".../e2e_test/infra/mock_mcp_server.py", line 60, in <module>
    from mcp.server.fastmcp import FastMCP
ModuleNotFoundError: No module named 'mcp.server.fastmcp'

Root cause (with receipts from job 80871944044)

  1. tensorrt-llm==1.3.0rc18 newly depends on mcp (unconstrained) — rc14 did not (Collecting mcp (from tensorrt-llm==1.3.0rc18)).
  2. ci_install_trtllm.sh installs with pip install --pre (required for NVIDIA pre-release wheels) — which lets every transitive dep resolve to pre-releases → mcp-2.0.0a1 (note the neighbours: pydantic-2.14.0a1, lxml-7.0.0a2).
  3. mcp 2.0 removed the legacy mcp.server.fastmcp module (verified by inspecting the wheel: zero fastmcp entries).
  4. Our floor mcp>=1.0 treats the alpha as already satisfied (Requirement already satisfied: mcp>=1.0 ... (2.0.0a1)), so the e2e deps install keeps it.
  5. e2e_test/infra/__init__.py eagerly imports the FastMCP-based mock — used only by the sglang-only responses/ lane — so even ci_download_model.sh (which just wants model specs) crashes.

Passing rc14 runs confirm the contrast: there mcp came only from e2e deps and resolved to stable mcp-1.27.2.

Fix

  • mcp>=1.2,<2 — the honest requirement (mcp.server.fastmcp was added in 1.2, removed in 2.0). Per PEP 440, <2 excludes pre-releases of 2.0 (verified with packaging: SpecifierSet(">=1.2,<2").contains("2.0.0a1", prereleases=True) == False), so pip install e2e_test/ now replaces the alpha with stable 1.x. TensorRT-LLM's own mcp requirement is unconstrained, so the downgrade leaves the environment consistent.
  • Lazy-load the mock MCP server via module __getattr__ in infra/__init__.py — model download and chat/router lanes no longer depend on the mcp SDK at all. The responses/ consumers (from infra import MockMcpServer, from infra.mock_mcp import mock_mcp_server) are unaffected.

Verification

  • mcp 2.0.0a1 wheel inspected: no mcp/server/fastmcp content; specifier semantics verified with packaging.
  • ruff check/format clean.
  • This PR's own e2e-1gpu-chat (trtllm) lane is the live regression test — it exercises the exact failing path (engine setup → e2e deps → model download → tests).

Summary by CodeRabbit

  • Chores
    • Updated MCP dependency version constraints to ensure E2E test compatibility.
    • Optimized test infrastructure module initialization with lazy loading.

Every trtllm e2e job dies at the model-download step since the
TensorRT-LLM 1.3.0rc18 bump (#1663): rc18 newly depends on mcp
(unconstrained), the trtllm install runs pip with --pre (required for
NVIDIA pre-release wheels), and pip resolves mcp to 2.0.0a1 — which
removed the legacy mcp.server.fastmcp module. Our e2e dependency floor
mcp>=1.0 treats the alpha as already satisfied, and e2e_test/infra
eagerly imports the FastMCP-based mock at package import, so even
ci_download_model.sh crashes with ModuleNotFoundError before any test
runs. rc14 never depended on mcp, which is why this only surfaced now.

Two fixes, both on our side of the contract:

- Declare the real requirement: mcp>=1.2,<2 (fastmcp was added in 1.2
  and removed in 2.0). PEP 440 excludes 2.0 pre-releases from <2, so
  the e2e deps install now replaces the alpha with stable 1.x instead
  of keeping it. TensorRT-LLM's own mcp requirement is unconstrained,
  so the downgrade stays consistent.

- Stop importing the mock MCP server eagerly in infra/__init__: only
  the sglang-only responses lane uses it, yet the eager import made
  model download and every chat/router lane depend on the mcp SDK.
  The symbols now resolve lazily via module __getattr__.

Signed-off-by: Simo Lin <25425177+slin1237@users.noreply.github.com>
@coderabbitai

coderabbitai Bot commented Jun 11, 2026 •

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 97a2f4f2-2584-48e7-998b-98e5bcc3b70c

📥 Commits

Reviewing files that changed from the base of the PR and between bb6373b and 7861ebd.

📒 Files selected for processing (2)
  • e2e_test/infra/__init__.py
  • e2e_test/pyproject.toml

📝 Walkthrough

Walkthrough

The pull request defers import of mock MCP server symbols in e2e_test.infra by replacing eager imports with a module-level __getattr__ lazy resolver, and pins the mcp dependency to versions 1.2–1.9 to ensure the required mcp.server.fastmcp module is available.

Changes

Lazy Mock MCP Resolution

Layer / File(s) Summary
Lazy attribute resolution for mock MCP exports
e2e_test/infra/__init__.py
Removed eager top-level import of IMAGE_GENERATION_PNG_BASE64, MockMcpServer, and mock_mcp_server from .mock_mcp, and added a module-level __getattr__ function that imports .mock_mcp and returns the requested symbol only when one of the lazy exports is first accessed.
MCP version constraint
e2e_test/pyproject.toml
Updated the mcp dependency from >=1.0 to >=1.2,<2 with an inline comment documenting that the version range is required because infra.mock_mcp_server depends on mcp.server.fastmcp, which was added in version 1.2 and removed in version 2.0.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Suggested labels

tests

Suggested reviewers

  • CatherineSue
  • key4ng
  • XinyueZhang369

Poem

🐰 Lazy imports hop by one by one,
Only loaded when the deed is done,
Version bounds keep fastmcp in sight,
No eager leaps—just-in-time feels right! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'fix(e2e): unbreak trtllm lanes broken by mcp 2.0.0a1' clearly describes the main fix: addressing broken e2e test lanes caused by mcp 2.0.0a1 incompatibility, which is the core issue resolved by the PR.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/e2e-mcp-constraint

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions github-actions Bot added dependencies Dependency updates tests Test changes labels Jun 11, 2026

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces lazy loading for mock MCP server symbols in e2e_test/infra/__init__.py to avoid importing the mcp SDK at import time, and restricts the mcp dependency version to mcp>=1.2,<2 in e2e_test/pyproject.toml. The reviewer suggested optimizing the lazy loading implementation by caching the resolved attributes in the module's globals to bypass subsequent __getattr__ lookups.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines +173 to +178
def __getattr__(name: str) -> object:
if name in _LAZY_MOCK_MCP:
from . import mock_mcp

return getattr(mock_mcp, name)
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

To optimize module attribute lookups, we can cache the resolved attributes in the module's globals. This ensures that __getattr__ is only triggered once per attribute, and subsequent accesses will bypass __getattr__ entirely by retrieving the value directly from the module's namespace.

Suggested change
def __getattr__(name: str) -> object:
if name in _LAZY_MOCK_MCP:
from . import mock_mcp
return getattr(mock_mcp, name)
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
def __getattr__(name: str) -> object:
if name in _LAZY_MOCK_MCP:
from . import mock_mcp
value = getattr(mock_mcp, name)
globals()[name] = value
return value
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")

@claude

claude Bot commented Jun 11, 2026

Copy link
Copy Markdown

👋 The PR description doesn't fully follow
PULL_REQUEST_TEMPLATE.md:

  • Missing header: ## Description
  • Missing header: ### Problem
  • Missing header: ### Solution
  • Missing header: ## Changes
  • Missing header: ## Test Plan

Please update the PR description so reviewers have the context they need.

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clean fix — lazy-loading the mock MCP symbols via __getattr__ and pinning mcp>=1.2,<2 are both correct. No issues found.

@slin1237
slin1237 merged commit 87d01f0 into main Jun 11, 2026
39 checks passed
@slin1237
slin1237 deleted the fix/e2e-mcp-constraint branch June 11, 2026 20:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependencies Dependency updates tests Test changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant