There is deliberately no zig_build, zig_test or zig_format here. They existed, and the author checked what actually happened: 526 invocations of zig build through the shell and zero calls to the tool that wrapped it — because a wrapper loses pipes, redirection and its own working directory. What remains is only what a shell genuinely cannot do: types that exist after comptime and never appear in the file, references that know about scope, and a syntax-tree query that will not match your comments. That is a rarer kind of design decision than the tool list itself.
A bridge between an MCP client and ZLS, the Zig language server. It spawns ZLS as a child process, speaks LSP to it and MCP to the assistant, and exposes fourteen tools that all answer from the compiler's semantic model rather than from text.
- The one true declaration for a symbol, followed through imports and aliases, addressed either by name or by file, line and character (zig_definition).
- Real usages rather than string matches — scope-aware, skipping same-named identifiers, comments and string literals, and searching through re-exports in symbol mode (zig_references).
- The type after comptime evaluation and inference, which is not visible anywhere in the source text, on hover or for every inferred type in a file at once (zig_hover, zig_inlay_hints).
- Errors for one file without building the project, re-synced against disk first (zig_diagnostics).
- Declarations by name across the workspace, and a file's outline with kinds and nesting (zig_workspace_symbols, zig_document_symbols).
- What can legally follow at a position with types attached, and the real signature at a call including comptime and generic parameters (zig_completion, zig_signature_help).
- Which files a rename would touch, scope-aware, and the quick fixes ZLS offers for a range (zig_rename, zig_code_action).
- The declaration of a value's type rather than of the value itself (zig_type_definition).
- Code matched by shape over the syntax tree — empty catch blocks, catch unreachable, undefined initializers, unreachable, @panic — so comments and string literals never match and multi-line forms always do (zig_ast_query).
- Private declarations nothing refers to, which is exact rather than heuristic because a non-pub name cannot escape its file (zig_unused_private).
Zig 0.17.0-dev.1415+64dfaa568 or newer, and ZLS — auto-detected from PATH, or pointed at with --zls-path. Installing as a Claude Code plugin builds the binary on first use and configures everything; otherwise clone and `zig build -Doptimize=ReleaseFast`. Point --workspace at the project root, or it uses the current directory.
One command — claude plugin marketplace add nzrsky/zig-mcp && claude plugin install zig-mcp@zig
