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.

gemini-climcpconfigurationtoolsoauthFact-checked 2026-06-15
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 pathScopeApplies to
~/.gemini/settings.jsonUserEvery project on the machine
.gemini/settings.jsonProjectThat repo only — commit to share with the team
mcp_config.jsonAlternateRead by standard MCP clients — identical mcpServers schema
Where MCP config lives. Same `mcpServers` schema in every file.

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 keyTransportUse it for
command (+ args, cwd)Stdio — local child processA locally run server: an npm/Docker binary, a Python script, an internal CLI
url (e.g. …/sse)SSE — Server-Sent EventsA remote endpoint over the older SSE protocol
httpUrlStreamable HTTPA remote endpoint over streamable HTTP — prefer this for new remote servers
headers (object)Modifier on url/httpUrlStatic auth/routing headers on a remote server, e.g. Authorization: Bearer …
The property selects the transport. Set exactly one of the first three keys per server.

Add a local stdio server (GitHub via Docker)

  1. 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.

  2. Add an `mcpServers` entry with `command` set

    Setting command selects the stdio transport — Gemini CLI spawns the process and talks over stdin/stdout. Put the binary in command and its arguments in args.

  3. 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.

  4. Reconnect

    Run /mcp reload in an interactive session to reconnect and re-discover tools, or restart Gemini CLI.

~/.gemini/settings.json — local stdio server
json
{
  "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.

CLIcodex mcp add
codex mcp add context7 \    -- npx -y @upstash/context7-mcp
Config~/.codex/config.toml
[mcp_servers.context7]command = "npx"args = ["-y", "@upstash/context7-mcp"]default_tools_approval_mode = "prompt"
Toggle the transport and see the required key swap between `command`+`args`, `url`, and `httpUrl`; flip trust, include/exclude lists, env secret pass-through, and OAuth, and read the live `mcpServers` JSON it produces.

Authenticate a remote server

Remote servers (SSE or HTTP) support a spectrum of auth. The simplest is a static headerheaders: { "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.

KeyWhereWhat it does
oauth.enablednested oauth objectBoolean — turns on the OAuth flow for this server
oauth.clientId / oauth.clientSecretnested oauthClient credentials; optional with dynamic registration / public clients
oauth.scopesnested oauthString array of requested scopes
oauth.authorizationUrl / oauth.tokenUrlnested oauthEndpoint URLs — auto-discovered if omitted
oauth.redirectUrinested oauthOverride the default random-port localhost callback
authProviderType: google_credentialsserver levelUse Google Application Default Credentials (ADC)
authProviderType: service_account_impersonationserver levelImpersonate a GCP service account via targetAudience + targetServiceAccount
OAuth and Google Cloud auth keys for remote servers.
IAP-protected GCP service via service-account impersonation
json
{
  "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.

KeyTypeWhat it does
includeToolsstring[]Allowlist — if set, only these tool names are exposed from this server
excludeToolsstring[]Blocklist — takes precedence over includeTools when a tool is in both
trustbooleanDefault false. When true, bypasses all tool-call confirmations for this server
timeoutnumber (ms)Request timeout. Default `600000` (10 min) — long calls will not fail fast
envobjectVars for a stdio process; supports $VAR / ${VAR} (all OSes), %VAR% (Windows)
authProviderTypestringdynamic_discovery (default), google_credentials, or service_account_impersonation
Per-server keys beyond the transport selector. Defaults from the official MCP server doc.

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.

CommandWhat it does
/mcp (or /mcp list, /mcp ls)List servers, status, and discovered tools/prompts/resources
/mcp descList with tool descriptions
/mcp schemaList with descriptions and parameter schemas
/mcp auth [server-name]Run the OAuth flow for a server; no name lists OAuth-capable servers
/mcp reloadReconnect every server and re-discover tools after editing config
/mcp enable <name> / /mcp disable <name>Toggle a server for the session
Interactive `/mcp` subcommands (official commands.md).
discover, diagnose, reload
… scroll to run this session
Triage loop: list servers, spot the stdio server stuck Disconnected on folder trust, fix it, and reload.

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.