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

# Screen MCP tool calls in Gemini CLI

Gemini CLI starts each MCP server in its settings 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.

One thing about Gemini CLI matters more than the rest here: it strips variables that look like secrets from a server's environment, and `TYPESAFE_API_KEY` looks like one. This covers MCP servers only. Gemini CLI's own shell commands and file edits do not go through MCP.

## Install it

```
npm install -g agent-chaperone
```

A global install means Gemini CLI 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

Servers live under `mcpServers` in `~/.gemini/settings.json`, and in `.gemini/settings.json` inside a project. A server before and after:

```
{
  "mcpServers": {
    "filesystem": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-filesystem", "/Users/me/project"]
    }
  }
}
```

```
{
  "mcpServers": {
    "filesystem": {
      "command": "agent-chaperone",
      "args": ["--server", "filesystem", "--",
               "npx", "-y", "@modelcontextprotocol/server-filesystem", "/Users/me/project"],
      "env": { "TYPESAFE_API_KEY": "$TYPESAFE_API_KEY" }
    }
  }
}
```

Everything after `--` is the server that would have run anyway. `--server` names the section of the policy file that applies. The `env` line is not optional on Gemini CLI, and the next section says why.

`agent-chaperone wrap ~/.gemini/settings.json` can make the command change, but not the `env` line, which you add afterwards. It reads the file as strict JSON, and Gemini CLI allows comments in its settings, so a file with comments is refused with an error and left untouched. A server Gemini CLI reaches by `url` is wrapped too, from 0.3.2. Gemini CLI reaches a `url` entry over Streamable HTTP, the transport the proxy uses too, unless the entry says `"type": "sse"`, and a `"type": "http"` becomes `stdio` once the entry runs a command. An entry that declares SSE, or carries its own `headers`, is left alone and the output says why. So is one written with `httpUrl`, the older spelling Gemini CLI has deprecated in favour of `url` with `"type": "http"`; make that change and run `wrap` again.

## Give it the API key

Gemini CLI removes variables from a server's inherited environment when their names suggest a credential, and a name containing `KEY` is one of the patterns. So a `TYPESAFE_API_KEY` exported in your shell never reaches the proxy on its own, and every judgment would record that no model was asked.

A variable set in the server's own `env` is not removed. Writing it as `"$TYPESAFE_API_KEY"` makes Gemini CLI fill in the value from its own environment when it reads the settings, so the key itself is never written into the file. It has to be exported in the shell Gemini CLI is started from; a missing variable becomes an empty string.

The proxy removes its own keys before it starts the server behind it, so the server never receives `TYPESAFE_API_KEY`, even though Gemini CLI handed it over.

## Check that it is working

Gemini CLI only starts a local server in a folder you have trusted, and shows it as disconnected anywhere else. `/mcp` inside a session, or `gemini mcp list` from the shell, shows each server's state.

Then use the server once from the agent 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 on Gemini CLI almost always means the `env` line is missing.

## What this does not cover

- **Gemini CLI's own tools.** Shell commands, file reads and file edits that Gemini CLI runs itself never cross an MCP connection. Gemini CLI has hooks for them, and an adapter for those [does not exist yet](https://github.com/agent-chaperone/agent-chaperone/issues/78).
- **A server that authenticates with headers.** Headers written in the Gemini CLI 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, and pass the token with `--header-env`.
- **A server that speaks only SSE.** The proxy reaches a URL over Streamable HTTP and nothing else, so an entry with `"type": "sse"` stays as it is.
- **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/gemini-cli
Put Gemini CLI's MCP servers behind agent-chaperone, and get the API key past the filter that strips anything named like a credential.
