使用 Spring AI 构建 MCP Server完整指南:以Cloudflare R2存储为例

1,106 阅读8分钟

大家好,今天分享的内容是关于如何使用 Spring Boot AI 构建 MCP Server。接下来我会一步步介绍开发 MCP Server的流程,以及对关键概念的解释,并通过一个实际案例(基于Spring Boot和Spring AI的Cloudflare R2对象存储MCP Server)进行演示,最后展示如何使用 Cursor IDE进行测试与集成。

如何使用 Spring Boot 构建 MCP 服务器

使用 Spring Boot AI 构建 MCP 服务器需要以下几个关键步骤。请依次按照以下步骤进行操作:

  1. 添加依赖
    在项目的 pom.xml 文件中,添加 Spring Boot Web 启动器和 MCP 服务器依赖项。这些依赖项为构建 MCP 服务器提供了必要的 Web 功能支持。
  2. 使用 @Tool 注解定义功能
    通过在方法上添加 @Tool 注解,暴露服务器的功能接口。
  3. 通过 ToolCallbackProvider 注册工具
    创建一个配置类,使用 ToolCallbackProvider 将包含 @Tool 注解的方法类对象注册到 MCP 框架中。这一步骤确保您的工具方法能够被 MCP 服务器发现并调用。
  4. 配置 MCP 服务器
    application.properties 文件中定义服务器相关设置,例如服务器名称、版本、日志信息等。

关键概念:@Tool 注解与 ToolCallbackProvider

在了解了构建 MCP 服务器的基本步骤后,接下来,我们首先探讨以下两个关键概念:

@Tool 注解

这个注解是用于标记 MCP 服务器中可暴露的方法,相当于声明:“此方法执行一个特定的可调用操作。”它通常附带描述信息,以便客户端应用(如 Claude、Cursor 桌面应用)能够了解该方法的功能。

它不仅将方法暴露为可调用工具,还提供描述性文本,用于说明该方法的具体作用。Tool Description的写法类似于prompt,重点是清楚的描述这个Tool标注的方法让MCP HOST知道如何使用,这对于客户端展示可用工具时非常有用。 以下是一个Tool Description的示例:

可以看到该描述中详细说明了上传对象支持的类型以及对应的方法参数。

ToolCallbackProvider

ToolCallbackProvider 是一个工具方法注册机制,负责将您的工具方法与 MCP 框架关联起来。

功能: 它会扫描提供的类对象,查找带有 @Tool 注解的方法,并将这些方法设置为可接收请求的状态。这一机制是确保 MCP 服务器能够在收到命令时定位并执行相应工具的关键步骤。

案例:Cloudflare R2 MCP Server

在这个案例中,我将展示如何构建一个与 Cloudflare R2对象存储 集成的 MCP Server

src/main/java/com/lskun/mcp/
├── SpringBootAiCloudflareR2McpServerApplication.java (应用程序入口)
├── config/
│   └── McpConfiguration.java (MCP配置类)
└── service/
    └── R2ServiceClient.java (R2服务客户端)

这个MCP Server主要提供了以下功能实现:

  • listBuckets: 列出Cloudflare R2中的所有存储桶
  • createBucket: 在Cloudflare R2中创建新的存储桶
  • deleteBucket: 从Cloudflare R2中删除存储桶
  • listObjects: 列出存储桶中的对象
  • uploadObject: 将对象上传到存储桶
  • downloadObject: 从存储桶下载对象
  • deleteObject: 从存储桶删除对象
  • getObjectMetadata: 获取对象元数据

接下来,我将通过以下几个步骤展示完整的MCP Server开发流程

步骤 1:添加必要的 Maven 依赖项

这个项目主要的依赖项包括Spring boot、Spring AI、AWS S3 SDK for Cloudflare R2以及mcp sdk; 我们依次在 pom.xml 文件中添加以下依赖项(完整的pom文件见文末发布的github项目地址):

<dependencies>
    <dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter</artifactId>
 </dependency>
 <dependency>
  <groupId>org.springframework.ai</groupId>
  <artifactId>spring-ai-mcp-server-spring-boot-starter</artifactId>
 </dependency>
 <!-- AWS S3 SDK for Cloudflare R2 -->
 <dependency>
  <groupId>software.amazon.awssdk</groupId>
  <artifactId>s3</artifactId>
 </dependency>
</dependencies>

