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-server 和 mcp-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

相关推荐
小和尚同志6 小时前
1.8k star 的开源 token 使用量监控神器— TokenTracker
人工智能·ai编程
光依旧7 小时前
MCP实战手记系列(十):MCP Server高可用实战
spring boot·高可用·nginx负载均衡·redis哨兵·mcp·微服务容错·resilience4j熔断
Setsuna_F_Seiei8 小时前
前端转型 Agent 开发 06 之 Agent Memory 记忆系统(让 Agent 更智能,更懂你)
前端·agent·ai编程
孟健10 小时前
Qwen3.8-27B 本地推理实测:从 14 tok/s 到 159 tok/s 的投机解码调优
人工智能·llm·ai编程
省钱兄--zs10 小时前
西安24小时自助健身房解决方案实战:系统开发与部署全流程指南
java·spring boot·系统架构·intellij-idea·需求分析
ly768913 小时前
Spring Boot 集成 Elasticsearch 的生产实践:客户端选型、索引生命周期与批量写入容错
spring boot·elasticsearch·索引生命周期·java api client·批量写入
程序猿_极客13 小时前
【免费】分享一套优质的基于SpringBoot的服装商城管理系统的设计与实现(带可视化图表、协同过滤功能),源码+文档+视频详解(讲解)
java·spring boot·后端·服装商城管理系统
bug菌14 小时前
🤔同事突然问我:Spring的注解 @Component 和 @Service 有何不同?
java·spring boot·后端
全栈弄潮儿14 小时前
30 天总结:从“会用 AI”到“拥有 AI 开发系统”
aigc·openai·ai编程
Lonely丶墨轩14 小时前
用 Vue + Spring Boot + Python 做一个 AI 双人海龟汤游戏:从出题、联机到自动审稿等核心技术设计与实现
spring boot·后端·游戏