Zoom 变成了一个 MCP 端点:该接什么,以及哪里会咬人

·阅读约13分钟·Evergreen Tools Team

💡 工具推荐: API 测试器、JWT 解析器、JSON 格式化

Zoom 在 2026 年 10 月 20 日 Zoomtopia 上的发布,主体是一个产品故事,但里面藏着一个开发者故事,而那部分才是有日期、可以立刻行动的东西。现在已经可用的有两块:覆盖整个产品组合的 MCP 服务端,以及 Search 与 Ask API——让 Claude、GPT、Codex、Muse、Microsoft Copilot、Gemini、Slackbot 以及兼容 MCP 的 Agent 去查询新的 Unified Context Layer。预计 10 月上线的有一块:用于对话式管理任务的 Admin MCP 服务端。其余听起来很带劲的——个性化补会转录、把共享屏幕与幻灯片挂到转录具体时刻的增强笔记、AI 护栏、深度伪造风险检测——都标着 11 月、12 月或 2027 年 Q1。这个划分就是全部的计划难题;搞错它,团队就会对着一个还不存在的演示去开发。

Zoom 变成了一个 MCP 端点:该接什么,以及哪里会咬人

Zoom 变成了一个 MCP 端点:该接什么,以及哪里会咬人

一、先读「可用时间」,再读功能列表

把这份公告分成三堆。现已可用:覆盖产品组合的 MCP 服务端、Search 与 Ask API、面向部分 Zoom Workplace 客户的 Sensitivity Labels、ZoomMate Agent Teams、60fps 屏幕共享。预计 2026 年 10 月:把受支持的 Zoom 能力接进 Claude、Codex、Copilot、Muse,Admin MCP 服务端,把摘要变成 Zoom Chat 或 Salesforce 后续工作的 My Notes Workflows,以及 Voice Translator。更晚的:11 月的增强笔记;12 月的补会转录、新 Chat 体验、集中式 AI 管理、深度伪造风险检测;2027 年 Q1 的 AI 护栏;2027 年 1 月的 Compliance Manager 对 My Notes 与 Canvas 的覆盖。只有第一堆属于本个迭代。其余属于季度评审,而且要有负责人和复核日期。

# Zoom API: pull the recordings/transcripts for a date range.
# Server-to-server OAuth (account_credentials grant) -- no user login needed,
# but the app must be installed by an admin and the user id is 'me' or an id.
import json, base64, urllib.parse, urllib.request

ACCOUNT_ID, CLIENT_ID, CLIENT_SECRET = "<account>", "<client>", "<secret>"

basic = base64.b64encode(f"{CLIENT_ID}:{CLIENT_SECRET}".encode()).decode()
body = urllib.parse.urlencode({
    "grant_type": "account_credentials",
    "account_id": ACCOUNT_ID,
}).encode()

tok = json.load(urllib.request.urlopen(urllib.request.Request(
    "https://zoom.us/oauth/token", data=body,
    headers={"Authorization": "Basic " + basic,
             "Content-Type": "application/x-www-form-urlencoded"})))
AT = tok["access_token"]

q = urllib.parse.urlencode({"from": "2026-10-01", "to": "2026-10-25", "page_size": 30})
req = urllib.request.Request(
    "https://api.zoom.us/v2/users/me/recordings?" + q,
    headers={"Authorization": "Bearer " + AT})
meetings = json.load(urllib.request.urlopen(req, timeout=60))

for m in meetings.get("meetings", []):
    print(m["id"], m["topic"], m["start_time"], len(m.get("recording_files", [])))

# Scope note: cloud recording read is a separate scope from meeting read.
# Grant the smallest set that produces the artifacts you actually store.

二、Unified Context Layer 是穿着聊天界面的检索产品

Zoom 把这个层描述为:把对话历史与相关文档和数据连接起来,依托 Zoom 及已连接第三方应用中的近实时活动,配有可配置的访问设置与控制,并通过多个 Agent 之间的协调把上下文变成行动。把词汇去掉,你得到的是一个覆盖会议、聊天与文档产物的检索索引,外加一套访问控制模型。这个框架决定你的集成方式:你要的不是一个会总结会议的 Agent,而是能点回某个时间戳的引用,以及一个你能明确说出口的新鲜度保证。Zoom 放在这个故事旁边的数字是商业论据,不是技术论据:Virtual Agent 客户数增长 256%,用户报告任务完成速度快一倍,72% 表示业务影响高或极高(市场平均 63%),来自 500 名美国知识工作者的调研。这些数字适合放商业论证那页,对决定检索设计毫无用处。

