跳到主要内容

モデルコンテキストプロトコル(MCP)

LangChain4jはモデルコンテキストプロトコル(MCP)をサポートしており、ツールを提供および実行できるMCP準拠サーバーと通信できます。プロトコルに関する一般的な情報はMCPウェブサイトで確認できます。

このプロトコルは2種類のトランスポートを指定しており、どちらもサポートされています:

  • HTTP:クライアントはサーバーからイベントを受信するためのSSEチャネルをリクエストし、HTTPのPOSTリクエストを通じてコマンドを送信します。
  • stdio:クライアントはMCPサーバーをローカルサブプロセスとして実行し、標準入出力を通じて直接通信できます。

チャットモデルやAIサービスにMCPサーバーが提供するツールを実行させるには、MCPツールプロバイダーのインスタンスを作成する必要があります。

MCPツールプロバイダーの作成

MCPトランスポート

まず、MCPトランスポートのインスタンスが必要です。

stdioの場合 - この例ではNPMパッケージからサーバーをサブプロセスとして起動する方法を示しています:

McpTransport transport = new StdioMcpTransport.Builder()
.command(List.of("/usr/bin/npm", "exec", "@modelcontextprotocol/server-everything@0.6.2"))
.logEvents(true) // ログにトラフィックを表示したい場合のみ
.build();

HTTPの場合、SSEチャネルを開始するためのURLと、POSTでコマンドを送信するためのURLの2つが必要です:

McpTransport transport = new HttpMcpTransport.Builder()
.sseUrl("http://localhost:3001/sse")
.logRequests(true) // ログにトラフィックを表示したい場合
.logResponses(true)
.build();

MCPクライアント

トランスポートからMCPクライアントを作成するには:

McpClient mcpClient = new DefaultMcpClient.Builder()
.transport(transport)
.build();

MCPツールプロバイダー

最後に、クライアントからMCPツールプロバイダーを作成します:

ToolProvider toolProvider = McpToolProvider.builder()
.mcpClients(List.of(mcpClient))
.build();

1つのMCPツールプロバイダーが同時に複数のクライアントを使用できることに注意してください。 これを利用する場合、特定のサーバーからツールの取得に失敗した場合のツールプロバイダーの動作を指定することもできます。 これはbuilder.failIfOneServerFails(boolean)メソッドで行います。デフォルトはfalseで、 これはツールプロバイダーが1つのサーバーからのエラーを無視し、他のサーバーと続行することを意味します。 trueに設定すると、いずれかのサーバーからの失敗によりツールプロバイダーは例外をスローします。

ツールプロバイダーをAIサービスにバインドするには、AIサービスビルダーのtoolProviderメソッドを使用するだけです:

Bot bot = AiServices.builder(Bot.class)
.chatModel(model)
.toolProvider(toolProvider)
.build();

LangChain4jのツールサポートに関する詳細はこちらで確認できます。

ロギング

MCPプロトコルは、サーバーがクライアントにログメッセージを送信する方法も定義しています。 デフォルトでは、クライアントの動作はこれらのログメッセージを変換し、SLF4Jロガーを使用してログに記録することです。 この動作を変更したい場合は、受信したログメッセージのコールバックとして機能する dev.langchain4j.mcp.client.logging.McpLogMessageHandlerというインターフェースがあります。 McpLogMessageHandlerの独自の実装を作成した場合は、MCPクライアントビルダーに渡します:

McpClient mcpClient = new DefaultMcpClient.Builder()
.transport(transport)
.logMessageHandler(new MyLogMessageHandler())
.build();

リソース

サーバー上のMCPリソースのリストを取得するには、 client.listResources()を使用するか、リソーステンプレートの場合はclient.listResourceTemplates()を使用します。 これによりMcpResourceオブジェクト(またはそれぞれMcpResourceTemplate)のリストが返されます。 これらにはリソースのメタデータが含まれており、最も重要なのはURIです。

リソースの実際の内容を取得するには、リソースのURIを指定してclient.readResource(uri)を使用します。 これはMcpReadResourceResultを返し、McpResourceContentsオブジェクトのリストが含まれています (1つのURIに複数のリソースコンテンツが存在する場合があります。例えばURIがディレクトリを表す場合など)。 各McpResourceContentsオブジェクトはバイナリブロブ(McpBlobResourceContents)または テキスト(McpTextResourceContents)のいずれかを表します。

プロンプト

サーバーからMCPプロンプトのリストを取得するには、 client.listPrompts()を使用します。このメソッドはMcpPromptのリストを返します。 McpPromptにはプロンプトの名前と引数に関する情報が含まれています。

プロンプトの実際の内容をレンダリングするには、client.getPrompt(name, arguments)を使用します。 レンダリングされたプロンプトには1つから複数のメッセージが含まれ、これらはMcpPromptMessageオブジェクトとして表されます。 各McpPromptMessageにはメッセージの役割(userassistantなど)と実際のメッセージの内容が含まれています。 現在サポートされているメッセージコンテンツタイプは:McpTextContentMcpImageContentMcpEmbeddedResourceです。

McpPromptMessage.toChatMessage()を使用して、LangChain4jコアAPIの一般的なdev.langchain4j.data.message.ChatMessageに変換できます。 ただし、これはすべての場合に可能というわけではありません。例えば、プロンプトメッセージのroleassistantで、 テキスト以外のコンテンツが含まれている場合、例外がスローされます。 役割に関係なく、バイナリブロブコンテンツを持つメッセージをChatMessageに変換することはサポートされていません。

DockerでGitHub MCPサーバーを使用する

それでは、モデルコンテキストプロトコル(MCP)を使用して、AIモデルと外部ツールを標準化された方法で橋渡しする方法を見てみましょう。 次の例では、LangChain4j MCPクライアントを通じてGitHubと対話し、公開GitHubリポジトリから最新のコミットを取得して要約します。 そのために、車輪の再発明は必要なく、MCP GitHubリポジトリにある既存のGitHub MCP サーバー実装を使用できます。

アイデアは、Dockerでローカルに実行されているGitHub MCPサーバーに接続して、最新のコミットを取得し要約するJavaアプリケーションを構築することです。 この例では、MCPのstdioトランスポートメカニズムを使用して、JavaアプリケーションとGitHub MCPサーバー間で通信します。

GitHub MCPサーバーのDockerでのパッケージ化と実行

GitHubと対話するには、まずDockerでGitHub MCPサーバーをセットアップする必要があります。 GitHub MCPサーバーは、モデルコンテキストプロトコルを通じてGitHubと対話するための標準化されたインターフェースを提供します。 これにより、ファイル操作、リポジトリ管理、検索機能が可能になります。

GitHub MCPサーバー用のDockerイメージをビルドするには、MCP serversのGitHubリポジトリからコードを取得する必要があります。リポジトリをクローンするか、コードをダウンロードしてください。 次に、ルートディレクトリに移動し、次のDockerコマンドを実行します:

docker build -t mcp/github -f src/github/Dockerfile .

Dockerfileは必要な環境をセットアップし、GitHub MCP サーバー実装をインストールします。 ビルドが完了すると、イメージはローカルでmcp/githubとして利用可能になります。

docker image ls

REPOSITORY TAG IMAGE ID SIZE
mcp/github latest b141704170b1 173MB

ツールプロバイダーの開発

LangChain4jを使用してGitHub MCPサーバーに接続するMcpGithubToolsExampleというJavaクラスを作成しましょう。このクラスは:

  • GitHub MCPサーバーをDockerコンテナで起動します(dockerコマンドは/usr/local/bin/dockerで利用可能)
  • stdioトランスポートを使用して接続を確立します
  • LLMを使用してLangChain4j GitHubリポジトリの最後の3つのコミットを要約します

注意:以下のコードでは、環境変数GITHUB_PERSONAL_ACCESS_TOKENでGitHubトークンを渡しています。ただし、認証が不要な公開リポジトリの一部のアクションについてはこれはオプションです。

実装は次のとおりです:

public static void main(String[] args) throws Exception {

ChatModel model = OpenAiChatModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.modelName("gpt-4o-mini")
.logRequests(true)
.logResponses(true)
.build();

McpTransport transport = new StdioMcpTransport.Builder()
.command(List.of("/usr/local/bin/docker", "run", "-e", "GITHUB_PERSONAL_ACCESS_TOKEN", "-i", "mcp/github"))
.logEvents(true)
.build();

McpClient mcpClient = new DefaultMcpClient.Builder()
.transport(transport)
.build();

ToolProvider toolProvider = McpToolProvider.builder()
.mcpClients(List.of(mcpClient))
.build();

Bot bot = AiServices.builder(Bot.class)
.chatModel(model)
.toolProvider(toolProvider)
.build();

try {
String response = bot.chat("LangChain4j GitHubリポジトリの最後の3つのコミットを要約してください");
System.out.println("RESPONSE: " + response);
} finally {
mcpClient.close();
}
}
备注

すべてのLLMが同じようにツールをサポートしているわけではありません。 ツールを理解し、選択し、正しく使用する能力は、特定のモデルとその機能に大きく依存します。 一部のモデルはツールをまったくサポートしていない場合もあれば、慎重なプロンプトエンジニアリングや 追加のシステム指示が必要な場合もあります。

注意:この例ではDockerを使用しているため、/usr/local/bin/dockerで利用可能なDockerコマンドを実行します(オペレーティングシステムに応じてパスを変更してください)。Dockerの代わりにPodmanを使用したい場合は、コマンドを適宜変更してください。

コードの実行

この例を実行するには、システム上でDockerが起動して実行されていることを確認してください。 また、環境変数OPENAI_API_KEYにOpenAI APIキーを設定してください。

次に、Javaアプリケーションを実行します。LangChain4j GitHubリポジトリの最後の3つのコミットを要約するレスポンスが得られるはずです:

LangChain4j GitHubリポジトリの最後の3つのコミットの要約:

1. **コミット [36951f9](https://github.com/langchain4j/langchain4j/commit/36951f9649c1beacd8b9fc2d910a2e23223e0d93)** (日付: 2025-02-05)
- **作者:** Dmytro Liubarskyi
- **メッセージ:** `upload-pages-artifact@v3`に更新。
- **詳細:** このコミットは、ページアーティファクトのアップロードに使用されるGitHub Actionをバージョン3に更新しています。

2. **コミット [6fcd19f](https://github.com/langchain4j/langchain4j/commit/6fcd19f50c8393729a0878d6125b0bb1967ac055)** (日付: 2025-02-05)
- **作者:** Dmytro Liubarskyi
- **メッセージ:** `checkout@v4`、`deploy-pages@v4`、`upload-pages-artifact@v4`に更新。
- **詳細:** このコミットは、複数のGitHub Actionをバージョン4に更新しています。

3. **コミット [2e74049](https://github.com/langchain4j/langchain4j/commit/2e740495d2aa0f16ef1c05cfcc76f91aef6f6599)** (日付: 2025-02-05)
- **作者:** Dmytro Liubarskyi
- **メッセージ:** `setup-node@v4`と`configure-pages@v4`に更新。
- **詳細:** このコミットは、`setup-node`と`configure-pages`のGitHub Actionをバージョン4に更新しています。

すべてのコミットは同じ作者(Dmytro Liubarskyi)によって同じ日に行われ、様々なGitHub Actionを新しいバージョンに更新することに焦点を当てています。