Skip to content

DDK MCP Starter ​

把应用用例暴露为 MCP(Model Context Protocol) 工具,AI 代理可以像浏览器调用 REST 接口一样调用业务能力。MCP server 与 @McpTool 的发现来自 Spring AI 2.0,本 starter 只补 DDD 服务需要的约定。

text
AI 代理 ──MCP──► adapter.mcp.*Tools ──► 应用服务 ──► 领域
                     │
                     └─ DDK:参数校验 · 业务异常转错误码 · 隐藏内部细节 · 审计日志

能做什么 ​

能力说明
默认 streamable HTTPSpring AI 未配置 spring.ai.mcp.server.protocol 时启用已被 MCP 规范弃用的 SSE 传输;DDK 以最低优先级设为 STREAMABLE,任何配置源里显式设置都会覆盖
参数校验@McpTool 参数上的 Bean Validation 注解在工具执行前校验,不需要在类上标 @Validated。失败返回 VALIDATION_ERROR: username: size must be between 4 and 20
错误码BusinessException、SystemException 转为以错误码开头的工具错误,如 USERNAME_TAKEN: 用户名已被占用:alice,模型可以据此判断是否换个参数重试
不泄露内部细节其他异常统一返回 SYSTEM_ERROR: 服务器内部错误,原始消息与堆栈只写日志
审计日志每次调用一行:MCP tool [get_user] -> USER_NOT_FOUND in 3 ms。出于隐私考虑不记录参数值

引入方式 ​

xml
<dependency>
    <groupId>com.ddk</groupId>
    <artifactId>ddk-mcp-starter</artifactId>
    <version>${ddk.version}</version>
</dependency>

工具类放在适配层,像控制器一样只调用应用服务:

java
@Component
@RequiredArgsConstructor
public class UserMcpTools {

    private final UserService userService;

    @McpTool(name = "get_user", description = "Get a user by ID. The phone number is masked.")
    public UserResponse get(@McpToolParam(description = "User ID") @Positive long id) {
        return userService.get(id);
    }
}

启动后端点是 /mcp。在 Claude Code 里接入:

bash
claude mcp add --transport http my-service http://localhost:8080/mcp

配置项 ​

配置项默认值说明
ddk.mcp.enabledtrue是否为 @McpTool 方法接入上述调用拦截
ddk.mcp.validationtrue是否校验工具参数
ddk.mcp.audit-logtrue是否每次调用输出一行审计日志
spring.ai.mcp.server.*Spring AI服务名、版本、端点、协议等仍由 Spring AI 配置

实现要点 ​

  • 拦截怎么生效:DDK 注册一个实现 Ordered 的 BeanPostProcessor,为含 @McpTool 方法的 Bean 创建 CGLIB 代理。Spring AI 的注解扫描器没有实现 Ordered,排在后面,登记到 MCP server 的因此是代理对象;它按目标类上的 Method 反射调用,只有子类代理才能让这次调用经过拦截。
  • 工具错误不带 cause:Spring AI 生成错误消息时会追溯异常链的根因,带上原始异常等于把它的消息原样交给模型。
  • 约束写在接口上:工具类实现接口时,Bean Validation 规范不允许在重写方法上重新声明参数约束,约束要写在接口方法上。

架构守卫 ​

CommonArchRules.MCP_TOOLS_MUST_RESIDE_IN_ADAPTER 要求 @McpTool 方法声明在 ..adapter.. 包里。结合分层规则,工具只能经由应用服务访问领域:模型拿不到仓储,也绕不过应用服务里的事务与业务校验。规则按注解全限定名匹配,ddk-archguard-starter 不依赖 Spring AI。

示例 ​

用户示例的 adapter.mcp.UserMcpTools 暴露了 register_user、get_user、disable_user。UserMcpToolsTest 启动真实端口,通过 MCP 客户端验证工具列表、注册到禁用的完整流程、领域错误码与参数校验。

不适用的场景 / 已知问题 ​

  1. 没有鉴权。/mcp 与其他接口一样,用 Spring Security 保护。
  2. 只支持 Servlet(WebMVC),不支持 WebFlux。
  3. 不提供 ddk-ai-starter。ChatClient 配置、结构化输出(.entity(...))、Token 用量指标(gen_ai_client_token_usage_total)Spring AI 2.0 都已内置,直接使用 Spring AI 即可。

文章以 CC BY-NC-SA 4.0 授权 · 代码片段以 MIT 授权