你的业务 API,
让 AI Agent 安全调用。
一个诚实的、生产级形态的 Spring Boot REST 脚手架。选定的 Service 方法同时暴露为 MCP 工具,Claude Code、Claude Desktop、Cursor 可以直接调用 —— 和 REST 同样的权限、同样的校验、同样的审计。
只需 JDK 21:./mvnw spring-boot:run,不需要数据库、Redis 或 Docker。
$ claude mcp add --transport http lazyrest \ http://localhost:8080/mcp --header "X-API-Key: lr_…" $ claude -p "Search LazyREST for articles about MCP…" ● lazyrest - searchArticles(query: "MCP") ⎿ 1 result · "Exposing Spring services as MCP tools" ● lazyrest - getArticle(id: 2)
问题
Agent 需要你的业务 API —— 但必须安全
越来越多团队希望 AI Agent 能查订单、读知识库、起草内容。真正难的不是“能不能调”,而是“调的时候守不守规矩”。
让 Agent 直连数据库
绕过所有业务规则:没有权限、没有所有权校验、没有参数校验,出了事也查不到是谁做的。
再写一套 Agent 专用接口
两套权限、两套校验、两套审计,迟早不一致 —— 而不一致的地方就是漏洞。
Agent 走同一个 Service 层
MCP 工具只是薄薄的适配器,调用和 REST 相同的 Service:@PreAuthorize、所有权、@Validated、@Audited 全部复用。
原理
一个 Service 层,两扇门
REST 客户端用 JWT,AI Agent 用个人 API Key 走 /mcp(Streamable HTTP)。两者经过同一条 Spring Security 过滤链,落到同一个数据库和同一张审计表。
isError: true + 一句可读的话(MCP),永不返回堆栈。MCP 接入
三步,让 Claude Code 调用你的接口
dev 环境自带一个演示 API Key(绑定 editor)。自己的 Key 用 POST /api/api-keys 创建,推荐只读。
启动应用
H2 内存库 + 演示数据,MCP 端点在 /mcp。
$ ./mvnw spring-boot:run注册 MCP 服务器
Claude Code 原生支持 HTTP 传输,用请求头带上 Key。
$ claude mcp add --transport http lazyrest \
http://localhost:8080/mcp \
--header "X-API-Key: lr_dev_editor_0123456789abcdefghijklmnop"直接提问
Agent 会自己选择工具;每次调用都进入审计日志(channel=MCP)。
> 搜索关于 MCP 的文章,读最相关的那篇,用两句话总结。
claude -p 运行记录(stream-json 原文排版成终端样式,未改动内容)。Claude Desktop 可通过 mcp-remote 桥接,MCP Inspector CLI 也已验证。里面有什么
每一项都已实现,并有测试覆盖
不写就不吹:没有缓存 / Redis、文件上传、多租户、OAuth2 授权服务器、MFA。需要时再加。
认证 auth
BCrypt 登录,JWT 访问令牌(HS256,15 分钟),不透明刷新令牌:哈希存储、每次轮换、重用检测吊销整组。登录 / 刷新 / 注册按 IP 限流(429 + Retry-After)。
API Key
lr_ 前缀,只存 SHA-256,明文只显示一次,可吊销,可设为只读;只在 /mcp 上被接受。
RBAC user
角色 + 细粒度权限(article:write、audit:read、mcp:write …),@PreAuthorize 方法级安全,管理员用户管理,首个管理员由环境变量引导。
示例领域 article
CRUD、Jakarta Validation、分页 + 白名单排序、安全转义的搜索、所有权校验(他人草稿 404、改他人文章 403)、乐观锁、发布流程。可整体删除。
审计 audit
@Audited 切面记录谁、做了什么、结果(SUCCESS / DENIED / FAILURE)、渠道(REST / MCP)、requestId、IP、耗时;独立事务持久化,管理员可查询。
MCP mcp
Streamable HTTP 端点 /mcp:searchArticles、getArticle、createArticleDraft。带 JSON Schema 和 readOnlyHint 等提示,必须认证。
错误与追踪
RFC 9457 application/problem+json(含 code、requestId、字段级 errors),X-Request-Id 写入日志 MDC。
持久化
Spring Data JPA + Flyway 迁移(Hibernate 只校验)。dev = H2 + 演示数据;prod = MySQL 8 或 PostgreSQL,缺少密钥直接拒绝启动。
运维与交付
OpenAPI 3 + Swagger UI、Actuator(仅 health 公开)、Prometheus、优雅停机、虚拟线程;多阶段 Dockerfile、docker-compose、GitHub Actions CI。68 个测试 + Testcontainers。
安全模型
Agent 的权限 = Key 主人的权限,一分不多
必须认证
/mcp 接受 X-API-Key: lr_…(或 Bearer lr_…),也接受普通 JWT;未认证返回 401 ProblemDetail。只读 Key 只保留 *:read 权限。
写工具三重门控
任何一道门关着,写操作都不会发生。Agent 只能创建草稿,发布永远需要人(仅 REST)。
每次调用都审计
每次工具调用记录一条 MCP_TOOL_CALL(参数摘要、结果、耗时),内部业务操作也以 channel=MCP 记录。工具错误以一句可读的话返回给模型,不泄露内部信息。
write-tools-enabledprod 默认关闭,关闭时工具不出现在 tools/list
mcp:write且不是只读 Key
article:write和 REST 同一个检查
仍需注意:注册一个工具就等于把它开放出去;Agent 读到的数据会进入模型上下文;用户写入的内容可能包含针对 Agent 的提示注入 —— 所以发布必须由人完成。尚未覆盖:MFA、MCP 的 OAuth 授权、TLS(请在反向代理终止)。
快速开始
一条命令跑起来
本地开发(只需 JDK 21)
$ git clone https://github.com/melonlee/LazyREST.git $ cd LazyREST $ ./mvnw spring-boot:run
Swagger UI:http://localhost:8080/swagger-ui.html MCP:http://localhost:8080/mcp
| admin / admin123 | 全部权限:用户管理、审计、Actuator |
| editor / editor123 | 写 + 发布文章,可用 MCP 写工具 |
| alice / alice123 | 读文章、写自己的草稿 |
演示账号与演示 Key 只在 dev profile 存在。
Docker Compose(MySQL 8.4)
$ cp .env.example .env # 填入 JWT_SECRET、数据库密码、管理员密码 $ docker compose up --build
使用 prod profile:Flyway 自动建表,首次启动按 LAZYREST_ADMIN_* 创建管理员;缺少必需的环境变量时直接拒绝启动并指出缺了什么。换 PostgreSQL 只需改 DB_URL。
作为模板:点 Use this template,改坐标和包名,删掉 article 示例模块,加上你的领域。
截图
全部来自运行中的应用
Swagger UI 是浏览器实拍;终端截图是真实命令的原样输出,只做了排版。


