Back to blog
Engineering10 min read

Why Isn't My MCP Server Showing Up?

Your MCP server usually fails to appear for one of four reasons: wrong config path, invalid JSON or TOML, no restart, or a remote server added in the wrong place.

NH
Nafiul Hasan
Founder, Prompt Architects

TL;DR: Your MCP server almost always fails to show up for one of four reasons: the config file is in the wrong folder for that specific client, the JSON or TOML inside it has a syntax error, the client was never fully restarted after you edited it, or — on Claude Desktop specifically — you added a remote server to the config file when remote servers only connect through Customize → Connectors.

Why Isn't My MCP Server Showing Up?

Your MCP server isn't showing up because the client either can't find the config entry, can't parse it, or hasn't reloaded it since you wrote it. Those are the only three failure modes a config-based client has, and a fourth applies only to Claude Desktop: adding a remote server where only local servers belong.

This post walks through all four in the order they're worth checking, because they're ordered by how often each one turns out to be the actual cause, not by how interesting they are to write about. If you've already ruled these out and the server still won't connect, or you're hitting something more specific like an OAuth loop or a server that connects then drops, tool calls that time out, or a permissions prompt that never appears, the wider 15-fix MCP troubleshooting guide covers the rest. This post stays narrow: the specific moment where you added a server and nothing showed up at all.

If you haven't set up an MCP client yet and want the full walkthrough for Cursor and Claude Desktop first, start there and come back here once something's configured but not appearing.

Is Your Config File in the Wrong Place?

Every MCP client that reads from a file expects that file in one specific location, and "close enough" doesn't work. A config saved to the wrong folder is invisible to the client; it doesn't error, because as far as the client's concerned, the file doesn't exist.

Claude Desktop reads claude_desktop_config.json from ~/Library/Application Support/Claude/claude_desktop_config.json on macOS, or %APPDATA%\Claude\claude_desktop_config.json on Windows. The safest way to find the real path is Claude menu → Settings → Developer → Edit Config, which opens the file Claude Desktop actually reads and creates it if missing, rather than trusting a path you remember from a tutorial.

Claude Code uses a different file depending on scope. A server added with default (local) scope lives inside ~/.claude.json, nested under your project's path, private to you. A server added with --scope project writes to .mcp.json at your project root, meant to be committed so your team shares it. A server added with --scope user also lives in ~/.claude.json, but applies across every project on your machine.

Cursor checks two files and merges them: .cursor/mcp.json in the project root, and ~/.cursor/mcp.json in your home directory for servers you want everywhere. If you added a server to the wrong one, it either only shows up in one project when you expected it everywhere, or vice versa.

Codex CLI and the Codex app both read ~/.codex/config.toml by default, with an optional project-scoped .codex/config.toml that only loads if you've marked that project trusted. An untrusted project silently skips its own local config, MCP servers included, which reads exactly like "the file isn't being picked up" even though the file is fine.

ClientConfig fileDefault pathFormat
Claude Desktopclaude_desktop_config.json~/Library/Application Support/Claude/ (macOS) · %APPDATA%\Claude\ (Windows)JSON
Claude Code.mcp.json (project) or ~/.claude.json (local/user)Project root, or home directoryJSON
Cursormcp.json.cursor/mcp.json (project) or ~/.cursor/mcp.json (global)JSON
Codex CLI / Codexconfig.toml~/.codex/config.toml, or .codex/config.toml (trusted projects only)TOML

Note the last column. Three of these four clients use JSON. Codex uses TOML, which looks close enough to JSON to invite mistakes if you're copying a config block from one client's setup instructions into another's file without translating the syntax.

Is Your JSON or TOML Actually Valid?

A single missing comma, an extra trailing comma, or an unquoted key is enough to make an entire config file unreadable, and most of these clients fail that silently: no error dialog, no crash, just a client that behaves as if the file were empty.

Here's a JSON config with a trailing comma, the single most common JSON mistake, since Python-style code and older JS habits both allow it and JSON doesn't:

{
  "mcpServers": {
    "prompt-architects": {
      "url": "https://mcp.prompt-architects.com/mcp",
    }
  }
}

That trailing comma after the closing brace of the "prompt-architects" object is invalid JSON. Remove it:

{
  "mcpServers": {
    "prompt-architects": {
      "url": "https://mcp.prompt-architects.com/mcp"
    }
  }
}

Don't proofread a config file by eye. Validate it. For JSON, either of these prints a clear line number on failure or hands the file back unchanged if it's valid:

python3 -m json.tool claude_desktop_config.json
# or
jq . claude_desktop_config.json

Codex's TOML has its own failure mode: writing the server block as if it were JSON nested under a JSON-style key, instead of TOML's table syntax. This is invalid:

mcp_servers = {
  prompt-architects = { url = "https://mcp.prompt-architects.com/mcp" }
}

TOML wants a [mcp_servers.<name>] table header, not an inline JSON-shaped map:

[mcp_servers.prompt-architects]
url = "https://mcp.prompt-architects.com/mcp"
bearer_token_env_var = "PA_TOKEN"

For a local stdio server instead of a remote one, the table takes command and args in place of url:

[mcp_servers.local-tool]
command = "npx"
args = ["-y", "some-mcp-server"]

There's no built-in jq for TOML in most shells, but a quick sanity check with Python 3.11 or later works the same way:

python3 -c "import tomllib,sys; tomllib.load(open(sys.argv[1],'rb'))" ~/.codex/config.toml

Silence means it parsed. An exception means the line it's pointing at is wrong.

Did You Restart the Client?

A config file that's in the right place with valid syntax still won't produce a visible server if the client already read its config before you finished editing.

Claude Desktop is the strictest about this: fully quit the app, not just close the window, then relaunch it. Claude Desktop's own troubleshooting steps list "restart Claude Desktop completely" as the first fix for a server or tool icon that doesn't appear, ahead of checking the config syntax, because it's the cheapest thing to rule out first.

Claude Code is more forgiving because most changes go through claude mcp add, which writes the config and reports Added ... immediately. A brand-new session picks up the change on start. Where people get tripped up is project-scoped servers: the first time you run claude in a project with a .mcp.json Claude Code hasn't seen before, it prompts you to approve those servers, and if you're running non-interactively or skip that prompt, the server sits at ⏸ Pending approval and never connects until you approve it in an interactive session.

Cursor doesn't require a full app restart in most cases. Toggling the affected server off and back on in Cursor Settings → MCP forces it to reread that entry, and that's usually enough; a full restart is the fallback if toggling doesn't pick up the change.

Codex needs an explicit restart step too: after editing config.toml, select Restart in the client, or start a fresh CLI session. An already-running session doesn't re-read the file mid-session.

Do You Have a Server Name Collision?

Two servers with the same name in different places doesn't produce an error in any of these clients. It produces one of them silently winning, which looks identical to "the server I just added isn't there" if the one that wins is the old one.

Claude Code resolves this by a fixed precedence order: local scope beats project scope, project beats user scope, user beats plugin-provided servers, and plugin servers beat claude.ai connectors. Add a same-named server at a lower-precedence scope than one that already exists, and your new definition is fully ignored, not merged with the old one; Claude Code uses the entire entry from whichever scope wins, field by field, not a combination of both.

Cursor works the same way between its two files: if .cursor/mcp.json and ~/.cursor/mcp.json both define a server called the same thing, the project-level file wins outright.

Claude Code also reserves a handful of names for its own built-in servers: workspace, claude-in-chrome, computer-use, Claude Preview, and Claude Browser. A user config that defines a server under one of those names gets skipped at load time with a warning to rename it, rather than replacing the built-in.

If a server is behaving like an older configuration you thought you'd removed, this is usually why. Check every scope for that exact name before assuming the file you're looking at is the only one that matters.

Are You on Claude Desktop, Trying to Add a Remote Server via the Config File?

This is the single most common reason an MCP server never shows up, and it only affects Claude Desktop. claude_desktop_config.json is for local servers: stdio processes that run on your machine, started by a command like npx or a local binary. A remote server, one you reach over HTTPS at a URL like https://mcp.prompt-architects.com/mcp, doesn't go in that file at all.

To add a remote server correctly: open Customize → Connectors, click the add button, choose "Add custom connector," and enter the connector name and the server's URL. Advanced settings there also let you set an OAuth client ID and secret if the server needs pre-registered credentials instead of dynamic registration. This is the same Connectors surface across claude.ai, Claude Desktop, and Cowork; adding a connector in one applies wherever you're signed in with that account.

This distinction trips people up specifically because most MCP setup instructions online default to showing the mcpServers JSON block, which is correct for local servers and for other clients like Cursor and Claude Code, but is the wrong target for a remote server on Claude Desktop specifically. If you copy a "url": "..." entry into claude_desktop_config.json because that's the pattern every guide shows, the entry sits there parsed correctly and connects to nothing, because Claude Desktop's config file was never the path for remote servers to begin with.

Worth checking too: prompt injection risk isn't unique to remote servers, but a remote connector you didn't set up yourself deserves the same scrutiny as any browser extension asking for permissions. If you're evaluating whether to trust a third-party MCP server before connecting it at all, the prompt injection guide covers what to check first. And if you're deciding between managing prompts through MCP servers versus a dedicated prompt management tool, that's a separate decision from getting either one to actually connect.

Free Chrome Extension

Stop rewriting prompts. Start shipping.

Works with ChatGPT, Claude, Gemini, Grok, Midjourney, Ideogram, Veo3 & Kling. 5.0★ on the Chrome Web Store.

Create An Account

Frequently asked questions

Free Chrome Extension

Stop rewriting prompts. Start shipping.

Works with ChatGPT, Claude, Gemini, Grok, Midjourney, Ideogram, Veo3 & Kling. 5.0★ on the Chrome Web Store.

Create An Account