Configuring MCP Servers
A practical guide to setting up Model Context Protocol (MCP) servers in the four most common AI coding tools, Claude Desktop, Claude Code, Gemini CLI, and Codex , and understanding how each one decides what's available where.
What MCP Is
MCP (Model Context Protocol) is an open standard that lets AI assistants talk to external tools, data sources, and services through a single, consistent interface. Instead of each AI tool inventing its own way to read your files, query your database, or post to Slack, they all speak MCP.
The vocabulary you'll see throughout this guide:
- MCP server, a small program that exposes capabilities (like "read GitHub issues" or "query Postgres") to an AI tool. The AI tool is the client; the server provides the tools.
- Transport, how the client and server talk to each other. The two common ones are stdio (the server runs as a local process on your machine; messages flow over stdin/stdout, best for local tools and CLIs) and HTTP (the server runs somewhere reachable over the network, often a hosted service, best for cloud services and team-shared servers). You may still see SSE in older docs; it's being phased out in favor of HTTP, use HTTP for new setups.
- Scope, which projects, users, or machines a given MCP server is available to. This is where each tool diverges.
If you've never set up an MCP server before, you don't need to read every section below. Jump to the tool you're actually using and start there.
The Four Most Common, One Paragraph Each
These four are the most common MCP-capable AI tools today, and the ones this guide walks through step by step. Other MCP clients exist, Cursor, Zed, custom in-house apps, and more, and the protocol is open, so the list grows. Most of them read MCP server config from a JSON or TOML file in a similar shape to what you'll see below, so the scoping rules and gotchas in this guide carry over even when the surrounding details differ.
Adding a Server in Each Tool
Reads MCP servers from a single JSON file. Three ways to edit it: the in-app menu, the file directly, or via the Extensions marketplace.
Option 1, in-app shortcut (easiest). Open Claude Desktop, go to Settings → Developer → Edit Config. This opens the config file in your default editor and creates it if it doesn't exist. Add your server, save, and fully quit and reopen Claude Desktop (not just close the window).
Option 2, edit the file directly. The config lives at:
| OS | Path |
|---|---|
| macOS | ~/Library/Application Support/Claude/claude_desktop_config.json |
| Windows | %APPDATA%\Claude\claude_desktop_config.json |
| Linux | ~/.config/Claude/claude_desktop_config.json |
A minimal example that gives Claude Desktop access to your Desktop and Downloads folders:
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-filesystem",
"/Users/you/Desktop",
"/Users/you/Downloads"
]
}
}
}
Restart the app. If everything worked, the new tools appear in the chat input area.
Option 3, Desktop Extensions. Claude Desktop also supports packaged MCP servers distributed as .mcpb files. They install with a double-click from the in-app Extensions marketplace, no JSON editing required. Good for non-technical users; the JSON method is better when you need custom servers or full control.
CLI-driven, so you'll mostly use the claude mcp command family rather than editing files by hand.
$ claude mcp add my-database -- \
npx -y @modelcontextprotocol/server-postgres postgresql://localhost/mydb
$ claude mcp add --transport http craft https://mcp.craft.do/my/mcp
$ claude mcp add my-server \
-e API_KEY=sk-abc123 \
-e DATABASE_URL=postgres://localhost/db \
-- node /path/to/server.js
$ claude mcp add-json weather-api '{"type":"http","url":"https://api.weather.com/mcp","headers":{"Authorization":"Bearer token"}}'
$ claude mcp list # show all configured servers $ claude mcp get my-server # show details for one $ claude mcp remove my-server # delete it
Inside an active Claude Code session, type /mcp to see status and handle OAuth logins for servers that need them.
--transport, --scope, --env,
--header) must come before the server name. The
-- separates Claude's flags from the command that gets passed to the
MCP server itself.
Same pattern as Claude Code, with a different command name and a different file.
$ gemini mcp add my-server -- /path/to/server arg1 arg2
Useful flags:
-s, --scope, user or project (see scoping section below).-H, --header, HTTP headers, e.g.-H "Authorization: Bearer abc123".--timeout, connection timeout in milliseconds.--trust, skip tool-call confirmation prompts (use carefully).--include-tools/--exclude-tools, allow/deny specific tools from a server.--description, a short description for your own reference.
Or edit the JSON directly. Gemini CLI reads from ~/.gemini/settings.json (user) or .gemini/settings.json (project). The block looks like this:
{
"mcpServers": {
"git": {
"command": "uvx",
"args": ["mcp-server-git"]
},
"github": {
"httpUrl": "https://api.githubcopilot.com/mcp/",
"headers": {
"Authorization": "Bearer YOUR_GITHUB_TOKEN"
},
"timeout": 5000
}
}
}
Environment variables in the env block are expanded automatically, you can reference ${VAR} and Gemini CLI will substitute from your shell environment. Inside a session, /mcp lists everything that connected successfully.
Uses TOML, not JSON, and the CLI and IDE extension share a single config file. This is convenient, configure once, use everywhere, but a syntax error breaks both.
$ codex mcp add context7 -- npx -y @upstash/context7-mcp
$ codex mcp add my-server --env API_KEY=xyz -- /path/to/server
Or edit ~/.codex/config.toml directly:
[mcp_servers.tooluniverse] command = "uvx" args = ["--refresh", "tooluniverse"] [mcp_servers.tooluniverse.env] PYTHONIOENCODING = "utf-8"
Open the config from the IDE extension: click the gear icon → Codex Settings → Open config.toml.
$ codex mcp list # show all servers $ codex mcp get NAME # show one $ codex mcp remove NAME $ codex mcp login NAME # OAuth login for HTTP servers that need it $ codex mcp logout NAME
Inside a TUI session, /mcp shows the active servers.
~/.codex/config.toml doesn't exist, you need to create it yourself
(or let codex mcp add create it on first use). Many people hit "my
server isn't loading" simply because they put their TOML under the wrong section
header, make sure it's [mcp_servers.NAME], not
[mcp.servers.NAME] or any other variation.
Where Each Tool Makes a Server Available
"Scope" answers a simple question: when I add a server, who and where is it available to? The four tools answer this very differently.
There's only one scope: the user, on this machine. Every server in claude_desktop_config.json is global to that user's Claude Desktop install. No per-project setup, no team-shared file. If you want a colleague to have the same server, you send them the config and they paste it into theirs.
| Scope | What it means | Where it lives | Shared? |
|---|---|---|---|
local (default) | Available only to you, only in this project. | ~/.claude.json (keyed by project path) | No |
project | Available to anyone who clones the repo. | .mcp.json at the project root | Yes, commit to git |
user | Available to you across all your projects. | ~/.claude.json | No (per machine) |
Set the scope when adding:
$ claude mcp add --scope project shared-db -- npx -y my-db-server $ claude mcp add --scope user my-personal-tool -- node /path/to/tool.js
Precedence when names collide: local > project > user. So a local-scope server with the same name as a project one will win for you, without affecting your teammates.
Project scope is gated by trust. When you clone a repo with a .mcp.json file, Claude Code won't silently start running other people's servers, it shows them as ⏸ Pending approval until you accept the workspace trust dialog. This is the right default; review what's in .mcp.json before approving.
user. Project-specific servers your team should all have →
project (and commit .mcp.json). Experiments and personal
credentials for one repo → local (the default).
Simpler: just user and project (sometimes called "workspace").
| Scope | File |
|---|---|
| User | ~/.gemini/settings.json |
| Project | .gemini/settings.json in the project root |
Set the scope when adding:
$ gemini mcp add --scope user my-tool -- /path/to/tool $ gemini mcp add --scope project team-tool -- /path/to/team-tool
When the same server name appears in both, project overrides user for that workspace.
The richest model. There are two places MCP servers can live, plus a layering system that affects all config (not just MCP):
| Layer | File | Notes |
|---|---|---|
| User | ~/.codex/config.toml | Your personal defaults. |
| Project | .codex/config.toml | Only loaded if the project is trusted. |
| Profile | ~/.codex/profile-name.config.toml | Named presets, selected with --profile. |
| CLI overrides | --config key=value flags | One-shot, highest precedence. |
Resolution order (highest precedence wins): CLI overrides → project config (closest to current directory wins if there are multiple) → profile → user config.
.codex/config.toml entirely, a security feature that
prevents a malicious repo from silently injecting MCP servers.
(2) Some keys are user-only. Codex deliberately ignores certain
keys (provider settings, telemetry, notifications) when they appear in a
project-local .codex/config.toml, and prints a warning on startup.
MCP servers themselves work fine in project config; this restriction is mainly
about who controls the model and where data goes.
All Four Tools Compared
| Feature | Claude Desktop | Claude Code | Gemini CLI | Codex |
|---|---|---|---|---|
| Config format | JSON | JSON | JSON | TOML |
| Main config file | claude_desktop_config.json (OS app-support dir) |
~/.claude.json & .mcp.json |
~/.gemini/settings.json & .gemini/settings.json |
~/.codex/config.toml & .codex/config.toml |
| CLI for managing servers | No (GUI only) | claude mcp … |
gemini mcp … |
codex mcp … |
| Number of scopes | 1 | 3 (local, project, user) | 2 (user, project) | 2 base + profiles + CLI overrides |
| Team-shared, in-repo config | No | Yes, .mcp.json |
Yes, .gemini/settings.json |
Yes, .codex/config.toml (trust required) |
| Trust gate on project config | N/A | Yes (approval dialog) | No | Yes (project must be trusted) |
| Precedence on name collision | N/A | local > project > user | project overrides user | CLI > project > profile > user |
| stdio transport | Yes | Yes | Yes | Yes |
| HTTP transport | Yes | Yes | Yes | Yes |
| In-session status command | Hammer icon in input | /mcp |
/mcp |
/mcp |
Which Scope Should I Use?
Claude Code: --scope user. Gemini CLI: --scope user. Codex: user config (~/.codex/config.toml). Claude Desktop: it's already the only scope, so just add it.
Claude Code: --scope project, commit .mcp.json. Gemini CLI: --scope project, commit .gemini/settings.json. Codex: commit .codex/config.toml. Never commit API keys, use environment variable references (${API_KEY}) and document which variables team members need to set.
Claude Code: default local scope. Gemini CLI / Codex: project scope (and .gitignore the file if you don't want to commit it).
Codex profiles are purpose-built for this. The other tools achieve the same effect with project-scoped configs in separate directories.
Things That Catch Everyone At Least Once
- JSON syntax errors silently disable everything. A single missing comma in
claude_desktop_config.jsonor a Gemini CLIsettings.jsonmeans zero servers load and the tool won't always tell you why. Validate first. - Paths must be absolute. Don't write
Desktop, write/Users/you/Desktop(orC:\Users\you\Desktopon Windows). Relative paths rarely resolve the way you expect. - Restart the app, don't just close the window. Claude Desktop in particular needs a full quit-and-relaunch to reload config changes.
- SSE is deprecated. If a guide tells you to use
--transport sse, prefer--transport httpfor new setups unless the server only supports SSE. - Each MCP server is a separate subprocess. Three to five servers is fine. Twenty is a problem, they slow startup, eat memory, and inflate the model's tool list (which actually hurts accuracy, because the model has to consider every tool on every turn). Install what you actually use.
- Secrets don't belong in committed files. When using project scope, reference secrets via environment variables (
${API_KEY}or${API_KEY:-default}), put real values in a.envfile, and add that file to.gitignore. localanduserscopes don't sync across machines. Only project scope (which lives in a file you can commit) gives you that. If you set up a beautiful tool collection on your laptop, your desktop won't see it unless you copy the config over or move things into project scope.
Official Docs
The official documentation for each tool is the most authoritative source if anything in this guide ever drifts out of date:
- Claude Desktop, Claude Help Center: Getting Started with Local MCP Servers
- Claude Code, Connect Claude Code to tools via MCP
- Gemini CLI, MCP servers with the Gemini CLI
- Codex, Model Context Protocol – Codex
- The protocol itself, modelcontextprotocol.io