LiteLLMとLangGraphでMCPサーバーのツールをエージェントから利用してみる

LiteLLMとLangGraphでMCPサーバーのツールをエージェントから利用してみる

2026.05.15

はじめに

データ事業本部のkobayashiです。

今回は MCP (Model Context Protocol) をLangGraphエージェントから利用する方法を紹介します。MCPはAnthropicが提唱したLLM向けのツール・リソース提供プロトコルで、2025年に急速に普及しました。サーバー側を実装すればClaude DesktopでもCursorでも自作エージェントでも同じツールが使えるのが利点です。今回はMCPをLangGraphエージェントが消費する側として使います。

MCP の仕組み

  • MCPサーバーがツール・リソース・プロンプトを公開
  • クライアント(LangGraphエージェントなど)が接続して利用
  • トランスポートは stdio / Streamable HTTP / SSE のいずれか

LangGraphから接続するには langchain-mcp-adapters パッケージを使います。

環境

Python 3.13
litellm 1.83.14
langgraph 1.1.10
langchain-mcp-adapters 0.1.0
mcp 1.5.0
langchain-litellm 0.6.4
$ uv pip install litellm langgraph langchain-litellm langchain-mcp-adapters mcp

サンプルMCPサーバー(FastMCP)

まず最小のMCPサーバーを書きます。fastapi_mcpの記事と同じFastMCPベースで、ローカル環境を確認するための2つのツール(Pythonバージョン取得 / インストール済みパッケージ一覧)を提供します。

sample_mcp_server.py
"""MCP サーバー側の最小サンプル: 開発者環境の情報を返すツール群。

stdio トランスポートで動く。クライアントから
python sample_mcp_server.py で起動される。
"""

import sys
from importlib.metadata import distributions

from mcp.server.fastmcp import FastMCP

mcp = FastMCP("dev-env-tools")

@mcp.tool()
def get_python_version() -> str:
    """現在実行中の Python のバージョン情報を返します。"""
    return sys.version

@mcp.tool()
def list_installed_packages(prefix: str = "") -> list[str]:
    """インストール済み Python パッケージを返します。

    prefix を指定すると、その文字列で始まるパッケージのみを返します
    (例: prefix="fastapi" で fastapi 系だけに絞り込み)。
    """
    packages = sorted(
        f"{dist.metadata['Name']}=={dist.version}"
        for dist in distributions()
        if dist.metadata["Name"]
    )
    if prefix:
        packages = [p for p in packages if p.lower().startswith(prefix.lower())]
    return packages

if __name__ == "__main__":
    mcp.run(transport="stdio")

このサーバーは単独で実行可能です(python sample_mcp_server.py)。@mcp.tool()のシグネチャと docstring がそのままMCPのスキーマになります。後段の Context7 と組み合わせると 「ローカル環境を確認 → 該当バージョンのドキュメントを引く」 という自然なワークフローが組めるようになります。

LangGraph から MCP ツールを利用

langchain-mcp-adaptersMultiServerMCPClient で MCP ツールをLangChain Toolに自動変換し、create_agentに渡せます。

mcp_client.py
"""LangGraph エージェントから MCP サーバーのツールを使う。

langchain-mcp-adapters の MultiServerMCPClient で
- ローカル sample_mcp_server.py(stdio)
- リモート Context7 MCP サーバー(streamable_http)
の2系統を束ね、1つのエージェントから利用する。
"""

import asyncio
import sys

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

async def main() -> None:
    # 複数のMCPサーバーを束ねる
    client = MultiServerMCPClient(
        {
            # ローカルのstdioサーバー
            "sample": {
                "command": sys.executable,
                "args": ["sample_mcp_server.py"],
                "transport": "stdio",
            },
            # リモートの Streamable HTTP サーバー(Context7: ライブラリのドキュメント検索)
            "context7": {
                "url": "https://mcp.context7.com/mcp",
                "transport": "streamable_http",
            },
        }
    )

    # MCP サーバーが提供するツール群を取得(自動的に LangChain Tool に変換)
    tools = await client.get_tools()
    print(f"取得したツール: {[t.name for t in tools]}")

    llm = ChatLiteLLM(model="openai/gpt-5-mini")
    agent = create_agent(model=llm, tools=tools)

    # 「ローカル環境を確認 → そのバージョンに合ったドキュメントを Context7 で引く」
    # という自然なワークフローを1つのエージェントで完結させる。
    result = await agent.ainvoke(
        {
            "messages": [
                {
                    "role": "user",
                    "content": (
                        "このプロジェクトにインストールされている fastapi のバージョンを確認し、"
                        "そのバージョンに合わせて StreamingResponse の使い方を Context7 で調べ、"
                        "ポイントを3行で要約してください。"
                    ),
                }
            ]
        }
    )
    print("\n=== 最終回答 ===")
    print(result["messages"][-1].content)

