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

Spring-Ai-McpSever从外到内

MCP是什么

Model Context Protocol (MCP) 是一个开放协议,它使 LLM 应用与外部数据源和工具之间的无缝集成成为可能。无论你是构建 AI 驱动的 IDE、改善 chat 交互,还是构建自定义的 AI 工作流,MCP 提供了一种标准化的方式,将 LLM 与它们所需的上下文连接起来
目前,MCP 已经积累了足够的临界规模和动能,因此它被视为 2023-2025 年“代理开放标准”之争的潜在赢家。有人预计,按照当前的速度,MCP 将在 7 月超OpenAPI

JAVA实现MCP

找了一个github的事例代码仅供参考
事例代码:
spring-ai-mcp-deepseek
代码模块比较清晰
在这里插入图片描述

mcp-server

基于springBoot启动配置
application.properties

# MCP服务端开启
spring.ai.mcp.server.enabled=true# MCP服务端配置
spring.ai.mcp.server.name=book-management-server
spring.ai.mcp.server.version=1.0.0
spring.ai.mcp.server.type=SYNC
spring.ai.mcp.server.sse-message-endpoint=/mcp/message
@Configuration
public class McpServerConfig {/*** 注册工具回调提供者,将BookQueryService中的@Tool方法暴露为MCP工具** @param bookService 图书服务* @return 工具回调提供者*/@Beanpublic ToolCallbackProvider bookToolCallbackProvider(BookService bookService) {return MethodToolCallbackProvider.builder().toolObjects(bookService).build();}}

打开 ToolCallbackProvider

