前言:在企业知识库助手场景下,我们经常需要让 AI 调用外部业务接口,传统 Function Call 配置繁琐。本文基于Spring AI MCP Server,快速实现一个支持查询年假余额、查询订单状态的 MCP 服务,可直接被 Claude Desktop、Cursor 等客户端调用,开箱即用、无缝对接 Java 生态。


一、MCP 是什么?优势在哪?

MCP(Model Context Protocol) 是一种标准化的 AI 工具调用协议,相比传统 Function Call 有明显优势:

表格

对比项 传统 Function Call Spring AI MCP Server
Schema 定义 手动编写 JSON Schema,代码冗余 注解自动生成,零冗余配置
调用方式 仅模型内部调用 支持 Stdio/HTTP,多客户端通用
客户端支持 仅限对接模型 Claude、Cursor、IDE 插件通用
Java 集成 需手动封装 Spring Boot 无缝集成
维护成本 高,参数变更需同步修改 Schema 低,注解驱动,自动更新

核心优势:使用@Tool/@McpTool注解定义工具,无需手写 JSON Schema,同时支持 Stdio 和 HTTP 两种传输方式。


二、场景与技术选型

1. 业务场景

延续企业知识库助手场景,提供两个业务工具:

  • getUserAnnualLeave:查询用户年假余额
  • getOrderStatus:查询订单物流状态

服务搭建完成后,Claude Desktop、Cursor 可直接调用该 MCP 服务查询企业内部数据。

2. 技术选型

  • 框架:Spring Boot 3.5.3 + Spring AI 1.0.0
  • 传输方式:Stdio(本地调用,适配 Claude/Cursor)
  • 工具定义@Tool 注解自动生成 Schema
  • 打包方式:Maven 打包可执行 Jar

注意:Spring AI 1.0 使用@Tool,2.0 已升级为@McpTool,本文以 1.0 版本为例。


三、Spring AI MCP Server 三种 Starter 对比

Spring AI 提供三种传输方式的启动器,按需选择:

表格

Starter 传输方式 适用场景
spring-ai-starter-mcp-server Stdio 本地工具,Claude/Cursor 调用
spring-ai-starter-mcp-server-webmvc Streamable HTTP 远程工具,团队共享
spring-ai-starter-mcp-server-webflux Streamable HTTP 响应式编程,高并发场景

本文使用:Stdio 模式,最简单、开箱即用


四、项目搭建全过程

1. 项目结构

plaintext

mcp-server-demo/
├── pom.xml
└── src/main/
    ├── java/com/nageoffer/ai/mcp/
    │   ├── McpServerApplication.java
    │   ├── config/
    │   │   └── McpServerConfig.java
    │   └── tools/
    │       └── EnterpriseTools.java
    └── resources/
        └── application.yml

2. Maven 依赖(pom.xml)

xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
         https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.5.3</version>
        <relativePath/>
    </parent>

    <groupId>com.nageoffer.ai</groupId>
    <artifactId>mcp-server-demo</artifactId>
    <version>1.0.0</version>
    <name>MCP Server Demo</name>
    <description>企业知识库助手 MCP Server</description>

    <properties>
        <java.version>17</java.version>
        <spring-ai.version>1.0.0</spring-ai.version>
    </properties>

    <dependencies>
        <!-- Spring AI MCP Server Starter(Stdio 传输) -->
        <dependency>
            <groupId>org.springframework.ai</groupId>
            <artifactId>spring-ai-starter-mcp-server</artifactId>
            <version>${spring-ai.version}</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

3. 业务工具实现(EnterpriseTools.java)

使用@Tool定义工具,@ToolParam定义参数,框架自动生成 JSON Schema

java

运行

package com.nageoffer.ai.mcp.tools;

import org.springframework.ai.tool.annotation.Tool;
import org.springframework.ai.tool.annotation.ToolParam;
import org.springframework.stereotype.Service;

/**
 * 企业知识库助手工具集
 * 每个@Tool方法自动注册为MCP工具
 */
@Service
public class EnterpriseTools {

