LangChainのエージェント機能でMCP(Model Context Protocol)を実装・検証
HEROZ Tech Blog は、Anthropic が発表した AI アシスタントとツールを接続するプロトコル「MCP」の仕様を分析し、LangChain での実装試行を通じて、現状のローカル限定動作や認証機能の欠如といった課題と、デスクトップ検索以外の応用可能性について考察している。
キーポイント
MCP の基本仕様とトランスポートの違い
MCP は AI と情報源を繋ぐプロトコルだが、stdio タイプはローカル内のみ動作し、SSE タイプはリモート通信も可能である。
LangChain 実装における制約と課題
現状の公式 SDK や langchain-mcp ライブラリは stdio タイプが主流であり、リモート環境での動作や複雑なチェイン構成(HEROZ ASK)への適用には難がある。
セキュリティと認証機能の欠如
現時点の MCP 仕様では認証・認可機能がコアに含まれておらず、インターネットを介した安全な通信は困難である。
Claude Desktop と MCP の関係性整理
MCP は単なる通信プロトコルであり、デスクトップ検索機能はあくまで応用例の一つに過ぎず、MCP 自体がデスクトップアプリを意味するわけではない。
SaaS型AIアシスタントのMCP導入パターンとHEROZ ASKの位置付け
MCPを組み込む構成にはクライアント側が情報を取得する「a」パターンと、リソースを提供するサーバー側となる「b」パターンの2つがあり、独自リソースを持たないHEROZ ASKは前者を目指している。
現状の技術的課題:セキュリティとネットワークアクセス
langchain-mcpがstdioタイプのみ対応しているため、ユーザーからの質問ごとにプロセスを起動する必要があり、セキュリティリスクやイントラネット内サーバーへのアクセス制限といった問題が発生する。
LangChainエージェント機能を用いたMCPの実装例
標準的な利用例に加え、LangChainのエージェント機能(AgentExecutor)と構造化されたプロンプトを組み合わせて、ファイルシステムサーバーを制御するコードサンプルが提示されている。
影響分析・編集コメントを表示
影響分析
この記事は、MCP という新規格が発表された直後の現状を冷静に分析しており、開発者が実装を検討する際の「ローカル限定」という重大な制約と、「認証未対応」というセキュリティリスクを明確に指摘しています。これにより、業界全体が MCP を単なる「デスクトップ検索機能」として誤解するのを防ぎ、プロトコルとしての真の価値と今後の拡張(リモート通信・認証)への期待を整理する役割を果たします。
編集コメント
新規格の発表直後にもかかわらず、実装時の制約やセキュリティリスクを具体的に示した非常に有益な分析記事です。MCP を導入する際は「ローカル限定」および「認証未対応」という事実を必ず確認する必要があります。
先月、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日報で今日の重要ニュースをまとめ読み