依赖项说明:

  • Spring Boot Starter:提供嵌入式服务器等基本功能。
  • Spring AI MCP Server Starter:将 MCP 框架与 Spring Boot 应用集成,使得暴露的工具方法能够被发现和调用。

步骤 2:定义服务客户端

服务客户端负责连接 Cloudflare R2,并包含通过 AWS S3 SDK集成进行操作的一系列方法,这些方法都使用 @Tool 注解来描述功能并将其暴露为可调用函数。

由于代码比较长,在这里给出了部分的代码示例(R2ServiceClient的初始化以及列出所有R2 存储桶的Tool调用实现):

@Service
public class R2ServiceClient {

    private static final Logger logger = LoggerFactory.getLogger(R2ServiceClient.class);
    private final S3Client s3Client;

    /**
     * Initializes the Cloudflare R2 client with the given credentials and endpoint.
     */
    public R2ServiceClient(
            @Value("${r2.access-key-id}") String accessKeyId,
            @Value("${r2.secret-access-key}") String secretAccessKey,
            @Value("${r2.endpoint}") String endpoint) {
        logger.info("Initializing R2ServiceClient with endpoint: {}", endpoint);
        
        // 创建HTTP客户端,设置更长的超时时间
        SdkHttpClient httpClient = ApacheHttpClient.builder()
                .connectionTimeout(Duration.ofSeconds(30))
                .socketTimeout(Duration.ofSeconds(120))
                .build();
        
        // 创建最简单的S3客户端配置
        this.s3Client = S3Client.builder()
                .credentialsProvider(StaticCredentialsProvider.create(
                        AwsBasicCredentials.create(accessKeyId, secretAccessKey)))
                .endpointOverride(URI.create(endpoint))
                .region(Region.of("auto"))
                .serviceConfiguration(S3Configuration.builder()
                        .checksumValidationEnabled(false)
                        .pathStyleAccessEnabled(true)
                        .build())
                .httpClient(httpClient)
                .build();
                
        logger.info("R2ServiceClient initialized successfully");
    }

    /**
     * Lists all buckets in Cloudflare R2.
     */
    @Tool(description = """
    List all buckets in Cloudflare R2.
    """)
    public List<StringlistBuckets() {
        logger.info("Fetching list of buckets.");
        try {
            List<StringbucketNames = new ArrayList<>();
            ListBucketsResponse response = s3Client.listBuckets();
            for (Bucket bucket : response.buckets()) {
                bucketNames.add(bucket.name());
            }
            logger.info("Buckets found: {}", bucketNames);
            return bucketNames;
        } catch (S3Exception e) {
            logger.error("Failed to list buckets: {}", e.getMessage(), e);
            throw new RuntimeException("Failed to list buckets: " + e.getMessage(), e);
        }
    }

这些方法支持对 Cloudflare R2 进行全方位的存储相关操作。

步骤 3:配置 MCP 服务器

在配置类中,设置一个 Bean 以注册 Cloudflare 服务的回调提供者:

@Configuration
public class McpConfiguration {

    @Bean
    public ToolCallbackProvider r2Tools(R2ServiceClient r2ServiceClient) {
        return MethodToolCallbackProvider.builder().toolObjects(r2ServiceClient).build();
    }
}

说明:

  • 该配置创建了一个 Bean,将 R2ServiceClient 中所有带有 @Tool 注解的方法注册到 MCP 框架中。
  • MethodToolCallbackProviderToolCallbackProvider 的具体实现,负责将服务客户端与 MCP 请求处理关联起来。

步骤 4:添加应用属性

application.properties 文件中添加以下属性:

spring.application.name=spring-boot-ai-cloudflare-r2-mcp-server

spring.main.banner-mode=off
spring.main.web-application-type=none
logging.file.name=./logs/spring-boot-ai-cloudflare-r2-mcp-server.log
logging.pattern.console=

spring.ai.mcp.server.name=cloudflare-r2-mcp-server
spring.ai.mcp.server.version=0.0.1

# Cloudflare R2 configuration
r2.access-key-id=${R2_ACCESS_KEY_ID}
r2.secret-access-key=${R2_SECRET_ACCESS_KEY}
r2.endpoint=${R2_ENDPOINT}

各属性作用:

  • spring.ai.mcp.server.name/version:定义 MCP 服务器的名称和版本。
  • r2.access-key-id/secret-access-key/endpoint:提供连接 Cloudflare R2 所需的凭据和端点。

R2存储相关秘钥的获取方式:

  • 创建之后,便可获取到对应的access-key-id、secret-access-key以及endpoint。

步骤 5:构建并准备 MCP 服务器

完成开发后,执行 Maven clean install 命令,确保构建稳定并生成 JAR 文件,以便与 Cursor IDE 集成。

步骤 6:与 Cursor 桌面应用集成与测试

按照以下步骤验证 Confluence MCP 服务器是否正常工作:

  1. 更新cursor settings中 mcp.json 中的配置:

在配置文件mcp.json文件中添加以下内容:

这里可以通过指定-Dspring.ai.mcp.server.transport的方式选择STDIO和SSE两种通信模式;

注意:args 部分,将 <complete-path-to-cloudflare-r2-mcp-jar-file>.jar 替换为 JAR 文件的完整路径(例如 /home/user/cloudflare-r2-mcp-server.jar)。

  1. reload Cursor IDE的并验证 MCP 服务器状态:

更新配置后,点击MCP配置面板中的reload按钮,看到cloudflare-r2-mcp-server左侧显示绿色,则说明MCP 服务器运行正常。

同时在output中选择cursor-mcp可以看到对应的启动和加载日志:

  1. 使用不同提示进行测试:
    在 Cursor IDE中发送提示,验证与 Cloudflare R2 MCP 服务器的集成效果。提示将调用服务器上的 @Tool 方法,并显示返回结果。

    以下是几个我操作的运行示例:

从r2 bucket下载到本地

从r2 bucket下载到本地

上传对象到对应的存储桶

上传对象到对应的存储桶

6. 源代码

完整示例代码可在 GitHub 上查看:

7. 注意事项

如果你接触MCP时间不久并且自己想动手开发一个mcp server,以下是我总结的一些实用建议以及常见的问题总结:

  • 配置管理: 使用环境变量或外部配置服务安全存储敏感信息(如 API 令牌、数据库 URI),避免将敏感数据硬编码到源码中。例如,您可以将 API 令牌存储在环境变量中,这样即使源码泄露,敏感信息也不会暴露。
  • 错误处理: 良好的错误处理机制可以让 MCP 服务器在遇到问题时仍然正常运行。
  • 日志与监控: 实现全面的日志记录,追踪服务器操作,便于调试。
  • 测试: 使用 MCP 客户端或 Claude、Cursor 桌面应用等工具测试服务器,模拟真实交互场景。
  • 安全最佳实践: 实施适当的身份验证和授权机制,验证工具方法的输入,防止注入攻击,确保数据安全。
  • 文档与可读性: 清晰记录每个暴露工具及其功能,规范的 @Tool 注解和代码组织有助于开发人员快速理解系统。
  • 版本与维护: 谨慎管理 MCP 服务器组件的版本更新,尽可能确保向下兼容,并维护清晰的版本文档,便于未来维护。

8. 常见问题解答

问:MCP 服务器中 @Tool 注解的作用是什么?
答: @Tool 注解用于将特定方法标记为 MCP 服务器中的可调用工具。它不仅让方法能被外部调用,还提供一个易懂的描述,帮助像 Claude 桌面应用这样的客户端了解可用功能。

问:为什么 ToolCallbackProvider 在构建 MCP 服务器中很重要?
答: ToolCallbackProvider 将包含 @Tool 方法的类对象注册到 MCP 框架中。这一注册过程至关重要,因为它使 MCP 服务器能够自动检测并将请求路由到相应的工具方法。

问:如何管理 MCP 服务器中的敏感配置信息?
答: 建议使用环境变量或安全的外部配置服务来管理 API 令牌、数据库 URI 和认证凭据等敏感信息,避免将其硬编码到源码中,以提升安全性。

问:是否可以扩展 MCP 服务器以支持更多功能?
答: 可以,MCP 服务器的模块化设计使其易于扩展。只需在服务客户端中添加新的 @Tool 注解方法,通过 ToolCallbackProvider 注册,并根据需要更新配置即可适应新的用例和业务逻辑。

写在最后

总体上看,使用 Spring Boot AI 开发、构建 MCP 服务器是一种集成和扩展应用功能的简便方法。通过上面分享的cloudflare-r2-mcp-server示例,展示了如何将服务转化为可调用工具,并与 Cursor IDE无缝测试。当你清晰的了解了上述所有的构建流程后,你就可以根据项目需求,自由创新和定制化 MCP Server解决方案,这会帮助你极大地扩展应用功能。好了,今天的分享就到这里,有问题的话可以在下方评论区一起讨论、交流。