    /**
     * 查询用户年假余额
     */
    @Tool(description = "查询用户的年假余额,包括总天数、已使用天数、剩余天数。当用户询问年假、假期余额、还有多少天假等问题时使用此工具。")
    public String getUserAnnualLeave(
            @ToolParam(description = "用户 ID,例如 user_12345") String userId) {

        // 实际项目对接HR系统API
        return String.format("""
                {
                    "userId": "%s",
                    "remainingDays": 5,
                    "totalDays": 10,
                    "usedDays": 5,
                    "year": 2026
                }
                """, userId);
    }

    /**
     * 查询订单状态
     */
    @Tool(description = "查询订单的物流状态和详细信息。当用户询问订单状态、物流进度、快递到哪了等问题时使用此工具。")
    public String getOrderStatus(
            @ToolParam(description = "订单号,例如 ORD-12345") String orderId) {

        // 实际项目对接订单系统API
        return String.format("""
                {
                    "orderId": "%s",
                    "status": "运输中",
                    "location": "北京市朝阳区分拨中心",
                    "estimatedDelivery": "2026-03-01",
                    "carrier": "顺丰速运",
                    "trackingNumber": "SF1234567890"
                }
                """, orderId);
    }
}

4. MCP 工具注册配置(McpServerConfig.java)

java

运行

package com.nageoffer.ai.mcp.config;

import com.nageoffer.ai.mcp.tools.EnterpriseTools;
import org.springframework.ai.tool.ToolCallbackProvider;
import org.springframework.ai.tool.method.MethodToolCallbackProvider;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class McpServerConfig {

    /**
     * 自动扫描@Tool方法并注册为MCP工具
     */
    @Bean
    public ToolCallbackProvider enterpriseToolProvider(EnterpriseTools enterpriseTools) {
        return MethodToolCallbackProvider.builder()
                .toolObjects(enterpriseTools)
                .build();
    }
}

5. 核心配置文件(application.yml)

⚠️ 关键注意点:Stdio 模式下,禁止输出 banner 和多余日志,否则会导致通信失败!

yaml

spring:
  ai:
    mcp:
      server:
        name: enterprise-assistant
        version: 1.0.0
        type: SYNC
  main:
    web-application-type: none
    banner-mode: off

logging:
  file:
    name: ./logs/mcp-server.log
  level:
    root: OFF

6. 启动类

java

运行

package com.nageoffer.ai.mcp;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class McpServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(McpServerApplication.class, args);
    }
}

五、项目打包与运行

1. Maven 打包

bash

运行

mvn clean package -DskipTests

打包完成后在target目录生成:mcp-server-demo-1.0.0.jar

2. 启动服务

bash

运行

java -jar mcp-server-demo-1.0.0.jar

启动无日志输出即为正常(Stdio 模式静默运行)。


六、客户端调用说明

1. 支持客户端

  • Claude Desktop
  • Cursor IDE
  • 其他支持 MCP 协议的 AI 客户端

2. 调用示例

  • 问:user_10086的年假还剩多少天?
  • AI 自动调用getUserAnnualLeave,返回:

json

{
    "userId": "user_10086",
    "remainingDays": 5,
    "totalDays": 10,
    "usedDays": 5,
    "year": 2026
}
  • 问:ORD-8888的订单状态是什么?
  • AI 自动调用getOrderStatus,返回物流信息。

七、常见坑点总结

  1. Stdio 模式通信异常
    • 原因:Spring Banner、日志输出到 stdout
    • 解决:配置banner-mode: off + root日志级别OFF
  2. 工具未被识别
    • 原因:@Tool未被MethodToolCallbackProvider扫描
    • 解决:确保工具类被 Spring 管理(@Service/@Component
  3. 参数解析失败
    • 解决:必须使用@ToolParam标注参数说明

八、总结

  1. Spring AI MCP Server 极大简化了 AI 工具调用开发,注解驱动、零 Schema 手写
  2. 支持 Stdio / HTTP 两种传输模式,适配本地 / 远程调用场景
  3. 完美对接 Claude、Cursor 等主流 AI 客户端,企业级场景落地成本极低
  4. Java 生态无缝集成,可直接对接现有 HR、订单、物流等内部系统
Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