# MCP path: let the agent call Zoom tools itself.
# Keep the allowlist explicit -- an agent with the whole toolbox will use it.
{
  "mcpServers": {
    "zoom": {
      "transport": "http",
      "url": "https://<your-zoom-mcp-endpoint>/mcp",
      "headers": { "Authorization": "Bearer ${ZOOM_MCP_TOKEN}" },
      "allowedTools": [
        "search_context",
        "get_transcript",
        "list_recordings",
        "create_followup_task"
      ],
      "blockedTools": ["admin_*"]
    }
  }
}

# Two rules that save incidents:
# 1) Never mix admin tools into the same server entry an end-user agent uses.
# 2) Log every tool call with arguments; the model's own narration is not
#    evidence, the invocation log is.

三、MCP 服务端还是 Search API?按「谁掌握循环」来选

这两个接口看起来可以互换,实际不是。MCP 服务端把一组工具交给外部 Agent,由 Agent 在它自己掌握的循环里调用:什么时候搜索、什么时候取转录、什么时候创建后续任务,都由 Agent 决定。当推理发生在你的 Agent 里时,这合适。Search 与 Ask API 给你一个直接查询上下文层的接口,适合你要让自己的应用发问、并用你自己的界面、自己的缓存、自己的评测来渲染答案。实操规则:如果产出是你的 Agent 做出的决策,用 MCP;如果产出是用户要读的一个界面,用 API,并把检索留在你自己的代码里,因为那里你能记日志、能测试。多数团队最后两样都上,而错误在于因为 MCP 演示更快就先做 MCP。

# The citation contract: what a meeting-derived fact must carry, always.
# Reject any agent answer that cannot fill these fields.
from dataclasses import dataclass, field
import datetime as dt

@dataclass
class Citation:
    artifact_id: str            # recording / transcript / note id
    meeting_id: str
    t_start_sec: int            # offset inside the recording
    t_end_sec: int
    participants: list[str]
    sensitivity_label: str      # from the source system, not inferred
    fetched_at: dt.datetime
    source_system: str = "zoom"

    def is_stale(self, max_age=dt.timedelta(hours=24)):
        return dt.datetime.now(dt.timezone.utc) - self.fetched_at > max_age

def enforce(answer: dict) -> dict:
    claims = answer.get("claims") or []
    for c in claims:
        cit = c.get("citation")
        if not cit or not cit.get("artifact_id") or cit.get("t_start_sec") is None:
            raise ValueError("claim without a locatable citation: %r" % c.get("text", "")[:60])
        if Citation(**cit).is_stale():
            raise ValueError("stale citation, re-fetch before serving")
    return answer

# If the model cannot cite, the honest output is "not in the corpus".
# Write that path first; it is the only one that never surprises a user.

四、把会议灌进 Agent 时会坏掉的四件事

第一,陈旧。转录不是不变的:笔记会被增强,说话人会被纠正,而 12 月的一个功能明确宣传把幻灯片与聊天挂到可搜索转录的具体时刻。如果你缓存过一份摘要,你现在有同一场会议的两个版本,却没有规则说哪个赢。第二,权限漂移。这一层有可配置的访问控制和连接器级设置,Sensitivity Labels 目前对部分客户可以按内容分级强制执行策略。一个继承用户令牌的 Agent 会继承该用户的可见范围,这没错;然后有人把它的输出分享给更大的群组,这就错了。第三,留存。对 AI 生成笔记与 Canvas 的 Compliance Manager 覆盖要到 2027 年 1 月,在那之前,归档责任是你自己的事。第四,对不确定性的沉默。向上下文层问一个语料里没有答案的问题,一个流畅的模型照样会回答。解决办法不是换个更好的模型。

# Before any context leaves for a third-party model, check the label and
# the retention rule. This is policy enforcement, not prompt wording.
POLICY = {
    # label -> allowed destinations
    "public":       {"internal", "external_model"},
    "internal":     {"internal"},
    "confidential": {"internal"},
    "restricted":   {"none"},
}

def may_send(label: str, destination: str) -> bool:
    allowed = POLICY.get(label.lower())
    if allowed is None:
        return False                      # unknown label never leaves
    return destination in allowed

def redact_if_needed(label: str, payload: dict, destination: str) -> dict:
    if may_send(label, destination):
        return payload
    # Do not silently summarise confidential content into an external model.
    # Return a refusal the caller can render, with the reason attached.
    return {"refused": True,
            "reason": f"label={label} not sendable to {destination}",
            "label": label}

# Zoom's Sensitivity Labels can sync from Microsoft Purview and enforce
# policies based on classification today for select Workplace customers.
# Your side of the contract is: read the label, act on it, log the decision.

五、先把「引用契约」建起来

在所有路线图日期都会变化的现实里,唯一能活下来的设计决策,是你存储的东西长什么样。把产物标识、会议或聊天 ID、时间戳区间、参与者集合、敏感度标签和抓取时间,与任何派生文本一起存下来。然后要求每个 Agent 的回答都带这些字段,否则拒收。这一件事同时做到三点:让人一键核验某个论断;给你一个便宜的陈旧性检查;让权限问题在事后可回答,因为你能指出某句话来自哪场会议、谁能看见。它不需要任何尚未发布的功能。它也正是团队会跳过的那部分工作,因为演示回答得很流畅,而没人问答案从哪来。

# Month-one evaluation: does the agent's answer actually match the artifact?
# Cheap, deterministic, and it catches the failure mode that matters.
import json, random

def score_answer(answer, artifact):
    text = (answer.get("text") or "").lower()
    facts = artifact["must_contain"]          # e.g. ["october 14", "2.3m"]
    cites = answer.get("citations") or []

    return {
        "facts_hit": sum(f.lower() in text for f in facts) / max(len(facts), 1),
        "has_citation": bool(cites),
        "citation_locatable": all(c.get("t_start_sec") is not None for c in cites),
        "length_ok": 40 <= len(text.split()) <= 220,
    }

def run(sample, ask_fn):
    rows = [score_answer(ask_fn(a["question"]), a) for a in random.sample(sample, min(50, len(sample)))]
    n = len(rows)
    print({
        "n": n,
        "facts_hit": round(sum(r["facts_hit"] for r in rows) / n, 3),
        "citation_rate": round(sum(r["has_citation"] for r in rows) / n, 3),
        "locatable_rate": round(sum(r["citation_locatable"] for r in rows) / n, 3),
        "verbose_rate": round(sum(not r["length_ok"] for r in rows) / n, 3),
    })

# Track these four numbers per release. A vendor demo cannot move them;
# your own wiring can. That is the difference between a pilot and a decision.

六、一个不依赖 12 月的三十天计划

第一周:挑一个失败代价容易观察的流程,比如给客户团队做会前简报,并写下「正确答案里应该包含什么」。第二周:把 Search 与 Ask API 接进一个只读内部工具,返回引用,并把每次查询连同结果集记下来——这样你的评测集是顺手得到的,不是立了个项目才有的。第三周:把 MCP 服务端加到一个 Agent 上,工具白名单收窄,然后在同一批问题上比较「走 MCP」与「走 API」的命中率谁更好。第四周:把引用契约发布为内部标准,并在 1 月之前定下留存方案。哪一条有效就扩大。数字没动,你也是用一个月而不是一个季度学到的,而且还留着那套评测集。

Zoom 变成了一个 MCP 端点:该接什么,以及哪里会咬人

Zoom 变成了一个 MCP 端点:该接什么,以及哪里会咬人

Zoom 变成了一个 MCP 端点:该接什么,以及哪里会咬人

Zoom 变成了一个 MCP 端点:该接什么,以及哪里会咬人

📌 常见问题 FAQ

Zoom 的 Unified Context Layer 是什么?

2026 年 10 月 20 日在 Zoomtopia 发布,它把对话历史与相关文档和数据连接起来,依托 Zoom 及已连接第三方应用中的近实时活动,配有可配置的设置与访问控制,并通过多个 AI Agent 之间的协调把上下文变成行动。

开发者今天能用什么?

覆盖产品组合的 MCP 服务端与 Search 及 Ask API 现已可用,可让 Claude、GPT、Codex、Muse、Microsoft Copilot、Gemini、Slackbot 以及兼容 MCP 的 Agent 查询上下文层。Sensitivity Labels 目前对部分 Zoom Workplace 客户可用,ZoomMate Agent Teams 也已可用。

哪些部分还没发布?

接入 Claude、Codex、Copilot、Muse 以及 Admin MCP 服务端预计 2026 年 10 月;增强笔记预计 11 月;补会转录、新 Chat 体验、集中式 AI 管理、深度伪造风险检测预计 12 月;AI 护栏预计 2027 年 Q1,Compliance Manager 对 My Notes 与 Zoom Canvas 的支持预计 2027 年 1 月。

该基于 MCP 服务端还是 Search 与 Ask API 开发?

按循环归谁所有来选。MCP 适合由 Agent 自己决定何时搜索、何时行动的场合;API 适合你自己的应用发问并用自己的界面、缓存与评测来呈现答案。因为 MCP 演示更快就先做 MCP,是最常见的错误。

把会议上下文灌进 Agent,最大的风险是什么?

权限漂移加上陈旧。继承用户令牌的 Agent 会继承其可见范围,把输出分享给更广的人群就破坏了模型;同时转录与笔记会被增强,缓存过的摘要会悄悄与来源分叉——除非你把产物 ID、时间戳区间与抓取时间和文本一起存下来。