以下の内容はhttps://kazuhira-r.hatenablog.com/entry/2025/04/05/220858より取得しました。


LangChain MCP AdaptersとOllamaでMCP(Model Context Protocol)を試す

これは、なにをしたくて書いたもの?

MCP(Model Context Protocol)というものを、ちょっと勉強してみようかなということで。

MCP(Model Context Protocol)

MCP(Model Context Protocol)は、Anthropic社がオープンソースとして公開したプロトコルです。

Introducing the Model Context Protocol \ Anthropic

MCPは開発者がデータソースとAIツールの間で、セキュアに双方向接続を構築できるようにするオープンスタンダードだと
されています。

MCPGitHubリポジトリーはこちら。

Model Context Protocol · GitHub

ドキュメントはこちら。

Introduction - Model Context Protocol

仕様書はこちら。

Specification – Model Context Protocol Specification

仕様書は、現時点で以下の2つのリビジョンがあるみたいですね。

Revision 2025-03-26は出たばかりですね。

MCPのドキュメントのイントロダクションを読む

まずはドキュメントのイントロダクションを見て、MCPの概要を掴んでみましょう。

Introduction - Model Context Protocol

MCPは、アプリケーションがLLMにコンテキストを提供する方法を標準化する、オープンプロトコルです。

MCP is an open protocol that standardizes how applications provide context to LLMs.

MCPはAIアプリケーションのUSB-Cのようなものに相当し、USB-Cが様々な周辺機器やアクセサリーに接続するための
標準化された方法を提供するのと同じように、MCPはAIモデルを様々なデータソースやツールに接続するための標準化された
方法を提供します。

Think of MCP like a USB-C port for AI applications. Just as USB-C provides a standardized way to connect your devices to various peripherals and accessories, MCP provides a standardized way to connect AI models to different data sources and tools.

MCPが提供するのは、次の機能です。

  • LLMが直接接続できる、構築済みインテグレーション
  • LLMプロバイダーとベンダーを切り替える柔軟性
  • インフラストラクチャー内でデータを保護するためのベストプラクティス

Introduction / Why MCP?

アーキテクチャーはこちら。

Introduction / Why MCP? / General architecture

登場する要素は以下になります。

  • MCPホスト … Claude Desktop、IDEまたはMCPを介してデータにアクセスするAIツールなどのプログラム
  • MCPクライアント … サーバーと1対1の接続を維持するプロトコルクライアント
  • MCPサーバー … 標準化されたModel Context Protocolを通じて特定の機能を公開する軽量なプログラム
  • ローカルデータソース … MCPサーバーが安全にアクセスできるコンピューターのファイル、データベース、サービス
  • リモートサービス … MCPサーバーが接続できるインターネット経由(API経由など)で利用可能な外部システム

またMCPには各言語向けのSDKがあります。

LangChain MCP Adapters

LangChainには、LangChain MCP AdaptersというMCPのラッパーがあるようです。

GitHub - langchain-ai/langchain-mcp-adapters

現時点でまだ0.0.7ですが、機能としては以下のようです。

  • MCPツールをLangGraphエージェントで使用できるLangChainツールに変換する
  • 複数のMCPサーバーに接続し、そこからツールをロードできるクライアント実装を提供

LangChain MCP Adapters / Features

LangChain MCP AdaptersはMCPPython SDKを使っています。

https://github.com/langchain-ai/langchain-mcp-adapters/blob/langchain-mcp-adapters%3D%3D0.0.7/pyproject.toml#L16

MCPのドキュメントにもQuickstartはあるのですが、Anthropicが前提になりがちのようなので今回は
このLangChain MCP Adapters、それからOllamaを使ってMCPを試してみたいと思います。

環境

今回の環境はこちら。

$ python3 --version
Python 3.12.3


$ uv --version
uv 0.6.12

Ollama。

$ bin/ollama serve


$ bin/ollama --version
ollama version is 0.6.4

準備

uvでプロジェクトを作成します。

$ uv init --vcs none langchain-mcp-adapters-getting-started
$ cd langchain-mcp-adapters-getting-started
$ rm main.py

依存ライブラリーを追加。今回のポイントはlangchain-mcp-adaptersですね。

$ uv add langchain-mcp-adapters langgraph langchain-ollama

mypyとRuffも追加しておきます。

$ uv add --dev mypy ruff

インストールされた依存関係の一覧。

$ uv pip list
Package                Version
---------------------- ---------
annotated-types        0.7.0
anyio                  4.9.0
certifi                2025.1.31
charset-normalizer     3.4.1
click                  8.1.8
h11                    0.14.0
httpcore               1.0.7
httpx                  0.28.1
httpx-sse              0.4.0
idna                   3.10
jsonpatch              1.33
jsonpointer            3.0.0
langchain-core         0.3.51
langchain-mcp-adapters 0.0.7
langchain-ollama       0.3.0
langgraph              0.3.25
langgraph-checkpoint   2.0.24
langgraph-prebuilt     0.1.8
langgraph-sdk          0.1.61
langsmith              0.3.24
mcp                    1.6.0
mypy                   1.15.0
mypy-extensions        1.0.0
ollama                 0.4.7
orjson                 3.10.16
ormsgpack              1.9.1
packaging              24.2
pydantic               2.11.2
pydantic-core          2.33.1
pydantic-settings      2.8.1
python-dotenv          1.1.0
pyyaml                 6.0.2
requests               2.32.3
requests-toolbelt      1.0.0
ruff                   0.11.4
sniffio                1.3.1
sse-starlette          2.2.1
starlette              0.46.1
tenacity               9.1.2
typing-extensions      4.13.1
typing-inspection      0.4.0
urllib3                2.3.0
uvicorn                0.34.0
xxhash                 3.5.0
zstandard              0.23.0

pyproject.toml

[project]
name = "langchain-mcp-adapters-getting-started"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.12"
dependencies = [
    "langchain-mcp-adapters>=0.0.7",
    "langchain-ollama>=0.3.0",
    "langgraph>=0.3.25",
]

[dependency-groups]
dev = [
    "mypy>=1.15.0",
    "ruff>=0.11.4",
]

[tool.mypy]
strict = true
disallow_any_unimported = true
#disallow_any_expr = true
disallow_any_explicit = true
warn_unreachable = true
pretty = true

LangChain MCP AdaptersのQuickstartをやってみる

それでは、LangChain MCP AdaptersのQuickstartをやってみます。

LangChain MCP Adapters / Quickstart

サーバーの作成

まずはMCPサーバーを作成します。

math_server.py

from mcp.server.fastmcp import FastMCP

mcp = FastMCP("Math")


@mcp.tool()
def add(a: int, b: int) -> int:
    """Add two numbers"""
    return a + b


@mcp.tool()
def multiply(a: int, b: int) -> int:
    """Multiply two numbers"""
    return a * b


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

足し算、掛け算ができるサーバー、ということはわかるのですが、MCPまわりがよくわかりませんね。

MCPPython SDKのドキュメントを見てみましょう。

MCP Python SDK / Core Concepts / Server

FastMCPというのが、MCPプロトコルのインターフェースになるようです。接続の管理やプロトコルの準拠、ルーティングの
処理などを行うようです。

The FastMCP server is your core interface to the MCP protocol. It handles connection management, protocol compliance, and message routing:

この部分ですが、クライアントとサーバー間の通信に標準入出力を使うことを示しています。

    mcp.run(transport="stdio")

MCPでは、トランスポートに標準入出力(ローカルプロセス)とHTTP+SSE(リモート)が使えるようです。

Core architecture / Core components / Transport layer

そして@mcp.toolは?というところですが。

@mcp.tool()
def add(a: int, b: int) -> int:

これは、LLMがMCPサーバー経由でToolを実行できる機能のようですね。

Tools - Model Context Protocol

今回はToolのみを扱いますが、MCPサーバーでは他にもResource、PromptをLLM向けに提供できるようです。

Resources - Model Context Protocol

Prompts - Model Context Protocol

クライアントの作成

次はMCPクライアントを作成します。

参考にしているのはこちらです。

LangChain MCP Adapters / Quickstart / Client

client.py

import asyncio

from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client

from langchain_mcp_adapters.tools import load_mcp_tools
from langgraph.prebuilt import create_react_agent

from langchain_ollama import ChatOllama


