Skip to content

Desktop: a native-capability tool skipped by the offer probe is invisible in Settings (MCP page still lists it as available) #4691

Description

@liuxiaocs7

Summary

#4592 makes an unrepresentable native-capability tool survivable: offerableToolDescriptor (apps/desktop/src/main/runtime-host-native-capabilities.ts) skips a tool whose schema can't be expressed over the Client Capability protocol and console.warns it, instead of failing the whole registration. That's a strictly better trade than the total outage it replaces — but it swaps a loud failure for a silent one: a skipped tool simply vanishes from the offer, and the only diagnostic is a main-process console line the user never sees.

Where the user actually looks, the tool still reads as live. The Settings MCP page renders the MCP manager's snapshot directly:

  • apps/desktop/src/renderer/mcp-page.tsx:922-924 shows status.tools.length and lists status.tools by name.
  • status.tools comes from McpServerStatus (packages/core/src/mcp.ts:308), which is populated by the MCP manager and knows nothing about the Desktop offer probe.

So a server can report "connected, N tools" in Settings while the model was handed fewer than N — the dropped tool is present in the manager snapshot but absent from the capability offer. No error, no indication which tool is missing or why.

Impact

Correctness of the surface, not of execution — the model genuinely doesn't have the skipped tool, and calling it isn't possible, so there's no wrong-result risk. But a user debugging "why won't the model use tool X" gets no signal from the UI, and the count in Settings actively contradicts what's available. Common triggers are ordinary MCP output: a JSON Schema keyword outside the protocol allowlist (prefixItems from a pydantic tuple[...], contentEncoding from bytes, patternProperties, not, if/then/else, deprecated), pending allowlist widening in #4614.

Proposal

Thread the skipped-tool information back to a user-visible seam so Settings can show which tools were dropped and why:

  • McpServerStatus already carries error?: string and stderrTail?: string[] — a parallel field (e.g. unofferedTools / skippedTools, name + reason) is a natural place, and mcp-page.tsx already renders status.error / status.stderrTail, so the row has somewhere to put it.
  • The offer probe in runtime-host-native-capabilities.ts already knows the exact serverId/name and the decode error at skip time; the gap is purely plumbing that back to the manager/status, which currently runs on the offering side and never reaches the manager snapshot.

Notes

Filed with Claude Code.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions