MCP Servers & Extensions
Out of the box, Gemini CLI can read files, search the web, and run shell commands. MCP servers extend that into a limitless integration surface: your databases, your APIs, your SaaS tools. This module covers the MCP protocol, how to install community and Google partner extensions, how the Google Workspace extension gives Gemini 100+ built-in Gmail/Docs/Drive skills, and how to build your own MCP server in 20 lines.
What You'll Learn
- Understand the three MCP primitives — Tool, Resource, Prompt — and how Gemini CLI uses each
- Install community MCP servers and configure them via
GEMINI.md - Survey the Google + partner extension catalog: Cloud Run, BigQuery, Figma, Stripe, and more
- Use the Google Workspace extension for Gmail, Docs, Drive, Sheets, and Calendar automation
- Configure OAuth 2.0 for remote MCP servers and prevent credential leakage via env var sanitization
- Build a minimal custom MCP server with FastMCP and connect it to Gemini CLI in under 30 minutes
What is MCP?
Before USB-C, connecting a peripheral to a laptop required knowing whether it used USB-A, Micro-B, Thunderbolt 2, or DisplayPort — each device manufacturer had its own plug. USB-C created one standard connector. MCP does the same for AI models and external tools: instead of every LLM vendor building bespoke integrations with every SaaS product, MCP defines one protocol that any model can speak and any service can implement.
The pain without MCP: Claude needs a Claude-specific Slack connector; Gemini needs a Gemini-specific Slack connector; the LLM vendor ships integrations, not the tool vendor. The mapping: Slack ships one mcp-slack-server — any MCP-compatible model (Gemini, Claude, GPT) connects to it identically. One server, all models.
The Model Context Protocol (MCP)An open standard developed by Anthropic (published November 2024) that defines how AI models communicate with external tools and data sources. An MCP server exposes capabilities as Tools, Resources, and Prompts. The model client (e.g., Gemini CLI) discovers capabilities, calls them during inference, and incorporates results into its response. Google adopted MCP natively in Gemini CLI 0.1.x. is a JSON-RPC 2.0 based protocol that standardizes how AI models interact with external capabilities. An MCP server exposes three primitive types and can be hosted locally (stdio transport) or remotely (HTTP/SSE transport). Gemini CLI is a native MCP client — it auto-discovers server capabilities when a server is configured in GEMINI.md.
The Three MCP Primitives
An action the model can invoke. Takes parameters, produces output. Examples: query_database, send_email, create_issue. The model decides when to call a tool based on the conversation.
A readable data source with a URI. Examples: file:///path/to/doc, postgres://table/users. Resources are read-only and provide context, not actions.
A reusable, parameterized prompt template. Examples: summarize_document, review_pr. Prompts are workflow shortcuts — pre-written prompts with slots for dynamic values.
Gemini CLI uses all three primitives. During a conversation, it can call Tools autonomously, expose Resources as context, and surface Prompts as slash-command shortcuts.
MCP turns Gemini CLI from a code assistant into a workflow orchestrator. With the right MCP servers installed, a single prompt like "Find all open P1 issues assigned to me, check if any have PRs ready, and ping the relevant engineers on Slack" becomes executable — Gemini calls the GitHub MCP server, the Slack MCP server, and assembles the result. No scripting required.
Adding MCP Servers to Gemini CLI
MCP servers are configured in GEMINI.md — the same memory file that holds project context. The ## MCP Servers section is a YAML block that Gemini CLI parses at startup.
# Install a community MCP server globally via npm
npm install -g @modelcontextprotocol/server-postgres
# Or install project-locally
npm install --save-dev @modelcontextprotocol/server-filesystem
# Verify the server binary is available
npx @modelcontextprotocol/server-postgres --help
# Install a community MCP server globally via npm
npm install -g @modelcontextprotocol/server-postgres
# Or install project-locally
npm install --save-dev @modelcontextprotocol/server-filesystem
# Verify the server binary is available
npx @modelcontextprotocol/server-postgres --help
GEMINI.md Configuration
Add an ## MCP Servers block to your project's GEMINI.md file:
## MCP Servers
- name: postgres
command: npx
args: ["@modelcontextprotocol/server-postgres"]
env:
DATABASE_URL: ${DATABASE_URL}
- name: filesystem
command: npx
args: ["@modelcontextprotocol/server-filesystem", "/home/user/projects"]
- name: github
command: npx
args: ["@modelcontextprotocol/server-github"]
env:
GITHUB_PERSONAL_ACCESS_TOKEN: ${GITHUB_TOKEN}
${DATABASE_URL} syntax means the actual value is read from your shell environment at startup — the secret never appears in the GEMINI.md file itself, which may be committed to git.
GEMINI.md in your project directory is committed to git. Never write literal credential values in the MCP Servers block — always use ${ENV_VAR} references.
Verifying Installed Tools
# Start Gemini CLI and list all loaded tools
gemini
# Inside the session:
/tools
# Or check from the command line (non-interactive)
gemini -p "/tools" | Out-String
# Start Gemini CLI and list all loaded tools
gemini
# Inside the session:
/tools
# Or check from the command line (non-interactive)
gemini -p "/tools"
Expected /tools output after configuring the postgres and github servers:
Available tools (15):
Built-in:
shell_execute Execute shell commands
file_read Read file contents
file_write Write or modify files
web_search Search the web
MCP — postgres:
query Run a SELECT query against the configured database
list_tables List all tables in the database
describe_table Get schema for a specific table
MCP — github:
create_issue Create a GitHub issue
list_issues List issues with filters
create_pull_request Create a pull request
get_pull_request Get PR details and diff
list_commits List recent commits
What Just Happened?
Gemini CLI started both MCP servers as child processes, called their tools/list endpoint via JSON-RPC, and registered the returned tool schemas. Every tool now appears as a callable function during inference. When you type "What are the 5 largest tables in the database?", Gemini autonomously calls list_tables followed by a query call — you see the answer, not the tool calls.
Google + Partner Extension Catalog
Google maintains a curated set of first-party and partner-verified MCP extensions. These are pre-authenticated, production-tested integrations that go beyond community servers.
Extension Catalog
| Extension | Install Command | What It Adds |
|---|---|---|
| Google First-Party | ||
google-workspace |
gemini extensions install google-workspace |
Gmail, Docs, Drive, Sheets, Calendar, Meet — 100+ built-in agent skills (see next section) |
cloud-run |
gemini extensions install google-cloud-run |
Deploy, list, and describe Cloud Run services; stream logs; update traffic splits |
bigquery |
gemini extensions install google-bigquery |
Run SQL against BigQuery datasets; explore schemas; explain query plans |
app-security |
gemini extensions install google-app-security |
Scan code for OWASP Top 10 vulnerabilities; generate security reports |
| Verified Partner Extensions | ||
dynatrace |
gemini extensions install dynatrace |
Query APM metrics, traces, and logs; get AI-powered root cause analysis |
figma |
gemini extensions install figma |
Read Figma designs; extract component specs; generate CSS from design tokens |
postman |
gemini extensions install postman |
Run Postman collections; generate API tests; read environment variables |
stripe |
gemini extensions install stripe |
Query customers, subscriptions, invoices; test webhooks; diagnose payment failures |
shopify |
gemini extensions install shopify |
Read product catalogs, orders, inventory; generate storefront code snippets |
Extensions installed via gemini extensions install are verified by Google: they follow MCP security best practices, handle OAuth automatically, and are updated alongside Gemini CLI. Community servers installed via npm install + GEMINI.md give more flexibility but require manual credential management and updates.
The Google Workspace Extension
A highly effective executive assistant doesn't just answer questions — they have your Gmail, Calendar, and Drive open simultaneously and act across all of them. "Send the meeting notes to the team" doesn't require three separate steps; they draft the email, find the notes in Drive, and send it while you're on the next call.
The pain without the Workspace extension: you copy content from Gmail into Gemini CLI, Gemini CLI generates a response, you copy the response back into Gmail. The mapping: the Workspace extension means Gemini CLI reads your Gmail directly, generates the response, and sends it — one prompt, one action.
Installation and Authentication
# Install the Workspace extension
gemini extensions install google-workspace
# Output: Installing google-workspace...
# Requesting OAuth scopes:
# - https://www.googleapis.com/auth/gmail.readonly
# - https://www.googleapis.com/auth/gmail.send
# - https://www.googleapis.com/auth/drive.readonly
# - https://www.googleapis.com/auth/calendar.events
# Opening browser for authorization...
# ✓ Authorized. Token stored in: ~\.gemini\extensions\google-workspace\token.json
# Verify installation
gemini extensions list
# Install the Workspace extension
gemini extensions install google-workspace
# Output: Installing google-workspace...
# Requesting OAuth scopes:
# - https://www.googleapis.com/auth/gmail.readonly
# - https://www.googleapis.com/auth/gmail.send
# - https://www.googleapis.com/auth/drive.readonly
# - https://www.googleapis.com/auth/calendar.events
# Opening browser for authorization...
# ✓ Authorized. Token stored in: ~/.gemini/extensions/google-workspace/token.json
# Verify installation
gemini extensions list
Once installed, Gemini gains over 100 built-in agent skills spanning all Workspace products:
| Service | Example Skills |
|---|---|
| Gmail | Read inbox, search by sender/subject, draft and send emails, label and archive, read threads |
| Google Docs | Read document content, create documents, append text, export as markdown/PDF |
| Google Drive | Search files, list recent, share with permissions, read file metadata |
| Google Sheets | Read cell ranges, append rows, create sheets, run named ranges, format cells |
| Google Calendar | List today's events, create events, find free slots, check attendee availability |
Cross-Service Example: Gmail + Slack
The real power emerges when Workspace skills combine with other MCP servers. With both google-workspace and a Slack MCP server installed:
Send a summary of today's unread emails from my product@company.com address
to the #product-updates Slack channel. Group by sender. Include action items.
Gemini's execution chain (invisible to the user):
- Calls Gmail
list_messageswith filterto:product@company.com is:unread newer_than:1d - Calls Gmail
get_messagefor each message to read full content - Generates a grouped summary with action items extracted from each thread
- Calls Slack MCP
post_messageto#product-updateswith the formatted summary
The installation process requests specific OAuth scopes. Before clicking "Allow", review which scopes are being requested. The gmail.send scope means Gemini can send emails as you. The drive.file scope is more restricted than drive.readonly — prefer the most restrictive scope that allows the workflows you need.
OAuth 2.0 and Remote MCP Servers
Not all MCP servers run locally. Remote MCP servers are hosted services that expose their capabilities over HTTPS using Server-Sent Events (SSE)An HTTP-based protocol where the server pushes a stream of events to the client over a persistent connection. MCP uses SSE as the transport for remote servers, allowing the server to send tool responses back to Gemini CLI asynchronously over a single long-lived HTTP connection. transport. Accessing them requires OAuth 2.0 for authentication.
## MCP Servers
- name: linear
type: remote
url: https://mcp.linear.app/sse
auth:
type: oauth2
client_id: ${LINEAR_MCP_CLIENT_ID}
client_secret: ${LINEAR_MCP_CLIENT_SECRET}
scopes: ["issues:read", "issues:write", "teams:read"]
- name: notion
type: remote
url: https://api.notion.com/mcp/sse
auth:
type: bearer
token: ${NOTION_INTEGRATION_TOKEN}
type: remote field tells Gemini CLI to connect via HTTP/SSE rather than spawning a child process. The auth block configures the credential exchange before the first tool call.
Environment Variable Sanitization
By default, Gemini CLI passes all environment variables to MCP server processes. This is a security risk if you install an untrusted community server — it could read your GITHUB_TOKEN, AWS_SECRET_ACCESS_KEY, or DATABASE_URL.
Use the env_allowlist configuration to explicitly restrict which environment variables a server process can see. Never install an untrusted MCP server without reviewing its source code — a malicious server can exfiltrate any environment variable it receives.
## MCP Servers
# Untrusted community server — restrict env access
- name: community-analytics
command: npx
args: ["community-analytics-mcp-server"]
env:
# Only pass the vars this server legitimately needs
ANALYTICS_API_KEY: ${ANALYTICS_API_KEY}
NODE_ENV: production
# Prevent inheriting the parent shell's environment entirely
env_inherit: false
env_inherit: false blocks the process from seeing any shell environment variable except those explicitly listed in the env block.
env_inherit: false, a community server process can read process.env.DATABASE_URL (Node.js) or os.environ["AWS_SECRET_ACCESS_KEY"] (Python) freely. This is not a Gemini CLI bug — it's standard Unix process behavior. The sanitization opt-in protects against it.
Building a Custom MCP Server
Every major software platform has a plugin system: VS Code extensions, Figma plugins, Chrome extensions. You write code against a defined API, package it, and the host application runs it. MCP is Gemini CLI's plugin system — and FastMCP makes writing a plugin as simple as decorating a Python function.
The pain: building against the raw MCP JSON-RPC protocol requires handling capability negotiation, tool schema generation, and message routing manually. The mapping: FastMCP is a Python library where @mcp.tool() turns any function into a fully spec-compliant MCP tool — it handles the protocol plumbing so you write business logic.
FastMCP in 20 Lines — Python
# Install: pip install fastmcp
from fastmcp import FastMCP
import httpx
mcp = FastMCP("company-data-server")
@mcp.tool()
def get_customer(customer_id: str) -> dict:
"""Look up a customer by ID from the internal CRM API."""
with httpx.Client() as client:
response = client.get(
f"https://crm.internal/api/customers/{customer_id}",
headers={"Authorization": f"Bearer {os.environ['CRM_API_KEY']}"}
)
response.raise_for_status()
return response.json()
@mcp.tool()
def list_open_orders(customer_id: str, limit: int = 10) -> list[dict]:
"""List open orders for a customer, newest first. Max 100."""
limit = min(limit, 100) # enforce ceiling
with httpx.Client() as client:
r = client.get(
f"https://orders.internal/api/orders",
params={"customer_id": customer_id, "status": "open", "limit": limit}
)
r.raise_for_status()
return r.json()["orders"]
if __name__ == "__main__":
mcp.run() # stdio transport (default)
// Install: npm install @modelcontextprotocol/sdk
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: "company-data-server", version: "1.0.0" });
server.tool(
"get_customer",
"Look up a customer by ID from the internal CRM API",
{ customer_id: z.string().describe("The customer UUID") },
async ({ customer_id }) => {
const res = await fetch(
`https://crm.internal/api/customers/${customer_id}`,
{ headers: { Authorization: `Bearer ${process.env.CRM_API_KEY}` } }
);
if (!res.ok) throw new Error(`CRM returned ${res.status}`);
const data = await res.json();
return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
}
);
const transport = new StdioServerTransport();
await server.connect(transport);
@mcp.tool() decorator reads the function's docstring (tool description), type annotations (parameter schema), and return type to generate the full MCP tool definition automatically.
StdioServerTransport to handle stdio communication. The server.connect(transport) call must be awaited at the module level — if you put it inside an Express route handler, it will never run.
Connect your new server to Gemini CLI via GEMINI.md:
## MCP Servers
- name: company-data
command: python
args: ["tools/mcp_server.py"]
env:
CRM_API_KEY: ${CRM_API_KEY}
env_inherit: false
What Just Happened?
The animation shows the JSON-RPC call sequence between Gemini CLI and the custom MCP server. The user's natural language question triggered an autonomous tool call — the user never wrote list_open_orders in their prompt. Gemini inferred the right tool from the docstring and the conversation context.
The MCP ecosystem is growing faster than any previous integration standard in developer tooling. As of mid-2025, over 5,000 MCP servers are publicly available. Every server you add multiplies what Gemini CLI can do without changing the model or writing new prompts — the context window becomes a unified interface to your entire digital environment.
Knowledge Check
1. What are the three MCP primitives and what distinguishes a Tool from a Resource?
2. Why is the docstring on a FastMCP @mcp.tool() function more important than the function name?
3. What security risk does env_inherit: false prevent when running an untrusted MCP server?
4. What is the correct way to include a database credential in an MCP server configuration in GEMINI.md?
DATABASE_URL: postgresql://user:password@host/dbgemini secrets encrypt before adding it to GEMINI.md${ENV_VAR} reference syntax: DATABASE_URL: ${DATABASE_URL} — the value is read from the shell environment at startup, never written to the GEMINI.md file.gemini-secrets.yaml file that GEMINI.md references by filename5. What is the key difference between a verified Google partner extension and a community MCP server installed via npm?
gemini extensions install, and receive updates managed by Google — community servers require manual credential management and version updates