MCP多服务器客户端(Spring Boot)
Spring Boot 3服务,连接并协调多个模型上下文协议(MCP)服务器。它公开了一个安全的REST API,用于注册MCP服务器、发现工具和资源、同步或通过后台作业调用工具以及监控总体运行状况。
特性
- 管理多个MCP服务器的整个生命周期(注册、启动时自动重新连接、注销)。
- 从每台服务器中发现工具和资源,并将元数据持久化到SQL server中。
- 直接调用工具或将Spring支持的异步作业排队
@Async执行。 - 基于JWT的身份验证,包括用户注册和登录端点。
- 全局速率限制(50个请求/分钟)和集中异常处理。
- 执行器健康检查加上自定义MCP健康指示器、Prometheus抓取和结构化日志记录。
- 用于探索API的交互式OpenAPI/Swagger UI。
技术栈
- Java 21,Spring Boot 3.5.7
- Spring Web、Spring验证、Spring数据JPA、Spring安全
- Microsoft SQL Server(通过
mssql-jdbc) - Jackson用于JSON-RPC处理,JJWT用于令牌,Bucket4j用于速率限制
- springdoc openapi,千分尺+普罗米修斯注册表
项目结构
src/main/java/com/mcp/client/ClientApplication.java:应用程序入口点(@SpringBootApplication,@EnableAsync).config/:安全(SecurityConfig)以及OpenAPI元数据。controller/:/api/auth和/api/mcpREST端点。service/:McpClientService(编排、持久性)和McpServerConnection(JSON-RPC桥)。entity/和repository/:服务器、工具、资源、作业和用户的JPA实体。security/:JWT生成/验证和UserDetailsService适配器。filter/RateLimitFilter:Bucket4j servlet过滤器将流量限制为每分钟50个请求。monitoring/McpServersHealthIndicator:为执行器运行状况贡献连接/总服务器计数。model/:JSON-RPC模型和DTO(ServerConfig,ToolCallRequest等等)。
client/
|-- README.md
|-- pom.xml
|-- mvnw
|-- mvnw.cmd
|-- .mvn/
| |-- wrapper/
| |-- maven-wrapper.jar
| |-- maven-wrapper.properties
|-- src/
| |-- main/
| | |-- java/
| | | |-- com/mcp/client/
| | | |-- ClientApplication.java
| | | |-- config/
| | | | |-- OpenApiConfig.java
| | | | |-- SecurityConfig.java
| | | |-- controller/
| | | | |-- AuthController.java
| | | | |-- McpController.java
| | | |-- entity/
| | | | |-- ResourceEntity.java
| | | | |-- ServerEntity.java
| | | | |-- ToolEntity.java
| | | | |-- ToolJobEntity.java
| | | | |-- UserEntity.java
| | | |-- exception/
| | | | |-- GlobalExceptionHandler.java
| | | |-- filter/
| | | | |-- RateLimitFilter.java
| | | |-- monitoring/
| | | | |-- McpServersHealthIndicator.java
| | | |-- model/
| | | | |-- InitializeRequest.java
| | | | |-- JsonRpcRequest.java
| | | | |-- JsonRpcResponse.java
| | | | |-- McpResource.java
| | | | |-- McpTool.java
| | | | |-- ServerConfig.java
| | | | |-- ToolCallRequest.java
| | | |-- repository/
| | | | |-- ResourceRepository.java
| | | | |-- ServerRepository.java
| | | | |-- ToolJobRepository.java
| | | | |-- ToolRepository.java
| | | | |-- UserRepository.java
| | | |-- security/
| | | | |-- CustomUserDetailsService.java
| | | | |-- JwtAuthFilter.java
| | | | |-- JwtService.java
| | | |-- service/
| | | |-- McpClientService.java
| | | |-- McpServerConnection.java
| | |-- resources/
| | |-- application.yml
| | |-- application.properties
| | |-- static/
| | |-- templates/
| |-- test/
| |-- java/
| |-- com/mcp/client/
| |-- ClientApplicationTests.java
|-- target/ (build output)先决条件
- JDK 21
- Maven 3.9+(或使用捆绑的
mvnw.cmd/mvnw包装) - Microsoft SQL Server 2019+(或Azure SQL),数据库名为
mcp_client - Node.js 18+和npm(仅当您想通过以下方式运行示例MCP服务器时才需要
npx)
配置
src/main/resources/application.yml 阅读自 .env 因此,您可以在不接触已提交的配置的情况下调整设置。提供以下值:
SERVER_PORTDB_URL,DB_USERNAME,DB_PASSWORDMCP_CLIENT_NAME,MCP_CLIENT_VERSIONJWT_SECRET,JWT_EXPIRATION_MINUTES
JPA配置了 ddl-auto: update 用于开发,Swagger UI保持公开 /swagger-ui.html执行器表面显示健康状况、指标和Prometheus,从盒子中抓取端点。如果缺少任何属性,Spring将很快失败,因此请确保您的 .env (或环境)包含上述整套。
通过环境变量或JVM参数覆盖任何属性,例如:
mvnw.cmd spring-boot:run ^
-Dspring-boot.run.jvmArguments="
-Dspring.datasource.url=jdbc:sqlserver://localhost:1433;database=mcp_client;encrypt=false
-Dspring.datasource.username=sa
-Dspring.datasource.password=ChangeMe!"安全说明: 替换默认数据源密码和JWT签名密钥(JwtService)在部署到本地开发之外之前。构建并运行
# Windows
mvnw.cmd clean package
mvnw.cmd spring-boot:run
# macOS/Linux
./mvnw clean package
./mvnw spring-boot:run服务正在监听 http://localhost:8080。要运行包装好的罐子:
java -jar target/client-0.0.1-SNAPSHOT.jar运行示例MCP服务器
使用官方MCP示例服务器来练习API:
npx -y @modelcontextprotocol/server-memory
npx -y @modelcontextprotocol/server-filesystem ./sandbox
npx -y @modelcontextprotocol/server-time使用启动命令注册每个服务器,以便客户端可以生成和管理进程。
身份验证工作流
- 注册用户(开放端点)
curl -X POST http://localhost:8080/api/auth/register \
-H "Content-Type: application/json" \
-d '{"username":"admin","password":"StrongPass!","role":"ADMIN"}'- 登录并获取JWT
curl -X POST "http://localhost:8080/api/auth/login?username=admin&password=StrongPass!"响应包含 token, username,以及 role.
- 使用令牌调用受保护的端点
curl http://localhost:8080/api/mcp/servers \
-H "Authorization: Bearer "端点位于 /api/auth/**, /swagger-ui/**,以及 /v3/api-docs/** 公开;其他一切都需要有效的Bearer令牌。
关键REST端点
| 方法 | 路径 | 描述 |
|---|---|---|
| 职位 | /api/mcp/servers | 注册并连接到新的MCP服务器(接受 ServerConfig). |
| 得到 | /api/mcp/servers | 列出已注册的服务器及其连接状态。 |
| 得到 | /api/mcp/servers/{serverId}/status | 检查服务器连接是否处于活动状态。 |
| 删除 | /api/mcp/servers/{serverId} | 优雅地断开并注销服务器。 |
| 得到 | /api/mcp/servers/{serverId}/tools | 从服务器获取实时工具定义;结果将同步到数据库。 |
| 得到 | /api/mcp/tools | 列出所有连接服务器上聚合的工具。 |
| 职位 | /api/mcp/servers/{serverId}/tools/call | 使用提供的参数立即调用工具。 |
| 职位 | /api/mcp/servers/{serverId}/tools/jobs | 将后台工具调用排队(持久化在 tool_jobs). |
| 得到 | /api/mcp/jobs/{id} | 检索作业状态和存储的工具输出。 |
| 得到 | /api/mcp/resources | 聚合所有服务器上的资源(也持久化)。 |
| 职位 | /api/mcp/refresh | 刷新每台服务器的工具和资源缓存。 |
| 得到 | /api/mcp/health | 轻量级运行状况摘要(总服务器与连接服务器)。 |
| 得到 | /swagger-ui.html | 交互式OpenAPI文档。 |
| 得到 | /actuator/health, /actuator/prometheus | 弹簧靴执行器端点(普罗米修斯需要千分尺刮擦)。 |
ToolJobEntity 记录自动从 PENDING -> RUNNING -> SUCCESS/FAILED 当异步执行器处理它们时。响应包括存储的JSON输出或错误有效载荷。
持久性和自动重启行为
- 服务器、工具、资源、作业和用户存储在SQL Server表中(
server_registry,mcp_tools,mcp_resources,tool_jobs,users).表是自动创建的(ddl-auto: update). - 在应用程序启动时,
McpClientService.restoreServers()重新连接到每个持久服务器,这样工具/资源发现就可以在没有人工干预的情况下继续进行。 - 工具/资源发现会擦除并重新填充每台服务器的缓存数据库条目,以保持元数据同步。
- 后台工作(
executeToolJob)异步运行,以便在处理长时间运行的工具调用时立即返回HTTP响应。
监控和操作
- 速率限制:
RateLimitFilter将全球所有请求限制在每分钟50个。调整Bucket4j配置以调整限制。 - 执行器健康状况:
/actuator/health包括MCP的具体细节McpServersHealthIndicator(连接数/总计数)。 - 韵律学:
/actuator/prometheus发布可用于普罗米修斯抓取的千分尺指标。 - 登录中: SLF4J+Logback,在中配置了包级覆盖
application.yml.
测试
mvnw.cmd test默认测试套件包括Spring上下文冒烟测试。在扩展应用程序时添加控制器/服务集成测试。
实用命令
- 健康探头:
curl http://localhost:8080/api/mcp/health - 注册示例服务器:
curl -X POST http://localhost:8080/api/mcp/servers \
-H "Authorization: Bearer " \
-H "Content-Type: application/json" \
-d '{ "id": "memory-server", "command": "npx", "args": ["-y","@modelcontextprotocol/server-memory"] }'- 列出服务器的缓存工具:
curl -H "Authorization: Bearer " "http://localhost:8080/api/mcp/tools/db?serverId=memory-server"
后续步骤
- 将敏感机密(数据源密码、JWT密钥)外部化到vault或环境变量中。
- 强化身份验证(延长令牌到期时间、刷新令牌、审计)。
- 通过测试容器添加对实时MCP服务器(内存/时间/文件系统)进行测试的集成测试。
- 使用Docker或Kubernetes清单打包服务以进行部署。
许可证
MIT许可证