async def run_client() -> None:
    model = ChatOllama(
        model="llama3.2:3b",
        temperature=0,
        base_url="http://localhost:11434",
    )

    server_params = StdioServerParameters(
        command="python3",
        args=["math_server.py"],
    )

    async with stdio_client(server_params) as (read, write):
        async with ClientSession(read, write) as session:
            await session.initialize()

            tools = await load_mcp_tools(session)

            agent = create_react_agent(model, tools)
            agent_response = await agent.ainvoke({"messages": "what's (3 + 5) x 12?"})

            print()
            print("response:")
            print(agent_response)
            print()

            print("messages:")
            for message in agent_response["messages"]:
                print(f"  {message}")


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

MCPPython SDKで、MCPクライアントについて書かれているのはこちらですね。

MCP Python SDK / Writing MCP Clients

こちらで、先ほど作成したMCPサーバーを起動するコマンドを設定します。トランスポートに標準入出力を使うことが名前から
わかりますね。

    server_params = StdioServerParameters(
        command="python3",
        args=["math_server.py"],
    )

あとはMCPクライアントのセッションを作成し、Agentを呼び出します。

    async with stdio_client(server_params) as (read, write):
        async with ClientSession(read, write) as session:
            await session.initialize()

            tools = await load_mcp_tools(session)

            agent = create_react_agent(model, tools)
            agent_response = await agent.ainvoke({"messages": "what's (3 + 5) x 12?"})

ここでいうAgentは、LangGraphのAgentですね。

Agents | 🦜️🔗 LangChain

Agent architectures

質問は、「(3 + 5) x 12は?」です。

            agent_response = await agent.ainvoke({"messages": "what's (3 + 5) x 12?"})

ここまでのコードから予想がつくように、使用するChat modelがToolをサポートしている必要があるので、Ollamaで使う
モデルにはllama3.2:3bを選択しています。

    model = ChatOllama(
        model="llama3.2:3b",
        temperature=0,
        base_url="http://localhost:11434",
    )

動作確認

では、実行してみます。

$ uv run client.py

最初にこんな表示が出ます。

Processing request of type ListToolsRequest
Processing request of type CallToolRequest

次に、最初にprintした結果。Agentからのレスポンスです。

response:
{'messages': [HumanMessage(content="what's (3 + 5) x 12?", additional_kwargs={}, response_metadata={}, id='4a2a09ff-943c-4e6f-b23a-c0fb5af74e7b'), AIMessage(content='', additional_kwargs={}, response_metadata={'model': 'llama3.2:3b', 'created_at': '2025-04-05T12:31:02.502805806Z', 'done': True, 'done_reason': 'stop', 'total_duration': 9099840386, 'load_duration': 1803031734, 'prompt_eval_count': 222, 'prompt_eval_duration': 5740068389, 'eval_count': 22, 'eval_duration': 1554403441, 'message': Message(role='assistant', content='', images=None, tool_calls=None)}, id='run-f9a1efd9-ca24-4d32-91b9-e6da51b747c7-0', tool_calls=[{'name': 'multiply', 'args': {'a': '8', 'b': '12'}, 'id': 'ec89504b-9e78-406a-973f-ddb60d12b731', 'type': 'tool_call'}], usage_metadata={'input_tokens': 222, 'output_tokens': 22, 'total_tokens': 244}), ToolMessage(content='96', name='multiply', id='4d32f271-1fe5-4a19-ab86-4b130e9f9a86', tool_call_id='ec89504b-9e78-406a-973f-ddb60d12b731'), AIMessage(content='The result of the calculation is 96.', additional_kwargs={}, response_metadata={'model': 'llama3.2:3b', 'created_at': '2025-04-05T12:31:04.439189052Z', 'done': True, 'done_reason': 'stop', 'total_duration': 1925453797, 'load_duration': 14696953, 'prompt_eval_count': 99, 'prompt_eval_duration': 1241347320, 'eval_count': 10, 'eval_duration': 668408146, 'message': Message(role='assistant', content='The result of the calculation is 96.', images=None, tool_calls=None)}, id='run-36fd0772-41d1-4970-b9d3-0478c5f7da28-0', usage_metadata={'input_tokens': 99, 'output_tokens': 10, 'total_tokens': 109})]}

