ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

MCP 是什么:Agent 如何通过标准协议连接工具和外部服务

MCP 是什么:Agent 如何通过标准协议连接工具和外部服务

前言

前面我们已经学习了 Tool Calling。

Tool Calling 的基本思路是:模型决定要调用什么工具,后端负责校验参数、执行真实业务,然后把结果返回给模型。

但是当 Agent 项目逐渐变多时,会出现一个新问题:

每个 Agent 都要重复接数据库工具吗? 每个 Agent 都要重复对接 Git、文件系统、接口文档吗? 不同模型、不同框架之间,工具定义能不能复用?

这时,MCP 就出现了。

MCP 全称是 Model Context Protocol,可以理解为一种让 AI 应用连接外部能力的标准协议。

它希望解决的问题不是“让模型变聪明”,而是:

让 Agent 能以更统一的方式发现、调用和使用外部工具、资源与提示词模板。

对于 Java 后端开发者来说,MCP 可以先理解成:

Agent 侧的标准化工具接入协议

它和我们平时做 REST API、RPC、消息队列一样,核心价值是降低系统之间的耦合。


一、没有 MCP 时,工具接入会遇到什么问题

假设我们开发了三个 Agent:

项目知识库助手 代码审查助手 运维排障助手

它们都可能需要访问一些公共能力:

查询 Git 提交记录 搜索项目文件 读取接口文档 查询发布记录 查询服务日志

如果每个 Agent 都自己封装一套工具,会变成下面这样:

知识库助手 -> 自己实现 Git 查询工具 代码审查助手 -> 再实现一套 Git 查询工具 运维助手 -> 再实现一套日志查询工具

久而久之就会出现:

  • 工具定义不统一;
  • 参数格式不统一;
  • 权限校验逻辑分散;
  • 错误处理方式不一致;
  • 工具升级时需要改多个项目;
  • 很难让新的 Agent 快速复用已有能力。

MCP 的思路是把这些能力标准化。

多个 Agent Client | | MCP 协议 | 多个 MCP Server | Git、数据库、文件、内部接口、日志系统

这样,Agent 不需要关心每个外部系统具体怎么实现,而是通过统一的工具描述和调用方式使用能力。


二、MCP 的核心角色

理解 MCP 时,可以先记住三个角色。

1. MCP Host

Host 是承载 AI 交互的应用。

例如:

  • 桌面 AI 客户端;
  • IDE 插件;
  • Agent 平台;
  • 企业内部智能助手;
  • Java 编写的聊天应用。

它负责管理用户交互、模型调用以及 MCP Client。

2. MCP Client

Client 负责连接具体的 MCP Server。

它通常会做这些事情:

  • 建立连接;
  • 获取工具列表;
  • 调用工具;
  • 获取资源;
  • 接收结果;
  • 处理异常和超时。

一个 Host 可以有多个 MCP Client,因为它可能要连接多个 MCP Server。

3. MCP Server

Server 是能力提供方。

它可以对外暴露:

  • Tools:可执行工具;
  • Resources:可读取资源;
  • Prompts:可复用提示词模板。

例如一个项目管理 MCP Server 可以提供:

get_project_info list_project_documents search_issue get_release_history

一个日志 MCP Server 可以提供:

search_error_logs get_service_health get_trace_detail

三、MCP 中的 Tools、Resources、Prompts

1. Tools:可执行能力

Tool 是模型可以请求调用的动作。

例如:

查询订单状态 搜索项目文件 获取服务健康状态 创建测试任务 查询发布记录

工具通常带有:

  • 工具名称;
  • 工具描述;
  • 参数定义;
  • 参数类型;
  • 返回结果;
  • 权限要求。

一个工具可以抽象成下面这个结构:

{"name":"get_order_status","description":"根据订单号查询订单当前状态,只能查询当前用户有权限访问的订单。","inputSchema":{"type":"object","properties":{"orderNo":{"type":"string","description":"订单编号"}},"required":["orderNo"]}}

模型会根据工具描述判断是否需要调用它。

但请注意:

工具描述是给模型理解能力边界用的,不是权限控制。

真正的权限校验必须由 MCP Server 或业务后端完成。


2. Resources:可读取资料

Resource 更像“外部可读取内容”。

例如:

项目 README 接口规范 数据库设计文档 部署手册 系统配置说明

资源可以理解为给 Agent 提供上下文的内容来源。

例如:

resource://project/readme resource://project/api-doc resource://ops/deploy-guide

与 Tool 的区别在于:

  • Tool 偏向执行动作;
  • Resource 偏向读取内容;
  • Tool 可能产生副作用;
  • Resource 一般用于提供信息。

例如“查询实时订单状态”应该是 Tool,“读取订单状态枚举说明”更适合作为 Resource。


3. Prompts:可复用提示词模板

Prompts 用于提供标准化的提示词模板。

例如:

代码审查模板 线上故障排查模板 接口设计模板 SQL 优化分析模板

一个“代码审查” Prompt 可能需要参数:

language diff focus

调用时可以传入:

{"language":"Java","focus":"安全性和事务边界","diff":"..."}

对于团队来说,这种方式可以把高质量 Prompt 沉淀下来,而不是让每个用户都从零写一遍。


四、MCP 和 Tool Calling 有什么关系

很多同学第一次看到 MCP 时,会觉得它和 Tool Calling 很像。

确实,它们有关联,但不是同一个概念。

对比项Tool CallingMCP
本质模型调用工具的机制工具、资源、提示词的标准协议
关注点模型如何选择并发起调用Agent 如何统一连接外部能力
工具定义常由应用自行维护可由 MCP Server 对外暴露
复用范围单个应用内也可使用更适合跨 Agent、跨客户端复用
权限控制由业务后端实现仍然由 MCP Server 和业务系统实现

可以这样理解:

Tool Calling 解决“模型怎么发起工具调用” MCP 解决“外部工具怎么以标准方式提供给 Agent”

它们完全可以配合使用。

用户提问 -> Agent 判断需要工具 -> 通过 MCP Client 发现并调用 MCP Tool -> MCP Server 校验权限并执行 -> 返回结果给 Agent -> Agent 组织最终回答

五、一个项目查询 MCP Server 的设计示例

假设我们要做一个“项目研发助手”,它需要查询项目文档、发布记录和接口信息。

可以先定义三个工具:

search_project_document get_release_history get_api_detail

1. 工具定义

@DatapublicclassMcpToolDefinition{privateStringname;privateStringdescription;privateMap<String,Object>inputSchema;}

构造一个查询发布记录工具:

publicMcpToolDefinitionbuildReleaseHistoryTool(){McpToolDefinitiontool=newMcpToolDefinition();tool.setName("get_release_history");tool.setDescription(""" 查询指定项目最近的发布记录。 只能查询当前用户有权限访问的项目。 返回发布时间、版本号、发布环境和发布状态。 """);Map<String,Object>properties=Map.of("projectId",Map.of("type","string","description","项目ID"),"limit",Map.of("type","integer","description","返回数量,范围1到20"));tool.setInputSchema(Map.of("type","object","properties",properties,"required",List.of("projectId")));returntool;}

这段代码只是表达工具描述的思路。实际接入 MCP SDK 时,会按照 SDK 提供的方式注册工具。


六、工具执行的正确边界

假设模型请求调用:

{"name":"get_release_history","arguments":{"projectId":"project-a","limit":10}}

后端不能直接拿参数执行查询,而应该完成以下步骤:

1. 校验工具是否允许调用 2. 校验参数格式 3. 校验当前用户是否登录 4. 校验用户是否有项目权限 5. 执行受控业务查询 6. 过滤敏感字段 7. 记录审计日志 8. 返回结构化结果

1. 参数对象

@DatapublicclassReleaseHistoryQuery{@NotBlank(message="项目ID不能为空")privateStringprojectId;@Min(value=1,message="limit不能小于1")@Max(value=20,message="limit不能大于20")privateIntegerlimit=10;}

2. 工具执行 Service

@Service@RequiredArgsConstructorpublicclassReleaseHistoryToolService{privatefinalProjectPermissionServiceprojectPermissionService;privatefinalReleaseRecordMapperreleaseRecordMapper;privatefinalAgentAuditLogServiceagentAuditLogService;publicToolExecuteResultexecute(LonguserId,ReleaseHistoryQueryquery){projectPermissionService.checkReadPermission(userId,query.getProjectId());List<ReleaseRecord>records=releaseRecordMapper.selectRecent(query.getProjectId(),query.getLimit());List<ReleaseRecordVO>result=records.stream().map(this::convertToSafeView).toList();agentAuditLogService.record(userId,"get_release_history",query.getProjectId(),"SUCCESS");returnToolExecuteResult.success(result);}privateReleaseRecordVOconvertToSafeView(ReleaseRecordrecord){ReleaseRecordVOvo=newReleaseRecordVO();vo.setVersion(record.getVersion());vo.setEnvironment(record.getEnvironment());vo.setStatus(record.getStatus());vo.setReleaseTime(record.getReleaseTime());returnvo;}}

文字说明:

  • 工具调用之前必须做项目权限校验;
  • 不要把数据库实体原样返回给模型;
  • 应该通过 VO 过滤内部字段;
  • 每次工具执行都应记录审计日志;
  • 工具失败时应该返回可控错误信息,而不是数据库异常堆栈。

七、为什么不要让 MCP Server 直接暴露数据库能力

有些人会想:

既然 Agent 要查数据,那我干脆提供一个 execute_sql 工具。

例如:

{"name":"execute_sql","arguments":{"sql":"SELECT * FROM user"}}

这在生产环境中风险非常高。

模型可能因为理解偏差、提示词注入或参数构造错误,生成危险 SQL:

DELETEFROMuser;

或者越权查询:

SELECT*FROMemployee_salary;

更合理的方式是提供业务语义明确的工具:

get_order_status list_user_orders get_project_release_history search_error_logs get_api_detail

这样可以让后端控制:

  • 查询范围;
  • 可返回字段;
  • 分页上限;
  • 权限逻辑;
  • 敏感字段脱敏;
  • 操作审计。

核心原则是:

模型负责表达意图,后端负责执行受控业务能力。


八、MCP Server 中的安全设计

1. 工具白名单

不要让客户端随意调用任意内部能力。

privatestaticfinalSet<String>ALLOWED_TOOLS=Set.of("search_project_document","get_release_history","get_api_detail");

当收到工具调用时:

publicvoidcheckToolAllowed(StringtoolName){if(!ALLOWED_TOOLS.contains(toolName)){thrownewBusinessException("不允许调用该工具");}}

2. 参数校验

模型生成的参数并不可靠。

例如它可能传:

{"limit":999999}

所以必须做:

  • 类型校验;
  • 必填校验;
  • 长度校验;
  • 枚举校验;
  • 数值范围校验;
  • 业务规则校验。

3. 高风险操作必须确认

以下操作不能因为模型调用了工具就立即执行:

  • 删除数据;
  • 修改权限;
  • 发布生产环境;
  • 发起支付;
  • 发送批量通知;
  • 调整库存;
  • 执行退款。

推荐的流程:

Agent 生成操作计划 -> 后端返回待确认信息 -> 用户确认 -> 后端执行 -> 返回执行结果

例如:

即将发布项目 project-a 到测试环境,版本为 v1.2.0。 本次操作会重启 2 个服务实例,是否确认?

4. 审计日志

建议至少记录:

用户ID 会话ID 工具名称 请求参数摘要 执行结果 耗时 时间 失败原因

但日志中不要记录完整 Token、密码、密钥和敏感业务字段。


九、MCP 与 RAG 如何配合

MCP 不等于 RAG。

RAG 主要解决“从文档中检索知识”,MCP 主要解决“以标准协议连接工具与资源”。

但它们可以结合。

例如用户问:

测试环境最近一次发布是什么时候?发布后错误率有没有升高?

Agent 可以拆成两个步骤:

步骤1:通过 MCP Tool 查询最近发布记录。 步骤2:通过 MCP Tool 查询发布前后的错误日志或监控指标。 步骤3:结合结果生成分析结论。

如果用户问:

项目的灰度发布流程是什么?

这更适合使用 RAG,从发布规范文档中检索答案。

简单记忆:

稳定说明文档 -> RAG 实时系统数据 -> MCP Tool 用户历史偏好 -> Memory 固定高风险流程 -> Workflow

十、实际开发建议

1. 先从只读工具开始

第一次做 MCP Server,建议先提供只读能力:

查询项目文档 查询接口说明 查询发布记录 查询日志摘要 查询服务健康状态

只读工具的风险更低,也更容易调试。

2. 工具粒度不要太粗

不推荐:

manage_project operate_system execute_database_command

推荐:

get_project_info get_release_history search_project_document get_service_health search_error_logs

工具名称越清晰,模型选择工具越稳定,后端也越容易控制权限。

3. 工具返回要简洁、结构化

不要把几百 KB 原始日志直接返回给模型。

推荐返回:

{"serviceName":"order-service","timeRange":"2026-07-18 10:00:00 ~ 2026-07-18 10:10:00","errorCount":12,"topErrors":[{"type":"DatabaseTimeoutException","count":8}]}

模型需要的是能用于推理和回答的信息,不是无限量原始数据。


十一、总结

这一篇我们认识了 MCP 的基本作用和开发边界。

重点可以记住:

  1. MCP 是 Agent 连接外部工具、资源和提示词模板的标准协议。
  2. MCP 包含 Host、Client、Server 三类角色。
  3. Tool 用于执行受控能力,Resource 用于读取资料,Prompt 用于复用提示词模板。
  4. MCP 与 Tool Calling 可以配合,但两者不是同一个概念。
  5. MCP Server 不应该直接暴露任意 SQL、Shell 或内部高危操作。
  6. 权限校验、参数校验、脱敏、审计日志必须由后端负责。
  7. 高风险操作需要显式确认,不能只靠模型判断。
  8. 初学阶段建议先实现只读、业务语义明确的工具。

下一篇我们继续学习多智能体协作:一个 Agent 不够用时,如何把规划、执行、审核等职责拆开。

返回列表