AIエージェント入門

LangGraph MCP連携3手順【2026年10月4日】

LangGraph MCP連携3手順【2026年10月4日】

この記事の結論

langgraph mcp連携を3手順で実装。2026年10月4日時点のMCPAdapterと旧langchain-mcp-adaptersの移行差分、StateGraph、認証・エラー対策をコードで確認できます。

必要なものは3つです。2026年10月4日時点のLangGraphとMCP連携は、①MCPサーバー、②ツール呼び出し対応モデル、③MCPツールをLangChainツールへ変換するアダプターを用意し、list_tools()で読み込んだツールをエージェントへ渡せば実装できます。

新規実装はlangchain.mcp.MCPAdapterを選びます。独立パッケージlangchain-mcp-adaptersは2026年9月17日にアーカイブされました。既存コードは環境を固定し、新規コードはlangchain[mcp]>=1.4.0へ移行します。

  • ローカル接続:PythonスクリプトをPathで渡し、stdioで起動する
  • リモート接続:MCPエンドポイントのURLを渡し、Streamable HTTPで接続する
  • LangGraph側:標準的な会話ループはcreate_agent、独自の分岐が必要ならStateGraphとToolNodeを使う

手順1:現行パッケージを入れ、接続方式を決める

手順1:現行パッケージを入れ、接続方式を決める
手順1:現行パッケージを入れ、接続方式を決める

2026年10月4日時点のLangChain公式MCPドキュメントは、MCP機能をlangchain.mcpへ移し、MCPAdapterを案内しています。現時点ではベータ版なので、検証したバージョンを固定して使います。

LangGraphからMCPツールを呼ぶ流れ

  • 利用者の依頼
  • LangGraphのエージェント
  • MCPAdapter
  • MCPサーバーのツール
  • ToolMessage

当日確認できる版はLangChain 1.4.3、LangGraph 1.2.12です。分離した仮想環境で次を実行します。

動作環境:Python 3.11、LangChain 1.4.3、LangGraph 1.2.12を想定した構成例

python -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip
python -m pip install "langchain[mcp]==1.4.3" "langgraph==1.2.12" langchain-openai

# 注意: 本番環境で使用する前に、必ずテスト環境で動作確認してください。
選ぶ対象 現行の書き方 向いている接続 注意点
単一のリモートサーバー MCPAdapter("https://.../mcp") Streamable HTTP 認証情報をソースへ直書きしない
単一のローカルサーバー MCPAdapter(Path("server.py")) stdio 文字列ではなくPathを渡す
複数サーバー MCPAdapter({"mcpServers": {...}}) stdioとHTTPの混在 サーバー名がツール名の接頭辞になる
旧システムの保守 MultiServerMCPClient 旧adapter対応範囲 保守終了済み。新規採用しない

stdioとStreamable HTTPは用途で分ける

同じマシンのスクリプトにはstdio、リモートのMCPサーバーにはStreamable HTTPを使います。現行MCPAdapterはURLならHTTP、Pathならstdioと推定するため、旧設定のtransport指定は基本形では不要です。

SSEは後方互換のため残っていますが、公式移行ガイドでは非推奨の接続方式として整理されています。新しいリモート実装をSSEから始める理由はありません。MCP自体の接続方式やサーバー側の構造から確認したい場合は、MCPサーバーとは|仕組み・接続手順・作り方・一覧も先に読むと迷いにくくなります。

LangGraph MCP連携の3手順

  • 1 接続先を決める:URL・Path・mcpServers
  • 2 ツールを発見する:list_tools
  • 3 グラフへ渡す:create_agent・ToolNode

手順2:MCPツールを読み込み、エージェントから呼ぶ

手順2:MCPツールを読み込み、エージェントから呼ぶ
手順2:MCPツールを読み込み、エージェントから呼ぶ

最短経路は、公開されているLangChainドキュメントMCPサーバーへ接続する例です。MCPAdapterがサーバーのツール一覧を取得し、create_agentへ渡します。モデルは利用者の依頼と各ツールの説明を見て、必要なツールを選びます。

