Editor MCP Recipe: policy-enforcing MCP in Claude Code, Cursor, Codex¶
Coding agents are MCP clients. You can put Assay between the agent and the MCP servers it uses by wrapping each server with assay mcp wrap, so every tool call is checked against your policy inline. No bespoke plugin is needed; you only change the server command in the agent's standard MCP config.
Install the Claude Code plugin¶
The marketplace plugin packages Assay's five MCP review tools and the assay-golden-path skill. It does not package either required binary: the skill uses the assay CLI, and the review tools use assay-mcp-server. The plugin does not invoke a target tool or enforce another MCP server by itself.
From the project where Claude Code should use Assay:
# 1. Install both prerequisites and confirm they are on PATH.
cargo install assay-cli --version 6.4.0 --locked
cargo install assay-mcp-server --version 6.4.0 --locked
assay version
assay-mcp-server --version
# 2. Add Assay's marketplace and install the plugin for this project.
claude plugin marketplace add Rul1an/assay
claude plugin install assay@assay --scope local
# 3. Verify that the installed plugin can start the server.
claude mcp list
# assay-editor-plugin-install-commands:end
Restart Claude Code after installation, then ask it to use assay:assay-golden-path. The skill carries its contract and the three fixtures it needs from the isolated plugin cache. Python is optional for steps 1-5; only the protected-action simulation in step 6 runs the bundled Python fixture.
The plugin starts assay-mcp-server --policy-root .. The . is resolved from the working directory supplied by the host; project scope does not by itself prove that the host selected the project root. If it did not, override the Assay entry in project MCP configuration with an explicit absolute --policy-root; do not edit the installed plugin cache.
Update and inspect stale state¶
Plugin updates may activate immediately. If the current session still shows stale plugin state, run /reload-plugins in Claude Code or restart the session before inspecting.
claude plugin marketplace update assay
claude plugin update assay@assay --scope local
claude plugin list --json
The JSON listing exposes the installed cache version and path. If an update still shows old bytes, remove and reinstall assay@assay rather than modifying the cache.
Diagnose the layer that failed¶
| Observation | Layer | Next step |
|---|---|---|
assay@assay is absent from claude plugin list --json | Plugin installation | Add/update the assay marketplace, then install the local-scope plugin. |
The skill cannot run assay version | CLI prerequisite | Run command -v assay, install assay-cli on PATH, then restart Claude Code. |
claude mcp list reports a spawn or command failure | Binary prerequisite | Run command -v assay-mcp-server, install it on PATH, then restart Claude Code. |
| The server connects but reports a missing policy | Project policy root | Start Claude Code from the project or configure an explicit absolute --policy-root. |
assay_policy_decide returns allowed=false | Assay policy verdict | Inspect the matched rule and change the proposed action or the reviewed policy. This is not an installation failure. |
A missing plugin, failed process spawn, or unavailable policy is never a clean Assay verdict. The server is local stdio and needs no network or transport authentication, but installing it does not prove provider execution or external side effects.
Maintainers can exercise the bounded, disposable installation contract without touching their normal Claude configuration:
Install Assay's review tools¶
The repository ships project configuration for the five tools exposed by the standalone assay-mcp-server binary. Install that binary on PATH, then open the repository in your client:
- Claude Code reads
.mcp.jsonfrom the repository root. - Cursor reads
.cursor/mcp.json. - Codex users can add the equivalent entry to project
.codex/config.tomlor user~/.codex/config.toml:
The server is local stdio and needs no network or transport authentication. It evaluates policy and trace inputs supplied to its tools; it does not invoke or enforce the target MCP tool call. --policy-root . resolves policy paths against the server process's working directory. If a host uses another directory, set an explicit local policy root in that client's uncommitted user or project configuration.
The release build exposes assay_check_args, assay_check_sequence, assay_policy_decide, assay_check_coverage, and assay_explain_trace. assay_test_outbound is test-feature-only and is not part of the release surface. Plain stdio mode exposes these review tools; it does not imply the separate proxy-enforce mode is active.
The rest of this guide covers a different surface: wrapping a real MCP server so Assay can enforce its tool calls at the protocol boundary.
The wrap command¶
Key options:
| Option | Effect |
|---|---|
--policy <PATH> | Policy file (default assay.yaml) |
--dry-run | Log decisions, do not block (start here) |
--verbose | Print decisions to stderr |
Recommended path: run with --dry-run first to see decisions, then drop it to enforce.
Claude Code¶
In your project MCP config, set the server's command to the wrapped form:
{
"mcpServers": {
"files": {
"command": "assay",
"args": ["mcp", "wrap", "--policy", "assay.yaml", "--",
"<real-mcp-server>", "<server-args>"]
}
}
}
Cursor¶
In .cursor/mcp.json, same shape:
{
"mcpServers": {
"files": {
"command": "assay",
"args": ["mcp", "wrap", "--policy", "assay.yaml", "--",
"<real-mcp-server>", "<server-args>"]
}
}
}
Codex¶
In your AGENTS.md / Codex MCP config, register the same wrapped command as the server entry. Codex uses project .codex/config.toml or user ~/.codex/config.toml; assay mcp config-path does not discover Codex config.
Remote servers¶
This recipe covers local stdio servers only, because that is the transport Assay enforces today. assay-mcp-server negotiates the legacy revisions 2024-11-05, 2025-06-18, and 2025-11-25 over stdio; a request declaring MCP revision 2026-07-28 is refused with JSON-RPC error -32022 rather than accepted, and the constant naming that revision is deprecated and read by no dispatch path.
Assay ships no remote HTTP transport for the wrapped server, so there is nothing here to point an editor at for a remote endpoint. The negotiated modern surface is tracked in #2358 and is not delivered; treat any remote-transport guidance as design work under that issue, not as a step in this recipe.
Honest limits¶
assay mcp wrapenforces policy at the MCP protocol boundary (which tools, which arguments). It is the protocol-level complement to kernel-level containment, not a replacement for it, and not a prompt-injection defense.- Least privilege still applies: scope the wrapped server's filesystem and network access, and grant more only when needed.
See also: Coding-Agent Governance, ADR-036.