docs/tools/mcp-server.md
This document provides a guide to configuring and using Model Context Protocol (MCP) servers with Gemini CLI.
An MCP server is an application that exposes tools and resources to the Gemini CLI through the Model Context Protocol, allowing it to interact with external systems and data sources. MCP servers act as a bridge between the Gemini model and your local environment or other services like APIs.
An MCP server enables Gemini CLI to:
With an MCP server, you can extend Gemini CLI's capabilities to perform actions beyond its built-in features, such as interacting with databases, APIs, custom scripts, or specialized workflows.
Gemini CLI integrates with MCP servers through a sophisticated discovery and
execution system built into the core package (packages/core/src/tools/):
mcp-client.ts)The discovery process is orchestrated by discoverMcpTools(), which:
settings.json
mcpServers configurationmcp-tool.ts)Each discovered MCP tool is wrapped in a DiscoveredMCPTool instance that:
Gemini CLI supports three MCP transport types:
Some MCP servers expose contextual “resources” in addition to the tools and prompts. Gemini CLI discovers these automatically and gives you the possibility to reference them in the chat. For more information on the tools used to interact with these resources, see MCP resource tools.
resources/list results./mcp command displays a Resources section alongside Tools and Prompts
for every connected server.This returns a concise, plain-text list of URIs plus metadata.
You can use the same @ syntax already known for referencing local files:
@server://resource/path
Resource URIs appear in the completion menu together with filesystem paths. When
you submit the message, the CLI calls resources/read and injects the content
in the conversation.
Gemini CLI uses the mcpServers configuration in your settings.json file to
locate and connect to MCP servers. This configuration supports multiple servers
with different transport mechanisms.
You can configure MCP servers in your settings.json file in two main ways:
through the top-level mcpServers object for specific server definitions, and
through the mcp object for global settings that control server discovery and
execution.
mcp)The mcp object in your settings.json lets you define global rules for all
MCP servers.
mcp.serverCommand (string): A global command to start an MCP server.mcp.allowed (array of strings): A list of MCP server names to allow. If
this is set, only servers from this list (matching the keys in the
mcpServers object) will be connected to.mcp.excluded (array of strings): A list of MCP server names to exclude.
Servers in this list will not be connected to.Example:
{
"mcp": {
"allowed": ["my-trusted-server"],
"excluded": ["experimental-server"]
}
}
mcpServers)The mcpServers object is where you define each individual MCP server you want
the CLI to connect to.
Add an mcpServers object to your settings.json file:
{ ...file contains other config objects
"mcpServers": {
"serverName": {
"command": "path/to/server",
"args": ["--arg1", "value1"],
"env": {
"API_KEY": "$MY_API_TOKEN"
},
"cwd": "./server-directory",
"timeout": 30000,
"trust": false
}
}
}
Each server configuration supports the following properties:
command (string): Path to the executable for Stdio transporturl (string): SSE endpoint URL (for example,
"http://localhost:8080/sse")httpUrl (string): HTTP streaming endpoint URLargs (string[]): Command-line arguments for Stdio transportheaders (object): Custom HTTP headers when using url or httpUrlenv (object): Environment variables for the server process. Values can
reference environment variables using $VAR_NAME or ${VAR_NAME} syntax (all
platforms), or %VAR_NAME% (Windows only).cwd (string): Working directory for Stdio transporttimeout (number): Request timeout in milliseconds (default: 600,000ms =
10 minutes)trust (boolean): When true, bypasses all tool call confirmations for
this server (default: false)includeTools (string[]): List of tool names to include from this MCP
server. When specified, only the tools listed here will be available from this
server (allowlist behavior). If not specified, all tools from the server are
enabled by default.excludeTools (string[]): List of tool names to exclude from this MCP
server. Tools listed here will not be available to the model, even if they are
exposed by the server. excludeTools takes precedence over includeTools. If
a tool is in both lists, it will be excluded.targetAudience (string): The OAuth Client ID allowlisted on the
IAP-protected application you are trying to access. Used with
authProviderType: 'service_account_impersonation'.targetServiceAccount (string): The email address of the Google Cloud
Service Account to impersonate. Used with
authProviderType: 'service_account_impersonation'.Gemini CLI automatically expands environment variables in the env block of
your MCP server configuration. This lets you securely reference variables
defined in your shell or environment without hardcoding sensitive information
directly in your settings.json file.
The expansion utility supports:
$VARIABLE_NAME or ${VARIABLE_NAME} (supported on
all platforms)%VARIABLE_NAME% (supported only when running on Windows)If a variable is not defined in the current environment, it resolves to an empty string.
Example:
"env": {
"API_KEY": "$MY_EXTERNAL_TOKEN",
"LOG_LEVEL": "$LOG_LEVEL",
"TEMP_DIR": "%TEMP%"
}
To protect your credentials, Gemini CLI performs environment sanitization when spawning MCP server processes.
By default, the CLI redacts sensitive environment variables from the base environment (inherited from the host process) to prevent unintended exposure to third-party MCP servers. This includes:
GEMINI_API_KEY, GOOGLE_API_KEY, etc.*TOKEN*, *SECRET*, *PASSWORD*,
*KEY*, *AUTH*, *CREDENTIAL*.If an environment variable must be passed to an MCP server, you must explicitly
state it in the env property of the server configuration in settings.json.
Explicitly defined variables (including those from extensions) are trusted and
are not subjected to the automatic redaction process.
This follows the security principle that if a variable is explicitly configured by the user for a specific server, it constitutes informed consent to share that specific data with that server.
<!-- prettier-ignore -->[!NOTE] Even when explicitly defined, you should avoid hardcoding secrets. Instead, use environment variable expansion (for example,
"MY_KEY": "$MY_KEY") to securely pull the value from your host environment at runtime.
Gemini CLI supports OAuth 2.0 authentication for remote MCP servers using SSE or HTTP transports. This enables secure access to MCP servers that require authentication.
For servers that support OAuth discovery, you can omit the OAuth configuration and let the CLI discover it automatically:
{
"mcpServers": {
"discoveredServer": {
"url": "https://api.example.com/sse"
}
}
}
The CLI will automatically:
When connecting to an OAuth-enabled server:
[!IMPORTANT] OAuth authentication requires that your local machine can:
- Open a web browser for authentication
- Receive redirects on
http://localhost:<random-port>/oauth/callback(or a specific port if configured viaredirectUri)
This feature will not work in:
Use the /mcp auth command to manage OAuth authentication:
# List servers requiring authentication
/mcp auth
# Authenticate with a specific server
/mcp auth serverName
# Re-authenticate if tokens expire
/mcp auth serverName
enabled (boolean): Enable OAuth for this serverclientId (string): OAuth client identifier (optional with dynamic
registration)clientSecret (string): OAuth client secret (optional for public clients)authorizationUrl (string): OAuth authorization endpoint (auto-discovered
if omitted)tokenUrl (string): OAuth token endpoint (auto-discovered if omitted)scopes (string[]): Required OAuth scopesredirectUri (string): Custom redirect URI (defaults to an OS-assigned
random port, e.g., http://localhost:<random-port>/oauth/callback)tokenParamName (string): Query parameter name for tokens in SSE URLsaudiences (string[]): Audiences the token is valid forOAuth tokens are automatically:
~/.gemini/mcp-oauth-tokens.jsonYou can specify the authentication provider type using the authProviderType
property:
authProviderType (string): Specifies the authentication provider. Can be
one of the following:
dynamic_discovery (default): The CLI will automatically discover the
OAuth configuration from the server.google_credentials: The CLI will use the Google Application Default
Credentials (ADC) to authenticate with the server. When using this provider,
you must specify the required scopes.service_account_impersonation: The CLI will impersonate a Google Cloud
Service Account to authenticate with the server. This is useful for
accessing IAP-protected services (this was specifically designed for Cloud
Run services).{
"mcpServers": {
"googleCloudServer": {
"httpUrl": "https://my-gcp-service.run.app/mcp",
"authProviderType": "google_credentials",
"oauth": {
"scopes": ["https://www.googleapis.com/auth/userinfo.email"]
}
}
}
}
To authenticate with a server using Service Account Impersonation, you must set
the authProviderType to service_account_impersonation and provide the
following properties:
targetAudience (string): The OAuth Client ID allowlisted on the
IAP-protected application you are trying to access.targetServiceAccount (string): The email address of the Google Cloud
Service Account to impersonate.The CLI will use your local Application Default Credentials (ADC) to generate an OIDC ID token for the specified service account and audience. This token will then be used to authenticate with the MCP server.
roles/iam.serviceAccountTokenCreator).{
"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
}
}
}
{
"mcpServers": {
"nodeServer": {
"command": "node",
"args": ["dist/server.js", "--verbose"],
"cwd": "./mcp-servers/node",
"trust": true
}
}
}
{
"mcpServers": {
"dockerizedServer": {
"command": "docker",
"args": [
"run",
"-i",
"--rm",
"-e",
"API_KEY",
"-v",
"${PWD}:/workspace",
"my-mcp-server:latest"
],
"env": {
"API_KEY": "$EXTERNAL_SERVICE_TOKEN"
}
}
}
}
{
"mcpServers": {
"httpServer": {
"httpUrl": "http://localhost:3000/mcp",
"timeout": 5000
}
}
}
{
"mcpServers": {
"httpServerWithAuth": {
"httpUrl": "http://localhost:3000/mcp",
"headers": {
"Authorization": "Bearer your-api-token",
"X-Custom-Header": "custom-value",
"Content-Type": "application/json"
},
"timeout": 5000
}
}
}
{
"mcpServers": {
"filteredServer": {
"command": "python",
"args": ["-m", "my_mcp_server"],
"includeTools": ["safe_tool", "file_reader", "data_processor"],
// "excludeTools": ["dangerous_tool", "file_deleter"],
"timeout": 30000
}
}
}
{
"mcpServers": {
"myIapProtectedServer": {
"url": "https://my-iap-service.run.app/sse",
"authProviderType": "service_account_impersonation",
"targetAudience": "YOUR_IAP_CLIENT_ID.apps.googleusercontent.com",
"targetServiceAccount": "[email protected]"
}
}
}
When Gemini CLI starts, it performs MCP server discovery through the following detailed process:
For each configured server in mcpServers:
CONNECTINGhttpUrl → StreamableHTTPClientTransporturl → SSEClientTransportcommand → StdioClientTransportDISCONNECTEDUpon successful connection:
includeTools and
excludeTools configuration_), hyphen (-), dot
(.), and colon (:) are replaced with underscores...)To prevent collisions across multiple servers or conflicting built-in tools, every discovered MCP tool is assigned a strict namespace.
mcp_{serverName}_{toolName}.[!WARNING] Do not use underscores (
_) in your MCP server names (for example, usemy-serverrather thanmy_server). The policy parser splits Fully Qualified Names (mcp_server_tool) on the first underscore following themcp_prefix. If your server name contains an underscore, the parser will misinterpret the server identity, which can cause wildcard rules and security policies to fail silently.
Tool parameter schemas undergo sanitization for Gemini API compatibility:
$schema properties are removedadditionalProperties are strippedanyOf with default have their default values removed (Vertex AI
compatibility)After discovery:
CONNECTED or
DISCONNECTEDWhen the Gemini model decides to use an MCP tool, the following execution flow occurs:
The model generates a FunctionCall with:
Each DiscoveredMCPTool implements sophisticated confirmation logic:
if (this.trust) {
return false; // No confirmation needed
}
The system maintains internal allow-lists for:
serverName → All tools from this server are trustedserverName.toolName → This specific tool is trustedWhen confirmation is required, users can choose:
Upon confirmation (or trust bypass):
Parameter preparation: Arguments are validated against the tool's schema
MCP call: The underlying CallableTool invokes the server with:
const functionCalls = [
{
name: this.serverToolName, // Original server tool name
args: params,
},
];
Response processing: Results are formatted for both LLM context and user display
The execution result contains:
llmContent: Raw response parts for the language model's contextreturnDisplay: Formatted output for user display (often JSON in markdown
code blocks)/mcp commandThe /mcp command provides comprehensive information about your MCP server
setup:
/mcp
This displays:
CONNECTED, CONNECTING, or DISCONNECTED/mcp outputMCP Servers Status:
📡 pythonTools (CONNECTED)
Command: python -m my_mcp_server --port 8080
Working Directory: ./mcp-servers/python
Timeout: 15000ms
Tools: calculate_sum, file_analyzer, data_processor
🔌 nodeServer (DISCONNECTED)
Command: node dist/server.js --verbose
Error: Connection refused
🐳 dockerizedServer (CONNECTED)
Command: docker run -i --rm -e API_KEY my-mcp-server:latest
Tools: mcp_dockerizedServer_docker_deploy, mcp_dockerizedServer_docker_status
Discovery State: COMPLETED
Once discovered, MCP tools are available to the Gemini model like built-in tools. The model will automatically:
The MCP integration tracks several states:
If an MCP server is provided by an extension (for example, the
google-workspace extension), you can still override its settings in your local
settings.json. Gemini CLI merges your local configuration with the extension's
defaults:
Tool lists: Tool lists are merged securely to ensure the most restrictive policy wins:
excludeTools): Arrays are combined (unioned). If either
source blocks a tool, it remains disabled.includeTools): Arrays are intersected. If both sources
provide an allowlist, only tools present in both lists are enabled. If
only one source provides an allowlist, that list is respected.excludeTools always takes precedence over includeTools.This ensures you always have veto power over tools provided by an extension and that an extension cannot re-enable tools you have omitted from your personal allowlist.
Environment variables: The env objects are merged. If the same variable
is defined in both places, your local value takes precedence.
Scalar properties: Properties like command, url, and timeout are
replaced by your local values if provided.
Example override:
{
"mcpServers": {
"google-workspace": {
"excludeTools": ["gmail.send"]
}
}
}
MCPServerStatus)DISCONNECTED: Server is not connected or has errorsCONNECTING: Connection attempt in progressCONNECTED: Server is connected and readyMCPDiscoveryState)NOT_STARTED: Discovery hasn't begunIN_PROGRESS: Currently discovering serversCOMPLETED: Discovery finished (with or without errors)Symptoms: Server shows DISCONNECTED status
Troubleshooting:
command, args, and cwd are correctSymptoms: Server connects but no tools are available
Troubleshooting:
Symptoms: Tools are discovered but fail during execution
Troubleshooting:
timeout settingSymptoms: MCP servers fail when sandboxing is enabled
Solutions:
--debug for verbose output (use F12
to open debug console in interactive mode)/mcp frequently: Monitor server status during developmenttrust option bypasses all confirmation dialogs. Use
cautiously and only for servers you completely control$schema, additionalProperties) for Gemini API compatibilityThis comprehensive integration makes MCP servers a powerful way to extend the Gemini CLI's capabilities while maintaining security, reliability, and ease of use.
MCP tools are not limited to returning simple text. You can return rich, multi-part content, including text, images, audio, and other binary data in a single tool response. This lets you build powerful tools that can provide diverse information to the model in a single turn.
All data returned from the tool is processed and sent to the model as context for its next generation, enabling it to reason about or summarize the provided information.
To return rich content, your tool's response must adhere to the MCP
specification for a
CallToolResult.
The content field of the result should be an array of ContentBlock objects.
Gemini CLI will correctly process this array, separating text from binary data
and packaging it for the model.
You can mix and match different content block types in the content array. The
supported block types include:
textimageaudioresource (embedded content)resource_linkHere is an example of a valid JSON response from an MCP tool that returns both a text description and an image:
{
"content": [
{
"type": "text",
"text": "Here is the logo you requested."
},
{
"type": "image",
"data": "BASE64_ENCODED_IMAGE_DATA_HERE",
"mimeType": "image/png"
},
{
"type": "text",
"text": "The logo was created in 2025."
}
]
}
When Gemini CLI receives this response, it will:
functionResponse part
for the model.inlineData part.This enables you to build sophisticated tools that can provide rich, multi-modal context to the Gemini model.
In addition to tools, MCP servers can expose predefined prompts that can be executed as slash commands within Gemini CLI. This lets you create shortcuts for common or complex queries that can be easily invoked by name.
Here's a small example of a stdio MCP server that defines prompts:
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import { z } from 'zod';
const server = new McpServer({
name: 'prompt-server',
version: '1.0.0',
});
server.registerPrompt(
'poem-writer',
{
title: 'Poem Writer',
description: 'Write a nice haiku',
argsSchema: { title: z.string(), mood: z.string().optional() },
},
({ title, mood }) => ({
messages: [
{
role: 'user',
content: {
type: 'text',
text: `Write a haiku${mood ? ` with the mood ${mood}` : ''} called ${title}. Note that a haiku is 5 syllables followed by 7 syllables followed by 5 syllables `,
},
},
],
}),
);
const transport = new StdioServerTransport();
await server.connect(transport);
This can be included in settings.json under mcpServers with:
{
"mcpServers": {
"nodeServer": {
"command": "node",
"args": ["filename.ts"]
}
}
}
Once a prompt is discovered, you can invoke it using its name as a slash command. The CLI will automatically handle parsing arguments.
/poem-writer --title="Gemini CLI" --mood="reverent"
or, using positional arguments:
/poem-writer "Gemini CLI" reverent
When you run this command, Gemini CLI executes the prompts/get method on the
MCP server with the provided arguments. The server is responsible for
substituting the arguments into the prompt template and returning the final
prompt text. The CLI then sends this prompt to the model for execution. This
provides a convenient way to automate and share common workflows.
gemini mcpWhile you can always configure MCP servers by manually editing your
settings.json file, Gemini CLI provides a convenient set of commands to manage
your server configurations programmatically. These commands streamline the
process of adding, listing, and removing MCP servers without needing to directly
edit JSON files.
gemini mcp add)The add command configures a new MCP server in your settings.json. Based on
the scope (-s, --scope), it will be added to either the user config
~/.gemini/settings.json or the project config .gemini/settings.json file.
Command:
gemini mcp add [options] <name> <commandOrUrl> [args...]
<name>: A unique name for the server.<commandOrUrl>: The command to execute (for stdio) or the URL (for
http/sse).[args...]: Optional arguments for a stdio command.Options (flags):
-s, --scope: Configuration scope (user or project). [default: "project"]-t, --transport: Transport type (stdio, sse, http). [default: "stdio"]-e, --env: Set environment variables (for example, -e KEY=value).-H, --header: Set HTTP headers for SSE and HTTP transports (for example,
-H "X-Api-Key: abc123" -H "Authorization: Bearer abc123").--timeout: Set connection timeout in milliseconds.--trust: Trust the server (bypass all tool call confirmation prompts).--description: Set the description for the server.--include-tools: A comma-separated list of tools to include.--exclude-tools: A comma-separated list of tools to exclude.This is the default transport for running local servers.
# Basic syntax
gemini mcp add [options] <name> <command> [args...]
# Example: Adding a local server
gemini mcp add -e API_KEY=123 -e DEBUG=true my-stdio-server /path/to/server arg1 arg2 arg3
# Example: Adding a local python server
gemini mcp add python-server python server.py -- --server-arg my-value
This transport is for servers that use the streamable HTTP transport.
# Basic syntax
gemini mcp add --transport http <name> <url>
# Example: Adding an HTTP server
gemini mcp add --transport http http-server https://api.example.com/mcp/
# Example: Adding an HTTP server with an authentication header
gemini mcp add --transport http --header "Authorization: Bearer abc123" secure-http https://api.example.com/mcp/
This transport is for servers that use Server-Sent Events (SSE).
# Basic syntax
gemini mcp add --transport sse <name> <url>
# Example: Adding an SSE server
gemini mcp add --transport sse sse-server https://api.example.com/sse/
# Example: Adding an SSE server with an authentication header
gemini mcp add --transport sse --header "Authorization: Bearer abc123" secure-sse https://api.example.com/sse/
gemini mcp list)To view all MCP servers currently configured, use the list command. It
displays each server's name, configuration details, and connection status. This
command has no flags.
Command:
gemini mcp list
[!NOTE] For security,
stdioMCP servers (those using thecommandproperty) are only tested and displayed as "Connected" if the current folder is trusted. If the folder is untrusted, they will show as "Disconnected". Usegemini trustto trust the current folder.
Example output:
✓ stdio-server: command: python3 server.py (stdio) - Connected
✓ http-server: https://api.example.com/mcp (http) - Connected
✗ sse-server: https://api.example.com/sse (sse) - Disconnected
To minimize noise during startup, MCP connection errors for background servers are "silent by default." If issues are detected during startup, a single informational hint will be shown: "MCP issues detected. Run /mcp list for status."
Detailed, actionable diagnostics for a specific server are automatically re-enabled when:
/mcp list, /mcp auth, etc.You can also use gemini mcp list from your shell to see connection errors for
all configured servers.
gemini mcp remove)To delete a server from your configuration, use the remove command with the
server's name.
Command:
gemini mcp remove <name>
Options (flags):
-s, --scope: Configuration scope (user or project). [default: "project"]Example:
gemini mcp remove my-server
This will find and delete the "my-server" entry from the mcpServers object in
the appropriate settings.json file based on the scope (-s, --scope).
gemini mcp enable, gemini mcp disable)Temporarily disable an MCP server without removing its configuration, or re-enable a previously disabled server.
Commands:
gemini mcp enable <name> [--session]
gemini mcp disable <name> [--session]
Options (flags):
--session: Apply change only for this session (not persisted to file).Disabled servers appear in /mcp status as "Disabled" but won't connect or
provide tools. Enablement state is stored in
~/.gemini/mcp-server-enablement.json.
The same commands are available as slash commands during an active session:
/mcp enable <name> and /mcp disable <name>.
Gemini CLI supports MCP server instructions, which will be appended to the system instructions.