<!-- Generated from /guides/vscode by scripts/make-markdown.mjs. The page is the source. -->

# 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](https://agentchaperone.dev/docs/hooks#vs-code).

## 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

- **VS Code's own tools, without hooks.** Terminal commands and file edits the agent makes through VS Code's built-in tools never cross an MCP connection. [Hooks](https://agentchaperone.dev/docs/hooks#vs-code) reach them, from 0.4.0, with limits. A result judged unsafe is annotated and still reaches the model, because VS Code has no way for a hook to replace a result, and a tool that failed is not screened, because VS Code fires no event for it. The hooks were written against VS Code's published contract and have not been checked in a live run of VS Code yet.
- **A server that authenticates with headers.** Headers written in the VS Code entry never reach the proxy, which is why `wrap` leaves such an entry alone. Put it behind the proxy by hand, as [the MCP guide](https://agentchaperone.dev/guides/mcp-security#wrap) shows, with `type` set to `stdio`, and pass the token with `--header-env`.
- **A server that speaks only the older SSE transport.** The proxy reaches a URL over Streamable HTTP and nothing else.
- **What a server does rather than what the call says.** This is not a sandbox. It reads the call and the result, and a server that does something its arguments did not describe is outside it.

## Next

It starts in shadow mode, which blocks nothing. [The MCP guide](https://agentchaperone.dev/guides/mcp-security) 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](https://agentchaperone.dev/docs/design).

---

Source: https://agentchaperone.dev/guides/vscode
Put VS Code agent mode's MCP servers behind agent-chaperone: the mcp.json change, the API key, when wrap can edit the file, and what it misses.
