crewAIInc/crewAI · error · ValueError
MCP server not started, run `mcp_server.start()` first befor
Error message
MCP server not started, run `mcp_server.start()` first before accessing `tools`
What it means
Raised by the `tools` property of MCPServerAdapt when the internal `self._tools` is still None, meaning `start()` was never called or did not complete. The constructor normally starts the server automatically, so this mainly surfaces after a failed init path or when the object was constructed in a state where start did not run.
Source
Thrown at lib/crewai-tools/src/crewai_tools/adapters/mcp_adapter.py:211
"""Start the MCP server and initialize the tools."""
self._tools = self._adapter.__enter__() # type: ignore[union-attr]
def stop(self) -> None:
"""Stop the MCP server."""
self._adapter.__exit__(None, None, None) # type: ignore[union-attr]
@property
def tools(self) -> ToolCollection[BaseTool]:
"""The CrewAI tools available from the MCP server.
Raises:
ValueError: If the MCP server is not started.
Returns:
The CrewAI tools available from the MCP server.
"""
if self._tools is None:
raise ValueError(
"MCP server not started, run `mcp_server.start()` first before accessing `tools`"
)
tools_collection = ToolCollection(self._tools)
if self._tool_names:
return tools_collection.filter_by_names(self._tool_names)
return tools_collection
def __enter__(self) -> ToolCollection[BaseTool]:
"""Enter the context manager.
Note that `__init__()` already starts the MCP server,
so tools should already be available.
"""
return self.tools
def __exit__(
self,View on GitHub (pinned to 754d7323be)
Solutions
- Call `mcp_server.start()` before reading `mcp_server.tools`.
- Prefer the context-manager form (`with MCPServerAdapt(...) as tools:`) so __enter__ guarantees a started server.
- If init previously failed, fix the underlying init error first (see 'Failed to initialize MCP Adapter') — a stopped server has no tools.
Example fix
# before server = MCPServerAdapt(params) print(server.tools) # ValueError if not started # after server = MCPServerAdapt(params) server.start() print(server.tools)
Defensive patterns
Strategy: validation
Validate before calling
def get_tools(server):
if getattr(server, "_tools", None) is None:
server.start() # idempotent enough via __enter__
return server.tools Type guard
def is_started(server) -> bool:
return server._tools is not None Try / catch
try:
tools = server.tools
except ValueError:
server.start()
tools = server.tools Prevention
- Prefer `with MCPServerAdapt(...) as tools:` so .tools is always populated.
- Never swallow exceptions from the MCPServerAdapt constructor — a half-initialized server has no tools.
- Check `server._tools is not None` (or call start()) before reading .tools.
When it happens
Trigger: Accessing `mcp_server.tools` before the server started — e.g. an object created when __init__ caught an exception path left _tools None, or a manually crafted/half-initialized instance where start() was skipped. The property checks `if self._tools is None` and raises ValueError.
Common situations: Using the adapter as a context manager but accessing `.tools` after an exception was swallowed, or subclassing/reconstructing MCPServerAdapt without calling start(). Also seen when init partially failed and the caller ignores the error then reads .tools.
Related errors
- async is not supported by the CrewAI framework.
- Failed to install mcp package
- `mcp` package not found, please run `uv add crewai-tools[mcp
- Failed to initialize MCP Adapter: {e}
- Tavily client is not initialized. Ensure 'tavily-python' is
AI-assisted analysis of crewAIInc/crewAI@754d7323be (2026-08-15).
Data as JSON: /api/errors/6ee156fa4ae658ea.
Report an issue: GitHub.