当前位置: 首页 > java >正文

LangChain4j(17)——MCP客户端

MCP介绍

MCP (Model Context Protocol) 是一个开放协议,用于标准化应用程序如何向 LLM 提供上下文。可以将 MCP 想象成 AI 应用程序的 USB 接口。就像 USB 为设备连接各种外设和配件提供标准化方式一样,MCP 为 AI 模型连接不同的数据源和工具提供了标准化的方式。

sever-everyting服务介绍

本例使用的mcp服务是server-everything。它是一个 MCP 客户端构建者的测试服务器,没有具体的用途。其支持的工具方法:

echo

回显输入消息的简单工具
输入:
        message(string):要回显的消息
返回: 带有回声消息的文本内容
add

将两个数字相加
输入:
        a(number):第一个数字
        b(number):第二个数字
返回: 添加的文本结果
longRunningOperation

演示长时间作的进度通知
输入:
        duration(number,默认值:10):持续时间(以秒为单位)
        steps(number,默认值:5):进度步骤数
返回: 包含持续时间和步骤的完成消息
        在执行过程中发送进度通知
sampleLLM

演示使用 MCP 采样功能的 LLM 采样功能
输入:
        prompt(string):要发送到 LLM 的提示
        maxTokens(number,默认值:100):要生成的最大令牌数
返回: 生成的 LLM 响应
getTinyImage

返回一个小的测试图像
无需输入
返回:Base64 编码的 PNG 图像数据
printEnv

打印所有环境变量,用于调试 MCP 服务器配置
无需输入
返回: 所有环境变量的 JSON 字符串
annotatedMessage

演示如何使用批注提供有关内容的元数据
输入:
        messageType(enum: “error” |“成功” |“debug”):用于演示不同注释模式的消息类型
        includeImage(boolean, default: false):是否包含示例图片
返回: 具有不同注释的内容:
        错误消息:高优先级 (1.0),对用户和助手都可见
        成功消息:中等优先级 (0.7),以用户为中心
        调试消息:低优先级 (0.3),以助手为中心
        可选图片:中等优先级 (0.5),以用户为中心

getResourceReference

返回 MCP 客户端可以使用的资源引用
输入:
        resourceId(number, 1-100):要引用的资源的 ID
返回: 一个资源引用,其中包含:
        文本介绍
        嵌入资源与type: "resource"
        使用资源 URI 的文本说明

使用LangChain4j调用MCP服务

LangChain4j 支持模型上下文协议 (MCP),用于与符合 MCP 的服务器通信。

该协议指定了两种传输类型:

Http:客户端请求一个 SSE 通道来接收来自服务器的事件,然后通过 HTTP POST 请求发送命令。
Stdio:客户端可以将 MCP 服务器作为本地子进程运行,并通过标准输入/输出直接与其通信。

注意:LangChain4j官网给出的案例中,sse方式无法连接server-everything服务(不确定是不是langchain4j版本的原因),本例使用stdio协议连接

