模型上下文协议 (MCP)
LangChain4j 支持模型上下文协议 (MCP),用于与符合 MCP 的服务器通信,这些服务器可以提供和执行工具。有关该协议的一般信息可以在 MCP 网站 上找到。
该协议指定了两种传输类型,两种都受支持:
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,你需要两个 URL,一个用于启动 SSE 通道,一个用于通过 POST
提交命令:
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();
请注意,一个 MCP 工具提供者可以同时使用多个客户端。
如果你利用这一点,你还可以指定工具提供者在从特定服务器检索工具失败的情况下的行为 - 这是通过 builder.failIfOneServerFails(boolean)
方法完成的。默认值为 false
,
这意味着工具提供者将忽略来自一个服务器的错误并继续使用其他服务器。如果你将其设置为 true
,任何服务器的失败都将导致工具提供者抛出异常。
要将工具提供者绑定到 AI 服务,只需使用 AI 服务构建器的 toolProvider
方法:
Bot bot = AiServices.builder(Bot.class)
.chatLanguageModel(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。
要获取资源的实际内容,使用 client.readResource(uri)
,提供资源的 URI。
这将返回一个 McpReadResourceResult
,其中包含 McpResourceContents
对象的列表(在单个 URI 上可能有多个资源内容,例如如果 URI 表示一个目录)。每个 McpResourceContents
对象表示二进制 blob(McpBlobResourceContents
)或文本(McpTextResourceContents
)。
提示
要从服务器获取 MCP 提示 列表,使用 client.listPrompts()
。此方法返回 McpPrompt
的列表。McpPrompt
包含有关提示的名称和参数的信息。
要渲染提示的实际内容,使用 client.getPrompt(name, arguments)
。渲染的提示可以包含一到多个消息,这些消息表示为 McpPromptMessage
对象。每个 McpPromptMessage
包含消息的角色(user
、assistant
...)和消息的实际内容。目前支持的消息内容类型有:McpTextContent
、McpImageContent
和 McpEmbeddedResource
。
你可以使用 McpPromptMessage.toChatMessage()
将其转换为 LangChain4j 核心 API 中的通用 dev.langchain4j.data.message.ChatMessage
。但这并非在所有情况下都可行。例如,如果提示消息的 role
是 assistant
并且它包含文本以外的内容,它将抛出异常。无论角色如何,将带有二进制 blob 内容的消息转换为 ChatMessage
都不受支持。
通过 Docker 使用 GitHub MCP 服务器
现在让我们看看如何使用模型上下文协议 (MCP) 以标准化的方式将 AI 模型与外部工具连接起来。 以下示例将通过 LangChain4j MCP 客户端与 GitHub 交互,获取并总结公共 GitHub 仓库的最新提交。 为此,无需重新发明轮子,我们可以使用 MCP GitHub 仓库 中现有的 GitHub MCP 服务器实现。
我们的想法是构建一个 Java 应用程序,连接到本地 Docker 中运行的 GitHub MCP 服务器,获取并总结最新的提交。 该示例使用 MCP 的 stdio 传输机制在我们的 Java 应用程序和 GitHub MCP 服务器之间进行通信。