perf: lazy-load MCP SDK and event types to reduce cold start by ~29%#5584
Merged
joaomdmoura merged 10 commits intomainfrom Apr 22, 2026
Merged
perf: lazy-load MCP SDK and event types to reduce cold start by ~29%#5584joaomdmoura merged 10 commits intomainfrom
joaomdmoura merged 10 commits intomainfrom
Conversation
- Change 'from crewai.mcp import MCPServerConfig' to direct path 'from crewai.mcp.config import MCPServerConfig' to avoid triggering mcp/__init__.py which eagerly loads the full mcp SDK (~300-400ms) - Move MCPToolResolver import into get_mcp_tools() method body since it's only used at runtime, not in type annotations Saves ~200ms on 'import crewai' cold start.
MCPClient, MCPToolResolver, BaseTransport, and TransportType now use __getattr__ lazy loading. These pull in the full mcp SDK (~400ms) but are only needed at runtime when agents actually connect to MCP servers. Lightweight config and filter types remain eagerly imported.
Previously only agent_events were lazy-loaded; all other event type modules (crew, flow, knowledge, llm, guardrail, logging, mcp, memory, reasoning, skill, task, tool_usage) were eagerly imported at package init time. Since events/__init__.py runs whenever ANY crewai.events.* submodule is accessed, this loaded ~12 Pydantic model modules unnecessarily. Now all event types use the same __getattr__ lazy-loading pattern, with TYPE_CHECKING imports preserved for IDE/type-checker support. Saves ~550ms on 'import crewai' cold start.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 24f774d. Configure here.
Fixes F821 (ruff) and name-defined (mypy) from lazy-loading the MCP import. The type annotation on _mcp_resolver needs the name available at type-check time.
lxml 5.3.2 has a known vulnerability. Bump to 5.4.0+ which includes the fix (libxml2 2.13.8). The previous <5.4.0 pin was for etree import issues that have since been resolved.
a79c6d9 to
bbecebd
Compare
lxml 6.1.0 (GHSA fix) was released April 17 but the exclude-newer date was set to April 17, missing it by timestamp. Bump to April 22.
scripts/benchmark_import_time.py measures import crewai cold start in fresh subprocesses. Supports --runs, --json (for CI), and --threshold (fail if median exceeds N seconds). The companion GitHub Action workflow needs to be pushed separately (requires workflow scope).
…ntain permissions' Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
joaomdmoura
approved these changes
Apr 22, 2026
joaomdmoura
approved these changes
Apr 22, 2026
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.

Summary
Reduces
import crewaicold start time by lazy-loading heavy dependencies that aren't needed at import time.Baseline: ~4.7s → After: ~3.4s (warm cache, ~29% improvement)
Changes
1. Fix MCP import path in
agent/core.pyfrom crewai.mcp import MCPServerConfig→from crewai.mcp.config import MCPServerConfigmcp/__init__.pywhich eagerly loaded the fullmcpSDK (~400ms)MCPToolResolverimport intoget_mcp_tools()method body (only needed at runtime)2. Lazy-load heavy MCP imports in
mcp/__init__.pyMCPClient,MCPToolResolver,BaseTransport,TransportTypenow use__getattr__lazy loadingcrewai/__init__.pyforMemory3. Lazy-load all event type modules in
events/__init__.pyagent_eventswere lazy-loaded; now all 12 event type modules are lazyevents/__init__.pyruns whenever ANYcrewai.events.*submodule is accessed (Python package init), so this prevents loading ~12 Pydantic model modules unnecessarilyTYPE_CHECKINGimports preserved for IDE/type-checker support__all__unchanged — public API is identicalWhat's NOT changed (intentionally)
Testing
python -c 'import crewai'— ✅ worksfrom crewai.events import CrewKickoffStartedEvent, LLMCallStartedEvent, ...— ✅ lazy resolution worksfrom crewai.events import crewai_event_bus, BaseEventListener— ✅ core imports unchanged__all__exports preservedNote
Medium Risk
Moderate risk because it changes import-time behavior via
__getattr__lazy loading in public packages, which can surface subtle runtime import/order issues; also updates dependency pins (notablylxml) that could affect optional integrations.Overview
Improves
import crewaiperformance by avoiding heavy imports at package init:crewai.mcpnow lazy-loadsMCPClient/MCPToolResolver/transport types,crewai.eventslazy-loads all event type classes (not just agent events), andAgent.get_mcp_tools()defers importingMCPToolResolverwhile switchingMCPServerConfigto import fromcrewai.mcp.config.Adds a new GitHub Actions workflow (
import-time.yml) that benchmarksimport crewaion the PR vs base branch and fails if median import time regresses by more than 5%. Also updates tooling/deps: bumpslxmlincrewai-toolsoptionalragextras for a security advisory, adjusts[tool.uv].exclude-newer, and ignoresUNKNOWN.egg-info/in.gitignore.Reviewed by Cursor Bugbot for commit 634ff3d. Bugbot is set up for automated code reviews on this repo. Configure here.