MCP 的价值在于把模型和外部工具、数据源之间的连接标准化。对后端开发来说,它很像给 Agent 暴露了一组可发现、可调用的能力。
但只要 Agent 能调用工具,就必须按生产系统的标准设计安全边界。
我的判断: MCP 接入业务系统时,最危险的不是模型回答错,而是模型“真的做了错事”。所以工具必须收口成业务动作,并且能审计、能关闭、能灰度。
工具能力要白名单
不要把数据库、Shell、文件系统能力直接完整暴露给 Agent。更安全的做法是封装成明确工具,比如“查询某项目任务状态”“读取指定知识库文档”,而不是“执行任意 SQL”。
参数要做服务端校验
MCP 客户端传来的参数也可能被 prompt injection 影响。后端必须校验路径、ID、枚举、时间范围和用户权限。
审计日志不能省
Agent 做了什么、调用了哪个工具、入参是什么、返回了什么、用户是谁,都应该记录。否则出了问题无法复盘。
和 RAG 的关系
RAG 更偏“找资料回答”,MCP 更偏“连接工具行动”。真实 Agent 往往两者都需要:先检索上下文,再决定是否调用工具。
实际场景:让 Agent 查询业务系统时要先收口能力
如果把 Agent 接到后端系统里,最容易被低估的是权限边界。比如一个内部助手想查询广告平台的任务状态、BI 平台的分群计算进度、某个看板的预计算结果,看起来只是“查数据”,但这些数据背后有项目、租户、角色、数据范围和审计要求。Agent 不是管理员,它只是另一种客户端。
我更倾向把 MCP 工具设计成业务动作,而不是底层能力。比如不要提供 executeSql(sql),而是提供 queryUserGroupCalcStatus(groupId)、queryBatchCreateResult(batchId)、queryMediaSpendSummary(projectId, dateRange)。工具名称越贴近业务,模型越不容易误用,后端也更容易做参数校验和权限控制。
参数校验必须在服务端完成。模型生成的参数可能来自用户自然语言,也可能受到文档或网页内容影响。比如用户说“帮我查最近所有项目的投放消耗”,后端不能真的返回所有项目,而应该根据当前用户可访问的项目列表过滤;时间范围不能无限大;批次 ID、分群 ID、项目 ID 都要校验归属关系。MCP 只是协议,不能替代业务权限。
审计也不能省。一个普通接口至少有用户、URL、入参、耗时、结果状态;Agent 工具调用也应该有调用人、会话 ID、工具名、参数摘要、权限判断结果和错误信息。尤其是会产生外部副作用的工具,比如创建任务、发送通知、刷新分群、重跑定时任务,更应该记录“为什么调用”和“调用后产生了什么影响”。
工具返回值也要设计。不要把数据库异常、SQL 片段或内部堆栈直接返回给模型。更好的做法是返回结构化结果和可解释错误,比如 status=RUNNING、progress=62%、retryable=false、message=时间范围不能超过31天。这样模型能继续和用户解释,后端也不会泄露实现细节。
MCP 接入后端系统的核心不是“让模型能力更大”,而是让模型在可控边界内完成明确任务。对 Java 后端来说,它和开放 API、管理后台、定时任务入口没有本质区别:都需要认证、鉴权、参数校验、限流、审计、失败回退和灰度开关。把这些基础能力做好,Agent 才能从演示功能变成可上线能力。
实际落地时还可以先从低风险工具开始灰度。第一阶段只开放查询类工具,并且只返回脱敏后的摘要;第二阶段开放可重试的后台任务,比如刷新某个分群状态或查询失败原因;第三阶段才考虑写操作。每一阶段都要能关闭工具、限制用户范围、限制调用频率。这样即使模型选择错工具,影响也被控制在很小范围内。
另外,Agent 的提示词和工具描述也需要版本管理。工具字段改名、返回结构变化、权限策略调整,都可能影响模型行为。后端最好把工具调用日志和工具版本关联起来,出了问题能知道当时模型看到的是哪一版能力说明。