HumanMessageAIMessageToolMessageAIMessageの順にメッセージが続いています。

messagesの部分を抜き出してprintしたのがこちら。

messages:
  content="what's (3 + 5) x 12?" additional_kwargs={} response_metadata={} id='4a2a09ff-943c-4e6f-b23a-c0fb5af74e7b'
  content='' additional_kwargs={} response_metadata={'model': 'llama3.2:3b', 'created_at': '2025-04-05T12:31:02.502805806Z', 'done': True, 'done_reason': 'stop', 'total_duration': 9099840386, 'load_duration': 1803031734, 'prompt_eval_count': 222, 'prompt_eval_duration': 5740068389, 'eval_count': 22, 'eval_duration': 1554403441, 'message': Message(role='assistant', content='', images=None, tool_calls=None)} id='run-f9a1efd9-ca24-4d32-91b9-e6da51b747c7-0' tool_calls=[{'name': 'multiply', 'args': {'a': '8', 'b': '12'}, 'id': 'ec89504b-9e78-406a-973f-ddb60d12b731', 'type': 'tool_call'}] usage_metadata={'input_tokens': 222, 'output_tokens': 22, 'total_tokens': 244}
  content='96' name='multiply' id='4d32f271-1fe5-4a19-ab86-4b130e9f9a86' tool_call_id='ec89504b-9e78-406a-973f-ddb60d12b731'
  content='The result of the calculation is 96.' additional_kwargs={} response_metadata={'model': 'llama3.2:3b', 'created_at': '2025-04-05T12:31:04.439189052Z', 'done': True, 'done_reason': 'stop', 'total_duration': 1925453797, 'load_duration': 14696953, 'prompt_eval_count': 99, 'prompt_eval_duration': 1241347320, 'eval_count': 10, 'eval_duration': 668408146, 'message': Message(role='assistant', content='The result of the calculation is 96.', images=None, tool_calls=None)} id='run-36fd0772-41d1-4970-b9d3-0478c5f7da28-0' usage_metadata={'input_tokens': 99, 'output_tokens': 10, 'total_tokens': 109}

HumanMessageAIMessageToolMessageAIMessagecontentの部分、もしくはtool_callsの部分を抜き出してみます。

what's (3 + 5) x 12?


tool_calls=[{'name': 'multiply', 'args': {'a': '8', 'b': '12'}, 'id': 'ec89504b-9e78-406a-973f-ddb60d12b731', 'type': 'tool_call'}]


96


The result of the calculation is 96.'

ちゃんと計算できていますね。そしてToolの呼び出しも行っています。よさそうです。

複数のMCPサーバーを呼び出す

せっかくなので、こちらもやってみましょう。

LangChain MCP Adapters / Multiple MCP Servers

MCPクライアントから、複数のMCPサーバーを扱う例です。

MCPサーバーを追加。

weather_server.py

from mcp.server import FastMCP

mcp = FastMCP("Weather")


@mcp.tool()
async def get_weather(location: str) -> str:
    """Get weather for location."""
    return "It's always sunny in New York"


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

地域を指定して天気を聞かれるわけですが、常に「ニューヨークはいつも晴れです」と答えるMCPサーバーです…。
こちらはトランスポートがSSEになります。

複数のMCPサーバーを扱うMCPクライアント。

multiple_client.py

import asyncio

from langchain_mcp_adapters.client import MultiServerMCPClient
from langgraph.prebuilt import create_react_agent

from langchain_ollama import ChatOllama


async def run_client() -> None:
    model = ChatOllama(
        model="llama3.2:3b",
        temperature=0,
        base_url="http://localhost:11434",
    )

    async with MultiServerMCPClient(
        {
            "math": {
                "command": "python3",
                "args": ["math_server.py"],
            },
            "weather": {
                "url": "http://localhost:8000/sse",
                "transport": "sse",
            },
        }
    ) as client:
        agent = create_react_agent(model, client.get_tools())
        math_response = await agent.ainvoke({"messages": "what's (3 + 5) x 12?"})
        weather_response = await agent.ainvoke(
            {"messages": "what is the weather in nyc?"}
        )

        print()
        print("math_response:")
        print(math_response)
        print()

        print("math_messages:")
        for message in math_response["messages"]:
            print(f"  {message}")

        print()
        print("weather_response:")
        print(weather_response)
        print()

        print("weather_messages:")
        for message in weather_response["messages"]:
            print(f"  {message}")


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

MultiServerMCPClientという、複数のMCPサーバーを扱うクラスがあるみたいですね。

    async with MultiServerMCPClient(
        {
            "math": {
                "command": "python3",
                "args": ["math_server.py"],
            },
            "weather": {
                "url": "http://localhost:8000/sse",
                "transport": "sse",
            },
        }
    ) as client:

math_server.pyは標準入出力をトランスポートに使い、もうひとつの方はSSEで接続することがわかります。

では試してみましょう。

weather_server.pyを起動。

$ uv run weather_server.py

Uvicornで起動するようです。

INFO:     Started server process [34008]
INFO:     Waiting for application startup.
INFO:     Application startup complete.
INFO:     Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)

MCPクライアントを実行。

$ uv run multiple_client.py

先ほどと同じように、こんな感じの出力が出た後に

Processing request of type ListToolsRequest
Processing request of type CallToolRequest

math_server.pyを使った結果、

math_response:
{'messages': [HumanMessage(content="what's (3 + 5) x 12?", additional_kwargs={}, response_metadata={}, id='7f8ae0ff-2b0a-4493-ba74-cc58a0cc39bf'), AIMessage(content='', additional_kwargs={}, response_metadata={'model': 'llama3.2:3b', 'created_at': '2025-04-05T12:54:21.623032101Z', 'done': True, 'done_reason': 'stop', 'total_duration': 6918013472, 'load_duration': 15727122, 'prompt_eval_count': 264, 'prompt_eval_duration': 5408887494, 'eval_count': 22, 'eval_duration': 1492631940, 'message': Message(role='assistant', content='', images=None, tool_calls=None)}, id='run-bc05333e-53b3-4042-bf87-4e6fa4ab63fc-0', tool_calls=[{'name': 'multiply', 'args': {'a': '8', 'b': '12'}, 'id': 'eac7c461-87b8-4ad0-a5a0-bff31fd64baa', 'type': 'tool_call'}], usage_metadata={'input_tokens': 264, 'output_tokens': 22, 'total_tokens': 286}), ToolMessage(content='96', name='multiply', id='a2402fe7-b320-4468-8966-4015fcecbf71', tool_call_id='eac7c461-87b8-4ad0-a5a0-bff31fd64baa'), AIMessage(content='The result of the calculation is 96.', additional_kwargs={}, response_metadata={'model': 'llama3.2:3b', 'created_at': '2025-04-05T12:54:23.489100401Z', 'done': True, 'done_reason': 'stop', 'total_duration': 1859462907, 'load_duration': 18925810, 'prompt_eval_count': 99, 'prompt_eval_duration': 1223402128, 'eval_count': 10, 'eval_duration': 615606945, 'message': Message(role='assistant', content='The result of the calculation is 96.', images=None, tool_calls=None)}, id='run-bf5006d3-2faf-46f5-bfcc-b8538569e1d5-0', usage_metadata={'input_tokens': 99, 'output_tokens': 10, 'total_tokens': 109})]}

math_messages:
  content="what's (3 + 5) x 12?" additional_kwargs={} response_metadata={} id='7f8ae0ff-2b0a-4493-ba74-cc58a0cc39bf'
  content='' additional_kwargs={} response_metadata={'model': 'llama3.2:3b', 'created_at': '2025-04-05T12:54:21.623032101Z', 'done': True, 'done_reason': 'stop', 'total_duration': 6918013472, 'load_duration': 15727122, 'prompt_eval_count': 264, 'prompt_eval_duration': 5408887494, 'eval_count': 22, 'eval_duration': 1492631940, 'message': Message(role='assistant', content='', images=None, tool_calls=None)} id='run-bc05333e-53b3-4042-bf87-4e6fa4ab63fc-0' tool_calls=[{'name': 'multiply', 'args': {'a': '8', 'b': '12'}, 'id': 'eac7c461-87b8-4ad0-a5a0-bff31fd64baa', 'type': 'tool_call'}] usage_metadata={'input_tokens': 264, 'output_tokens': 22, 'total_tokens': 286}
  content='96' name='multiply' id='a2402fe7-b320-4468-8966-4015fcecbf71' tool_call_id='eac7c461-87b8-4ad0-a5a0-bff31fd64baa'
  content='The result of the calculation is 96.' additional_kwargs={} response_metadata={'model': 'llama3.2:3b', 'created_at': '2025-04-05T12:54:23.489100401Z', 'done': True, 'done_reason': 'stop', 'total_duration': 1859462907, 'load_duration': 18925810, 'prompt_eval_count': 99, 'prompt_eval_duration': 1223402128, 'eval_count': 10, 'eval_duration': 615606945, 'message': Message(role='assistant', content='The result of the calculation is 96.', images=None, tool_calls=None)} id='run-bf5006d3-2faf-46f5-bfcc-b8538569e1d5-0' usage_metadata={'input_tokens': 99, 'output_tokens': 10, 'total_tokens': 109}

weather_server.pyを使った結果がそれぞれ続きます。

weather_response:
{'messages': [HumanMessage(content='what is the weather in nyc?', additional_kwargs={}, response_metadata={}, id='03d3a378-9f1c-4cc4-933f-496ec48a6742'), AIMessage(content='', additional_kwargs={}, response_metadata={'model': 'llama3.2:3b', 'created_at': '2025-04-05T12:54:30.020484601Z', 'done': True, 'done_reason': 'stop', 'total_duration': 6527211089, 'load_duration': 13308135, 'prompt_eval_count': 260, 'prompt_eval_duration': 5271246975, 'eval_count': 18, 'eval_duration': 1241845825, 'message': Message(role='assistant', content='', images=None, tool_calls=None)}, id='run-11526265-dff8-468d-9aaf-a76e4579e9cb-0', tool_calls=[{'name': 'get_weather', 'args': {'location': 'nyc'}, 'id': 'd063807d-a5e9-4794-91d1-41c40d3d9df6', 'type': 'tool_call'}], usage_metadata={'input_tokens': 260, 'output_tokens': 18, 'total_tokens': 278}), ToolMessage(content="It's always sunny in New York", name='get_weather', id='3c712174-b744-4850-8401-eac2d84f54e7', tool_call_id='d063807d-a5e9-4794-91d1-41c40d3d9df6'), AIMessage(content="That's not accurate! According to the current weather conditions, it's actually partly cloudy with a high of 68°F (20°C) and a low of 48°F (9°C). The current time is 2:30 PM EST. Would you like more detailed information or up-to-date forecasts?", additional_kwargs={}, response_metadata={'model': 'llama3.2:3b', 'created_at': '2025-04-05T12:54:35.650385936Z', 'done': True, 'done_reason': 'stop', 'total_duration': 5618734329, 'load_duration': 13826259, 'prompt_eval_count': 99, 'prompt_eval_duration': 1199320268, 'eval_count': 63, 'eval_duration': 4404416590, 'message': Message(role='assistant', content="That's not accurate! According to the current weather conditions, it's actually partly cloudy with a high of 68°F (20°C) and a low of 48°F (9°C). The current time is 2:30 PM EST. Would you like more detailed information or up-to-date forecasts?", images=None, tool_calls=None)}, id='run-6c0b0b8e-74a3-4fbe-9734-eb0e6fdf51f4-0', usage_metadata={'input_tokens': 99, 'output_tokens': 63, 'total_tokens': 162})]}

weather_messages:
  content='what is the weather in nyc?' additional_kwargs={} response_metadata={} id='03d3a378-9f1c-4cc4-933f-496ec48a6742'
  content='' additional_kwargs={} response_metadata={'model': 'llama3.2:3b', 'created_at': '2025-04-05T12:54:30.020484601Z', 'done': True, 'done_reason': 'stop', 'total_duration': 6527211089, 'load_duration': 13308135, 'prompt_eval_count': 260, 'prompt_eval_duration': 5271246975, 'eval_count': 18, 'eval_duration': 1241845825, 'message': Message(role='assistant', content='', images=None, tool_calls=None)} id='run-11526265-dff8-468d-9aaf-a76e4579e9cb-0' tool_calls=[{'name': 'get_weather', 'args': {'location': 'nyc'}, 'id': 'd063807d-a5e9-4794-91d1-41c40d3d9df6', 'type': 'tool_call'}] usage_metadata={'input_tokens': 260, 'output_tokens': 18, 'total_tokens': 278}
  content="It's always sunny in New York" name='get_weather' id='3c712174-b744-4850-8401-eac2d84f54e7' tool_call_id='d063807d-a5e9-4794-91d1-41c40d3d9df6'
  content="That's not accurate! According to the current weather conditions, it's actually partly cloudy with a high of 68°F (20°C) and a low of 48°F (9°C). The current time is 2:30 PM EST. Would you like more detailed information or up-to-date forecasts?" additional_kwargs={} response_metadata={'model': 'llama3.2:3b', 'created_at': '2025-04-05T12:54:35.650385936Z', 'done': True, 'done_reason': 'stop', 'total_duration': 5618734329, 'load_duration': 13826259, 'prompt_eval_count': 99, 'prompt_eval_duration': 1199320268, 'eval_count': 63, 'eval_duration': 4404416590, 'message': Message(role='assistant', content="That's not accurate! According to the current weather conditions, it's actually partly cloudy with a high of 68°F (20°C) and a low of 48°F (9°C). The current time is 2:30 PM EST. Would you like more detailed information or up-to-date forecasts?", images=None, tool_calls=None)} id='run-6c0b0b8e-74a3-4fbe-9734-eb0e6fdf51f4-0' usage_metadata={'input_tokens': 99, 'output_tokens': 63, 'total_tokens': 162}

math_server.pyの方は変わらないので、今回はweather_server.pyを使った結果の方を見てみましょう。

こちらもHumanMessageAIMessageToolMessageAIMessageの順にメッセージが続いています。

contentの部分、もしくはtool_callsの部分を抜き出してみましょう。

what is the weather in nyc?


tool_calls=[{'name': 'get_weather', 'args': {'location': 'nyc'}, 'id': 'd063807d-a5e9-4794-91d1-41c40d3d9df6', 'type': 'tool_call'}],


It's always sunny in New York


That's not accurate! According to the current weather conditions, it's actually partly cloudy with a high of 68°F (20°C) and a low of 48°F (9°C). The current time is 2:30 PM EST. Would you like more detailed information or up-to-date forecasts?

最後、どこからその答えになった?というメッセージになっている気はしますがひとまずMCPサーバーを呼び出せていることは
わかったのでよしとしましょう…。

ちなみに、weather_server.py側に記録されるアクセスログはこんな感じです。

INFO:     127.0.0.1:38980 - "GET /sse HTTP/1.1" 200 OK
INFO:     127.0.0.1:38996 - "POST /messages/?session_id=dbfb4909800e43f8b3c879131204bd7b HTTP/1.1" 202 Accepted
INFO:     127.0.0.1:38996 - "POST /messages/?session_id=dbfb4909800e43f8b3c879131204bd7b HTTP/1.1" 202 Accepted
INFO:     127.0.0.1:38996 - "POST /messages/?session_id=dbfb4909800e43f8b3c879131204bd7b HTTP/1.1" 202 Accepted
Processing request of type ListToolsRequest
INFO:     127.0.0.1:41512 - "POST /messages/?session_id=dbfb4909800e43f8b3c879131204bd7b HTTP/1.1" 202 Accepted
Processing request of type CallToolRequest

今回はスキップするもの

LangGraph API Serverとの組み合わせは、そもそもLangGraph API Serverを使ったことがないので今回は
スキップすることにします。

LangChain MCP Adaptersj / Using with LangGraph API Server

おわりに

MCPを、LangChain MCP AdaptersとOllamaを使って試してみました。

MCPについては名前こそ見かけていたものの、ちゃんと調べたことがなかったので学ぶいいきっかけになりました。
これで概念も少しは押さえられましたしね。

このプロトコルを使うと、確かにいろいろできそうですね。




以上の内容はhttps://kazuhira-r.hatenablog.com/entry/2025/04/05/220858より取得しました。
このページはhttp://font.textar.tv/のウェブフォントを使用してます

不具合報告/要望等はこちらへお願いします。
モバイルやる夫Viewer Ver0.14