cool-solution — dev.blog
Technologies

Add an MCP server to Claude Code and Codex

Giving a terminal agent the right tools means wiring it to MCP servers. The procedure to add an MCP to Claude and Codex is surprisingly similar: both have a dedicated command and a configuration file. In this guide I walk it twice with the same example — the Playwright server — first on Claude Code (the /mcp command and ~/.claude.json), then on Codex (~/.codex/config.toml), with annotated screenshots pointing at every section.

Claude Code's /mcp panel with the MCP servers (playwright, github, notion, sentry) and, beside it, a card of the ~/.codex/config.toml file.

🔍 What an MCP server is and how you add one

The Model Context Protocol (MCP) is the open standard that connects an AI assistant to external tools: an MCP server exposes tools, resources and prompts the agent can call — browse a page, read a database, hit an API. Adding one to Claude or Codex gives the agent real new capabilities.

The good news is that the mechanism is almost identical across the two: there is always a command to manage servers and a file where they are listed. To show it I use a single example, the Playwright server that drives a browser, so you see the same operation first on Claude and then on Codex.

The example server · Playwright
# One package, the same for Claude and for Codex
npx @playwright/mcp@latest

Official docs · Playwright MCP

The official package is @playwright/mcp, launched with npx.

⌨️ Claude Code: the /mcp command

Let's start with Claude Code. Inside a session, the /mcp command opens an interactive panel: it lists the configured servers, shows the connection status, how many tools each one exposes, and lets you authenticate the ones gated by OAuth.

It is the first place to look when a server won't respond: if you read needs login or failed next to the name, the problem is there, not in your prompt. From the panel you restart, disconnect or authenticate a server without opening any file.

The /mcp panel inside the session
claude — MCP servers> /mcpManage MCP servers · 4 configuredSERVERSTATOTOOL / NOTEplaywright✔ connected21 toolslocalgithub✔ connected8 toolsprojectnotion⚠ needs loginOAuthusersentry✖ failedview logslocal↑↓ select · ↵ view tools / authenticate · d disconnect1stato + toolOgni server mostra lo stato dellaconnessione e quanti tool espone.2⚠ needs loginServer OAuth: premi ↵ sulla rigaper autenticarti dal browser.

Status per server, tool count and scope; ↵ on an OAuth server starts the login.

🛠️ Claude Code: list, add and remove from the terminal

Outside the session, management goes through the claude mcp subcommand. The three you'll always use: list to see what's configured, add to add a server, remove to drop it; with get you inspect a single server.

The flag that matters is --scope (or -s): local is just for you in this project, project lands in a versionable file shared with the team, user applies across all your projects. Pick the scope before you add, not after.

  • list — lists the servers and their status.
  • add — adds a server (stdio or http).
  • remove — removes a server from the chosen scope.
claude mcp · list, get, add, remove
# List, inspect, remove
claude mcp list
claude mcp get playwright
claude mcp remove playwright

# Add a stdio server: everything after -- is the command to launch
claude mcp add playwright -- npx @playwright/mcp@latest

# ...with an explicit scope and an environment variable
claude mcp add -s project -e API_KEY=*** github -- npx -y github-mcp-server

Official docs · MCP in Claude Code

Everything after -- is the command Claude uses to launch the server.

⚙️ Claude Code: the configuration file

Every server you add lands in a JSON file. At the user level it is ~/.claude.json; at the project level it is .mcp.json in the repo root — the one you share with the team. There is a single key, mcpServers, with one entry per server.

A stdio entry has command and args (how to launch the process); an http entry has type and url for a remote server. Tokens are never written in plain text: pass them through environment variables, as in the annotated example below.

~/.claude.json · the annotated mcpServers block
~/.claude.json1{2"mcpServers": {3"playwright": {4"command": "npx",5"args": ["@playwright/mcp@latest"]6},7"github": {8"type": "http",9"url": "https://api.githubcopilot.com/mcp",10"headers": { "Authorization": "Bearer ${GITHUB_TOKEN}" }11}12}13}1mcpServersLa chiave radice: ogni voce quidentro è un server MCP.2command + argsServer stdio: npx avvia il pacchetto@playwright/mcp@latest.3type: http + urlServer remoto: niente processo,solo un endpoint HTTP.4headersIl token arriva da ${GITHUB_TOKEN}:mai scritto in chiaro nel file.

Playwright over stdio, GitHub over http: the arrows point at the parts explained in the text.

🧱 Claude Code: add Playwright step by step

Let's put it together. To add Playwright to Claude one line is enough: the server name, then --, then the command that launches it. Claude registers it, starts it and discovers its tools on the fly.

Verify right away with claude mcp listplaywright must show up — or open /mcp in session. If instead you read spawn npx ENOENT Node or npx is not on the PATH: it's the most common error, and it isn't an MCP problem.