動作環境:Python 3.11、langchain[mcp]==1.4.3、langchain-openai、環境変数OPENAI_API_KEYとLANGCHAIN_MODEL_ID。後者には利用中のプロバイダーで有効なツール呼び出し対応モデルIDを設定してください。

# 注意: 本番環境で使用する前に、必ずテスト環境で動作確認してください。
import asyncio
import os

from langchain.agents import create_agent
from langchain.mcp import MCPAdapter


async def main() -> None:
    if not os.getenv("OPENAI_API_KEY"):
        raise RuntimeError("OPENAI_API_KEYを環境変数に設定してください")
    model_id = os.environ["LANGCHAIN_MODEL_ID"]

    async with MCPAdapter("https://docs.langchain.com/mcp") as adapter:
        tools = await adapter.list_tools()
        agent = create_agent(model_id, tools=tools)
        result = await agent.ainvoke(
            {
                "messages": [
                    {
                        "role": "user",
                        "content": "LangGraphで短期メモリを追加する公式手順を探して",
                    }
                ]
            }
        )

    print(result["messages"][-1].content)


if __name__ == "__main__":
    asyncio.run(main())

ポイントは次の3点です。

  • list_tools()は、MCPサーバーが公開しているツールをLangChainのツールへ変換して返します。
  • ainvoke()へ渡すのは通常のメッセージです。MCP固有のJSON-RPCをアプリ側で組み立てる必要はありません。
  • ツール呼び出し対応モデルが必要です。モデルIDは利用中のプロバイダーで有効なものへ置き換えてください。

接続をいつ閉じるか

公式ガイドでは、async withを抜けた後も取得済みツールを呼べます。既定では呼び出しごとに接続します。同じ接続を再利用するなら、上の例のようにainvoke()もコンテキスト内で行います。

ツール発見から回答まで

  • list_tools
  • tool call
  • MCPサーバーが実行
  • ToolMessage
  • 最終回答

手順3:StateGraphへToolNodeを組み込む

手順3:StateGraphへToolNodeを組み込む
手順3:StateGraphへToolNodeを組み込む

独自の承認分岐、業務状態、専用ノード、終了条件が必要ならStateGraphを直接組みます。MCPツールはToolNodeへそのまま渡せます。

動作環境:手順1と同じ。MCPエンドポイントは環境変数MCP_SERVER_URL、モデルIDはLANGCHAIN_MODEL_IDから取得

# 注意: 本番環境で使用する前に、必ずテスト環境で動作確認してください。
import asyncio
import os

from langchain.chat_models import init_chat_model
from langchain.mcp import MCPAdapter
from langgraph.graph import MessagesState, START, StateGraph
from langgraph.prebuilt import ToolNode, tools_condition


async def build_graph():
    endpoint = os.environ["MCP_SERVER_URL"]
    model_id = os.environ["LANGCHAIN_MODEL_ID"]

    async with MCPAdapter(endpoint) as adapter:
        tools = await adapter.list_tools()
        model = init_chat_model(model_id).bind_tools(tools)

        async def call_model(state: MessagesState):
            response = await model.ainvoke(state["messages"])
            return {"messages": [response]}

        builder = StateGraph(MessagesState)
        builder.add_node("agent", call_model)
        builder.add_node("tools", ToolNode(tools))
        builder.add_edge(START, "agent")
        builder.add_conditional_edges("agent", tools_condition)
        builder.add_edge("tools", "agent")
        return builder.compile()


async def main() -> None:
    graph = await build_graph()
    result = await graph.ainvoke(
        {"messages": [{"role": "user", "content": "利用可能なツールを使って依頼を処理して"}]}
    )
    print(result["messages"][-1].content)


if __name__ == "__main__":
    asyncio.run(main())

tools_conditionは、モデルの最後のメッセージにツール呼び出しがあればtoolsノードへ、なければ終了へ進めます。ToolNodeがMCPツールを実行し、その結果がmessagesへ追加され、再びagentへ戻ります。StateGraphの状態、ノード、エッジを先に整理したい場合は、LangGraph完全ガイド|StateGraph実装とv1.2新機能を参照してください。

旧langchain-mcp-adaptersコードはこう読み替える

旧langchain-mcp-adaptersコードはこう読み替える
旧langchain-mcp-adaptersコードはこう読み替える

2026年9月以前の解説で多いのが、MultiServerMCPClientを使う実装です。既存プロジェクトの調査用に旧コードを示しますが、新しいプロジェクトへコピーする例ではありません。

対象環境:読解用の別仮想環境にPython 3.11、langchain-mcp-adapters==0.3.2、langchain==1.4.3、langgraph==1.2.12、langchain-openaiを固定します。必要な環境変数はOPENAI_API_KEY、LANGCHAIN_MODEL_ID、MCP_BEARER_TOKENです。MCP Python SDK 2系とは混在させません。

# 既存コードの読解用です。新規実装ではMCPAdapterを使用してください。
# 注意: 本番環境で使用する前に、必ずテスト環境で動作確認してください。
import asyncio
import os

from langchain.agents import create_agent
from langchain_mcp_adapters.client import MultiServerMCPClient


async def main() -> None:
    token = os.environ["MCP_BEARER_TOKEN"]
    model_id = os.environ["LANGCHAIN_MODEL_ID"]
    client = MultiServerMCPClient(
        {
            "internal": {
                "transport": "http",
                "url": "https://example.com/mcp",
                "headers": {"Authorization": f"Bearer {token}"},
            }
        },
        tool_name_prefix=True,
        handle_tool_errors=True,
    )
    tools = await client.get_tools()
    agent = create_agent(model_id, tools=tools)
    result = await agent.ainvoke(
        {"messages": [{"role": "user", "content": "利用可能なツールで状態を確認して"}]}
    )
    print(result["messages"][-1].content)


if __name__ == "__main__":
    asyncio.run(main())
旧langchain-mcp-adapters 現行langchain.mcp 移行時の確認点
pip install langchain-mcp-adapters pip install "langchain[mcp]" 同じ環境へ両方を残さない
MultiServerMCPClient MCPAdapter 非同期コンテキスト管理へ変更
get_tools() list_tools() メソッド名を置換
サーバー辞書を直接渡す {"mcpServers": {...}} 標準MCPConfig形状に変更
transportを明示 URL/Path/設定から推定 ローカルスクリプトはPath
tool_name_prefix=True 複数サーバーでは自動接頭辞 プロンプトや監視のツール名も更新
Callbacks FastMCP Clientのhandler ログ・進捗処理を書き替える
tool_interceptors LangChain middleware 認可・監査処理を移す

複数サーバーはmcpServersの下に名前付きで並べます。ツール名はサーバー名で区別されます。ローカル側の作り方は、FastMCPでMCPサーバーを自作するPythonガイドで確認できます。

旧APIから現行APIへの移行

  • langchain-mcp-adapters → langchain[mcp]
  • MultiServerMCPClient → MCPAdapter
  • get_tools → list_tools
  • transportを指定 → URL・Pathから推定

本番へ進む前に認証・権限・エラー境界を固める

本番へ進む前に認証・権限・エラー境界を固める
本番へ進む前に認証・権限・エラー境界を固める

トークンはFastMCP Clientへ渡す

現行APIの認証は、接続設定へトークン文字列を埋め込むのではなく、FastMCPのClientへ渡します。環境変数やシークレットマネージャーから読み込み、ログへ値を出さないでください。

動作環境:langchain[mcp]>=1.4.0、FastMCPクライアント、Bearer認証対応MCPサーバー

# 注意: 本番環境で使用する前に、必ずテスト環境で動作確認してください。
import os

from fastmcp.client import Client
from langchain.mcp import MCPAdapter


