connect-tools-and-mcp について
CrewAI エージェントにカスタムツール、crewai_tools、MCP 接続を設定する開発者向けガイドです。CrewAI 1.15.x で検証され、見落とされやすい API の違いや実行時の問題を扱います。
主な機能
- 01カスタムツールと MCP の接続方式選択
- 02stdio、HTTP、SSE 接続の設定
- 03ツール名とフィルター規則の確認
- 04キャッシュとツール失敗処理の整理
- 05crewai_tools の利用可能な名前の確認
活用シーン
- 01CrewAI エージェントへのローカル・リモート MCP サーバー接続
- 02ツールのインポートや実行エラーの調査
- 03ツールのキャッシュと失敗ポリシーの設定
MCP 対応
CrewAI エージェントを MCP サーバーに接続する方法を解説します。ネイティブ設定や MCPServerAdapter、トランスポート、ツールフィルターを扱います。
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ crewaiinc/ skills --skill connect-tools-and-mcpインストール後、Claude Code で/connect-tools-and-mcpを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/crewai-tools-names.mdcustom-tools.mdmcp-connections.md詳細
CrewAI エージェントにツールと MCP サーバーを接続する
エージェントにツール(カスタム Python、組み込みの crewai_tools、または MCP サーバー)を使わせる際に、気づかないうちに失敗する 0.x 時代の間違いを避けましょう。
2026-10-01 に crewai 1.15.22 および 1.15.23 で検証済みです。
2026-10-01 に CrewAI AMP と実際の LLM でライブテスト済みです。
まず crewai version を実行してください。メジャーまたはマイナーバージョンが 1.15 と異なる場合は、バージョンに依存する項目を信頼する前に、ask-docs スキルで再確認してください。
1. 仕組みを選ぶ
| 必要なもの | 使用するもの | セクション |
|---|---|---|
| ツールとして使う手早い Python 関数 | crewai.tools の @tool | 3 |
| 設定、状態、または文書化された入力スキーマを持つツール | args_schema を備えた BaseTool サブクラス | 3 |
| 組み込みの検索/スクレイピング/ファイル用ツール | crewai_tools — ただし、名前が存在することを確認するため、一度インポートしてください | 5 |
| リモート MCP サーバー | Agent(mcps=[MCPServerHTTP(...)]) — クルーがデプロイされている場合や akickoff() を使う場合は、https:// 文字列を使わないでください | 6, 8 |
| コードに同梱される MCP サーバー | Agent(mcps=[MCPServerStdio(...)]) — サーバーがパッケージ内にあれば、CrewAI AMP でも動作します | 6, 10 |
| CrewAI AMP アカウントで接続済みのインテグレーション | mcps=["<slug>"] または "<slug>#<tool>" | 6 |
| MCP ツール名を直接指定する場合、または起動/停止を手動で管理する場合 | MCPServerAdapter(crewai-tools[mcp] が必要です) | 9 |
mcp はすでに crewai 1.15.x のコア依存関係に含まれているため、ネイティブの mcps= に追加インストールは不要です。
2. インポート
| おそらく書いていたコード | 現在の形式 | 古い形式で起きること |
|---|---|---|
from crewai_tools import BaseTool | from crewai.tools import BaseTool | ImportError: cannot import name 'BaseTool' from 'crewai_tools' |
from crewai_tools import tool | from crewai.tools import tool | ImportError: cannot import name 'tool' from 'crewai_tools' |
from crewai_tools import CodeInterpreterTool | サンドボックスツール:E2BPythonTool、DaytonaPythonTool | ImportError — 削除済み |
from crewai_tools import ZapierActionsAdapter | from crewai_tools.adapters.zapier_adapter import ZapierActionsAdapter(またはトップレベルの ZapierActionTools) | トップレベルで ImportError |
アダプター用の from crewai.mcp import ... | from crewai_tools import MCPServerAdapter | アダプターは crewai_tools にあり、ネイティブ設定は crewai.mcp にあります |
from crewai.tools import BaseTool, tool, ToolFailure, ToolExecutionFailedError
from crewai.mcp import (
MCPServerStdio, MCPServerHTTP, MCPServerSSE,
create_static_tool_filter, create_dynamic_tool_filter,
)
from crewai.mcp.exceptions import MCPConnectionError
3. カスタムツール
from pydantic import BaseModel, Field
from crewai.tools import BaseTool, tool
class PriceInput(BaseModel):
sku: str = Field(..., description="Product SKU, e.g. 'A-100'")
currency: str = Field("EUR", description="ISO currency code")
class PriceTool(BaseTool):
name: str = "price_lookup"
description: str = "Return the unit price for a SKU. Use before quoting a price."
args_schema: type[BaseModel] = PriceInput
def _run(self, sku: str, currency: str = "EUR") -> str:
return f"{sku} costs 9.99 {currency}"
@tool("Unit Converter")
def convert(km: float) -> str:
"""Convert kilometres to miles."""
return f"{km * 0.621371:.1f} mi"
print(PriceTool().run(sku="A-100")) # args are validated against PriceInput first
print(convert.run(km=10))
実際の障害を防ぐルール:
| ルール | 防止する障害 |
|---|---|
非同期ツールでも、必ず _run を定義します | _run は抽象メソッドです。実装しないと、TypeError: Can't instantiate abstract class ... without an implementation for abstract method '_run' が発生します |
非同期コードは async def _run(...) に記述します | エージェントは kickoff() と akickoff() のどちらでも _run を通じてツールを実行します。_arun のオーバーライドが使われるのは、自分で tool.arun() を呼び出した場合のみです |
@tool 関数には docstring を付けます | デコレーション時に ValueError: Function must have a docstring が発生します |
| LLM 向けに、ツールの機能と使用するタイミングを説明します | エージェントは説明に基づいてツールを選択します。特に MCP ツールは、名前から機能が分かりにくいものです(セクション 7) |
| 表示名はサニタイズされるものと想定します | @tool("Unit Converter") は、LLM には unit_converter として提示されます(claude-haiku-4-5 の実行時に確認) |
エラー文字列ではなく ToolFailure を返します | エラー文字列はデータとして扱われます。ToolFailure は TaskOutput.tool_failures に記録され、実行を中断させることができます(以下を参照) |
ツールごとのオプション(すべて BaseTool で使用でき、記載のあるものは @tool(...) でも指定できます):
| フィールド | 効果(検証済み) |
|---|---|
max_usage_count=N(@tool("x", max_usage_count=N) でも指定可能) | 1 つのタスク内で N 回実行すると、エージェントには Tool '...' has reached its usage limit of N times and cannot be used anymore. と表示されます。次のタスクまたは kickoff では使用回数がリセットされるため、「実行ごとに 1 回」の副作用は自分で制御してください。0 または負の値を指定すると ValidationError になります |
result_as_answer=True(@tool でも指定可能) | ツールの戻り値がタスクの出力になり、それ以降の LLM 呼び出しは行われません |
cache_function=lambda args, result: bool | 呼び出しごとに、結果をキャッシュできるかどうかを決定します(セクション 4) |
tool_failure_policy="ignore" | "warn" | "raise" | Agent、Task、Crew でも指定できます。デフォルトは warn です。raise を指定すると、ToolExecutionFailedError で実行が中断されます |
失敗について:ツールが例外を発生させても、crew は失敗しません。例外の内容はエージェントに返され、ツールの失敗として記録されますが、crew は「成功」として終了します。後続のコードで失敗を把握する必要がある場合は、ToolFailure(...) を返して tool_failure_policy="raise" を設定するか、result.tasks_output[i].tool_failures を確認してください。完全な例については、references/custom-tools.md を参照してください。
Task(tools=[...]) は、そのタスクでエージェントのツールを置き換えます。追加するものではありません。
4. ツール結果のキャッシュ
| 設定 | 1.15.22-1.15.23 でのデフォルト | 効果 |
|---|---|---|
Crew(cache=...) | False | オプトインです。True の場合、引数が同じ呼び出しを繰り返すと、ツールを実行せずに最初の結果を返します |
Agent(cache=...) | True | キャッシュへの参加を許可するだけです。False にすると、crew がキャッシュを使用していても、そのエージェントは対象外になります |
BaseTool(cache_function=...) | 常にキャッシュ | 結果をキャッシュ対象外にするには False を返します |
crewai 1.15.2 までは、crew はデフォルトでツールの結果をキャッシュしていました。1.15.3 以降はオプトインです。以前の動作に依存していた場合は、明示的に Crew(cache=True) を設定してください。ライブデータを扱うツールや状態を変更するツールでは、cache_function が False を返す場合を除き、決して有効にしないでください。
キャッシュとは別に、再実行を防ぐ仕組みもあります。エージェントがまったく同じ呼び出しを連続して繰り返すと、キャッシュの有効・無効にかかわらず、crewai は 2 回目の呼び出しを拒否します("I tried reusing the same input...")。
5. crewai_tools:存在する名前
crewai-tools 1.15.22-1.15.23 は118個の名前をエクスポートします。その名前を使ったコードを書く前に、ツールをインポートしてください。モデルは次の名前を頻繁にでっち上げます。
| 幻覚された名前(ImportError) | 実際の 1.15.22-1.15.23 の名前 |
|---|---|
CodeInterpreterTool | 削除済み — E2BPythonTool / DaytonaPythonTool を使用 |
BedrockKBRetriever | BedrockKBRetrieverTool |
GitHubSearchTool、GithubTool | GithubSearchTool |
ArxivTool | ArxivPaperTool |
ComposioToolSet | ComposioTool |
GoogleSearchTool、WebSearchTool、DuckDuckGoSearchTool | SerperDevTool、BraveSearchTool、TavilySearchTool、EXASearchTool |
PDFTextWritingTool、PGSearchTool | なし |
WikipediaTool、PythonREPLTool、ShellTool、CalculatorTool、HumanTool、LangChainTool、SeleniumTool | なし(SeleniumScrapingTool は存在します)— カスタムツールを作成してください |
多くのツールにはサードパーティ製パッケージが必要です。パッケージがない場合、ツールを作成すると You are missing the '<pkg>' package. Would you like to install it? [y/N] と表示されます(EXASearchTool、TavilySearchTool、FirecrawlSearchTool、SeleniumScrapingTool で確認済み)。ターミナルが接続されていると処理が永久にブロックされ、stdin が閉じていると click.exceptions.Abort が発生します。例として、追加パッケージを事前にインストールしてください:uv add "crewai-tools[exa-py]"。組み込みツールはクラス名ではなく、サニタイズされた表示名で LLM に提供されます。DirectoryReadTool は list_files_in_directory、FileReadTool は read_a_files_content として表示されます。RAG ツール(WebsiteSearchTool、PDFSearchTool など)は、埋め込みモデルのキーがないと作成時に失敗します。全リストと追加パッケージについては、references/crewai-tools-names.md を参照してください。
6. ネイティブの Agent(mcps=[...])
from crewai import Agent
from crewai.mcp import MCPServerHTTP, MCPServerSSE, MCPServerStdio, create_static_tool_filter
agent = Agent(
role="Inventory analyst",
goal="Answer stock questions",
backstory="Careful with numbers.",
mcps=[
MCPServerHTTP(url="https://mcp.example.com/mcp",
headers={"Authorization": "Bearer <your-key>"}),
MCPServerSSE(url="https://legacy.example.com/sse"),
MCPServerStdio(command="uvx", args=["mcp-server-time"],
tool_filter=create_static_tool_filter(allowed_tool_names=["get_current_time"])),
"https://docs.example.com/mcp#search_docs", # https string, one tool (sync kickoff only - section 8)
"acme#lookup_stock", # AMP-connected integration, one tool
"acme#list_warehouses", # second tool = second ref
],
)
文字列の参照は作成時に検証されます。タスクが実行されるまで接続は行われません。
| 形式 | ルール(すべて検証済み) |
|---|---|
MCPServerStdio(command, args, env, tool_filter, cache_tools_list) | クルーが実行される場所でサブプロセスを起動します。サーバーは環境を継承しません。受け取るのは HOME, LOGNAME, PATH, SHELL, TERM, USER と env= のみなので、API キーは明示的に env で渡してください。cwd フィールドもタイムアウトフィールドもありません |
MCPServerHTTP(url, headers, streamable=True, tool_filter, cache_tools_list) | ストリーミング可能な HTTP。http:// と https:// の両方が動作します。IP アドレスではなくホスト名を使用してください。http://127.0.0.1:8765/mcp ではツール名が数字で始まり、Anthropic モデルが拒否します(ValueError: Anthropic function name '127_0_0_1_8765_mcp_lookup_stock' must start with a letter or underscore)。http://localhost:8765/mcp は動作します |
MCPServerSSE(url, headers, tool_filter, cache_tools_list) | レガシー SSE サーバー(通常は /sse パス) |
"https://host/path" 文字列 | https:// で始まる必要があります。任意で #tool を付けると、1つのツールだけが残ります。実行中のイベントループ内(await crew.akickoff() を使う場合や、CrewAI AMP にデプロイされたクルー(セクション8))では、ツールが0個に黙って解決されます |
"slug" / "slug#tool" 文字列 | CrewAI AMP アカウントに接続済みのインテグレーションを指定します。レガシー形式の "crewai-amp:slug" も動作します。アカウントで接続されていない slug を指定すると、ツールは0個となり、実行は続行されます(AMP で確認) |
"http://localhost:8000/mcp" または https:// でも slug でもない文字列 | Agent の作成時に ValidationError: ... Invalid MCP reference: 'http://...'. String references must be an 'https://' URL or a valid slug が発生します。http:// には MCPServerHTTP を使用してください |
"slug#a,b" | 同じ Invalid MCP reference ValidationError が発生します。ツールごとに参照を1つ指定してください |
"https://...#a,b" | 受け入れられますが、ツールは0個選択されます(# の後に指定できる名前は1つです)。ツールごとに参照を1つ指定してください |
tool_filter の名前 | サニタイズされたツール名と照合されます。サーバーのツール名が getForecast の場合、get_forecast として指定する必要があります |
各トランスポート、動的フィルター、AMP 形式の全例については、references/mcp-connections.md を参照してください。
7. MCP ツール名は書き換えられます — ハードコードしないでください
ネイティブ MCP ツールは、<server name>_<tool name> として LLM に提供された後、サニタイズされます。すべて小文字に変換され、英数字以外の文字は _ になり、camelCase は分割され、最大 64 文字になります。
| ソース | ツール lookup_stock に対して LLM に表示される名前 |
|---|---|
MCPServerStdio(command="python", args=["servers/inventory.py"]) | python_servers_inventory_py_lookup_stock |
絶対パスを使う MCPServerStdio。例:/opt/app/.venv/bin/python + /opt/app/servers/inventory_server.py | opt_app_venv_bin_python_opt_app_servers_inventory_serve_a87662e9 — 64 文字を超えるため、切り詰められてハッシュ化され、ツール名が失われます。command=sys.executable でも、ローカル環境と AMP の両方で同じことが起こります |
MCPServerHTTP(url="http://localhost:8765/mcp") | localhost_8765_mcp_lookup_stock(IP ホストの場合、名前は数字で始まります — セクション 6) |
MCPServerHTTP(url="https://mcp.example.com/mcp")、または同じ https:// 文字列 | mcp_example_com_mcp_lookup_stock |
"acme#lookup_stock"(AMP) | acme ではなく、アカウントから返されるサーバー URL をもとに生成されます — _lookup_stock のサフィックスだけが安定しています |
MCPServerAdapter | lookup_stock(そのまま) |
このため、次の点に注意してください。
- タスクの説明や背景情報に「
lookup_stockツールを呼び出してください」と書かないでください。機能を説明する(「inventory ツールで在庫レベルを確認する」)か、実行時に正確な名前を導出してください。ネイティブの関数呼び出しモデルなら通常は対処できます(claude-haiku-4-5 は「lookup_stock ツールを呼び出してください」と指示されるとpython_mcp_server_py_lookup_stockを呼び出しました)が、テキスト ReAct 経路のモデルはAction 'lookup_stock' don't existというエラーになり、ハッシュ化された名前の場合は説明だけを手掛かりにすることになります。 - stdio の
command/argsは短く保ち("uvx"、"npx"、相対スクリプトパスなど)、名前が読みやすく、64 文字以内に収まるようにしてください。絶対パスを使うと、ファイルシステムの構成もすべてのプロンプトに含まれます。スコープ付き npx パッケージは約 45 文字をすでに使用します。npx -y @modelcontextprotocol/server-filesystem ./dataではlist_allowed_directoriesが..._data_list_4ab656eeにハッシュ化されました。名前をそのまま使う必要がある場合はMCPServerAdapterを使ってください。 - コードでは、解決済みのネイティブ MCP ツールを
tool.nameではなくtool.original_tool_nameで識別してください。
8. タイムアウト、再試行、失敗時の動作
| 経路 | 接続 | ツール呼び出しごと | 再試行 | サーバー停止時 |
|---|---|---|---|---|
MCPServerStdio/HTTP/SSE 設定および AMP スラッグ | 30 s | 30 s | タイムアウト時に 3 回試行 — 毎回ツールが再実行されます。実際の実行では、35 s かかるツールが 3 回実行され(約 99 s)、エージェントは観測結果として Error executing tool: Error executing MCP tool slow_report: Operation timed out after 30 seconds を受け取り、ツールの失敗が記録され、crew は終了しました。直接の tool.run() は代わりに RuntimeError を発生させます | kickoff で MCPConnectionError が発生します |
"https://..." 文字列 | 10 s、検出時は 15 s | 60 s | 3 回試行(65 s かかるツールが 3 回実行され、約 198 s)、その後エラーを文字列として返します | エージェントはMCP ツールなしで実行され、エラーは発生しません |
MCPServerAdapter | connect_timeout=(デフォルトは 30) | crewai のタイムアウトなし(35 s の呼び出しが完了しました) | なし | コンストラクターで RuntimeError: Failed to initialize MCP Adapter が発生します |
1.15.22-1.15.23 では、ネイティブのタイムアウトはモジュール定数です。MCPServerStdio、MCPServerHTTP、MCPServerSSE、Agent のどのフィールドでも変更できません。そのため、次の点に注意してください。
- MCP ツールの呼び出しは 30 s を大幅に下回る時間で完了させてください。タイムアウトした呼び出しは再送信されるため、冪等にしてください。時間のかかるジョブでは、1 つのツールでジョブ ID を返し、別のツールでポーリングしてください。
- 本番環境では
https://文字列より設定オブジェクトを優先してください。設定オブジェクトは kickoff 時に明示的に失敗しますが、文字列ではツールが通知なく除外されます。 https://文字列はasyncio.run()でツールを検出します。実行中のイベントループ内ではこれが失敗し、エージェントはエラーなしでツールを 1 つも受け取りません(RuntimeWarning: coroutine 'MCPToolResolver._get_mcp_tool_schemas_async' was never awaitedのみが発生します)。await crew.akickoff()の実行時や CrewAI AMP のデプロイで実際に確認されています。この場合、エージェントはツールなしで実行され、実行していないツール呼び出しについて回答することがあります。同じサーバーをMCPServerHTTP(url=...)として使うと、どちらの環境でも動作しました。同期のcrew.kickoff()は、同期 Flow ステップから呼び出した場合も含め、文字列を正しく解決します。isError: trueを含む MCP の結果は、テキストとしてエージェントに渡されます。これはmcp_errorツールの失敗として記録され、tool_failure_policy="raise"によってToolExecutionFailedErrorが発生します。
9. MCPServerAdapter と @CrewBase の mcp_server_params
MCPServerAdapter には追加の依存関係が必要です:uv add "crewai-tools[mcp]"(mcpadapt がインストールされます。mcp 自体はすでに含まれています)。追加の依存関係がない状態でこれを構築すると、You are missing the 'mcp' package. Would you like to install it? [y/N] と尋ねられます。入力を受け付けないターミナルでは永久に停止し、stdin が閉じている場合(一般的な CI 環境)には click.exceptions.Abort が発生します。追加の依存関係を明示的にインストールしてください。
from mcp import StdioServerParameters
from crewai_tools import MCPServerAdapter
params = StdioServerParameters(command="python", args=["mcp_server.py"])
with MCPServerAdapter(params, "lookup_stock", connect_timeout=60) as tools:
print([t.name for t in tools]) # ['lookup_stock'] - bare names, filtered by name
# build agents with tools=tools and kick off INSIDE the with-block
サーバーはコンストラクターで起動し、with ブロックを抜けると停止します。その後にツールを使用すると失敗します。リモートサーバーの場合は、辞書を渡してトランスポートを指定してください:{"url": "https://<host>/mcp", "transport": "streamable-http"}。"transport" を指定しない場合、アダプターは SSE を使用します。streamable-HTTP の /mcp エンドポイントに接続すると、Couldn't connect to the MCP server after <connect_timeout> seconds で失敗します。
@CrewBase クラスでは、mcp_server_params(必要に応じて mcp_connect_timeout も指定できます。デフォルトは 30)を設定し、@agent メソッド内で self.get_mcp_tools("name", ...) を呼び出してください。crewai は kickoff のたびにそのアダプターを停止します。同じインスタンスで .crew().kickoff() を 2 回目に呼び出すと、すべての MCP 呼び出しが Event loop is closed を返す一方で、crew は「成功」したままでした。実行ごとに新しいインスタンスを作成してください:InventoryCrew().crew().kickoff()。
10. ホスト型デプロイ:CrewAI AMP で動作するもの
CrewAI AMP へのデプロイ(ZIP デプロイ、crewai 1.15.23、anthropic/claude-haiku-4-5)で測定しました。各フォームにつきキックオフは 1 回です。
| デプロイしたクルーのフォーム | 結果 |
|---|---|
MCPServerHTTP(url="https://<public host>/mcp") | 動作します。モデルは <host>_mcp_<tool> を呼び出しました |
"https://<public host>/mcp#tool" 文字列 | ツールはゼロ件、実行は SUCCESS。モデルは回答内でツール呼び出しをでっち上げました(セクション 8) |
MCPServerStdio(command="python", args=["-m", "<pkg>.inv_server"])。サーバーモジュールは src/<pkg>/ 内 | 動作します。パッケージに含めた stdio サーバーがデプロイ環境内で実行されます |
command=sys.executable を使用した同じ設定 | 動作します(ツール名はハッシュ化されます。セクション 7) |
X がデプロイ環境変数の場合の MCPServerStdio(..., env={"X": os.environ["X"]}) | サーバーは X を認識します。env= がない場合は認識しません |
pyproject.toml に crewai-tools[mcp] がある場合の MCPServerAdapter(StdioServerParameters(...)) | 動作します。ツール名はそのままです |
デプロイ環境にないファイル(ラップトップ上のパス)を指す MCPServerStdio | MCPConnectionError で実行が失敗します |
MCPServerStdio(command="npx", ...) | 同様に実行が失敗します。デプロイ環境にあるのは、Python プロジェクトがインストールするものだけです |
誤ったパスを指定した MCPServerHTTP(HTTP 404) | 同様に実行が失敗します |
アカウントに接続されていない "<slug>#tool" | ツールはゼロ件、実行は SUCCESS |
API から MCP 接続の失敗を確認した場合の状態:上記の各 MCPConnectionError の実行では、数分後も含め、ポーリングのたびに GET /status/{kickoff_id} は JSON の FAILED 状態ではなく、HTTP 500 Internal Server Error(プレーンテキスト)を返しました。同じクルーで通常の例外が発生した場合は、ドキュメントに記載された形式で返されました:{"state": "FAILED", "status": "ValueError: ..."}。/status が継続的に 500 を返す場合は「実行に失敗した」と判断し、まず MCP 接続を確認してください。
ルール:
- stdio サーバーは、クルーが実行される場所で子プロセスとして動作します。サーバーをパッケージ内に含め(
src/<pkg>/server.py。python -m <pkg>.serverで起動)、その Python 依存関係もpyproject.toml/uv.lockに含めてください。ラップトップ上のパスや Node/npx サーバーはデプロイ環境にありません。 - リモートサーバーには
MCPServerHTTP(url="https://<host>/mcp")(またはMCPServerSSE)を使用し、https://文字列は決して使用しないでください。デプロイ先には管理下にある安定したホスト名を指定し、認証を必須にしてください。また、一時的なトンネルを起動したままにしないでください。 - ヘルスチェック:正常なストリーマブル HTTP MCP エンドポイントに対して
curl -s -o /dev/null -w "%{http_code}" https://<host>/mcpを実行すると 406 が返ります(公開サーバーとローカル環境で確認済み)。404 はパスが誤っていることを示し、000/接続拒否はサーバーがダウンしていることを示します。 - トークンは環境変数から読み取って
headersに設定してください(os.environ["ACME_MCP_TOKEN"])。URL 文字列やコードに含めてはいけません。stdio サーバーにデプロイ環境変数を渡すにはenv=が必要です。
よくある間違い
| 症状 | 原因 | 修正方法 |
|---|---|---|
cannot import name 'BaseTool' from 'crewai_tools' | 0.x のインポートパスです | from crewai.tools import BaseTool, tool |
Can't instantiate abstract class ... '_run' | _arun しか定義されていません | _run を定義します(async def でもかまいません) |
Action 'lookup_stock' don't exist, these are the only available Actions: ...、またはエージェントが MCP ツールをまったく使用しません | プロンプトではツール名をそのまま(lookup_stock)指定していますが、LLM には python_..._lookup_stock と表示されています | 機能を説明し、実行時に名前を取得します |
ValidationError ... Invalid MCP reference: 'github#a,b' | # に指定できるツール名は1つです | ["github#a", "github#b"] |
mcps=["https://...#a,b"] を指定してもツールが見つかりません | 同じ原因ですが、https 文字列は検証されません | ツールごとに1つの参照を指定します |
ValidationError ... Invalid MCP reference: 'http://localhost:8000/mcp' | 文字列は https:// またはスラッグである必要があります | MCPServerHTTP(url="http://localhost:8000/mcp") |
Anthropic function name '127_0_0_1_...' must start with a letter or underscore | MCP サーバーの URL に IP アドレスが使われています | ホスト名(localhost)を使用します |
https:// 文字列の MCP で akickoff() の実行中または AMP 上でツールが見つからず、回答でツール呼び出しが捏造されます | 文字列参照は、イベントループの実行中に解決できません | MCPServerHTTP(url=...) |
GET /status が失敗し続けるか、実行が完了しません | MCPConnectionError が発生した可能性があります(stdio コマンドまたはファイルがない、URL が間違っているなど) | クルーをローカルで実行してエラーを確認し、MCP 接続を修正します |
tool_filter で何も残りません | サーバーのキャメルケース名をフィルターに使用しています | サニタイズされた名前(get_forecast)を使用します |
| 「Would you like to install it? [y/N]」で実行が停止します | オプションのパッケージ(crewai-tools[mcp]、exa-py など)がありません | 実行前に追加パッケージをインストールします |
| ツールが3回実行された/副作用が繰り返されました | ネイティブ MCP 呼び出しが30秒を超え、再試行されました | 呼び出しを短くし、冪等にします |
| クルーの実行は「成功」しますが、回答ではツールがエラーになったとされています | ツールの例外はエージェントに渡され、送出されません | ToolFailure を返し、tool_failure_policy="raise" を設定して、tool_failures を確認します |
Crew(cache=True) を有効にした後、結果が古くなっています | ライブデータを取得するツールがキャッシュされています | cache_function=lambda a, r: False または Agent(cache=False) |
| 同一の呼び出しを繰り返すと、毎回 API が呼び出されます | 1.15.x ではクルーのキャッシュはオプトインです | Crew(cache=True) |
同じ @CrewBase インスタンスで2回目の kickoff を実行すると、Event loop is closed が発生します | 最初の kickoff の後にアダプターが停止しました | kickoff ごとに新しいクルーインスタンスを作成します |
stdio MCP サーバーに API キーが設定されている .env があるにもかかわらず、API キーがないと表示されます | stdio サーバーが受け取るのは、ユーザーの環境ではなく最小限の環境です | MCPServerStdio(..., env={"X_API_KEY": os.environ["X_API_KEY"]}) |
| ローカルでは動作しますが、デプロイ後に失敗します | stdio サーバーのファイルまたはコマンド(npx、ノート PC 上のパス)がデプロイ先にありません | サーバーをパッケージに含めるか、安定した URL で HTTP 経由で提供します |
チェックリスト
-
crewai.toolsからBaseTool/toolをインポートします。crewai_toolsの各名前は、存在を確認するために一度ずつインポートします - カスタムツールでは
_runを定義し、args_schema(または型指定された@toolのシグネチャ)と、LLM 向けの説明を用意します - 失敗は
ToolFailureとして返し、tool_failure_policyを意図的に選択します -
Crew(cache=...)を明示的に設定し、ライブデータを扱うツールはキャッシュ対象から除外します - 対話型プロンプトで処理が止まらないよう、オプションパッケージと
crewai-tools[mcp]を事前にインストールします - ツールごとに
"slug#tool"形式の参照を1つ使います。http://のサーバーには文字列ではなくMCPServerHTTPを使い、IP アドレスではなくホスト名を指定します - デプロイする Crew、または
akickoff()では、https://形式の文字列参照を使わず、MCPServerHTTPを使います - プロンプトやコードが、名前だけの MCP ツール名に依存しないようにします。stdio コマンドは短く保ちます
- stdio サーバーには
env=を使ってキーを渡します(Crew の環境変数は継承されません) - MCP ツールの呼び出しは、30 秒を大幅に下回る時間で完了し、冪等であるようにします
- デプロイする Crew では、安定した URL で、GET のみのリクエストに 406 を返す HTTP/SSE MCP サーバー、またはパッケージに同梱された stdio サーバーを使います
-
mcp_server_paramsを使う場合、kickoff ごとに新しい@CrewBaseインスタンスを作成します
参考資料
- カスタムツール - BaseTool、
@tool、非同期処理、ToolFailure と失敗ポリシー、キャッシュ、使用制限、および実行可能なサンプル - MCP 接続 -
mcps=のすべての形式、フィルター、名前の導出、タイムアウト、MCPServerAdapter、@CrewBase、デプロイ - crewai_tools の名前 - 1.15.22~1.15.23 のエクスポート一覧、誤って生成された名前、追加パッケージ、構築時の動作
- 公開ドキュメント:https://docs.crewai.com/en/concepts/tools および https://docs.crewai.com/en/mcp/overview
関連スキル:
- check-crewai-api - ツール以外の現在の Agent/Task/Crew API とインポート
- design-agent - エージェントに割り当てるツール数の選定、役割/目標/バックストーリーの作成
- test-crewai-project - スタブ LLM を使ったオフラインでのツール呼び出し
- deploy-to-amp - MCP 接続を使うプロジェクトを CrewAI AMP にデプロイ
- ask-docs - インストール済みバージョンと異なる場合に、最新のドキュメントを参照