Add and verify Playwright on Claude
claude mcp add playwright -- npx @playwright/mcp@latest
claude mcp list
#  playwright   ✔ connected · 21 tools

Official docs · Playwright MCP

Added, started and verified in two commands.

🔌 Codex: add an MCP from the terminal

On to Codex, OpenAI's CLI. The logic is the same as Claude's, the details change. The subcommand is codex mcp: add to add, list to list, remove to remove; here too -- separates the server name from the command to run.

The Playwright example is almost identical to Claude's: same package, same npx, only the wrapping command changes. Environment variables are passed with --env (or -e).

  • codex mcp add — adds a server.
  • codex mcp list — lists the servers (--json for scripting).
  • codex mcp remove — removes a server.
codex mcp · add, list, remove
# Add Playwright to Codex
codex mcp add playwright -- npx @playwright/mcp@latest

# List and remove
codex mcp list
codex mcp remove playwright

# ...with an environment variable
codex mcp add -e API_KEY=*** github -- npx -y github-mcp-server

Official docs · MCP in Codex

Same shape as Claude: the name, then -- and the server's command.

📄 Codex: the config.toml file

Codex doesn't use JSON but TOML. The configuration lives in ~/.codex/config.toml and each server is a dedicated table, [mcp_servers.name]: the server name is the part after the dot.

Inside the table you put command and args for a stdio server, and env for environment variables. It is the exact equivalent of Claude's mcpServers block, written in TOML instead of JSON.

~/.codex/config.toml · one table per server
~/.codex/config.toml1# ~/.codex/config.toml2[mcp_servers.playwright]3command = "npx"4args = ["@playwright/mcp@latest"]56[mcp_servers.github]7command = "npx"8args = ["-y", "github-mcp-server"]9env = { GITHUB_TOKEN = "ghp_••••" }1[mcp_servers.NAME]Una tabella per server: il nomedel server è dopo il punto.2command + argsServer stdio: come avviare ilprocesso, qui con npx.3envVariabili d'ambiente passate alserver: token e chiavi API.

[mcp_servers.playwright] is the equivalent of Claude's JSON entry.

⚖️ Claude and Codex side by side

Both paths reach the same result. It's worth keeping the practical differences in mind when you switch between them: what changes most is where the configuration lands and with what syntax you write it.

MCP on Claude Code and on Codex

Claude Code

  • In-session panel: /mcp
  • CLI: claude mcp add / list / remove
  • JSON config: ~/.claude.json and .mcp.json
  • mcpServers key · scopes local/project/user
  • Variables: -e flag or env block

Codex

  • CLI management: codex mcp add / list / remove
  • TOML config: ~/.codex/config.toml
  • [mcp_servers.name] tables
  • Variables: --env flag or env key
  • Same Playwright package via npx

Same mechanism, different syntax: JSON for Claude, TOML for Codex.

✅ Apply and verify

The loop is always the same, on both: add the server, check it shows as connected, use it in chat and, if something won't start, read the status and the logs before touching the configuration.

One last habit: version the configuration with no secrets. On Claude you share .mcp.json, on Codex config.toml, but tokens stay in environment variables, never inside the file.

From zero to a live server, in four steps
  1. 01
    Add the serverclaude mcp add … or codex mcp add …
  2. 02
    Verify the status/mcp and claude mcp list · codex mcp list
  3. 03
    Use the tools in chatThe agent asks for confirmation before acting.
  4. 04
    Debug from the logsspawn npx ENOENT? Node/npx not on the PATH.

Frequently asked questions about add MCP to Claude and Codex

What's the difference between the /mcp command and claude mcp?

/mcp is interactive and used inside a Claude Code session to see server status and authenticate them; claude mcp is the terminal subcommand you automate add, list and remove with. They are complementary.

Where are Claude's and Codex's MCP servers stored?

Claude uses JSON: ~/.claude.json (user) and .mcp.json (project, versionable). Codex uses TOML: ~/.codex/config.toml, with one [mcp_servers.name] table per server.

Which is the right package for the Playwright server?

The official one is @playwright/mcp, launched with npx @playwright/mcp@latest. Avoid the unofficial packages with similar names: the same command works for Claude and for Codex.

How do I pass a token to an MCP server without writing it in the file?

With environment variables: on Claude the -e NAME=value flag (or the env block in JSON), on Codex --env NAME=value (or the env key in TOML). That way the configuration file stays shareable.

Let's talk

If this topic is relevant to you, write to me: comparing notes on code and AI is always time well spent.

All articles

More articles from the blog

tips-claude-resume-luglio-2026.mdJuly 10, 2026claude-code-hooks-quality-gate-2026.mdJuly 9, 2026orchestrazione-agenti-ai-multi-agent-dotnet-2026.mdJuly 8, 2026