MCP servers
What an MCP server is
Section titled “What an MCP server is”The Model Context Protocol (MCP) is an open wire format for connecting an AI tool to an external service — a database, a browser, a ticket tracker, a file store, a search index. An MCP server exposes a set of tools (e.g. jira.search_issues, postgres.query, figma.get_node) over that protocol. The CLI is the client: it discovers the server’s tools at startup and lets the model call them as if they were built in.
All five tools in scope are MCP clients. Codex is the only one that can also be an MCP server — exposing its own coding capabilities as a tool other agents can call.
Why you’d want one
Section titled “Why you’d want one”The agent is brilliant at the code. It knows your language, your patterns, your test framework. You ask it to “close out the auth bug ticket once the fix is in,” and it doesn’t know what a ticket is. You ask it to “check what tickets are blocked on the migration” and it can’t see Jira at all. You ask it to “pull the current pricing from the staging DB to test against” and it has no way to reach the database.
So you do what you always do: you switch tabs, open Jira, copy the ticket title, paste it back. Open a SQL client, run the query, paste the rows back. Hit Figma, screenshot a frame, drop it in. The agent does the coding; you are the integration layer to everything else. Every external system is a context switch you pay for.
That’s the gap MCP servers close. An MCP server is a typed adapter that gives the agent first-class access to one of these systems — the agent itself runs jira.get_ticket("AUTH-412") or postgres.query("select * from prices where ...") as a tool call, sees the result, and acts on it. The integration moves from “you, by hand” to “the agent, in-flow.”
Real-world examples of MCP servers people actually run:
- Issue trackers — Jira, Linear, GitHub Issues. The agent reads the ticket it’s working on, posts updates, closes it on merge.
- Databases — Postgres, MySQL, SQLite. “Check the actual schema before you write this query.” No more guessing the column name.
- Browser automation — Playwright/Puppeteer. The agent navigates a staging site, fills a form, screenshots the result to verify a UI change.
- Cloud consoles — AWS, Cloudflare, Vercel. List buckets, check deployments, read logs without leaving the session.
- Design tools — Figma. The agent reads the actual component spec instead of you describing it.
- Search & knowledge — Notion, Confluence, internal vector stores. The agent looks up the runbook on its own.
- Filesystem at scale — large data lakes, S3, object stores. Beyond what local Read/Glob can reach.
The test: if the answer to “why did you do it that way?” is “I had to guess because I can’t see the source,” there’s probably an MCP server that closes the gap.
What MCP actually is
Section titled “What MCP actually is”MCP is a protocol — a wire format. There are exactly two roles:
┌────────────────────────┐ ┌────────────────────────┐ │ MCP CLIENT │ │ MCP SERVER │ │ (your AI CLI) │ ── stdio / HTTP ──────► │ (jira, postgres, │ │ │ ◄────────────────── │ figma, your own…) │ │ │ │ │ │ discovers tools │ "list_tools" → │ exposes a typed │ │ exposes them │ ← [search_issues, │ set of tools │ │ to the model │ get_issue, …] │ │ │ │ │ │ │ │ "call_tool │ runs the call │ │ │ search_issues(…)" → │ against the real │ │ │ ← {issues: […]} │ system (Jira API…) │ └────────────────────────┘ └────────────────────────┘The CLI is the client. It connects, asks the server “what tools do you offer?”, and registers each one as a tool the model can call. The server is whatever exposes the protocol — a tiny stdio binary, a remote HTTP service, a one-off Python script. When the model calls jira.search_issues, the CLI forwards the call over the protocol to the server; the server hits the real Jira API, returns the result, and the CLI feeds it back to the model.
Three things follow from this shape, and they explain most of the per-tool quirks below:
- Discovery is dynamic. The server defines what tools exist. Change the server, you change the agent’s surface area without changing the CLI.
- Cost lands in the context window. Every tool the server registers is a tool definition that has to live in the model’s context. A server exposing 60 tools is a 60-tool tax on the window — which is why most CLIs in scope now defer MCP schemas until they’re used, and why
/mcpcommands exist to inspect what each server is costing you. - One side or the other. Most tools in scope are MCP clients only. Codex is the only one that can also be a server — exposing its own coding capabilities as tools that another agent (or another Codex) can call. When someone says “I’m using Codex over MCP,” ask which direction.
The unusual property of MCP — and the reason it spread fast — is that the client and server are decoupled. The Jira MCP server you wrote for Claude Code works in Codex, opencode, Cursor, and Copilot unchanged. Compare with skills, which converged on a shared format only after a year of per-tool divergence; MCP was a shared format from day one.
Why this and not…
Section titled “Why this and not…”| You want to… | Reach for | Not |
|---|---|---|
| Connect the agent to a real external system | MCP server | Skill describing the system |
| Encode procedures or institutional knowledge | Skill | MCP server |
| Inject the same context every session | Rules | MCP server |
| Restrict what tools the agent can call | Permissions | MCP-server choice alone |
| Run a side effect on every tool call | Hook | MCP server |
| Bundle and distribute a server + skills + commands | Plugin | Raw MCP install |
MCP is about reach — letting the agent touch systems outside the CLI. Skills, memory, and hooks are about behaviour. If you’re trying to teach the agent what to do, you want a skill. If you’re trying to give the agent something to act on, you want an MCP server.
How it works in each tool
Section titled “How it works in each tool”Configuration: .mcp.json at the project root, or claude mcp add to register from the CLI. Servers can be scoped:
- Local (default) — stored in
~/.claude.jsonunder the current project, private to you - Project —
.mcp.jsonchecked into the repo, shared with your team - User — registered via
claude mcp add --scope user, available across all your projects
Precedence (most-wins): local > project > user.
Inspect and manage: /mcp in-session shows connected servers, token cost per server, and current health. MCP connections can fail silently mid-session — use /mcp if Claude stops being able to use a tool it had access to earlier.
Tool search is on by default — idle MCP tools consume minimal context until used. You can disable this for predictable token accounting.
Configuration: ~/.codex/config.toml with a [mcp_servers.<name>] table per server, or the codex mcp subcommand (codex mcp add, codex mcp login) to manage them from the CLI. Codex supports both stdio (local process via command/args) and streamable HTTP (url) transports.
Codex as an MCP server: the codex mcp-server subcommand runs Codex itself as an MCP server over stdio, exposing codex and codex-reply tools so another MCP client (Claude Desktop, Zed, the OpenAI Agents SDK, etc.) can drive it.
Inspect: /mcp in the TUI shows active MCP servers.
Configuration: the mcp field in opencode.json. Each server is declared with type: "local" (with a command array) or type: "remote" (with a url, plus optional headers and OAuth). MCP servers inherit opencode’s general config layering — project (opencode.json in the project root) merges over global (~/.config/opencode/opencode.json), with macOS-managed preferences and file-based managed settings taking precedence above everything else.
opencode also ships LSP server integration alongside MCP, configured via a separate lsp field in opencode.json. The agent receives LSP diagnostics as feedback while working in the codebase, without needing an MCP wrapper.
Configuration: mcp.json, resolved in priority order:
- Project:
<repo>/.cursor/mcp.json - User:
~/.cursor/mcp.json(also~/.config/cursor/mcp.jsonon Linux)
The schema mirrors the common MCP shape: type, command, args, env, envFile for stdio; url and headers for remote. Variable interpolation works in command, args, env, url, and headers.
Transports: all three are supported — stdio (Cursor spawns and manages a local process), SSE (local or remote, Server-Sent Events), and streamable HTTP (local or remote).
One-click install: Cursor has a curated Marketplace in-app and a community directory at cursor.directory. An “Add to Cursor” button uses a deep link to write the server into the user’s mcp.json and trigger OAuth if needed.
OAuth: remote servers can use Cursor’s built-in OAuth flow; the redirect URL is fixed at cursor://anysphere.cursor-mcp/oauth/callback. Static OAuth client credentials can be embedded in mcp.json when the provider requires fixed Client IDs.
There is also an MCP Extension API for extensions to register MCP servers programmatically — niche, but it exists.
Configuration (VS Code Chat agent mode):
- Workspace:
.vscode/mcp.json(commit to repo to share with the team) - User: VS Code
settings.jsonor a user-scopemcp.json - Install via: the MCP Registry browser, the
--add-mcpCLI flag, the extensions marketplace (@mcpsearch), or hand-editingmcp.json - Auto-discovery of Claude Desktop configs via
chat.mcp.discovery.enabled - Tool approval prompts fire on first use; auto-approve via
chat.tools.terminal.autoApproveand friends
GitHub MCP Registry — a curated, one-click-installable server list browsable from inside the IDE.
Org policy: chat.mcp.access gates which servers can be used; Business/Enterprise admins can apply org-wide MCP policy.
Other surfaces (out of IDE scope, mentioned for completeness): the Copilot Coding Agent has its own MCP configuration in the GitHub repo settings UI with the mcpServers schema, no OAuth support, and tools-only (no resources/prompts). Copilot CLI ships with the GitHub MCP server installed by default. JetBrains, Visual Studio 17.14+, Xcode, and Eclipse 2024-09+ all support MCP via the Registry or manual mcp.json — feature parity with VS Code is Unverified as of 2026-05-21.
Comparison
Section titled “Comparison”| Aspect | Claude Code | Codex | opencode | Cursor | Copilot |
|---|---|---|---|---|---|
| Config file | .mcp.json | ~/.codex/config.toml | opencode.json | .cursor/mcp.json | .vscode/mcp.json |
| Scopes | local / project / user / managed | user (~/.codex/) / project (.codex/) / managed | global / project / managed | project / user | workspace / user / org |
| Inspect command | /mcp | /mcp | /mcp | — | — |
| Transports | stdio, HTTP (streamable-http), SSE (deprecated) | stdio, streamable HTTP | local (stdio), remote (HTTP) | stdio, SSE, streamable HTTP | stdio, HTTP, SSE |
| Can be an MCP server | No | Yes (codex mcp-server) | No | No | No |
| Tool search (lazy schemas) | Yes (default on) | — | — | — | — |
| LSP servers as first-class | No (LSP via MCP if at all) | No | Yes (diagnostics into agent context) | — | — |
| One-click install | — | — | — | “Add to Cursor” deep link | MCP Registry browser |
| OAuth for remote servers | Yes | Yes | Yes | Yes (fixed redirect URL) | Yes (VS Code); — (Coding Agent) |
Name collisions
Section titled “Name collisions”- “MCP” specifically refers to the Model Context Protocol. Don’t confuse with generic “plugins” — see Plugins & marketplaces for distribution-layer packaging.
- Codex’s dual MCP role — both consumer and producer — is unique in the foundations set. When someone says “I’m using Codex over MCP,” ask which direction.
- Copilot’s MCP surface spans VS Code Chat agent mode, the Coding Agent, and the CLI — they share the protocol but not the config schema or capabilities. The IDE story (VS Code Chat,
.vscode/mcp.json) is what this chapter focuses on.