crewAIInc/crewAI · warning · NotImplementedError
async is not supported by the CrewAI framework.
Error message
async is not supported by the CrewAI framework.
What it means
NotImplementedError raised by CrewAIToolAdapter.async_adapt: the CrewAI framework's tool interface is synchronous, so the MCP adapter has no async adaptation path. Any attempt to adapt an MCP tool coroutine through this adapter is rejected by design, not due to a bug.
Source
Thrown at lib/crewai-tools/src/crewai_tools/adapters/mcp_adapter.py:89
for content in result.content
if isinstance(content, TextContent)
]
)
def _generate_description(self) -> None:
schema = self.args_schema.model_json_schema()
schema.pop("$defs", None)
self.description = (
f"Tool Name: {self.name}\n"
f"Tool Arguments: {schema}\n"
f"Tool Description: {self.description}"
)
return CrewAIMCPTool()
async def async_adapt(self, afunc: Any, mcp_tool: Tool) -> Any:
"""Async adaptation is not supported by CrewAI."""
raise NotImplementedError("async is not supported by the CrewAI framework.")
MCP_AVAILABLE = True
except ImportError as e:
logger.debug(f"MCP packages not available: {e}")
MCP_AVAILABLE = False
class MCPServerAdapter:
"""Manages the lifecycle of an MCP server and make its tools available to CrewAI.
Note: tools can only be accessed after the server has been started with the
`start()` method.
Usage:
# context manager + stdio
with MCPServerAdapter(...) as tools:
# tools is now available
View on GitHub (pinned to 754d7323be)
Solutions
- Use the sync adapt path (CrewAIToolAdapter.adapt) — this is the supported route for CrewAI.
- If async execution is required, run the sync CrewAI tool in a worker thread (asyncio.to_thread) instead of the adapter's async_adapt.
- Pick a different adapter class for frameworks with native async tool support.
Example fix
# before await adapter.async_adapt(afunc, mcp_tool) # NotImplementedError # after tool = adapter.adapt(mcp_tool.func, mcp_tool) # sync adaptation result = await asyncio.to_thread(tool._run, **args) # async-friendly invocation
Defensive patterns
Strategy: fallback
Type guard
def supports_async(adapter) -> bool:
return getattr(adapter, "async_adapt", None) is not None and not getattr(adapter, "async_adapt").__doc__.startswith("Async adaptation is not supported") Try / catch
try:
tool = await adapter.async_adapt(afunc, mcp_tool)
except NotImplementedError:
tool = adapter.adapt(mcp_tool.func, mcp_tool) # sync fallback Prevention
- Treat CrewAI tools as synchronous; use asyncio.to_thread for non-blocking invocation.
- Do not route CrewAIToolAdapter through generic async adaptation layers.
- Catch NotImplementedError explicitly when writing adapter-agnostic code.
When it happens
Trigger: Passing CrewAIToolAdapter to an MCPAdapt setup that then calls async_adapt (e.g. a framework expecting per-tool async adapters), or manually invoking adapter.async_adapt(afunc, mcp_tool).
Common situations: Reusing the adapter outside crewai-tools in a generic MCP adaptation layer that supports both sync and async; upgrading a pipeline that previously used an async-capable adapter.
Related errors
- Client is not initialized
- Failed to install mcp package
- `mcp` package not found, please run `uv add crewai-tools[mcp
- Failed to initialize MCP Adapter: {e}
- MCP server not started, run `mcp_server.start()` first befor
AI-assisted analysis of crewAIInc/crewAI@754d7323be (2026-08-15).
Data as JSON: /api/errors/5e62145d6741654a.
Report an issue: GitHub.