はじめに
Model Context Protocol(MCP) は、LLM に外部ツールやデータソースを接続するための標準プロトコルです。サーバーは急速に増えましたが、いざ自前のエージェントから使おうとすると「どの LLM プロバイダーからどのサーバーへどう接続するか」を毎回書く手間が残ります。
mcp-use は、この接続部分を肩代わりする OSS(MIT ライセンス)の Python フレームワークです。任意の LLM を任意の MCP サーバーにつなぎ、数行で自律エージェントを組める のが特徴です。本記事では pip install から、複数サーバーの束ね方・効率化・ストリーミングまでを、そのまま動かせるコードで解説します。
この記事で学べること
- mcp-use で MCP サーバーのツールを直接呼ぶ方法(
MCPClient) - 自然言語の指示からツールを自動実行するエージェントの作り方(
MCPAgent) - 複数の MCP サーバーを 1 つのエージェントに束ね、Server Manager で効率化する方法
- 実行過程をリアルタイムに受け取るストリーミング
対象読者
- MCP サーバーを自前のエージェントから使いたいエンジニア
- 特定の LLM プロバイダーにロックインされないツール実行基盤を作りたい方
前提環境
- Python 3.11 以上
- Node.js(サンプルの MCP サーバーを
npxで起動するため) - 利用する LLM プロバイダーの API キー(例:
OPENAI_API_KEY/ANTHROPIC_API_KEY)
TL;DR
- mcp-use は「任意の LLM × 任意の MCP サーバー」をつなぐ OSS フレームワーク(MIT・本記事執筆時点 v1.32.1)
-
MCPClientでツールを直接叩け、MCPAgentなら自然言語の指示からツールを自動選択・実行できる -
use_server_manager=Trueで複数サーバーのツール混在による混乱を抑え、必要なサーバーにだけ接続する -
agent.stream()で中間ステップ(どのツールを何の引数で呼んだか)を逐次受け取れる
mcp-use が解決する課題
MCP サーバーは「ファイルシステム」「データベース」「Web 検索」などツールごとに分かれて提供されます。これを複数の LLM プロバイダーから使おうとすると、プロバイダーごと・サーバーごとに接続コードが増え、組み合わせの数(M×N)だけ実装が膨らみます。
mcp-use は LangChain のチャットモデルを LLM として受け取り、MCP サーバーへの接続・セッション管理・ツール一覧の取得を共通化します。結果として、LLM プロバイダーを差し替えても、MCP サーバーを足しても、エージェント側のコードはほぼ変わりません。
セットアップ
pip install mcp-use
# 使う LLM プロバイダーの LangChain 連携も入れる
pip install langchain-openai langchain-anthropic
API キーは環境変数で渡します。
export OPENAI_API_KEY="sk-..."
export ANTHROPIC_API_KEY="sk-ant-..."
ステップ1: MCPClient でツールを直接呼ぶ
まずは LLM を挟まず、MCP サーバーのツールを直接呼んでみます。サーバーは公式の server-everything(動作確認用のサンプルサーバー)を npx で起動します。
import asyncio
from mcp_use import MCPClient
async def main():
config = {
"mcpServers": {
"calculator": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-everything"],
}
}
}
client = MCPClient.from_dict(config)
await client.create_all_sessions()
session = client.get_session("calculator")
result = await session.call_tool(name="add", arguments={"a": 5, "b": 3})
print(f"Result: {result.content[0].text}") # => Result: 8
await client.close_all_sessions()
asyncio.run(main())
config の mcpServers に「サーバー名」と「起動コマンド」を書くだけで、mcp-use がプロセス起動とセッション確立まで面倒を見ます。ツールの戻り値は result.content[0].text で取り出せます。
ステップ2: MCPAgent で自然言語からツールを実行する
次に LLM を挟み、「やりたいこと」を自然言語で渡してツールを自動選択・実行させます。ここがエージェントの本体です。
import asyncio
from langchain_openai import ChatOpenAI
from mcp_use import MCPAgent, MCPClient
async def main():
config = {
"mcpServers": {
"filesystem": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"],
}
}
}
client = MCPClient.from_dict(config)
llm = ChatOpenAI(model="gpt-4o")
agent = MCPAgent(llm=llm, client=client)
result = await agent.run("List all files in the directory")
print(result)
asyncio.run(main())
MCPAgent は client が公開する全ツールを LLM に提示し、指示に応じて適切なツールを呼び出します。
LLM プロバイダーを差し替える
mcp-use は LangChain のチャットモデルを受け取るだけなので、LLM 部分を入れ替えてもエージェントのコードは変わりません。 Anthropic の Claude を使う場合は、llm の生成だけを差し替えます。
from langchain_anthropic import ChatAnthropic
# model はアカウントで利用可能なモデル ID に置き換える
llm = ChatAnthropic(model="claude-sonnet-4-6")
agent = MCPAgent(llm=llm, client=client)
このプロバイダー非依存性が、特定ベンダーへのロックインを避けたいケースで効いてきます。
ステップ3: 複数サーバーを束ねて Server Manager で効率化する
複数の MCP サーバーを 1 つのエージェントに束ねられます。ただしサーバーが増えるとツール数も増え、LLM がツール選択で混乱しやすくなります。これを抑えるのが Server Manager です。
import asyncio
from langchain_openai import ChatOpenAI
from mcp_use import MCPAgent, MCPClient
async def main():
config = {
"mcpServers": {
"filesystem": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"],
},
"everything": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-everything"],
},
}
}
client = MCPClient.from_dict(config)
llm = ChatOpenAI(model="gpt-4o")
agent = MCPAgent(
llm=llm,
client=client,
max_steps=40, # ツール呼び出しの最大ステップ数
use_server_manager=True, # 必要なサーバーにだけ動的に接続する
)
result = await agent.run("一時ディレクトリのファイル一覧を取得して、件数を数えて")
print(result)
asyncio.run(main())
use_server_manager=True を付けると、エージェントは「そのステップで選んだツールが属するサーバー」にだけ接続します。全サーバーへ常時つなぐ無駄を省き、ツール検索もサーバー単位に整理されるため、サーバーが多いほど効果が出ます。特定のサーバーだけを使わせたい場合は、agent.run("...", server_name="filesystem") のように対象を明示することもできます。
max_stepsは安全装置でもあります。ツールを延々と呼び続けるループを防ぐため、タスクの複雑さに応じて適切な上限を設定してください。
ステップ4: 実行過程をストリーミングで受け取る
長時間タスクや対話 UI では、最終結果だけでなく「途中でどのツールを呼んだか」を逐次見せたくなります。agent.stream() は (action, observation) のペアを順次 yield します。
async def main():
# ... client / llm / agent の準備は同上 ...
async for action, observation in agent.stream("一時ディレクトリのファイルを一覧して"):
# action: 呼び出したツール・入力・思考ログ
print(f"[tool] {action.tool} <- {action.tool_input}")
# observation: ツールの実行結果
print(f"[result] {observation}")
action には呼び出したツール名(tool)・入力(tool_input)・推論ログ(log)が、observation にはツールの実行結果が入ります。これを UI に流せば、エージェントの「考えながら手を動かす」過程をそのまま可視化できます。
ハマりポイント
ポイント1: MCP サーバーの起動コマンドが解決できない
サンプルは npx で MCP サーバーを起動するため、Node.js が未インストールだとセッション確立に失敗します。node -v / npx -v が通ることを先に確認してください。Python 製サーバーを使う場合は command を uvx や python に変えます。
ポイント2: API キー未設定で MCPAgent がエラーになる
MCPClient 単体(ステップ1)は LLM を使わないため API キー不要ですが、MCPAgent は LLM を呼ぶため対応する環境変数(OPENAI_API_KEY など)が必要です。プロバイダーを差し替えたら、対応するキーも設定し直してください。
ポイント3: Server Manager は「多サーバー時」に効く
サーバーが 1 つだけのときは use_server_manager の効果は小さく、かえってオーバーヘッドになります。ツールが多数のサーバーにまたがり、LLM がツール選択で迷う段階になってから有効化するのが目安です。
まとめ
- mcp-use を使うと「任意の LLM × 任意の MCP サーバー」の接続を共通化でき、プロバイダーやサーバーを差し替えてもエージェント側のコードを保てる
-
MCPClientでツールを直接呼び、MCPAgentで自然言語からツールを自動実行できる - 複数サーバーを束ねるときは
use_server_manager=Trueとmax_stepsで効率と安全性を確保する -
agent.stream()で実行過程を可視化でき、対話 UI や長時間タスクの監視に使える
MCP サーバーが増え続けるなか、「つなぎ込み」を標準化しておくと、エージェントの構築・乗り換えが一気に楽になります。まずは server-everything でツール呼び出しの感触をつかむところから始めてみてください。
参考リンク
-
mcp-use(GitHub) — インストール・
MCPClient/MCPAgentの最小例で引用 -
mcp-use ドキュメント: Server Manager —
use_server_managerの挙動で引用 - Model Context Protocol 公式 — MCP の概要で引用