Skip to content

fix(desktop): publish MCP tools through native capabilities - #4490

Open
me2seeks wants to merge 7 commits into
apache:mainfrom
me2seeks:fix/desktop-mcp-capability-schema
Open

fix(desktop): publish MCP tools through native capabilities#4490
me2seeks wants to merge 7 commits into
apache:mainfrom
me2seeks:fix/desktop-mcp-capability-schema

Conversation

@me2seeks

@me2seeks me2seeks commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

Summary

Desktop can connect to an MCP server while still failing to publish its tools to Runtime Host: MCP tools carry an AI SDK JSON Schema wrapper, but the native-capability adapter previously accepted Zod only. The connection then appears healthy while the model cannot see or call the tool.

Teach the single Desktop native-capability adapter to publish declared JSON Schema and, when available, honor the wrapper's validator. Zod-backed Desktop tools retain the existing path. This keeps MCP execution and validation authority where it already belongs instead of adding a Desktop-specific MCP path.

Verification

  • npm run build
  • npm --workspace @maka/desktop run typecheck
  • npm --workspace @maka/desktop run build:main
  • node --test apps/desktop/dist/main/__tests__/mcp-runtime-e2e.test.js apps/desktop/dist/main/__tests__/runtime-host-native-capabilities.test.js (15 passed)

The new end-to-end test connects the real stdio MCP fixture, builds its tools, publishes them through the Desktop capability provider, validates the protocol payload, and invokes the offered tool. No screenshot applies: this repairs capability publication behind the existing MCP settings UI.

AI use

  • No generative tool made a substantive contribution
  • Generative tooling made a substantive contribution

Tool(s) and scope: OpenAI Codex assisted investigation, implementation, tests, and review; the commit includes the required trailer.

Checklist

  • Tests cover the change and fail without it
  • Lint, format, typecheck and the affected suites pass locally

Does this PR entail a change in behavior?

  • Yes — connected Desktop MCP tools are now published to and invocable through Runtime Host.
  • No

@github-actions github-actions Bot added the effort/M Under 500 readable lines label Sep 1, 2026
@me2seeks
me2seeks force-pushed the fix/desktop-mcp-capability-schema branch 4 times, most recently from 37d94f6 to 0c2aae4 Compare September 3, 2026 10:56

@M4n5ter M4n5ter left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

English

I found two issues that should be resolved or explicitly scoped before this is treated as a complete Runtime Host fix.

  1. prepareCapabilityGroups() validates MCP tools individually, but publishes every surviving MCP tool in one desktop_mcp offer. The protocol caps an offer at 64 tools, the full manifest at 256 tools and 56 KiB. With 65 otherwise valid small tools, the complete capability replacement is rejected with Invalid Client Capability offer tools, so MCP can also prevent Browser, Settings, Rive, and the other Desktop capabilities from registering.

    The existing CLI MCP provider already sorts and chunks tools before validating the complete replacement. Desktop needs equivalent aggregate handling, including a defined policy for the total-count/byte ceiling that preserves the fixed Desktop capabilities and reports why MCP publication was omitted.

  2. The new E2E test calls provider.call() directly, so it does not cross Runtime Host admission. In the default managed ask mode, managedClientCapabilityGrantTarget() only recognizes Desktop Settings and Browser; a published desktop_mcp call still fails with Client Capability has no managed admission policy.

    This does not require moving MCP ownership into Host. If this PR is intentionally limited to publication and Full Access invocation, say that explicitly and narrow the behavior claim/test accordingly. If it is meant to make Desktop MCP invocable on the default path, wire the existing desktop_mcp / mcp_tool grant into the coordinator and add a Host-level invocation test. #4012 tracks that work, and #4143 explicitly left Desktop MCP admission to a follow-up.

I did not find a useful simplification in the adapter itself: the prepared tool/descriptor pair, per-group omission policy, and shared descriptor decoder each prevent a real consistency problem.

中文

这次改动的方向没问题,但现在还不能算“Desktop MCP 已经完整走通 Runtime Host”,有两个坑需要处理清楚。

  1. 现在只检查了每个 MCP 工具自己是否合法,最后却把剩下的工具一股脑塞进同一个 desktop_mcp offer。协议规定单个 offer 最多 64 个工具,整份清单最多 256 个工具、56 KiB。我用 65 个很小的合法工具复现后,整次 capability replacement 会直接报 Invalid Client Capability offer tools。倒霉的不只是 MCP:Browser、Settings、Rive 等同一批注册的 Desktop 能力也会一起发布失败。

    CLI 那套 MCP provider 已经会先稳定排序、分组,再校验完整清单。Desktop 至少也得把总量限制管起来;超过总工具数或字节上限时,要保证固定的 Desktop 能力还能正常注册,同时明确告诉用户为什么这次没有发布 MCP,不能让一组动态工具把整包能力拖死。

  2. 新的 E2E 实际上是直接调用 provider.call(),没有经过 Runtime Host 的准入逻辑。默认 managed ask 模式里,Host 目前只给 Desktop Settings 和 Browser 配了策略;desktop_mcp 就算成功出现在工具列表里,调用时仍然会报 Client Capability has no managed admission policy

    这里不需要把 MCP 的执行权搬到 Host。如果这个 PR 只打算修“能发布、Full Access 下能调用”,就把 PR 的行为说明和测试范围写准确;如果目标是默认模式也能用,那就把现成的 desktop_mcp / mcp_tool grant 接到 coordinator,并补一条真正穿过 Host 的调用测试。#4012 正在跟踪这件事,#4143 也明确说 Desktop MCP admission 留到后续。

简化审计没有发现值得删的结构:prepared tool/descriptor、按 group 决定是否跳过不兼容工具,以及共享 decoder,都在避免真实的一致性问题。

@me2seeks
me2seeks force-pushed the fix/desktop-mcp-capability-schema branch from 0c2aae4 to d5f1fb8 Compare September 3, 2026 14:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

effort/M Under 500 readable lines

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants