Skip to main content
MCP(Model Context Protocol)生态里已经有大量现成能力:GitHub、数据库、浏览器、各类 SaaS API。扣瓦可以接入它们,agent 直接用这些服务器提供的工具。 这一页讲清楚它怎么接、配置怎么写、以及有哪些你需要知道的取舍。

为什么不把 MCP 工具直接注册进工具表

业界有两种接法,扣瓦选了第二种,原因是提示词缓存。

全量注册(未采用)

每个 MCP 工具作为一个独立工具注册给模型。模型用起来最顺手,但一个服务器就能带来 10k+ token 的 schema,而且服务器一增删就改写工具表。

代理网关(本项目采用)

只注册一个约 200 token 的网关工具。模型先 search 发现、再 call 调用, 断连状态下也能靠元数据缓存搜索。
理由很硬:扣瓦的系统提示词与工具 schema 在会话间字节级不变,这是 OpenAI 前缀增量 与 Anthropic tools 块能命中缓存的前提(见提示词缓存)。 MCP 服务器是你运行时配置的,动态注册会把这个前提打爆。 所以模型看到的是一个叫 mcp 的工具,四个动作: 工具的内部全名是 mcp__<服务器>__<工具>,search 返回的就是全名,describe 和 call 接受全名。 约定是先 search 再 call。这条写进了系统提示词,模型照做。

配置:三层合并

MCP 服务器的配置分三层,低到高: 按服务器 id 合并,高层整条覆盖低层同名 id。同一 id 但传输方式不同,视为不同定义。
工作区标准层用 .mcp.json(生态标准),但只认 command / args / env / url / headers / type 这几个字段——扣瓦专属字段写在这里会被忽略,要生效得写到 .kova/mcp.json。
启停开关不入文件,落 SQLite(键 mcp.disabled.<层>.<id>)。个人开关不该写进 随仓库共享的文件里——和子代理的处理方式一致。
工作区来源的服务器默认是关闭的(系统层与插件层默认开)。服务器命令在首次调用时 就会被拉起,早于任何审批——所以”仓库里带了一份 .mcp.json”不该等于”本机自动 跑起那个进程”。要跑就在设置 → MCP 里显式启用一次;那条启用记录存在本机 SQLite 里, 是这台机器上唯一能授权的状态。

写一个配置

没有 settings 这一层,也没有全局免审批开关:approveTools 是每台服务器的字段, 输出防护是常开的。启停只在设置页切换(落本机 SQLite)——文件里写 disabled 这类 键不会被读取,上面没有列出的键同样如此。
改 URL 会丢掉认证字段。 headers / env 里疑似凭证的项与 URL 绑定——防止你把配置 共享出去时,别人把服务器指向自己的地址却带走你的凭证。

上限

合并后系统 + 工作区共 ≤ 32 个服务器,每服务器 ≤ 64 个工具,同时活跃连接 ≤ 16。 校验规则收得比较紧:id 只允许字母数字下划线连字符;stdio 与 http 字段互斥; command 不含 ..;url 必须绝对。

审批

MCP 的 call 一律走现有的逐工具审批回路(和写文件、跑 bash 的是同一条路), 不另造机制。审批被拒时,模型收到的是 blocked 工具结果,和其他工具被拒的语义一致。 有两条免审批的路——都必须是”你自己机器上的决定”,跟着仓库走的文件授权不了:
  • 服务器的 approveTools 配了 glob 且命中该工具名,且这份声明来自系统层 (~/.kova/mcp.json)。写在工作区层(.mcp.json / .kova/mcp.json)的 approveTools 不产生效力,只作为审批卡上那句「这个项目请求 X 免审批」出现 ——clone 一个别人的项目不该让那个仓库给自己的工具免审批。它也不会因为你启用了 这个服务器而生效:启用表达的是”我愿意跑它”,不是”我同意它免问”。
  • 本机清单 allowMcpTools:审批卡上点「允许并记住这个工具」写进 <工作区>/.kova/permissions.local.json,粒度是工具全名逐字相等(记一个不会 顺带放开同服务器的其他工具)。
search / describe / status 不触发审批——它们只读本地缓存和连接状态。

输出防护

MCP 服务器返回的东西可能很大。扣瓦的做法和 read / grep 一致:有界 + 可续取。 这不是丢数据,是换个方式给——模型拿到的是一个有界的结果加上一个能续读的指针。

断连了还能搜

元数据缓存(mcp-cache.ts)让 search / describe 在服务器连不上时仍然可用:
  • 条目按 configHash 键控(覆盖 command/args/env/url/headers),所以换配置自动失效
  • 每次成功握手后全量更新;TTL 默认 7 天,服务器自己声明 ttlMs 则优先
  • 读命中缓存时先返回旧值、后台异步刷新——前台不等网络

连接管理

连接是进程内全局单例,跨会话共享连接池(懒连接 + 空闲断开)。不按会话隔离—— MCP 服务器本身没有会话语义。 服务器状态有四态:idle / connecting / ready / failed(含退避 backoff)。 设置页里每行有状态点和一个「测试连接」按钮(强制重新握手)。 改配置会热重载:按新配置 diff 连接池,变更或禁用就断连、删除就释放。 系统提示词和工具表不需要重新注入——代理模式下工具表从来没变过。

设置页

设置 → MCP。骨架和子代理页一致:双层分组(系统 / 工作区),每行有传输方式图标、 名称、启停开关、状态徽章(ready · N 工具 / connecting / failed + 原因), 行菜单里有测试连接与删除。 指向非 loopback 的明文 HTTP 会显示警告条。

已知取舍

args 走 JSON 字符串

call 的参数是 JSON 字符串而不是对象。原因是部分模型对嵌套 union schema 不稳,字符串形态更鲁棒。如果实测主流模型用对象没问题,会放宽成两种都收。

search 没有正则与分页

目前是字段加权匹配(名 12 / 服务器 8 / 描述 5,完整匹配 > 前缀 > 包含, 命中全名额外加权),默认返回 12 条、上限 40。正则与分页在后续迭代。

Windows 孤儿进程

stdio 服务器是 sidecar 直接 spawn 的。正常路径会 kill,异常退出(尤其 Windows) 可能残留子进程,收尾按进程树清理。这条还需要真实使用验证。

OAuth 尚未支持

目前认证靠配置里的 headers / env 静态提供。OAuth、资源(resources)、采样、 elicitation 按后续节奏推进。

下一步

权限档位

MCP 审批走的是同一条逐工具审批回路,与权限档位的关系在这里。

Agent 引擎

内置工具清单与代理网关工具的关系。