Skip to content

fix(zed): translate MCP servers, map the global default and write_file, use the Windows config dir - #2450

Merged
dyoshikawa merged 2 commits into
mainfrom
resolve-scrap-issue-2415-zed
Jul 28, 2026
Merged

fix(zed): translate MCP servers, map the global default and write_file, use the Windows config dir#2450
dyoshikawa merged 2 commits into
mainfrom
resolve-scrap-issue-2415-zed

Conversation

@dyoshikawa

Copy link
Copy Markdown
Owner

Summary

Fixes gaps 1, 3, 4 and 7 of #2415 (Refs #2415 — gaps 2, 5 and 6 are feature additions and stay open there). Zed silently ignores config keys it does not know, so several canonical fields used to produce settings Zed reads as something else — most seriously, a server the user disabled in rulesync was emitted enabled.

Changes

Gap 1 — MCP translation (zed-mcp.ts). context_servers entries are now translated into the shapes Zed's untagged enum actually parses, instead of forwarding canonical fields verbatim:

  • disabled: trueenabled: false (and imports back as disabled: true); a server that says nothing about disabled writes no enabled key.
  • httpUrl is normalized to the url Zed reads; an array command is flattened to Zed's single command string with the rest prepended to args.
  • Canonical-only keys (type/transport, alwaysAllow, trust, cwd, networkTimeout, the Kiro lists…) are dropped — the drop list is derived from McpServerSchema itself, so unknown fields (a remote server's oauth, an extension server's settings) pass through untouched.
  • A server Zed cannot start is skipped with a warning via the shared mcp-transport.ts helpers: sse/ws transports (Zed has neither), a remote server with no url, a local one with no command.
  • A transport-less server is written as Zed's extension-provided variant, and on import lands in the tool-scoped zed.mcpServers block rather than the shared map (mirroring the Kilo/OpenCode handling from fix(kilo): accept a bare MCP toggle entry, and type steps as the number it is #2448).

Gap 3 — global tool-permission default (zed-permissions.ts). The canonical * category's catch-all rule now sets agent.tool_permissions.default (rung 6 of Zed's precedence ladder, and the documented mechanism for MCP tools) instead of an inert tools["*"] entry. Round-tripped on import; a stale tools["*"] entry written by an earlier version is cleaned up when the canonical config carries a * category; pattern-scoped *-category rules are dropped with a warning; a user-set default survives when canonical says nothing.

Gap 4 — write mapping. Canonical write maps to Zed's write_file tool (same class of bug as the fixed web_searchsearch_web, #1850). Also corrected the stale websearch → web_search claim in the docs.

Gap 7 — Windows global path. getZedGlobalDir() resolves the user config dir to %APPDATA%\Zed on Windows (per Zed's docs) for rules, MCP and permissions. Both spellings are declared to the shared-write derivation via getExtraSharedWritePaths and to the gateway ownership table, so the cross-check tests stay platform-complete; the zed-related e2e specs now use the platform-aware path.

Verification

  • pnpm cicheck green (unit tests include new cases for every behavior above).
  • e2e-mcp / e2e-permissions / e2e-rules specs pass locally.
  • Upstream claims re-verified against zed.dev docs (MCP shapes, tool-permission list and default, %APPDATA%\Zed paths).

🤖 Generated with Claude Code

cm-dyoshikawa and others added 2 commits July 28, 2026 06:12
…e, use the Windows config dir

Zed silently ignores config keys it does not know, so several canonical
fields used to produce settings Zed reads as something else - most
seriously a server with disabled: true was emitted enabled.

- MCP: translate canonical servers into the context_servers shapes Zed
  parses (disabled -> enabled: false, httpUrl -> url, array command ->
  string command + args), drop canonical-only keys, pass unknown fields
  through, skip sse/ws/url-less/command-less servers with a warning,
  write a transport-less server as the extension variant and import it
  into the zed-scoped block.
- permissions: the canonical * category's catch-all now sets
  agent.tool_permissions.default instead of an inert tools['*'] entry
  (round-tripped, stale entry cleaned up), and canonical write maps to
  Zed's write_file tool.
- global scope: resolve the user config dir to %APPDATA%/Zed on Windows
  for rules, MCP and permissions, with both spellings declared to the
  shared-write derivation and gateway ownership table.

Refs #2415 (fixes gaps 1, 3, 4 and 7; gaps 2, 5, 6 stay open there).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…en MCP entry handling

Review follow-ups on the previous commit:

- toRulesyncPermissions read a stale tools['*'] entry (which Zed ignores)
  after the top-level default (which Zed enforces), so the ignored value
  overwrote the enforced one in the canonical model - a deny could come
  back as allow. The stale entry is now read only when no enforced
  default exists.
- A transport-less server's canonical fields beyond disabled are dropped
  with a warning naming them, matching the Kilo toggle convention.
- A null or array context_servers entry is skipped on import instead of
  crashing the run with a destructuring TypeError.
- A non-boolean enabled value stays in place on import instead of having
  a disablement intent silently erased.

Refs #2415

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@dyoshikawa
dyoshikawa merged commit 6cb9946 into main Jul 28, 2026
9 checks passed
@dyoshikawa

Copy link
Copy Markdown
Owner Author

@dyoshikawa Thank you!

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants