LangChainのエージェント機能でMCP(Model Context Protocol)を実装・検証
本文の状態
日本語全文を表示中
詳細モードで約8分の本文を読めます。
同じ出来事の情報源
この情報源を基点に整理
HEROZ Tech Blog
Anthropic社が発表したAIアシスタントと情報源を接続するプロトコルMCPを、LangChainのエージェント機能で実装・動作検証した事例。
Source Article
元記事を日本語で読む
本文に関係しない購読案内、埋め込み通知、サイト内プロモーションは除いています。
先月、Anthropic社よりMCP(Model Context Protocol)というプロトコルが発表されました。 www.anthropic.com MCPはAIアシスタント(RAGシステム)と情報源やツール群をつなげるための通信規約(プロトコル)ですが、現時点で何がどこまでできるかが未知数でしたので、調査を行い、LangChainのエージェント機能で動作させました。 とりあえずは、得られた知見についてシステム構成面の切り口で考察していきたいと思います。
MCPの各種情報は以下にあります。
modelcontextprotocol.io
github Python SDK
servers: サーバーのリファレンス実装もある
langchain-mcp: 上記のPython SDKを使用したLangChainへの実装。ToolkitもしくはToolの形態をしている
MCPはプロトコル仕様のArchitectureにある下記の図のようにアプリケーションがMCPのクライアントとなり、ローカルやリモートに位置するMCPのサーバーと通信して、情報を取得したり、ツールを動作させたりします。 アプリケーションにはデスクトップアプリやSaaSサービスが想定されます。
MCPの概要図
そして、MCP自体は以下のようなプロトコルのフローやメッセージの中身が規定されています。
MCPのプロトコルフロー
プロトコルの規定の中で気になったのは、現時点では認証に対応しておらず、今後議論していくように書かれていました。 認証が存在しない以上、インターネットを介しての通信は難しいかもしれません。
Authentication and authorization are not currently part of the core MCP specification, but we are considering ways to introduce them in future. Join us in GitHub Discussions to help shape the future of the protocol!
Clients and servers MAY negotiate their own custom authentication and authorization strategies.
プロトコル仕様のTransportsによると、MCPには以下の2つのトランスポートがあるそうです。
stdio(標準入出力)
HTTP with SSE(Server Side Event)
後者のSSEタイプはhttpsを介した通信なのでMCPのサーバーはローカルとリモートを問わずに適用できます。 一方で、前者のstdioタイプはMCPのクライアントがMCPのサーバーとなるプロセスを起動して、パイプ機能による標準入出力(stdio)を介して通信するため、stdioタイプはローカル内でしか動作しないです。
SDKとリファレンスサーバー群
MCPの公式githubにはPython SDKとTypeScript SDKが整備されており、これらを使用したリファレンスやサードパーティのサーバー群も提供されています。
リファレンスサーバー群
SDKは前述した2つのトランスポートの両方に対応しているのですが、リファレンスサーバー群のほとんどはstdioタイプで作られているため、リモートで動作するものはないです。
Python SDKを使用してLangChainへ実装したlangchain-mcpというライブラリもありますが、stdioタイプを前提としているため、ローカル内でのみ動作します(=リモートでは動作しません)。 langchain-mcpはToolkitとして実装されています。
このlangchain-mcpはasync with文でMCPサーバーとのセッションを確立する作りになっているため、LangChainのチェインやエージェントの初期化時には接続が確立しておらず、実行時に接続を確立するような使い方が難しいです。
async with stdio_client(server_params) as (read, write): async with ClientSession(read, write) as session: toolkit = MCPToolkit(session=session) await toolkit.initialize() (toolkitを使用してrunする)
HEROZ ASKはチェインの構成と実行のタイミングが離れているので、langchain-mcpが適用しづらく、組み込みについては一旦は断念することにしました。
MCPの動作についてシステム構成面で図を交えて考察していきます。
Claude Desktopでのシステム構成
Anthropic社はMCPの発表とともに応用例としてデスクトップ版Claude(Claude Desktop)からのデスクトップ検索を提示しています。 これが「デスクトップ検索が便利だ」や「デスクトップを覗かれるのは危険だ」みたいな感想とともに強調されてしまい、「MCP=デスクトップ検索」や「MCP=Claude Desktop」みたいな勘違いが発生しています。 MCPはあくまで通信プロトコルであって、Claude Desktopやデスクトップ検索は直接的には関係なく、単なる応用例の一つに過ぎません。
Claude Desktopでのシステム構成を図にすると、以下になります。 Claude DesktopはMCPクライアントとして位置し、必要なMCPサーバーを自ら起動して、stdioタイプのトランスポートで接続します。 そして、起動したMCPサーバーのプロセスからデスクトップのファイルにアクセスしています。
Claude Desktopでのシステム構成
起動するMCPサーバーの種類やアクセス先は設定ファイルのjsonにてClaude Desktopに渡しますが、任意のプログラムが起動できたり、ローカルのリソースに自由にアクセスできるという点で、安全とは言えない代物です。
SaaSシステムでの目指したいシステム構成
HEROZ ASKのようなSaaS型のAIアシスタントサービスにMCPを組み込む場合には、以下のような2つのパターンのシステム構成があると思います。
SaaSシステムで目指したいシステム構成
a.はSaaSサービスがMCPクライアントとなるパターンで、ユーザーからの質問に応じて、AIアシスタントがリモートサーバーにある情報を取得したり、ツールで何か実行したりします。 b.はSaaSサービスがMCPサーバーとなるパターンで、SaaSサービスが持っているリソースに対して、ユーザのAIアシスタントアプリや、別のSaaSサービスのAIアシスタントからのアクセスを受け付けます。 こちらはSaaSサービスが持つリソースが重要となるので、どちらかと言うとコンテンツプロバイダー的な位置付けになります。
HEROZ ASKは独自のリソースを持つわけではないので、a.のパターンを狙うことになります。 また、HEROZ ASKのようなエンタープライズ向けのサービスの場合には、リモートサーバーはお客様の情報やツールが入ったサーバーになることが想定されます。
前述のようにAIアシスタントのSaaSサービスはa.のようなMCPクライアントとして、リモートサーバーへのアクセスを望む場合が多いですが、現状はlangchain-mcpがstdioタイプのトランスポートにしか対応していないため、下記のようなシステム構成にならざるをえません。
現状のシステム構成
すなわち、ユーザから質問を受け取ると、MCPサーバーとなるプロセスを起動するとともに、SaaSサービスが動作しているサーバーのリソースにアクセスします。 これは、セキュリティ的にも問題が多いので、HTTP with SSEの対応が待たれます。
仮にlangchain-mcpがHTTP with SSEタイプのトランスポートに対応したとしても、お客様のサーバーに情報を取りに行ったり、ツールを実行しに行ったりする場合には以下のような問題があります。
MCPに認証機能が実装されていないので、非公開情報のアクセスができない
お客様のサーバーがイントラネット内に存在する場合には、アクセスするための術がない
これらを図示すると以下となります。
SaaSシステムでの問題点
LangChainのエージェント機能で動かしてみた
langchain-mcpのREADMEにはエージェント機能を使わない例が載っていますが、せっかくなのでエージェント機能を使って動作させてみました。 /docディレクトリにファイルシステムサーバーを接続してみます。
!pip install langchain langchain-openai langchain-mcp langchain-community==0.3.12 langchain-core==0.3.25 !mkdir -p /doc !touch /doc/test.txt import os import asyncio from langchain_openai import ChatOpenAI from langchain import hub from langchain.agents import AgentExecutor, create_structured_chat_agent from mcp import ClientSession, StdioServerParameters from mcp.client.stdio import stdio_client from langchain_mcp import MCPToolkit os.environ["OPENAI_API_KEY"] = "(OpenAIのAPIキー)" server_params = StdioServerParameters( command="npx", args=["-y", "@modelcontextprotocol/server-filesystem", "/doc"], ) from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder from langchain.agents.structured_chat.prompt import FORMAT_INSTRUCTIONS, PREFIX, SUFFIX HUMAN_MESSAGE_TEMPLATE = "{input}\n\n{agent_scratchpad}" prompt = ChatPromptTemplate.from_messages( [ ("system", "\n\n".join([PREFIX, "{tools}", FORMAT_INSTRUCTIONS, SUFFIX])), MessagesPlaceholder("chat_history", optional=True), ("human", HUMAN_MESSAGE_TEMPLATE), ] ) async def main(message): async with stdio_client(server_params) as (read, write): async with ClientSession(read, write) as session: toolkit = MCPToolkit(session=session) await toolkit.initialize() model = ChatOpenAI(model_name="gpt-4o") tools = toolkit.get_tools() agent = create_structured_chat_agent(model, tools, prompt) agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True) await agent_executor.ainvoke({"input": message}) asyncio.run(main("/docには何のファイルがありますか?"))
langchain-communityとlangchain-coreのバージョンを指定しないとエラーになるので注意が必要です。
実行結果
新しく登場したMCPは外部の情報やツールを活用できるので、期待の技術と思っていたのですが、以下の理由によりまだまだ時期尚早のように思いました。
プロトコルの仕様に認証機能が搭載されていないため、インターネット経由の接続が難しい
リファレンスサーバーやlangchain-mcpのトランスポートがstdioタイプなので、ローカル内でしか実行できない(リモートサーバーへの接続ができない)
Python SDKはasync with文で接続を確立する作りになっているため、LangChainのチェインやエージェントに組み込むのが難しい
とは言え、これらの技術課題が解決されれば、大規模言語モデル(LLM)を用いたエンタープライズサーチの実現も夢が広がります。こうしたOSSへのコントリビュートについても一緒にやってくれる仲間を募集しています。
原文を表示
Auth 2つのトランスポート
SDKとリファレンスサーバー群
システム構成 Claude Desktopでのシステム構成
SaaSシステムでの目指したいシステム構成
LangChainのエージェント機能で動かしてみた
先月、Anthropic社よりMCP(Model Context Protocol)というプロトコルが発表されました。 www.anthropic.com MCPはAIアシスタント(RAGシステム)と情報源やツール群をつなげるための通信規約(プロトコル)ですが、現時点で何がどこまでできるかが未知数でしたので、調査を行い、LangChainのエージェント機能で動作させました。 とりあえずは、得られた知見についてシステム構成面の切り口で考察していきたいと思います。
MCPの各種情報は以下にあります。
modelcontextprotocol.io
github Python SDK
servers: サーバーのリファレンス実装もある
langchain-mcp: 上記のPython SDKを使用したLangChainへの実装。ToolkitもしくはToolの形態をしている
MCPはプロトコル仕様のArchitectureにある下記の図のようにアプリケーションがMCPのクライアントとなり、ローカルやリモートに位置するMCPのサーバーと通信して、情報を取得したり、ツールを動作させたりします。 アプリケーションにはデスクトップアプリやSaaSサービスが想定されます。
MCPの概要図
そして、MCP自体は以下のようなプロトコルのフローやメッセージの中身が規定されています。
MCPのプロトコルフロー
プロトコルの規定の中で気になったのは、現時点では認証に対応しておらず、今後議論していくように書かれていました。 認証が存在しない以上、インターネットを介しての通信は難しいかもしれません。
Authentication and authorization are not currently part of the core MCP specification, but we are considering ways to introduce them in future. Join us in GitHub Discussions to help shape the future of the protocol!
Clients and servers MAY negotiate their own custom authentication and authorization strategies.
プロトコル仕様のTransportsによると、MCPには以下の2つのトランスポートがあるそうです。
HTTP with SSE(Server Side Event)
後者のSSEタイプはhttpsを介した通信なのでMCPのサーバーはローカルとリモートを問わずに適用できます。 一方で、前者のstdioタイプはMCPのクライアントがMCPのサーバーとなるプロセスを起動して、パイプ機能による標準入出力(stdio)を介して通信するため、stdioタイプはローカル内でしか動作しないです。
SDKとリファレンスサーバー群
MCPの公式githubにはPython SDKとTypeScript SDKが整備されており、これらを使用したリファレンスやサードパーティのサーバー群も提供されています。
リファレンスサーバー群
SDKは前述した2つのトランスポートの両方に対応しているのですが、リファレンスサーバー群のほとんどはstdioタイプで作られているため、リモートで動作するものはないです。
Python SDKを使用してLangChainへ実装したlangchain-mcpというライブラリもありますが、stdioタイプを前提としているため、ローカル内でのみ動作します(=リモートでは動作しません)。 langchain-mcpはTool
このlangchain-mcpはasync with
async with stdio_client(server_params) as (read, write): async with ClientSession(read, write) as session: toolkit = MCPToolkit(session=session) await toolkit.initialize() (toolkitを使用してrunする)
HEROZ ASKはチェインの構成と実行のタイミングが離れているので、langchain-mcpが適用しづらく、組み込みについては一旦は断念することにしました。
MCPの動作についてシステム構成面で図を交えて考察していきます。
Claude Desktopでのシステム構成
Anthropic社はMCPの発表とともに応用例としてデスクトップ版Claude(Claude Desktop)からのデスクトップ検索を提示しています。 これが「デスクトップ検索が便利だ」や「デスクトップを覗かれるのは危険だ」みたいな感想とともに強調されてしまい、「MCP=デスクトップ検索」や「MCP=Claude Desktop」みたいな勘違いが発生しています。 MCPはあくまで通信プロトコルであって、Claude Desktopやデスクトップ検索は直接的には関係なく、単なる応用例の一つに過ぎません。
Claude Desktopでのシステム構成を図にすると、以下になります。 Claude DesktopはMCPクライアントとして位置し、必要なMCPサーバーを自ら起動して、stdioタイプのトランスポートで接続します。 そして、起動したMCPサーバーのプロセスからデスクトップのファイルにアクセスしています。
Claude Desktopでのシステム構成
起動するMCPサーバーの種類やアクセス先は設定ファイルのjsonにてClaude Desktopに渡しますが、任意のプログラムが起動できたり、ローカルのリソースに自由にアクセスできるという点で、安全とは言えない代物です。
SaaSシステムでの目指したいシステム構成
HEROZ ASKのようなSaaS型のAIアシスタントサービスにMCPを組み込む場合には、以下のような2つのパターンのシステム構成があると思います。
SaaSシステムで目指したいシステム構成
a.はSaaSサービスがMCPクライアントとなるパターンで、ユーザーからの質問に応じて、AIアシスタントがリモートサーバーにある情報を取得したり、ツールで何か実行したりします。 b.はSaaSサービスがMCPサーバーとなるパターンで、SaaSサービスが持っているリソースに対して、ユーザのAIアシスタントアプリや、別のSaaSサービスのAIアシスタントからのアクセスを受け付けます。 こちらはSaaSサービスが持つリソースが重要となるので、どちらかと言うとコンテンツプロバイダー的な位置付けになります。
HEROZ ASKは独自のリソースを持つわけではないので、a.のパターンを狙うことになります。 また、HEROZ ASKのようなエンタープライズ向けのサービスの場合には、リモートサーバーはお客様の情報やツールが入ったサーバーになることが想定されます。
前述のようにAIアシスタントのSaaSサービスはa.のようなMCPクライアントとして、リモートサーバーへのアクセスを望む場合が多いですが、現状はlangchain-mcpがstdioタイプのトランスポートにしか対応していないため、下記のようなシステム構成にならざるをえません。
現状のシステム構成
すなわち、ユーザから質問を受け取ると、MCPサーバーとなるプロセスを起動するとともに、SaaSサービスが動作しているサーバーのリソースにアクセスします。 これは、セキュリティ的にも問題が多いので、HTTP with SSEの対応が待たれます。
仮にlangchain-mcpがHTTP with SSEタイプのトランスポートに対応したとしても、お客様のサーバーに情報を取りに行ったり、ツールを実行しに行ったりする場合には以下のような問題があります。
MCPに認証機能が実装されていないので、非公開情報のアクセスができない
お客様のサーバーがイントラネット内に存在する場合には、アクセスするための術がない
これらを図示すると以下となります。
SaaSシステムでの問題点
LangChainのエージェント機能で動かしてみた
langchain-mcpのREADMEにはエージェント機能を使わない例が載っていますが、せっかくなのでエージェント機能を使って動作させてみました。 /doc
!pip install langchain langchain-openai langchain-mcp langchain-community==0.3.12 langchain-core==0.3.25 !mkdir -p /doc !touch /doc/test.txt import os import asyncio from langchain_openai import ChatOpenAI from langchain import hub from langchain.agents import AgentExecutor, create_structured_chat_agent from mcp import ClientSession, StdioServerParameters from mcp.client.stdio import stdio_client from langchain_mcp import MCPToolkit os.environ["OPENAI_API_KEY"] = "(OpenAIのAPIキー)" server_params = StdioServerParameters( command="npx", args=["-y", "@modelcontextprotocol/server-filesystem", "/doc"], ) from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder from langchain.agents.structured_chat.prompt import FORMAT_INSTRUCTIONS, PREFIX, SUFFIX HUMAN_MESSAGE_TEMPLATE = "{input}\n\n{agent_scratchpad}" prompt = ChatPromptTemplate.from_messages( [ ("system", "\n\n".join([PREFIX, "{tools}", FORMAT_INSTRUCTIONS, SUFFIX])), MessagesPlaceholder("chat_history", optional=True), ("human", HUMAN_MESSAGE_TEMPLATE), ] ) async def main(message): async with stdio_client(server_params) as (read, write): async with ClientSession(read, write) as session: toolkit = MCPToolkit(session=session) await toolkit.initialize() model = ChatOpenAI(model_name="gpt-4o") tools = toolkit.get_tools() agent = create_structured_chat_agent(model, tools, prompt) agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True) await agent_executor.ainvoke({"input": message}) asyncio.run(main("/docには何のファイルがありますか?"))
langchain-community
実行結果
新しく登場したMCPは外部の情報やツールを活用できるので、期待の技術と思っていたのですが、以下の理由によりまだまだ時期尚早のように思いました。
プロトコルの仕様に認証機能が搭載されていないため、インターネット経由の接続が難しい
リファレンスサーバーやlangchain-mcpのトランスポートがstdioタイプなので、ローカル内でしか実行できない(リモートサーバーへの接続ができない)
Python SDKはasync with
とは言え、これらの技術課題が解決されれば、大規模言語モデル(LLM)を用いたエンタープライズサーチの実現も夢が広がります。こうしたOSSへのコントリビュートについても一緒にやってくれる仲間を募集しています。
関連記事
今日のまとめ
AIデイリーブリーフで今日の重要ニュースをまとめ読み