Antigravity-Manager 本地代理接入 z.ai MCP:三个端点、认证模型与 Vision 内置服务深度解析
【免费下载链接】Antigravity-ManagerProfessional Antigravity Account Manager & Switcher. One-click seamless account switching for Antigravity Tools. Built with Tauri v2 + React (Rust).专业的 Antigravity 账号管理与切换工具。为 Antigravity 提供一键无缝账号切换功能。项目地址: https://gitcode.com/gh_mirrors/an/Antigravity-Manager
本文聚焦 Antigravity-Manager 内置本地代理中针对 z.ai MCP(Model Context Protocol)的实现:它如何把 z.ai 的 Web Search、Web Reader 两个远端 MCP 服务以反向代理形式暴露在本地,又如何将官方@z_ai/mcp-server的 Vision 能力直接内嵌为本地 HTTP MCP 服务,从而让任意 MCP 客户端无需配置 z.ai 密钥即可调用。读完本文,你将掌握完整的配置项语义、三个本地端点的请求/响应链路、认证注入机制,以及用原始 JSON-RPC 快速验证接入是否成功的可复现方法。
为什么需要本地 MCP 端点
在 Antigravity-Manager 中,z.ai 集成(proxy.zai)的核心诉求是:用户只在代理处集中维护 z.ai API Key,各下游应用(Claude Code、Cherry Studio、各类 MCP 客户端等)无需各自配置密钥即可使用 z.ai 的模型与能力。这一设计原则同样被延伸到 MCP 场景,具体有三个目标:
- 允许应用直接使用 z.ai 的 MCP 服务器,而不需要在这些应用里配置 z.ai 密钥;
- 避免把密钥放进 URL(杜绝 query-string 鉴权这种易泄漏、易被日志记录的做法);
- 让每个 MCP 能力(Web Search / Web Reader / Vision)都可以独立开关。
最终落地形态:当proxy.zai.mcp.enabled=true时,本地代理会在自身 base URL 下暴露一组/mcp/...端点,密钥由代理统一注入,客户端只需要指向本地地址。
三个本地 MCP 端点一览
从 server.rs 的路由注册 可以看到,本地代理共暴露三个 MCP 端点,其中两个是远程反向代理,一个是内置服务:
| 本地端点 | 上游目标 | 类型 | 处理器 |
|---|---|---|---|
/mcp/web_search_prime/mcp | https://api.z.ai/api/mcp/web_search_prime/mcp | 远程反向代理 | handle_web_search_prime |
/mcp/web_reader/mcp | https://api.z.ai/api/mcp/web_reader/mcp | 远程反向代理 | handle_web_reader |
/mcp/zai-mcp-server/mcp | 无(本地实现) | 内置 Streamable HTTP MCP 服务 | handle_zai_mcp_server |
三个路由均通过 axum 的any(...)注册,即 GET / POST / DELETE 等任意 HTTP 方法都会进入对应处理器,由处理器内部按方法分发,这与 MCP Streamable HTTP 传输层"以普通 HTTP 承载 JSON-RPC"的工作方式一致。
三个端点的处理器都集中在 handlers/mcp.rs:handle_web_search_prime、handle_web_reader、handle_zai_mcp_server。
能力开关:配置项语义与默认值
MCP 相关配置在 proxy/config.rs 的ZaiMcpConfig中定义,四个开关全部默认为false(关闭):
| 配置项 | 类型 | 默认值 | 作用 |
|---|---|---|---|
proxy.zai.mcp.enabled | bool | false | 总开关,决定是否暴露任何/mcp/...端点 |
proxy.zai.mcp.web_search_enabled | bool | false | 是否开放/mcp/web_search_prime/mcp |
proxy.zai.mcp.web_reader_enabled | bool | false | 是否开放/mcp/web_reader/mcp |
proxy.zai.mcp.vision_enabled | bool | false | 是否开放/mcp/zai-mcp-server/mcp |
注意这些开关是叠加生效的:enabled是总闸,三个子开关可以任意组合(例如只开 Vision、或同时开三者),从而精确控制暴露面。
除 MCP 自身配置外,还依赖上层 z.ai 配置(见 ZaiConfig):
proxy.zai.enabled(bool,默认false):z.ai 集成总开关;proxy.zai.api_key(string,默认空):z.ai API Key,由代理统一持有并注入上游;proxy.zai.base_url(string,默认见default_zai_base_url()):z.ai API 基础地址。
配置校验逻辑(源码级)
从 handlers/mcp.rs 的forward_mcp可以看出严格的启用检查顺序:
let zai = state.zai.read().await.clone(); if !zai.enabled || zai.api_key.trim().is_empty() { return (StatusCode::BAD_REQUEST, "z.ai is not configured").into_response(); } if !zai.mcp.enabled { return StatusCode::NOT_FOUND.into_response(); }即:proxy.zai.enabled为假或api_key为空时返回400;mcp.enabled为假时返回404。而每个子端点还会再校验自己的开关,例如 handle_web_search_prime 中if !zai.mcp.web_search_enabled { return StatusCode::NOT_FOUND }。这种分层校验保证了"配置没开就 404、密钥没配就 400"的可预期行为,便于排查。
认证模型:密钥只存在于代理一处
z.ai MCP 的认证模型是整个设计的核心:
- 本地代理鉴权(如果启用)由代理中间件统一处理,实现在 middleware/auth.rs。这意味着本地端点本身可以按你的需要受保护;
- z.ai 鉴权始终由代理注入上游:代理使用
proxy.zai.api_key,在转发时以Authorization: Bearer <api_key>的形式附加上游请求头(见 forward_mcp 中的注入逻辑); - 指向本地端点的 MCP 客户端无需配置任何 z.ai 密钥。
也就是说,客户端拿到的永远是一个"无密钥"的本地地址,密钥在整个链路中只存在于代理配置里。这样既规避了密钥随 URL 传播的风险,也大幅简化了多客户端接入的配置成本。
转发链路的实现细节
forward_mcp是一个通用的远程反向代理函数,两个远程端点(Web Search / Web Reader)都复用它,核心流程如下:
- 透传头过滤:仅放行
content-type、accept、user-agent三个请求头到上游(见 copy_passthrough_headers),其他头不转发; - 注入 z.ai 认证:追加
Authorization: Bearer <api_key>; - 读取请求体:通过
to_bytes(body, 100 * 1024 * 1024)读取,即请求体上限为 100 MB; - 转发并回传:将上游响应(状态码 +
content-type头)原样透传,响应体以流式(bytes_stream)方式回传,从而支持 MCP 长会话与流式输出。
该函数还支持通过upstream_proxy配置(build_client,见 handlers/mcp.rs)让上游请求走企业代理,超时时间取自state.request_timeout,且下限为 5 秒(timeout_secs.max(5))。
内置 Vision MCP:从 stdio 到内嵌 HTTP 服务
第三个端点/mcp/zai-mcp-server/mcp是最有技术含量的一部分。上游官方 Vision MCP 包(@z_ai/mcp-server)被设计为本地 stdio 服务,如果照搬,桌面应用 + 内嵌代理就需要用户(或应用自身)额外管理一个 Node 运行时/进程,运维复杂度明显上升。因此项目选择把 Vision MCP 服务器直接内嵌进代理进程(设计依据见 docs/zai/vision-mcp.md),收益有三点:
- 无需额外运行时依赖;
- z.ai 密钥只有一个存放处(代理配置);
- 应用可以按标准的 "MCP over HTTP" 协议访问本地代理。
最小化的 Streamable HTTP MCP 协议面
处理器handle_zai_mcp_server(见 handlers/mcp.rs)按 HTTP 方法分发:
| 方法 | 行为 |
|---|---|
POST /mcp | 处理 JSON-RPC 方法:initialize、tools/list、tools/call |
GET /mcp | 对已存在的会话返回 SSE 流(含 keepalive ping,间隔 15 秒) |
DELETE /mcp | 终止一个会话 |
这是刻意保持的最小实现,足以支撑工具调用;prompts/resources、会话恢复(resumability)、流式工具输出等均留作后续扩展空间。
会话管理:会话由 zai_vision_mcp.rs 的ZaiVisionMcpState维护,用HashMap<String, ZaiVisionSession>存会话 ID(uuid::Uuid::new_v4()生成),支持创建、查询、删除三个原子操作。会话 ID 通过响应头mcp-session-id返回给客户端,客户端后续请求必须携带该头(大小写均可,见 mcp_session_id)。
JSON-RPC 细节(见 handle_vision_post):
- 非 JSON 请求体返回
-32700(Parse error); - 缺少
method返回-32600(Invalid Request); - 通知类消息(无
id或id为 null)按 JSON-RPC 规范返回204 No Content,不产生响应体; initialize时创建会话并回写mcp-session-id响应头,serverInfo.name固定为zai-mcp-server,version取自CARGO_PKG_VERSION,并回显客户端请求的protocolVersion(默认2024-11-05);- 未携带或携带无效会话 ID 时返回
-32000错误; - 未知方法返回
-32601(Method not found)。
八种视觉工具
工具注册表tool_specs()与执行函数call_tool(...)都位于 zai_vision_tools.rs,共 8 个工具(高层对齐上游官方包):
| 工具名 | 用途 | 关键入参 |
|---|---|---|
ui_to_artifact | 把 UI 截图转换为产物(代码/提示词/规格/描述) | image_source、output_type(code/prompt/spec/description)、prompt |
extract_text_from_screenshot | 从截图提取文本/代码(类 OCR) | image_source、prompt、language_hint(可选) |
diagnose_error_screenshot | 诊断错误截图(堆栈、日志、运行时错误) | image_source、prompt、context(可选) |
understand_technical_diagram | 解析架构/流程/UML/ER 图 | image_source、prompt、diagram_type(可选) |
analyze_data_visualization | 分析图表/仪表盘,提取洞察与趋势 | image_source、prompt、analysis_focus(可选) |
ui_diff_check | 对比两张 UI 截图并报告视觉差异 | expected_image_source、actual_image_source、prompt |
analyze_image | 通用图像分析 | image_source、prompt |
analyze_video | 视频内容分析 | video_source、prompt |
每个工具都有独立的 system prompt 设计,例如ui_to_artifact会根据output_type切换到"前端工程师生成代码 / 生成复现提示词 / 设计系统架构师输出规格 / 自然语言描述"四种角色;ui_diff_check要求按严重程度分组报告差异并给出可操作的修复建议。可选的提示增强参数(如language_hint、context、diagram_type、analysis_focus)会被追加到用户 prompt 之后。
上游调用与模型参数
所有工具最终汇聚到vision_chat_completion(...)(见 zai_vision_tools.rs),调用 z.ai 的 PaaS 视觉对话补全端点:
- 上游地址:
https://api.z.ai/api/paas/v4/chat/completions - 认证:
Authorization: Bearer <proxy.zai.api_key> - 模型:
glm-4.6v(目前硬编码) - 消息:system prompt + 一个包含图片/视频与文本提示的多模态 user 消息
- 参数:
stream: false(目前单次返回一个工具结果)、temperature: 0.8、top_p: 0.6、max_tokens: 32768,并开启thinking: { "type": "enabled" } - 附加请求头:
X-Title: Vision MCP Local、Accept-Language: en-US,en
工具执行失败时不会直接报 HTTP 错误,而是返回isError: true的 JSON-RPC 结果(符合 MCP 工具错误语义);上游解析要求存在choices[0].message.content字符串,否则视为无效响应。
本地文件处理:data URL 编码
为支持 MCP 客户端传入的本地文件路径,zai_vision_tools.rs 实现了image_source_to_content与video_source_to_content两个转换函数:
- 若
image_source/video_source以http://或https://开头,则直接作为 URL 透传(image_url/video_url); - 否则按本地文件处理:读取文件字节并编码为
data:<mime>;base64,...的 data URL; - 图片支持
.png(image/png)、.jpg/.jpeg(image/jpeg),上限 5 MB; - 视频支持
.mp4(video/mp4)、.mov(video/quicktime)、.m4v(video/x-m4v),上限 8 MB; - 超出大小、文件不存在或不支持的扩展名都会返回明确的中文/英文错误信息。
快速验证:原始 JSON-RPC 三连
不依赖任何 MCP 客户端框架,直接用 curl 即可验证内置 Vision 端点。假设本地代理已启动在http://127.0.0.1:PORT(端口以实际配置为准)。
1. 初始化会话(注意捕获响应头Mcp-Session-Id):
curl -i -X POST http://127.0.0.1:PORT/mcp/zai-mcp-server/mcp \ -H 'Content-Type: application/json' \ -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{}}}'响应中的mcp-session-id头即为后续请求的会话凭证,例如SESSION_ID。
2. 列出工具:
curl -X POST http://127.0.0.1:PORT/mcp/zai-mcp-server/mcp \ -H 'Content-Type: application/json' \ -H 'Mcp-Session-Id: <SESSION_ID>' \ -d '{"jsonrpc":"2.0","id":2,"method":"tools/list"}'返回 8 个工具的定义(name、description、inputSchema)。
3. 调用工具(以analyze_image为例):
curl -X POST http://127.0.0.1:PORT/mcp/zai-mcp-server/mcp \ -H 'Content-Type: application/json' \ -H 'Mcp-Session-Id: <SESSION_ID>' \ -d '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"analyze_image","arguments":{"image_source":"/path/to/file.png","prompt":"Describe this image"}}}'验证过程中可对照上文"配置校验逻辑":若未启用对应开关会得到404,若proxy.zai.enabled未开或api_key为空会得到400。
从零到一:完整的启用步骤
综合原文档的 Validation 章节与配置结构,一次完整的接入流程如下:
- 开启 z.ai 集成:设置
proxy.zai.enabled=true,并配置proxy.zai.api_key; - 开启 MCP 总开关:设置
proxy.zai.mcp.enabled=true; - 按需开启子能力:在
proxy.zai.mcp.web_search_enabled、proxy.zai.mcp.web_reader_enabled、proxy.zai.mcp.vision_enabled中任意组合(可只开一个); - 启动本地代理;
- 配置 MCP 客户端:让客户端指向对应的本地端点,例如:
- Web Search:
http://127.0.0.1:PORT/mcp/web_search_prime/mcp - Web Reader:
http://127.0.0.1:PORT/mcp/web_reader/mcp - Vision:
http://127.0.0.1:PORT/mcp/zai-mcp-server/mcp
- Web Search:
客户端无需任何 z.ai 密钥;若你为本地代理启用了本地鉴权,则在客户端侧配置代理要求的凭据即可。
UI 接线与更多资料
MCP 能力开关与本地端点地址已接入前端代理管理页面,展示在 src/pages/ApiProxy.tsx 中,用户可以在界面里直接切换各 MCP 能力并查看本地端点,而无需手写配置文件。
想深入了解设计动机、协议面取舍与更多细节,可继续阅读仓库内的配套文档:
- docs/zai/mcp.md:MCP 端点、认证模型与验证步骤的原始设计文档;
- docs/zai/vision-mcp.md:内置 Vision MCP 服务器的完整设计说明;
- docs/zai/implementation.md 与 docs/zai/provider.md:z.ai 集成与 Provider 层面的实现笔记。
限制与注意事项
- 模型硬编码:Vision 工具当前固定使用
glm-4.6v,stream固定为false,这些是当前仓库的实现事实,未来可能随版本演进; - 最小协议面:内置 Vision MCP 仅实现
initialize/tools/list/tools/call,不提供 prompts/resources、会话恢复与流式工具输出; - 大小限制:本地图片文件上限 5 MB、视频上限 8 MB,请求体整体上限 100 MB;
- 开关叠加:四个开关全为默认关闭,必须按上文步骤显式开启,否则对应端点返回 404;
- 密钥集中管理:z.ai 密钥仅配置在代理处(
proxy.zai.api_key),客户端侧不要也不应再配置密钥,避免密钥通过 URL 或客户端配置扩散。
【免费下载链接】Antigravity-ManagerProfessional Antigravity Account Manager & Switcher. One-click seamless account switching for Antigravity Tools. Built with Tauri v2 + React (Rust).专业的 Antigravity 账号管理与切换工具。为 Antigravity 提供一键无缝账号切换功能。项目地址: https://gitcode.com/gh_mirrors/an/Antigravity-Manager
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考