The Cartographer · 11 min mission
Configure MCP servers in Gemini CLI
Wire up local and remote MCP servers in Gemini CLI without the trust, secret, and transport traps.
On this page
An MCP (Model Context Protocol) server is an external process or remote endpoint that exposes tools, prompts, and resources to Gemini CLI. You register each server under an mcpServers block in settings.json; Gemini CLI then connects, namespaces what the server exposes, and lets the model call those tools like built-in ones. This guide covers where the config lives, how the transport is chosen, auth, the two kinds of trust, tool exposure, and the /mcp command. Current as of 2026-06-15, Gemini CLI v0.46.0.
| File path | Scope | Applies to |
|---|---|---|
~/.gemini/settings.json | User | Every project on the machine |
.gemini/settings.json | Project | That repo only — commit to share with the team |
mcp_config.json | Alternate | Read by standard MCP clients — identical mcpServers schema |
Pick a transport by setting one key
Exactly one of command, url, or httpUrl is required per server, and that key selects the transport — there is no type field. Selection is deterministic precedence: httpUrl is checked first, then url, then command; the first present wins. The remaining keys are optional modifiers.
| Set this key | Transport | Use it for |
|---|---|---|
command (+ args, cwd) | Stdio — local child process | A locally run server: an npm/Docker binary, a Python script, an internal CLI |
url (e.g. …/sse) | SSE — Server-Sent Events | A remote endpoint over the older SSE protocol |
httpUrl | Streamable HTTP | A remote endpoint over streamable HTTP — prefer this for new remote servers |
headers (object) | Modifier on url/httpUrl | Static auth/routing headers on a remote server, e.g. Authorization: Bearer … |
Add a local stdio server (GitHub via Docker)
Open the user or project settings file
Edit
~/.gemini/settings.json(user scope) or.gemini/settings.json(project scope). Create the file if it does not exist.Add an `mcpServers` entry with `command` set
Setting
commandselects the stdio transport — Gemini CLI spawns the process and talks over stdin/stdout. Put the binary incommandand its arguments inargs.Pass secrets by reference in `env`, never as literals
Use
"GITHUB_PERSONAL_ACCESS_TOKEN": "${GITHUB_PERSONAL_ACCESS_TOKEN}"so the value expands from your shell at launch and is never committed.Reconnect
Run
/mcp reloadin an interactive session to reconnect and re-discover tools, or restart Gemini CLI.
{
"mcpServers": {
"github": {
"command": "docker",
"args": [
"run", "-i", "--rm",
"-e", "GITHUB_PERSONAL_ACCESS_TOKEN",
"ghcr.io/github/github-mcp-server:latest"
],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "${GITHUB_PERSONAL_ACCESS_TOKEN}"
}
}
}
}Environment variable expansion and sanitization
In env, $VAR and ${VAR} expand on all platforms; %VAR% expands on Windows only. Undefined variables resolve to an empty string. When spawning a stdio server, Gemini CLI first sanitizes the inherited environment: it redacts GEMINI_API_KEY, GOOGLE_API_KEY, and anything whose name matches *TOKEN*, *SECRET*, *PASSWORD*, *KEY*, *AUTH*, or *CREDENTIAL*, plus certificate and private-key patterns. A secret reaches the server only if you name it explicitly in that server's env block (explicit entries are treated as consent and pass through).
Local vs. remote at a glance
Local (stdio)
Set command. Gemini CLI spawns and supervises the process; env/cwd/args shape it; the environment sanitizer applies. It shows Connected only when the current folder is trusted.
{ "command": "npx", "args": ["-y", "my-server"] }
Remote (SSE / HTTP)
Set url or httpUrl. No process is spawned; headers carry static auth and oauth handles interactive flows. Remote servers are not gated by folder trust.
{ "httpUrl": "https://api.example.com/mcp/", "headers": { "Authorization": "Bearer $API_PAT" } }
Build an mcpServers block and watch the transport flip
Codex MCP config builder
Wire an MCP server into Codex. Pick the transport, add env vars, and set tool governance — the codex mcp add command and the matching [mcp_servers.<id>] block stay in sync, so either one drops straight into your setup.
Server identity
The name becomes the [mcp_servers.<id>] table key — it gets slugified to a safe id.
Config id: context7
Transport
stdio launches a local process and talks over stdin/stdout. HTTP connects to a remote streamable endpoint.
Launch command
The command Codex spawns, plus its arguments. Everything after -- is the server launcher.
Environment variables
Passed to the launched process. Forwarded as --env KEY=VALUE on the CLI and an env = { … } map in TOML.
Tool governance
How Codex treats this server's tools. default_tools_approval_mode sets the baseline; lists narrow what's exposed.
default_tools_approval_mode
Ask before each tool call.
codex mcp add context7 \ -- npx -y @upstash/context7-mcp[mcp_servers.context7]command = "npx"args = ["-y", "@upstash/context7-mcp"]default_tools_approval_mode = "prompt"Authenticate a remote server
Remote servers (SSE or HTTP) support a spectrum of auth. The simplest is a static header — headers: { "Authorization": "Bearer $API_PAT" } — sent on every request. For OAuth-capable servers, you can omit the oauth block entirely: Gemini CLI does automatic discovery, detects a 401, reads endpoints from the server's metadata, and runs the flow. It opens a browser and listens for the redirect on http://localhost:<random-port>/oauth/callback. Tokens are stored at ~/.gemini/mcp-oauth-tokens.json and refreshed automatically.
| Key | Where | What it does |
|---|---|---|
oauth.enabled | nested oauth object | Boolean — turns on the OAuth flow for this server |
oauth.clientId / oauth.clientSecret | nested oauth | Client credentials; optional with dynamic registration / public clients |
oauth.scopes | nested oauth | String array of requested scopes |
oauth.authorizationUrl / oauth.tokenUrl | nested oauth | Endpoint URLs — auto-discovered if omitted |
oauth.redirectUri | nested oauth | Override the default random-port localhost callback |
authProviderType: google_credentials | server level | Use Google Application Default Credentials (ADC) |
authProviderType: service_account_impersonation | server level | Impersonate a GCP service account via targetAudience + targetServiceAccount |
{
"mcpServers": {
"iap-service": {
"url": "https://my-gcp-service.run.app/sse",
"authProviderType": "service_account_impersonation",
"targetAudience": "YOUR_IAP_CLIENT_ID.apps.googleusercontent.com",
"targetServiceAccount": "your-sa@your-project.iam.gserviceaccount.com"
}
}
}Trust means two different things
Gemini CLI uses "trust" for two unrelated gates. Per-server trust: true bypasses confirmation prompts: by default the first time the model calls a server's tool, Gemini CLI pauses with four choices — Proceed once, Always allow this tool (serverName.toolName), Always allow this server (serverName), Cancel. Setting trust: true skips all of them for that server. Folder trust is separate and affects stdio servers only: a command-based server is listed and shows Connected only when the current folder is trusted; in an untrusted folder it shows Disconnected by design. Run gemini trust to trust the folder. Remote (url/httpUrl) servers are never gated this way.
Control which tools are exposed
At discovery Gemini CLI iterates mcpServers, connects, lists tools, validates schemas, applies your filters, sanitizes names, registers them, then fetches resources. Every tool gets a fully qualified name mcp_{serverName}_{toolName}. The policy parser splits that name on the first underscore after mcp_, so an underscore in a server name (e.g. my_server) corrupts its identity and can make wildcard/auto-approval rules fail silently — use hyphens (my-server).
Filter exposed tools with two per-server lists: includeTools (allowlist — if set, only those are exposed) and excludeTools (blocklist). When a tool is in both, excludeTools wins. Across extension merges, excludeTools arrays are unioned and includeTools arrays are intersected, so your local settings.json keeps veto power.
| Key | Type | What it does |
|---|---|---|
includeTools | string[] | Allowlist — if set, only these tool names are exposed from this server |
excludeTools | string[] | Blocklist — takes precedence over includeTools when a tool is in both |
trust | boolean | Default false. When true, bypasses all tool-call confirmations for this server |
timeout | number (ms) | Request timeout. Default `600000` (10 min) — long calls will not fail fast |
env | object | Vars for a stdio process; supports $VAR / ${VAR} (all OSes), %VAR% (Windows) |
authProviderType | string | dynamic_discovery (default), google_credentials, or service_account_impersonation |
Manage servers with /mcp and gemini mcp
Inside an interactive session, bare /mcp defaults to list mode: each server, its status (CONNECTED / CONNECTING / DISCONNECTED), a config summary with sensitive data excluded, and the discovered tools, prompts, and resources. Outside a session, the gemini mcp subcommands manage servers for scripting.
| Command | What it does |
|---|---|
/mcp (or /mcp list, /mcp ls) | List servers, status, and discovered tools/prompts/resources |
/mcp desc | List with tool descriptions |
/mcp schema | List with descriptions and parameter schemas |
/mcp auth [server-name] | Run the OAuth flow for a server; no name lists OAuth-capable servers |
/mcp reload | Reconnect every server and re-discover tools after editing config |
/mcp enable <name> / /mcp disable <name> | Toggle a server for the session |
Resources, prompts, and diagnostics
MCP servers can expose more than tools. Resources are addressable content: Gemini CLI runs resources/list at discovery, surfaces them in /mcp, and pulls one into chat via an @ reference — @server://resource/path — calling resources/read on submit. Prompts become slash commands: a server prompt named poem-writer is invoked as /poem-writer --title="Gemini CLI" --mood="reverent" (or with positional args). A server's own instructions are appended to Gemini CLI's system instructions.
Background MCP connection errors are silent by default; on startup you get one hint — "MCP issues detected. Run /mcp list for status." Detailed diagnostics re-enable when you run /mcp list or /mcp auth, when the model calls a server tool, or when you invoke an MCP prompt. Launch with --debug (F12 in interactive) for verbose output while wiring up a new server.
Knowledge check
You add a remote MCP server and want it to use the current streamable-HTTP transport, with a bearer token on every request. Which config is correct?
Reach the end and this star joins your charted sky.