Spring-AI 结合自定义 mcp server 实现飞书智能机器人

1. 简介

本文主要介绍基于 spring ai 自定义搭建 mcp 服务端和客户端,主要场景是:

基于本地的mcp服务让飞书机器人跟场景回答不同的问题

实现效果如下

最后附了源码链接.整体代码非常简单,容易上手。

2.概念

2.1 什么是 AI MCP?

MCP(Model Context Protocol) 是一种 ​标准化协议​,用来解决一个长期痛点:

👉 如何让 AI"安全、可控、标准化地"调用外部工具 / 系统能力?

它的核心目标不是"让 AI 更聪明",而是:

  • AI 能调用真实系统
  • 同时 避免 AI 乱编、乱连、乱访问
  • 并且 工具接入方式统一

2.2 MCP 解决了什么问题?

1️⃣ 传统 Function Call 的问题

以 OpenAI Function Calling / Tool Calling 为例:

  • 工具定义写死在 Prompt 或代码里
  • 每个 AI 框架一套接口
  • 权限 / 生命周期 / 连接管理全靠业务自己写
  • 工具多了以后 极难维护

👉 在真实系统里会变成:

  • Prompt 很长
  • Tool 定义重复
  • 不同 AI 模型不可复用

2️⃣ MCP 的解决思路

MCP 把 ​工具变成一个标准化的 Server​:

arduino 复制代码
AI Model
   |
   |  MCP 协议
   |
MCP Client  ────── MCP Server
                   ├─ 查数据库
                   ├─ 调内部系统
                   ├─ 查文件
                   ├─ 调 HTTP API

AI ​不直接接触工具实现​,只通过 MCP 协议:

  • 发现工具
  • 调用工具
  • 获取结构化结果

3. 工程结构

主要分为2个模块,mcp-servermcp-client, mcp-client里面通过 java -jar 的形式运行 mcp 服务端,在 mcp-client 最终结合 AI 以及飞书机器人的集成实现消息的回复.

4. 相关源码介绍

4.1 mcp 服务端

服务端非常简单,例如保留一个天气的服务,只需要在方法上加入org.springframework.ai.tool.annotation.Tool; 注解即可

java 复制代码
import io.kings1990.mcp.mcpserver.enums.WeatherType;
import io.kings1990.mcp.mcpserver.record.WeatherRequest;
import io.kings1990.mcp.mcpserver.record.WeatherResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.tool.annotation.Tool;
import org.springframework.ai.tool.annotation.ToolParam;
import org.springframework.stereotype.Service;

@Service
@Slf4j
public class WeatherService {


    @Tool(name = "getWeather", description = "查询指定城市的天气")
    public WeatherResult getWeather(@ToolParam(description = "请求参数") WeatherRequest req) {
        log.info("MCP Tool getWeather called, city={}", req.city());
        return new WeatherResult(
                req.city(),
                WeatherType.SUNNY,
                "25°C",
                "°C",
                "mcp:getWeather"
        );
    }
}

4.2 mcp客户端

4.2.1让 AI 集成 ToolCallbacks

java 复制代码
@Configuration
public class AiConfig {

    @Bean
    public ChatClient chatClient(ChatClient.Builder builder, List<McpSyncClient> mcpSyncClients) {
        return builder
                .defaultSystem("你是一个AI助手,必须调用工具 kings-spring-ai-mcp-tools 下的方法,如果工具不可用,就明确说明无法调用工具,不要编造。")
                .defaultToolCallbacks(
                        SyncMcpToolCallbackProvider.builder()
                                .mcpClients(mcpSyncClients)
                                .build()
                )
                .build();
    }
}

4.2.2基于飞书机器人的长链接集成,实现消息的自动回复

java 复制代码
import cn.hutool.core.thread.ThreadUtil;
import com.lark.oapi.event.EventDispatcher;
import com.lark.oapi.service.im.ImService;
import com.lark.oapi.service.im.v1.model.P2MessageReceiveV1;
import com.lark.oapi.ws.Client;
import jakarta.annotation.Resource;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;

@Component
public class LarkWsListener implements CommandLineRunner, DisposableBean {

    @Resource
    private LarkBotService botService;

    @Resource
    private Client.Builder larkWsBuilder;

    @Override
    public void run(String... args) {
        //verificationToken和 encryptionKey 可选,用于验证和解密事件
        EventDispatcher handler = EventDispatcher.newBuilder("", "")
                .onP2MessageReceiveV1(new ImService.P2MessageReceiveV1Handler() {
                    @Override
                    public void handle(P2MessageReceiveV1 event) throws Exception {

                        // 1) messageId 用于 reply
                        String messageId = event.getEvent().getMessage().getMessageId();

                        // 2) content 是 JSON 字符串,需要解析出文本
                        String contentJson = event.getEvent().getMessage().getContent();

                        System.err.println("收到消息: " + contentJson);

                        String userText = LarkMsgParser.extractText(contentJson);

                        ThreadUtil.execAsync(() -> {
                            botService.onUserMessage(messageId, userText);
                        });

                    }
                })
                .build();

        // 建议把 appId/appSecret 放配置文件
        Client wsClient = larkWsBuilder.eventHandler(handler).build();

        wsClient.start();
    }


    @Override
    public void destroy() throws Exception {

    }
}

4.2.3 AI Api-Key 植入

我这边使用 zhipu ai. 这边可以获取api-key.

加入依赖

xml 复制代码
<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-starter-model-zhipuai</artifactId>
</dependency>

并且在配置中配置 api-key

xml 复制代码
spring:
  ai:
    zhipuai:
      api-key: your_api_key_here
      chat:
        options:
          model: glm-4.6

5.启动

直接运行mcp-client 主程序,查看飞书机器人是否注册成功

arduino 复制代码
connected to wss://msg-frontier.feishu.cn/

启动成功后在飞书应用里输入例如北京,等待机器人回复

6.源码

github 仓库. 可以 star 查看后续更新


Fast Request是一个类似于 Postman 的 IDEA 插件。它是一个强大的 restful api 工具包插件,可以根据已有的方法帮助您快速生成 url 和 params。 Restful Fast Request = API调试工具 + API管理工具 + API搜索工具。 它有一个漂亮的界面来完成请求、检查服务器响应、存储你的 api 请求和导出 api 请求。插件帮助你在 IDEA 界面内更快更高效得调试你的 API

相关推荐
KEEN的创享空间4 小时前
AI编程从0到1之10X提效(Vibe Coding 氛围式编码 )09篇
openai·ai编程
初次攀爬者4 小时前
RocketMQ在Spring Boot上的基础使用
java·spring boot·rocketmq
花花无缺5 小时前
搞懂@Autowired 与@Resuorce
java·spring boot·后端
AlienZHOU5 小时前
为 AI Agent 编写高质量 Skill:Claude 官方指南
agent·ai编程·claude
恋猫de小郭5 小时前
移动端开发稳了?AI 目前还无法取代客户端开发,小红书的论文告诉你数据
前端·flutter·ai编程
Derek_Smart6 小时前
从一次 OOM 事故说起:打造生产级的 JVM 健康检查组件
java·jvm·spring boot
KaneLogger6 小时前
【翻译】打造 Agent Skills 的最佳实践
agent·ai编程·claude
王小酱7 小时前
Everything Claude Code 文档
openai·ai编程·aiops
雮尘8 小时前
如何在非 Claude IDE (TARE、 Cursor、Antigravity 等)下使用 Agent Skills
前端·agent·ai编程
刘贺同学8 小时前
Day12-龙虾哥打工日记:OpenClaw 子 Agent 到底看到了什么?
aigc·ai编程