async def load_authenticated_tools():
    endpoint = os.environ["MCP_SERVER_URL"]
    token = os.environ["MCP_BEARER_TOKEN"]
    client = Client(endpoint, auth=token)

    async with MCPAdapter(client) as adapter:
        return await adapter.list_tools()

auth="oauth"も利用できますが、資格情報の保存、利用者とのひも付け、コールバック処理はアプリケーション側の責任です。

ツール実行エラーと接続障害を分ける

isError=TrueはToolMessage(status="error")としてモデルへ戻るため、引数を直して再試行できます。接続、セッション、変換の障害は例外です。監視でも両者を分けます。

destructiveHintだけで自動許可しない

readOnlyHintやdestructiveHintは承認分岐に使えます。ただし、MCP公式のツール注釈解説が示すとおり、注釈は強制制御ではなく、信頼できないサーバーの値を鵜呑みにはできません。

  • 接続可能なMCPサーバーを許可リストで制限する
  • 削除、送信、決済、公開などの操作は実行前に人の承認を挟む
  • ツールへ渡す引数をスキーマだけでなく業務ルールでも検証する
  • 秘密情報へアクセスするツールと外部送信ツールを同じ無制限エージェントへ集めない
  • ツール名、サーバー名、実行結果、エラー種別を監査ログへ残す

失敗と承認を切り分ける

  • isError → ToolMessage → 引数を見直す
  • 接続・セッション → 例外 → 再接続を判断
  • 破壊的・外部副作用 → 人の承認 → 許可後に実行

実装で詰まりやすい5つの原因

旧パッケージを新規環境へ入れてしまう

❌ 検索上位の古い例を見て、langchain-mcp-adaptersから新規開発を始める。

⭕ langchain[mcp]を入れ、MCPAdapterとlist_tools()を使う。旧パッケージは既存環境の調査時だけ参照する。

ローカルスクリプトを文字列で渡す

❌ MCPAdapter("weather_server.py")のように、ローカルパスを単なる文字列で渡す。

⭕ MCPAdapter(Path("weather_server.py"))とする。現行APIでは文字列ターゲットはHTTPまたはHTTPSのURLである必要があります。

新APIでget_toolsを呼ぶ

❌ await adapter.get_tools()と書き、属性エラーになる。

⭕ 現行MCPAdapterではawait adapter.list_tools()を使う。旧コードの機械置換ではimportと設定形状も同時に直します。

asyncの境界を曖昧にする

❌ 通常関数からawaitを呼ぶ、またはNotebook上の既存イベントループ内でasyncio.run()を重ねる。

⭕ スクリプトはasync def main()とasyncio.run(main())を使い、Notebookではセルからawait main()を呼びます。

ツール注釈を権限制御だと思い込む

❌ readOnlyHint=Trueなら無条件で安全だと判断する。

⭕ 信頼できるサーバーかを別途検証し、許可リスト、引数検証、ネットワーク制御、人の承認で強制します。注釈はUIや承認判断の補助情報に限定します。

疎通確認はモデルを呼ぶ前に行う

問題が起きたら、まずツール一覧の名前と説明を確認し、読み取り専用ツールを一つだけ呼び、最後にLangGraphへ組み込みます。

確認順序:

  1. MCPサーバーのエンドポイントへ到達できる
  2. list_tools()が空でなく、想定したツール名を返す
  3. ツールの入力スキーマが意図どおりである
  4. 読み取り専用の呼び出しが成功する
  5. LangGraphがtool callからToolMessageへ戻る
  6. 接続障害とサーバー実行エラーを別々に記録できる

複数サーバーを同時に使う場合は、各サーバーを単独で確認した後に統合します。リモート接続のサーバー側実装まで追うなら、MCP Streamable HTTP完全実装ガイドも参照してください。

よくある質問

Q1. LangGraphとMCPは何が違いますか?

