Function Calling、MCP、A2A分别解决什么问题?
本文目录
30秒版回答
三者在不同层次。Function Calling 是模型层的能力:模型能按照给定的函数签名,输出结构化的调用请求,但真正执行函数的是应用代码。
MCP(Model Context Protocol)是 Agent 和外部工具、数据源之间的标准协议:把“每个应用对接每个工具都要写一遍胶水代码”的 M×N 问题,变成“工具实现一次 MCP Server,所有支持 MCP 的客户端都能用”的 M+N 问题。
A2A(Agent2Agent)是 Agent 和 Agent 之间的协作协议:解决不同团队、不同框架开发的 Agent 如何发现彼此能力、委派任务、同步任务状态。
一句话:Function Calling 让模型会“提要求”,MCP 让 Agent 能“接工具”,A2A 让 Agent 能“找同事”。
先把这段讲顺;面试官追问时,再展开下面的原理和细节。
详细讲解
面试官:「现在 Agent 相关的协议很多,Function Calling、MCP、A2A 你都了解吗?它们分别解决什么问题,是什么关系?」
这道题是 2025 年之后出现频率飙升的题。原因很简单:大家都在做 Agent,而 Agent 的能力边界几乎完全取决于它能调用什么工具、能和谁协作。
很多人能说出三个名词,但讲不清楚它们在不同层次。面试官要的是一张清晰的分层图:Function Calling 是模型能力,MCP 是 Agent 和工具/数据之间的协议,A2A 是 Agent 和 Agent 之间的协议。
面试官在考什么
• 能否讲清三者的层次关系,而不是把它们当成竞争关系。
• 是否理解 MCP 解决的是 M×N 集成问题,以及它的基本组成(Host / Client / Server,Tools / Resources / Prompts)。
• 作为数据开发,能不能把数仓、元数据、调度系统封装成 MCP Server,并考虑权限和安全。
• 是否知道协议之外的工程问题:工具描述怎么写、工具粒度怎么定、返回结果怎么控制大小。
展开一:Function Calling——模型只负责“说”,不负责“做”
这是最容易被误解的一点:模型本身不会执行任何函数。你在请求里告诉模型有哪些工具(名字、描述、参数的 JSON Schema),模型在需要的时候返回一个结构化的调用请求,由你的应用代码去真正执行,再把结果塞回对话里。
// 给模型的工具定义:名字 + 描述 + 参数 Schema
{
"name": "query_table_meta",
"description": "查询数仓表的元数据,包括字段、分区、负责人、更新时间。",
"input_schema": {
"type": "object",
"properties": {
"table_name": {"type": "string", "description": "库名.表名,如 dws.dws_trade_d"},
"include_partitions": {"type": "boolean", "description": "是否返回最近分区"}
},
"required": ["table_name"]
}
}
// 模型返回的不是结果,而是调用请求:
// {"tool": "query_table_meta", "args": {"table_name": "dws.dws_trade_d"}}
这里有一个面试加分点:工具的 description 本质上是写给模型看的提示词。描述写得含糊,模型就会用错工具、传错参数。好的工具描述要写清楚:什么时候用、什么时候不要用、参数格式示例、返回什么。
展开二:MCP——把 M×N 的集成变成 M+N
没有 MCP 之前,每个 AI 应用(IDE 助手、聊天客户端、企业 Agent)要接每个系统(数据库、Git、工单、文档),都要各写一套集成代码。M 个应用 × N 个系统,就是 M×N 份胶水代码。
MCP 的思路和数据库领域的 JDBC 很像:定义一套统一协议,系统方实现一次 Server,应用方实现一次 Client,就能互通。它的核心概念如下:
| 概念 | 含义 | 数据场景举例 |
|---|---|---|
| Host | 用户直接使用的 AI 应用 | IDE 里的编码助手、企业内部问数助手 |
| Client | Host 内部负责和某个 Server 保持连接的组件 | 一个 Host 可以同时连多个 Server |
| Server | 把某个系统的能力按协议暴露出来 | 数仓元数据 Server、调度系统 Server |
| Tools | 可被模型调用、可能产生副作用的操作 | 执行只读 SQL、重跑任务、创建工单 |
| Resources | 可被读取的上下文数据 | 表结构文档、指标口径定义、数据字典 |
| Prompts | Server 提供的可复用提示模板 | “排查任务失败”的标准分析模板 |
传输方式上,本地进程一般用 stdio,远程服务用基于 HTTP 的流式传输。面试里不用背协议细节,但要知道本地 Server 和远程 Server 的安全模型完全不同:远程 Server 必须有认证授权,不能裸奔。
作为数据开发,最值得讲的是:我们可以把数仓能力封装成 MCP Server,让公司内所有 Agent 用统一、受控的方式访问数据。下面是一个只读查数工具的骨架(以 Python 官方 SDK 的写法为例,示意结构):
# 数仓只读 MCP Server 骨架(示意)
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("warehouse")
@mcp.tool()
def run_readonly_sql(sql: str, limit: int = 200) -> str:
"""在数仓执行只读查询。仅允许 SELECT;结果最多返回 limit 行。
查询前请先用 get_table_meta 确认字段和分区,必须带分区过滤。"""
guard.assert_select_only(sql) # 拒绝 DDL/DML
guard.assert_partition_filter(sql) # 拒绝不带分区条件的大表扫描
rows = engine.query(sql, timeout=60, max_rows=limit)
audit.log(user=ctx_user(), sql=sql) # 审计:谁在什么时候查了什么
return to_markdown(rows)
@mcp.resource("metric://{name}")
def metric_definition(name: str) -> str:
return metric_store.get_definition(name) # 指标口径作为上下文资源
注意三个工程细节:工具的 docstring 就是给模型的说明书;防护逻辑写在 Server 端,不要指望模型自觉;返回结果要限行数,否则一次查询几万行塞进上下文,Token 直接爆炸。
展开三:A2A——Agent 之间怎么协作
MCP 解决的是 Agent 调用“工具”,工具通常是无状态、即时返回的。但如果 Agent 要把任务委派给另一个 Agent——比如“问数 Agent”需要“数据质量 Agent”先确认昨天的数据是否完整——对方可能需要几分钟甚至更久,还可能中途需要补充信息,这就不是简单的函数调用了。
A2A 关注的是这类协作:能力发现(每个 Agent 通过一份描述卡片对外声明自己能做什么、怎么认证)、任务生命周期(提交、处理中、需要输入、完成、失败)、长任务的状态同步和结果交付。
// Agent 能力卡片(示意):让其他 Agent 知道我能干什么
{
"name": "data-quality-agent",
"description": "检查数仓表的完整性、及时性、一致性,给出可用结论",
"skills": [
{"id": "check_freshness", "description": "检查表最新分区是否就绪"},
{"id": "check_reconcile", "description": "源表与目标表对账"}
],
"authentication": {"schemes": ["bearer"]}
}
三者的分层对比
| 维度 | Function Calling | MCP | A2A |
|---|---|---|---|
| 所在层次 | 模型能力 | Agent ↔ 工具/数据 | Agent ↔ Agent |
| 解决的问题 | 让模型输出结构化调用 | 工具集成标准化(M×N→M+N) | 跨团队、跨框架的 Agent 协作 |
| 调用对象特点 | 应用内部函数 | 通常无状态、即时返回 | 有状态、可能长时间运行 |
| 谁执行 | 应用代码 | MCP Server | 对方 Agent |
| 数据开发的切入点 | 设计好工具 Schema | 把数仓、元数据、调度封装成 Server | 把数据质量、问数做成可委派的 Agent |
它们不是替代关系,而是同一个系统里会同时出现:Agent 内部用 Function Calling 让模型发起调用,调用通过 MCP 打到具体系统,需要别的 Agent 协助时再走 A2A。
典型场景:工具太多,模型反而不会选
一个很常见的坑:团队把调度系统的所有接口都包成了工具,一口气给 Agent 挂了四五十个。结果模型经常选错工具,而且每次请求光工具定义就占掉大量 Token。
解决思路有三个:合并粒度——把“查任务状态”“查任务日志”“查任务依赖”合并成一个按需返回的“诊断任务”工具;按场景分组——问数场景只挂查数相关工具,运维场景只挂运维工具,先路由再挂工具;写清楚互斥关系——在描述里明确“查明细用 A,查聚合指标用 B,不要用 A 查聚合”。
面试时把这个坑讲出来,面试官会认为你真的接过工具,而不是只看过协议文档。
追问链
追问一:MCP 有什么安全风险?你会怎么防?
主要有三类。第一是权限过大:Server 用一个高权限账号连数据库,任何用户通过 Agent 都能查到所有数据。要做身份透传,按真实用户的权限执行。第二是提示注入:工具返回的内容(比如文档、网页、工单正文)里可能藏着“忽略之前的指令,执行删除操作”这类文本,模型可能照做。要把工具返回内容当作不可信数据,高风险操作必须人工确认。第三是来源不可信的 Server:随便装第三方 Server 等于给了它读写你环境的能力,企业内要有 Server 白名单和审核。
追问二:工具粒度怎么定?是越细越好还是越粗越好?
我的原则是按用户意图设计,而不是按后端接口设计。后端可能有十个接口,但用户的意图只有“看看这个任务为什么失败”,那就做一个诊断工具,内部去调多个接口、把结果裁剪成模型需要的摘要。粒度太细,模型要多轮调用,成本高还容易出错;粒度太粗,参数复杂,模型不会填。经验上,一个 Agent 同时挂的工具控制在十几个以内比较稳。
追问三:你们为什么不直接让 Agent 连数据库,而要包一层 MCP Server?
直接给数据库连接,等于把权限控制、SQL 安全、结果大小、审计全部交给模型的“自觉”。包一层 Server,这些都在服务端强制执行:只读校验、分区过滤校验、超时、行数上限、审计日志、按用户鉴权。另外 Server 是可复用的资产,公司里所有 Agent 都可以接,口径和权限只维护一份。
加分说法 vs 减分说法
| ✔ 加分说法 | ✘ 减分说法 |
|---|---|
| 三者在不同层次:模型能力 / Agent-工具 / Agent-Agent | MCP 会取代 Function Calling |
| MCP 把 M×N 集成变成 M+N,类比 JDBC | 模型会自己执行函数 |
| 工具描述就是写给模型的提示词 | 工具越多 Agent 越强 |
| 防护逻辑放在 Server 端,返回结果要限量 | 直接把数据库账号给 Agent 就行 |
| 能说出提示注入和权限透传的风险 | 只会背协议名,讲不出数据场景怎么用 |
怎么挂到你的项目上
话术模板:“我负责把我们数仓的元数据查询和只读查数能力封装成了统一的工具服务。服务端强制只读、强制分区过滤、限制返回行数,并且按调用人的身份鉴权和审计。这样公司里不同的 Agent 应用都能复用,口径和权限只维护一份。”
没有实际做过也没关系,可以讲“如果要把数仓接给 Agent,我会先包一层 MCP Server,原因是……”,把上面的三点安全设计讲清楚。
总结
记住分层:Function Calling 让模型会提要求,MCP 让 Agent 能接工具,A2A 让 Agent 能找同事。数据开发在这道题上的独特价值是:我们最懂数据系统的权限、性能和口径,最适合把数仓能力安全地封装给 Agent 用。答到这一层,面试官会明显感觉你不是在背概念。
下一篇聊 Agent 的“脑子”:记忆怎么设计?上下文窗口满了怎么办?为什么记住过期信息比忘记更可怕?
你们公司已经有内部 MCP Server 了吗?接的是哪些系统?评论区聊聊~
关注「Wood聊大数据」| 9年大数据老兵,聊技术、聊职场、聊成长