public interface ToolCallbackProvider {//回调函数接口需要实现类去实现的FunctionCallback[] getToolCallbacks();//静态方法接口默认实现 ,不需要实现类实现public static ToolCallbackProvider from(List<? extends FunctionCallback> toolCallbacks) {return new StaticToolCallbackProvider(toolCallbacks);}public static ToolCallbackProvider from(FunctionCallback... toolCallbacks) {return new StaticToolCallbackProvider(toolCallbacks);}}

ToolCallbackProvider 得实现类图

在这里插入图片描述

在这里插入图片描述

打开源码 StaticToolCallbackProvider


public class StaticToolCallbackProvider implements ToolCallbackProvider {private final FunctionCallback[] toolCallbacks;// 可以使用构造器去实例化类,入参不能null 可以是空的数组public StaticToolCallbackProvider(FunctionCallback... toolCallbacks) {Assert.notNull(toolCallbacks, "ToolCallbacks must not be null");this.toolCallbacks = toolCallbacks;}public StaticToolCallbackProvider(List<? extends FunctionCallback> toolCallbacks) {Assert.noNullElements(toolCallbacks, "toolCallbacks cannot contain null elements");this.toolCallbacks = toolCallbacks.toArray(new FunctionCallback[0]);}// 必须实现父类的接口方法@Overridepublic FunctionCallback[] getToolCallbacks() {return this.toolCallbacks;}}

打开源码(MethodToolCallbackProvider)


package org.springframework.ai.tool.method;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ai.tool.ToolCallback;
import org.springframework.ai.tool.ToolCallbackProvider;
import org.springframework.ai.tool.annotation.Tool;
import org.springframework.ai.tool.definition.ToolDefinition;
import org.springframework.ai.tool.metadata.ToolMetadata;
import org.springframework.ai.tool.util.ToolUtils;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.ReflectionUtils;import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.Stream;public class MethodToolCallbackProvider implements ToolCallbackProvider {private static final Logger logger = LoggerFactory.getLogger(MethodToolCallbackProvider.class);// 我们要实例化对象的属性private final List<Object> toolObjects;//构造器私有化了 不能new去实例化对象private MethodToolCallbackProvider(List<Object> toolObjects) {Assert.notNull(toolObjects, "toolObjects cannot be null");Assert.noNullElements(toolObjects, "toolObjects cannot contain null elements");this.toolObjects = toolObjects;}//实现接口默认方法@Overridepublic ToolCallback[] getToolCallbacks() {var toolCallbacks = toolObjects.stream().map(toolObject -> Stream.of(ReflectionUtils.getDeclaredMethods(toolObject.getClass())).filter(toolMethod -> toolMethod.isAnnotationPresent(Tool.class)).filter(toolMethod -> !isFunctionalType(toolMethod)).map(toolMethod -> MethodToolCallback.builder().toolDefinition(ToolDefinition.from(toolMethod)).toolMetadata(ToolMetadata.from(toolMethod)).toolMethod(toolMethod).toolObject(toolObject).toolCallResultConverter(ToolUtils.getToolCallResultConverter(toolMethod)).build()).toArray(ToolCallback[]::new)).flatMap(Stream::of).toArray(ToolCallback[]::new);validateToolCallbacks(toolCallbacks);return toolCallbacks;}//实现类自己的私有方法private boolean isFunctionalType(Method toolMethod) {var isFunction = ClassUtils.isAssignable(toolMethod.getReturnType(), Function.class)|| ClassUtils.isAssignable(toolMethod.getReturnType(), Supplier.class)|| ClassUtils.isAssignable(toolMethod.getReturnType(), Consumer.class);if (isFunction) {logger.warn("Method {} is annotated with @Tool but returns a functional type. "+ "This is not supported and the method will be ignored.", toolMethod.getName());}return isFunction;}//实现类自己的校验方法private void validateToolCallbacks(ToolCallback[] toolCallbacks) {List<String> duplicateToolNames = ToolUtils.getDuplicateToolNames(toolCallbacks);if (!duplicateToolNames.isEmpty()) {throw new IllegalStateException("Multiple tools with the same name (%s) found in sources: %s".formatted(String.join(", ", duplicateToolNames),toolObjects.stream().map(o -> o.getClass().getName()).collect(Collectors.joining(", "))));}}
//静态方法 构建器 直接用类.builder调用(创建型模式)public static Builder builder() {//使用 new 关键字 内部实例化对象return new Builder();}
//静态内部类,私有化构造器,只能在内部被实例化public static class Builder {// 接toolObjects方法的入参private List<Object> toolObjects;private Builder() {}public Builder toolObjects(Object... toolObjects) {Assert.notNull(toolObjects, "toolObjects cannot be null");//这个是Builder 的toolObjects 对象赋值this.toolObjects = Arrays.asList(toolObjects);//返回Builder对象return this;}public MethodToolCallbackProvider build() {//返回实例化并且初始化后的 MethodToolCallbackProvider 对象return new MethodToolCallbackProvider(toolObjects);}}}

mcp-client

先看一下项目的application.properties
我用硅基流的第三方模型,这个模型deepseek-ai/DeepSeek-R1-Distill-Qwen-7B是免费试用的。你们自己看情况去选择

server.port=8082spring.ai.openai.api-key=你自己的key
spring.ai.openai.base-url=https://api.siliconflow.cn
spring.ai.openai.chat.options.model=deepseek-ai/DeepSeek-R1-Distill-Qwen-7Bspring.ai.mcp.client.sse.connections.server1.url=http://localhost:8081
spring.ai.mcp.client.sse.toolcallback.enabled=true

客户端配置启动连接服务端

package com.example.client.config;import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.tool.ToolCallbackProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class ChatClientConfig {// 自动注入回调服务工具类@Autowiredprivate ToolCallbackProvider toolCallbackProvider;/*** 配置ChatClient,注册系统指令和工具函数*/@Beanpublic ChatClient chatClient(ChatClient.Builder builder) {return builder.defaultSystem("你是一个智能AI管理员。")// 注册工具方法.defaultTools(toolCallbackProvider).build();}
}

使用对话

package com.example.client.controller;
import jakarta.annotation.Resource;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;/*** 聊天控制器,处理AI聊天请求*/
@RestController
@RequestMapping("/c3")
public class ChatController {// 依赖注入bean初始化完的实例对象@Resourceprivate ChatClient chatClient;@RequestMapping("/api/chat")public String chat(@RequestParam String message) {// 使用API调用聊天String content = chatClient.prompt("你要问什么?").user(message).call().content();System.out.println(">>> 问题: " + message);System.out.println(">>> 回答:" + content);return content;}}

打开 ChatClient

ChatClient.Builder 有个默认实现类DefaultChatClientBuilder
ChatClient 本身是接口无法实现所以有一个DefaultChatClient 默认的实现类

public ChatClient build() {return new DefaultChatClient(this.defaultRequest);}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

结语

chatClient客户端对话就比较简单了,咱们多看看源码接口提供的方法,多看几遍在看网上的事例代码就容易多了。也可以自己尝试修改一些参数。

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

相关文章:

  • 深入 Vue 核心:通信、生命周期与 API 的全面解析
  • 如何通过电路测量运放的增益带宽积(GBP)和压摆率(SR)
  • vant表单自定义校验
  • 20242817-李臻-课上测试:网络编程
  • 跟着尚硅谷学vue-day5
  • Office 2019 (含Visio+Project)官方IOS 下载
  • 【软件测试学习day5】Selenium自动化测试框架Java环境搭建
  • Shell脚本-for循环应用案例
  • OS库的常用操作
  • 用python进行OCR识别
  • etcher 刻录系统,装系统,ubuntu安装不要联网,grub tryinstall参数记得改为nomodeset
  • datax通过官网工具包,使用Python命令启动时报错
  • Python图像变清晰与锐化,调整对比度,高斯滤波除躁,卷积锐化,中值滤波钝化,神经网络变清晰
  • 多层级的对象如何修改、或json格式
  • Python实验四
  • 2025年保安员证考试题库及答案
  • 深入剖析EM算法:原理、推导与应用
  • CV大模型、NLP大模型与语音处理技术全景解析-AI学习Day5
  • 三维天地智能路径规划引擎:以算法驱动,重新定义智能路径优化技术
  • 前端面试(Vue React)内容目录与备考建议
  • NCCL通信中Group与独立操作的区别
  • OpenCv高阶(九)——背景建模
  • 每天学一个 Linux 命令(31):md5sum
  • SQL语句练习 自学SQL网 基础查询
  • 伟世通与火山引擎深度合作 前沿AI智能座舱解决方案亮相上海车展
  • playwright的简单使用
  • 信令与流程分析
  • 谷歌终止新冠疫情时期结构化数据支持:SEO影响与应对策略
  • 14-DevOps-快速部署Kubernetes
  • K8S Service 原理、案例