asyncio.run(main())

ポイント:

複数サーバーの統合

MultiServerMCPClientの辞書には、stdio・HTTP・SSE が混在していてOKです。上記の例ではローカルの stdio サーバー(sample)リモートの Streamable HTTP サーバー(Context7) を同時に登録し、エージェントから一括で利用しています。Context7 はライブラリ・フレームワークのドキュメントを検索する公開MCPサーバーで、認証なしで試せるため動作確認に便利です。

トランスポートの違い

transport 用途
stdio ローカルの子プロセスとして起動。Claude Desktopもこれ
streamable_http HTTP経由(モダンな本番運用向け)
sse レガシーなHTTP+SSE形式(旧仕様、新規採用は非推奨)

実行結果は以下のようになります(ローカルMCPサーバー側のログが混在する)。

$ python mcp_client.py
INFO     Processing request of type ListToolsRequest      server.py:727
INFO     Processing request of type CallToolRequest       server.py:727
INFO     Processing request of type ListToolsRequest      server.py:727
取得したツール: ['get_python_version', 'list_installed_packages', 'resolve-library-id', 'query-docs']

=== 最終回答 ===
fastapi==0.136.1 がインストールされています。
StreamingResponse async generator または通常の generator/iterator content に取り、bytes(または文字列)チャンクを逐次送信でき、media_type / status_code / headers を指定して大きなレスポンスをメモリ効率よく配信します。
ストリーム後のクリーンアップは BackgroundTasks(または StreamingResponse background 引数)で行い、プロキシ時は hop-by-hop ヘッダを除外、キャンセル対応のために await anyio.sleep(0) 等のチェックポイントを入れるのが推奨されます。

get_tools() でローカル sample 由来の get_python_version / list_installed_packages と、Context7 由来の resolve-library-id / query-docs計4ツールが1つのリスト として返り、エージェントはそれらを自律的に組み合わせて使っています。具体的には、まず list_installed_packages(prefix="fastapi") でローカル環境の fastapi バージョン(0.136.1)を特定し、続いて Context7 の resolve-library-idquery-docs で該当ライブラリの StreamingResponse 周辺ドキュメントを取得し、最後に3行に要約しています。create_agent に渡すツールの中身が「ローカル関数」か「リモートMCPサーバー越しの関数」かはエージェント側からは透過的で、ローカルの環境情報とリモートのドキュメントが1つのワークフローに自然に繋がっているのがポイントです。

LiteLLMでのモデル使い分け

ロール モデル 理由
ReActエージェント openai/gpt-5-mini tool_use 安定性。MCPツールも結局は LangChain Tool として扱われるため、tool_callsの相性が良いGPTを採用

MCP は「ツール提供プロトコル」なので、LiteLLM 側で重要なのは取得したMCPツールに対して安定した tool_calls を発行できるモデルを選ぶことです。ChatLiteLLM(model="openai/gpt-5-mini")anthropic/claude-sonnet-4-6 に置き換えれば即座に Claude 経由で同じMCPツールを使えるので、本番運用でモデルを切り替える検証も簡単です。

まとめ

LangGraphエージェントから MCP (Model Context Protocol) サーバーのツールを利用する方法を、langchain-mcp-adaptersMultiServerMCPClient で stdio / HTTP のMCPサーバーを束ね、create_agent にそのまま渡す形で紹介しました。

@mcp.tool() のシグネチャと docstring がそのまま MCP のスキーマとして公開され、クライアント側では client.get_tools() で受け取った瞬間に LangChain Tool に変換されるため、エージェント側のコードは「ローカル関数」も「MCPサーバー越しの関数」も区別なく扱えます。組織独自のツールを一度MCPサーバーとして実装しておけば、Claude Code・Cursor・社内エージェントすべてから再利用でき、LiteLLMでモデルだけプロバイダー非依存に切り替える運用と組み合わせると、モデルとツールの両方をプロバイダーに縛られずに構成できます。

最後まで読んでいただきありがとうございました。


生成AI活用はクラスメソッドにお任せ

過去に支援してきた生成AIの支援実績100+を元にホワイトペーパーを作成しました。御社が抱えている課題のうち、どれが解決できて、どのようなサービスが受けられるのか?4つのフェーズに分けてまとめています。どうぞお気軽にご覧ください。

生成AI資料イメージ

無料でダウンロードする

この記事をシェアする

関連記事