LangGraphは状態、ノード、分岐、永続化を管理するエージェント実行基盤です。MCPはツールやコンテキストをクライアントへ提供するためのプロトコルです。LangGraphが処理の流れを決め、MCPが外部ツールとの共通接続面を提供します。

Q2. langchain-mcp-adaptersはもう使えませんか?

既存の固定環境で直ちに動かなくなるという意味ではありません。ただし公式リポジトリは2026年9月17日にアーカイブされ、継続的な修正とサポートはlangchain.mcpへ移りました。新規実装では選ばず、既存コードも移行計画を作ってください。

Q3. MultiServerMCPClientは何に置き換わりましたか?

MCPAdapterに置き換わりました。複数サーバーは{"mcpServers": {...}}形式の設定を渡し、list_tools()でツールを取得します。

Q4. stdioとStreamable HTTPはどちらを選びますか?

同一マシンのローカルスクリプトならstdio、ネットワーク越しのサーバーならStreamable HTTPが基本です。旧HTTP/SSEは後方互換用で、新規リモート実装の第一候補ではありません。

Q5. MCPサーバーが複数あるとツール名は衝突しませんか?

現行の複数サーバー設定では、ツール名がサーバー名で名前空間化されます。移行時は、旧ツール名を前提にしたシステムプロンプト、テスト、監視ルールも更新してください。

Q6. MCPツールのセッションは維持されますか?

現行の既定パターンでは、ツール呼び出しごとに接続して処理後に解放します。一つの実行中に接続を再利用したい場合は、エージェント実行をMCPAdapterのコンテキスト内に置きます。サーバー側の状態を暗黙のセッションだけに依存させない設計も重要です。

Q7. ツールがisErrorを返すとグラフ全体が停止しますか?

現行APIでは、サーバーが返す実行エラーは通常ToolMessage(status="error")としてモデルへ届きます。モデルが入力を修正できる余地があります。一方、接続や変換の障害は例外になるため、アプリケーション側で捕捉し、再試行条件と上限を決めます。

Q8. 認証ヘッダーをMCPAdapterへ直接書けばよいですか?

現行の推奨はFastMCP Clientへ認証を設定し、そのクライアントをMCPAdapterへ渡す方法です。秘密値は環境変数やシークレットマネージャーから取得し、コード、設定ファイル、ログへ残さないでください。

Q9. create_agentとStateGraphのどちらを使うべきですか?

標準的な「モデルがツールを選び、結果を受けて回答する」ループならcreate_agentが簡潔です。承認、独自状態、複数の業務ノード、特殊な終了条件を組み込みたいならStateGraphとToolNodeを選びます。

運営元 Uravation よりAIエージェントを構想から本番運用まで進める順番と、体制・KPIの決め方をまとめた資料を無料で公開しています。 AIエージェント導入ロードマップを受け取る(無料)

参考・出典

結論と次の一歩

LangGraphからMCPツールを呼ぶ実装は、MCPAdapterで接続し、list_tools()でツールを読み込み、create_agentまたはToolNodeへ渡す3手順です。2026年10月4日時点では、langchain-mcp-adaptersを新規採用するのではなく、LangChain本体のlangchain.mcpを使うのが公式の移行先です。

  1. 公開ドキュメントMCPサーバーで、現行MCPAdapterのツール一覧取得を確認する
  2. 対象のMCPサーバーを一つだけ接続し、読み取り専用ツールで疎通を確認する
  3. 削除・送信・公開などの副作用があるツールへ承認ゲートを追加してから業務フローへ組み込む

この記事を読んで導入イメージが固まってきた方へ

UravationではAIエージェント導入の研修・コンサルを行っています。

Need help moving from reading to rollout?

この記事を読んで導入イメージが固まってきた方へ

Uravationでは、AIエージェントの要件整理、PoC設計、社内導入、研修まで一気通貫で支援しています。

この記事をシェア

X Facebook LINE

※ 本記事の情報は2026年10月時点のものです。サービスの料金・仕様は変更される可能性があります。最新情報は各サービスの公式サイトをご確認ください。

関連記事