Screen MCP tool calls in VS Code

VS Code starts each MCP server you configure for agent mode as a local process and talks to it over stdio. agent-chaperone goes in front of that process. It reads each tool call before the server gets it and each result before the agent does, and nothing about the server changes.

This page covers MCP servers. The terminal commands and file edits the agent runs through VS Code's own tools do not go through MCP, so the proxy does not see them. From 0.4.0, VS Code's agent hooks, a preview feature, reach them instead: the configuration is in the hooks reference.

Install it #

npm install -g agent-chaperone

A global install means VS Code starts the proxy directly. Running it through npx works too, but adds a package lookup every time a server starts.

Put a server behind it #

VS Code reads servers from .vscode/mcp.json in a workspace and from the mcp.json in your user profile, which MCP: Open User Configuration opens. Both list servers under servers, not mcpServers. A server before and after:

{
  "servers": {
    "filesystem": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-filesystem", "${workspaceFolder}"]
    }
  }
}
{
  "servers": {
    "filesystem": {
      "type": "stdio",
      "command": "agent-chaperone",
      "args": ["--server", "filesystem", "--",
               "npx", "-y", "@modelcontextprotocol/server-filesystem", "${workspaceFolder}"]
    }
  }
}

Everything after -- is the server that would have run anyway, and VS Code still fills in variables like ${workspaceFolder} before it starts anything. --server names the section of the policy file that applies.

agent-chaperone wrap can make the edit. It reads the file as strict JSON, and VS Code allows comments in mcp.json, so a file with comments is refused with an error and left untouched; edit that one by hand as above. A server VS Code reaches by URL is wrapped too, from 0.3.2, with its type changed from http to stdio because the entry now runs a command, and --unwrap changes it back. One that carries its own headers, or declares the older SSE transport, is left alone and the output says why.

agent-chaperone wrap .vscode/mcp.json
agent-chaperone wrap .vscode/mcp.json --write

A new server can also be added from the command line, straight into your user profile:

code --add-mcp '{"name":"filesystem","command":"agent-chaperone","args":["--server","filesystem","--","npx","-y","@modelcontextprotocol/server-filesystem","/Users/me/project"]}'

Give it the API key #

The model screens need TYPESAFE_API_KEY. A server started by VS Code gets VS Code's own environment, and on macOS VS Code reads your shell profile when it starts, including when it is opened from the Dock. A key exported in .zshrc or .bashrc reaches the proxy once VS Code has been restarted. If VS Code shows an error about resolving your shell environment, starting it with code . from a terminal avoids the problem.

To keep the key out of your shell profile, point the entry at a file of NAME=value lines with envFile:

"filesystem": {
  "type": "stdio",
  "command": "agent-chaperone",
  "args": ["--server", "filesystem", "--", "npx", "-y", "@modelcontextprotocol/server-filesystem", "${workspaceFolder}"],
  "envFile": "/Users/me/.config/agent-chaperone/env"
}

The proxy removes its own keys before it starts the server behind it, so the server never receives TYPESAFE_API_KEY either way.

Without a key the proxy still starts, the deterministic rules still run, and every judgment records that no model was asked. It never refuses to start because a key is missing.

Check that it is working #

A server in .vscode/mcp.json only starts in a trusted workspace. Run MCP: List Servers, pick the server, and Show Output has what the process printed, including a line from the proxy if it started without a key.

Then use the server once from agent mode and read what was decided:

agent-chaperone log

Each line is one call or result, with the decision and, in shadow mode, what enforcing would have done instead. A line ending in [not screened] was decided without a model, which means the key did not arrive.

What this does not cover #

Next #

It starts in shadow mode, which blocks nothing. The MCP guide covers what each screen asks, how to read a shadow-mode log, and when to switch to enforce. The exact wording of every question is in the design document.