package com.renr.langchain4jnew.app2;import com.renr.langchain4jnew.constant.CommonConstants;
import dev.langchain4j.community.model.zhipu.ZhipuAiChatModel;
import dev.langchain4j.mcp.McpToolProvider;
import dev.langchain4j.mcp.client.DefaultMcpClient;
import dev.langchain4j.mcp.client.McpClient;
import dev.langchain4j.mcp.client.transport.McpTransport;
import dev.langchain4j.mcp.client.transport.stdio.StdioMcpTransport;
import dev.langchain4j.service.AiServices;
import dev.langchain4j.service.tool.ToolProvider;import java.time.Duration;
import java.util.List;/*** @Title: AI Service基本使用* @Author 老任与码* @Date 2025-04-12 9:25*/
public class AppMPC {public static void main(String[] args) {// 创建智谱的模型对象ZhipuAiChatModel zhipuAiChatModel = ZhipuAiChatModel.builder()// 模型key.apiKey(CommonConstants.API_KEY)// 精确度.temperature(0.9).model("GLM-4-Flash").maxRetries(3).logRequests(true).logResponses(true).callTimeout(Duration.ofSeconds(60)).connectTimeout(Duration.ofSeconds(60)).writeTimeout(Duration.ofSeconds(60)).readTimeout(Duration.ofSeconds(60)).build();// 使用stdio协议创建传输对象,由于在window环境测试,这里需要指定windows下npm命令的路径McpTransport transport = new StdioMcpTransport.Builder().command(List.of("C:/Program Files/nodejs/npm.cmd", "exec", "@modelcontextprotocol/server-everything@2025.4.28")).logEvents(true) // 仅当你想在日志中查看流量时.build();// 实际测试,无法连接
//        McpTransport transport = new HttpMcpTransport.Builder()
//                .sseUrl("http://127.0.0.1:3001/sse") // SSE 事件channel地址
//                .logRequests(true) // 开启请求日志
//                .logResponses(true) // 开启响应日志
//                .build();// 创建mcp客户端对象McpClient mcpClient = new DefaultMcpClient.Builder().transport(transport).build();// 创建工具对象ToolProvider toolProvider = McpToolProvider.builder().mcpClients(List.of(mcpClient)).build();// 模型中,指定使用的工具Assistant assistant = AiServices.builder(Assistant.class).chatLanguageModel(zhipuAiChatModel).toolProvider(toolProvider).build();// 发送消息,本例测试是否会调用mcp服务的add函数String info = assistant.chat("100加100等于多少");System.out.println(info);}
}

执行结果:

从执行结果看,大模型选择让用户调用add函数执行加法运算。

第一次发送的请求数据:

tools属性中给出了server-everything中定义的函数,并将这些信息一起发送给大模型。

Request:
- method: POST
- url: https://open.bigmodel.cn/api/paas/v4/chat/completions
- headers: [Authorization: Bearer ey...fQ..EsWKuDgfSyfeaAg10__UaDzVuty1QOkzosp-g0-bVdo]
- body: {"model" : "GLM-4-Flash","messages" : [ {"role" : "user","content" : "100加100等于多少"} ],"stream" : false,"temperature" : 0.9,"max_tokens" : 512,"tools" : [ {"type" : "function","function" : {"name" : "echo","description" : "Echoes back the input","parameters" : {"type" : "object","properties" : {"message" : {"type" : "string","description" : "Message to echo"}},"required" : [ "message" ]}}}, {"type" : "function","function" : {"name" : "add","description" : "Adds two numbers","parameters" : {"type" : "object","properties" : {"a" : {"type" : "number","description" : "First number"},"b" : {"type" : "number","description" : "Second number"}},"required" : [ "a", "b" ]}}}, {"type" : "function","function" : {"name" : "printEnv","description" : "Prints all environment variables, helpful for debugging MCP server configuration","parameters" : {"type" : "object","properties" : { },"required" : [ ]}}}, {"type" : "function","function" : {"name" : "longRunningOperation","description" : "Demonstrates a long running operation with progress updates","parameters" : {"type" : "object","properties" : {"duration" : {"type" : "number","description" : "Duration of the operation in seconds"},"steps" : {"type" : "number","description" : "Number of steps in the operation"}},"required" : [ ]}}}, {"type" : "function","function" : {"name" : "sampleLLM","description" : "Samples from an LLM using MCP's sampling feature","parameters" : {"type" : "object","properties" : {"prompt" : {"type" : "string","description" : "The prompt to send to the LLM"},"maxTokens" : {"type" : "number","description" : "Maximum number of tokens to generate"}},"required" : [ "prompt" ]}}}, {"type" : "function","function" : {"name" : "getTinyImage","description" : "Returns the MCP_TINY_IMAGE","parameters" : {"type" : "object","properties" : { },"required" : [ ]}}}, {"type" : "function","function" : {"name" : "annotatedMessage","description" : "Demonstrates how annotations can be used to provide metadata about content","parameters" : {"type" : "object","properties" : {"messageType" : {"type" : "string","description" : "Type of message to demonstrate different annotation patterns","enum" : [ "error", "success", "debug" ]},"includeImage" : {"type" : "boolean","description" : "Whether to include an example image"}},"required" : [ "messageType" ]}}}, {"type" : "function","function" : {"name" : "getResourceReference","description" : "Returns a resource reference that can be used by MCP clients","parameters" : {"type" : "object","properties" : {"resourceId" : {"type" : "number","description" : "ID of the resource to reference (1-100)"}},"required" : [ "resourceId" ]}}} ],"tool_choice" : "auto"
}

大模型收到第一次请求,根据用户提问和tools中支持的函数,返回的第一次响应中要求用户执行add函数,然后发送第二次请求:

 Request:
- method: POST
- url: https://open.bigmodel.cn/api/paas/v4/chat/completions
- headers: [Authorization: Bearer ey...fQ..EsWKuDgfSyfeaAg10__UaDzVuty1QOkzosp-g0-bVdo]
- body: {"model" : "GLM-4-Flash","messages" : [ {"role" : "user","content" : "100加100等于多少"}, {"role" : "assistant","tool_calls" : [ {"id" : "call_-8666101128331871791","type" : "function","function" : {"name" : "add","arguments" : "{\"a\": 100, \"b\": 100}"}} ]}, {"role" : "tool","content" : "The sum of 100 and 100 is 200."} ],"stream" : false,"temperature" : 0.9,"max_tokens" : 512,"tools" :......
}

根据第二次请求的数据,tool_calls属性表示执行了add函数。

http://www.xdnf.cn/news/9535.html

相关文章:

  • 在PHP编程中包(Package)和库(Library)怎么区分?
  • 企业级AI开启落地战,得场景者得天下
  • LeeCode 94. 二叉树的中序遍历
  • YARN架构解析:大数据资源管理核心
  • 【MYSQL】mysql单表亿级数据查询优化处理
  • 2021年认证杯SPSSPRO杯数学建模D题(第二阶段)停车的策略全过程文档及程序
  • 探寻黄金奶源带,悠纯乳业打造西北乳业新标杆
  • Spring AI框架快速入门
  • day12 leetcode-hot100-20(矩阵3)
  • 【Linux】网络(上)
  • Vue开发系列——如何使用Vue
  • 图像卷积OpenCV C/C++ 核心操作
  • 【DB2】ERRORCODE=-4499, SQLSTATE=08001
  • 【C++基础知识】匿名命名空间
  • mysql prepare statement
  • 如何查询服务器的端口号
  • 数据结构 -- 树相关面试题
  • SFTP工具类实现文件上传下载_
  • 关于ios点击分享自动复制到粘贴板的问题
  • CEH Practical 实战考试真题与答案
  • C++异步通信-future学习
  • maven项目编译时复制xml到classes目录方案
  • 服务器关机
  • 实验设计与分析(第6版,Montgomery)第4章随机化区组,拉丁方, 及有关设计4.5节思考题4.18~4.19 R语言解题
  • 【OSS】 前端如何直接上传到OSS 上返回https链接,如果做到OSS图片资源加密访问
  • [AI voiceFFmpeg windows系统下CUDA与cuDNN详细安装教程]
  • 记录一次session安装应用recyclerview更新数据的bug
  • Transformer架构详解:从Attention到ChatGPT
  • 数据脱敏后的测试方法
  • 宏的高级应用 ——一种 C 语言的元编程技巧(X-Macro)