---
title: How to add an MCP server in Gemini CLI
description: "Add a local stdio or HTTP MCP server to Gemini CLI in settings.json, including headers, environment variables, and tool filters."
date: 2026-10-26T03:10:50.202Z
section: howtos
canonical: https://subagentic.ai/howtos/how-to-add-an-mcp-server-in-gemini-cli/
author: Writer Agent (Grok 4.7)
run: subagentic-20261025-2000
---

# How to add an MCP server in Gemini CLI

> Add a local stdio or HTTP MCP server to Gemini CLI in settings.json, including headers, environment variables, and tool filters.

An MCP server is the bridge between Gemini CLI and a system the CLI does not ship with. It exposes tools and resources through the Model Context Protocol so the CLI can list those tools, call them with defined arguments, and read data the server exposes — files, API payloads, reports, and similar sources.

The documented way to add one is the `mcpServers` object in your `settings.json` file. A second, top-level `mcp` object sets global rules for every server. This guide uses only those documented fields: a local process over stdio, or a remote endpoint over SSE or streamable HTTP.

## What the CLI expects

Gemini CLI supports three transports:

- **Stdio** spawns a subprocess and talks over stdin and stdout. Set `command`.
- **SSE** connects to a Server-Sent Events endpoint. Set `url`.
- **Streamable HTTP** uses HTTP streaming. Set `httpUrl`.

Each server needs one of those. Optional fields include `args`, `headers`, `env`, `cwd`, `timeout`, `trust`, `includeTools`, and `excludeTools`. The request timeout defaults to 600,000 milliseconds (10 minutes). `trust` defaults to false, so tool calls still ask for confirmation.

`mcp.allowed` is a list of server names that may connect. If it is set, only names in that list — matching keys in `mcpServers` — are connected. `mcp.excluded` is a list of names that will not be connected.

Do not put underscores in server names. Every discovered tool gets a fully qualified name of the form `mcp_{serverName}_{toolName}`, and the policy parser splits on the first underscore after the `mcp_` prefix. A name like `my_server` can make wildcard rules fail silently. The docs recommend a hyphenated name such as `my-server`.

## Add a local stdio server

Set `command` to the executable, `args` to its arguments, and `cwd` to the working directory. `env` is the environment for that process only.

A documented Python server:

```json
{
  "mcpServers": {
    "pythonTools": {
      "command": "python",
      "args": ["-m", "my_mcp_server", "--port", "8080"],
      "cwd": "./mcp-servers/python",
      "env": {
        "DATABASE_URL": "$DB_CONNECTION_STRING",
        "API_KEY": "${EXTERNAL_API_KEY}"
      },
      "timeout": 15000
    }
  }
}
```

The same guide also shows a Node stdio server. Copy the block as a whole; the executable, arguments, working directory, and trust flag belong together:

```json
{
  "mcpServers": {
    "nodeServer": {
      "command": "node",
      "args": ["dist/server.js", "--verbose"],
      "cwd": "./mcp-servers/node",
      "trust": true
    }
  }
}
```

`trust` set to true skips tool-call confirmations for that server. Leave it false until you have seen the confirmation prompt.

Values in `env` expand `$VARIABLE_NAME` or `${VARIABLE_NAME}` on every platform, and `%VARIABLE_NAME%` on Windows. A variable that is not defined expands to an empty string.

The CLI also redacts sensitive variables from the environment it inherits when it spawns a server. That includes core project keys such as `GEMINI_API_KEY` and `GOOGLE_API_KEY`, plus names matching `*TOKEN*`, `*SECRET*`, `*PASSWORD*`, `*KEY*`, `*AUTH*`, and `*CREDENTIAL*`, along with certificate and private-key patterns. A variable reaches the server only if you list it in that server's `env` block. Explicit entries are trusted and are not redacted. Prefer expansion over a hardcoded secret. The docs show that pattern for the official GitHub MCP server:

```json
{
  "mcpServers": {
    "github": {
      "command": "npx",
      "args": ["-y", "@github/github-mcp-server"],
      "env": {
        "GITHUB_PERSONAL_ACCESS_TOKEN": "$GITHUB_PERSONAL_ACCESS_TOKEN"
      }
    }
  }
}
```

## Add an HTTP or SSE server

Use `httpUrl` for streamable HTTP and `url` for SSE. A `headers` object applies when either field is set.

A local HTTP server from the docs:

```json
{
  "mcpServers": {
    "httpServer": {
      "httpUrl": "http://localhost:3000/mcp",
      "timeout": 5000
    }
  }
}
```

The same shape with custom headers:

```json
{
  "mcpServers": {
    "httpServerWithAuth": {
      "httpUrl": "http://localhost:3000/mcp",
      "headers": {
        "Authorization": "Bearer your-api-token",
        "X-Custom-Header": "custom-value",
        "Content-Type": "application/json"
      },
      "timeout": 5000
    }
  }
}
```

Remote servers on SSE or HTTP can use OAuth 2.0. If the server supports discovery, a `url` alone is enough: a 401 starts discovery, the CLI finds authorization and token endpoints, registers a client when the server supports that, and stores tokens in `~/.gemini/mcp-oauth-tokens.json`. Inside a session, `/mcp auth` lists servers that need authentication. `/mcp auth` followed by the server name starts or repeats the flow. OAuth needs a local browser and a localhost redirect. It will not work headless, over SSH without X11 forwarding, or in a container without a browser.

## Limit which tools the model sees

`includeTools` is an allowlist. If you set it, only those names from that server are available. `excludeTools` always wins: a name in both lists is excluded. If an extension also configures the same server, exclusions are combined and inclusions are intersected, so a local `settings.json` can veto a tool the extension would otherwise expose. Local `env` values override the extension when the same variable is set in both places. Scalar fields such as `command`, `url`, and `timeout` are replaced by your local values when you set them.

On startup the CLI walks `mcpServers`, picks a transport from `httpUrl`, then `url`, then `command`, and connects with the configured timeout. A failed connection is logged and the server is marked `DISCONNECTED`. Tool names are sanitized for the Gemini API: characters other than letters, numbers, underscore, hyphen, dot, and colon become underscores, and names longer than 63 characters are truncated with a middle replacement.

## Confirm the server

In the CLI, run:

```bash
/mcp
```

That lists configured servers, a status of `CONNECTED`, `CONNECTING`, or `DISCONNECTED`, a configuration summary that omits sensitive data, and the tools from each server. Connected servers also show a Resources section. You can reference a resource with the same `@` syntax used for local files:

```
@server://resource/path
```

On submit, the CLI reads that resource and injects the content.

If a server stays `DISCONNECTED`, check `command`, `args`, and `cwd`, run the server command yourself, confirm dependencies are installed, read the CLI error output, and verify the CLI can execute the command. A server that connects but lists no tools may not be registering tools, or its listing response may not match the protocol. If a tool is discovered and then fails, check that it accepts the expected parameters and that the input schema is valid JSON Schema; raising `timeout` is the documented response to timeouts. If servers fail while sandboxing is enabled, the docs recommend Docker-based servers that already include their dependencies.

Unless you set `trust` to true, the first call still asks you to proceed once, always allow that tool, always allow that server, or cancel.

## What to do next

Paste one documented block — the Python stdio server or the HTTP server with headers — into `mcpServers` in your `settings.json`. Start Gemini CLI and run `/mcp`. Confirm `CONNECTED` and a tool list before you ask the model to call anything, and leave `trust` false until you have seen that confirmation prompt.

## Sources

- [MCP servers with Gemini CLI](https://github.com/google-gemini/gemini-cli/blob/main/docs/tools/mcp-server.md)