GET /api/articles 的真实响应


tools/list 与 tools/callFAQ
常见问题
能部署多个副本吗?
REST 部分完全无状态,可以。MCP 的 Streamable HTTP 会话保存在内存里:多副本时请开启粘性会话,或者切换到 protocol: STATELESS(同时把 McpServerConfig 的传输 Bean 换成无状态版本)。
MCP 支持 OAuth 吗?
还不支持。目前用个人 API Key(或普通 JWT)认证。MCP 的 OAuth 2.1 授权在路线图上;在有授权服务器之前,LazyREST 刻意不在 WWW-Authenticate 里声明 OAuth 元数据,以免客户端尝试一个无法完成的登录流程。
限流在多实例下准吗?
不准 —— 登录 / 刷新 / 注册的限流是单实例内存实现,每个实例单独计数。需要全局限流时,可换成 Bucket4j + Redis。
有缓存 / Redis 吗?
没有。示例里没有任何东西需要它,所以 v2 不声称有。
生产环境默认安全吗?
prod profile 下:缺少 JWT_SECRET / 数据库配置直接拒绝启动,dev 假密钥被拒绝,MCP 写工具、自助注册和 Swagger UI 默认关闭,Actuator 只公开 health。
能用 PostgreSQL 吗?
可以。把 DB_URL 换成 jdbc:postgresql://host:5432/lazyrest,Flyway 会自动选择 db/migration/postgresql。CI 用 Testcontainers 在 MySQL 8.4 和 PostgreSQL 17 上跑全流程。
你负责偷懒,河狸负责把接口接给 AI。
一条命令跑起来,接口同时就是 MCP 工具。河狸是 LazyREST 的吉祥物,和 喵想 同属 FantasyAI Lab 吉祥物家族。