claude_desktop_config.json is the file Claude Desktop reads at launch to start local MCP servers. Each entry is a command line. Claude Desktop runs that command as a child process and talks MCP to it over stdin and stdout. That's it. The file does not hold remote server URLs, OAuth tokens, or Desktop Extensions, and most "my server never shows up" threads come down to someone expecting it to.

This is the reference we wanted when we set up our own server: where the file lives, every key that works, the environment your server actually gets, and how to read the logs. We checked it against Anthropic's and the MCP project's docs on October 7, 2026, and flag claims that rest only on bug reports.

If you just want to add one server and move on, How to add an MCP server to Claude is the shorter walkthrough. This page is for when that didn't work, or when you want to know why.

Where claude_desktop_config.json lives

A grey industrial control panel covered in rows of labelled switches, knobs and red, green and amber indicator lights
Photo: Elsie esq. / Flickr (CC BY 2.0).

There is one file per user account. The chat side of Claude Desktop has no project-level config. The app's Code tab is different: it loads servers from this file alongside Claude Code's ~/.claude.json and .mcp.json, while the standalone claude CLI ignores this file entirely.

PlatformPathSource
macOS~/Library/Application Support/Claude/claude_desktop_config.jsonMCP docs
Windows%APPDATA%\Claude\claude_desktop_config.jsonMCP docs
Windows, MSIX-packaged install%LOCALAPPDATA%\Packages\Claude_pzs8sxrjxfjjc\LocalCache\Roaming\Claude\claude_desktop_config.jsonUser reports (open bug)
Linux (beta)~/.config/Claude/claude_desktop_config.jsonCommunity builds; Anthropic documents the logs folder next to it

The safe way to open the right file is from inside the app. On macOS, use the Claude menu in the system menu bar, not the account menu inside the window, then Settings… → Developer → Edit Config. If the file doesn't exist yet, that button creates it.

Windows has a trap. Anthropic's GitHub tracker has an open report (#26073, still open as of October 2026) that on MSIX-packaged installs, Edit Config opens the file under %APPDATA% while the app reads a virtualized copy under %LOCALAPPDATA%\Packages. Another report in the same tracker says the Store, WinGet and the regular installer all deploy as MSIX now. So if your edits on Windows seem to vanish, look in the Packages folder first. The workaround users report is to create %APPDATA%\Claude yourself before installing.

Linux is officially supported in beta (Ubuntu 22.04+ and Debian 12+, x64 and arm64). We could not find an Anthropic page that names the Linux config path. The path above is what community builds use, and it sits next to ~/.config/Claude/logs/, which Anthropic does document.

The file, key by key

A minimal working file has one top-level object, mcpServers, with one entry per server:

{
  "mcpServers": {
    "filesystem": {
      "command": "npx",
      "args": [
        "-y",
        "@modelcontextprotocol/server-filesystem",
        "/Users/you/Desktop",
        "/Users/you/Downloads"
      ]
    }
  }
}

That is the example from the official MCP guide, with the username swapped. Here is what each key does, and what happens with keys people copy over from other clients.

KeyWorks in Claude Desktop?What it does
mcpServersYes, requiredThe root object. Server blocks placed outside it are ignored.
Server name (e.g. "filesystem")YesYour label, shown in the app. Must be unique. Stick to letters, digits, hyphens and underscores if you ever want to import it into Claude Code.
commandYes, requiredThe executable to launch: npx, uvx, uv, docker, node, or an absolute path to a binary.
argsYesAn array of strings, one argument per element. Don't rely on shell features: write out ~, globs and variables in full. On Windows, avoid spaces inside a single argument (see the mcp-remote note below).
envYesExtra environment variables for that one server, as string values. This is where API keys usually go.
"type": "stdio"AcceptedOptional. Anthropic's own Claude Code docs include it in a Desktop config example. Leaving it out changes nothing.
url, "type": "http"NoNot supported here. Bug reports from early 2026 describe a schema error saying command is required, an app crash, or the whole mcpServers block being dropped.
headersNoNo HTTP entries, so no headers. Use a bridge (below) if you need one.
cwdUnclearThe official MCP quickstart's Ruby example sets it, but a July 2026 bug report on Linux says Desktop ignored it. Use uv --directory or absolute paths so it doesn't matter.
disabled / enabledNoThere is no on/off flag in the file. Delete the entry, or keep a backup copy of the file without it.

Secrets in env are stored in plain text. Anyone who can read your home folder can read them. If that bothers you, and for a shared machine it should, package the server as a Desktop Extension instead. Extension fields marked "sensitive": true go into the macOS Keychain, Windows Credential Manager or your Linux keyring.

Don't expect ${VAR} to expand. Claude Code documents ${VAR} expansion for .mcp.json. No Anthropic doc says Claude Desktop does the same, and the MCP project's own Windows troubleshooting tells you to put the expanded APPDATA value into env, which only makes sense if it doesn't. Write literal values.

The app writes to this file too

mcpServers is not the only thing in there. Anthropic's release notes added a top-level chromiumFlags setting for GPU switches like --disable-gpu. Users also report a preferences block the app manages itself, with keys like quickEntryShortcut and sidebarMode. Leave those alone.

The catch is that the app rewrites the whole file when it saves a preference. Several reports on Anthropic's tracker describe mcpServers getting wiped after a hand edit raced with an app write, or after an invalid entry failed validation. Two habits prevent nearly all of it: quit Claude Desktop before you edit, and keep a copy of your working file somewhere else.

Three entries that cover most servers

A Node package

"memory": {
  "command": "npx",
  "args": ["-y", "@modelcontextprotocol/server-memory"],
  "env": { "MEMORY_FILE_PATH": "/Users/you/claude-memory.jsonl" }
}

The -y stops npx waiting on an install prompt that nobody will ever see. Anthropic's help center mentions a built-in Node.js runtime only for Desktop Extensions, and the MCP guide still lists Node.js as a prerequisite for JSON entries. They call whatever npx is on the PATH, so install Node yourself.

A Python server you wrote

"notes": {
  "command": "/Users/you/.local/bin/uv",
  "args": ["--directory", "/Users/you/code/notes-server", "run", "server.py"]
}

This is the pattern from the official MCP quickstart, with one change: an absolute path to uv. Find yours with which uv on macOS and Linux, or where uv on Windows. --directory is how uv finds your project. Without it the server starts in whatever working directory Claude Desktop happens to have, often / on macOS. If you are building the server itself, our Python MCP server guide covers the SDK side.

A remote server through a local bridge

"dialmcp": {
  "command": "npx",
  "args": ["-y", "dialmcp-connector"]
}

That entry runs a small stdio process on your machine that forwards to a remote server, here our hosted endpoint at https://mcp.dialmcp.com/mcp. The next section explains when you would want that instead of a connector.

Remote MCP servers: connectors or a bridge

Because the file only launches commands, a remote server reaches Claude Desktop one of two ways.

A custom connector. Add the server URL under Customize → Connectors. It replaced the old Settings list in September 2026. Connectors work on Free, Pro, Max, Team and Enterprise, with Free limited to one custom connector. The detail that matters: Anthropic's help center says custom connectors "connect to your MCP server from Anthropic's cloud, not from your local device." So localhost and anything not reachable from the public internet won't work. An Anthropic engineer adds on GitHub that plain http:// URLs won't either. A firewalled server can allowlist Anthropic's IP ranges instead. The upside is that a connector is tied to your Claude account, so once added it is available on claude.ai and in the mobile apps too.

A stdio bridge in the JSON file. mcp-remote is the common one. It's an MIT-licensed community project, not Anthropic's. It runs on your machine, so it can reach a server on localhost, handles the OAuth browser sign-in, and caches tokens in ~/.mcp-auth:

"my-remote": {
  "command": "npx",
  "args": ["-y", "mcp-remote", "https://example.com/mcp"]
}

Useful flags from its README: --header for a static token, --allow-http for a plain-HTTP server on a trusted private network, --transport to force Streamable HTTP or the old SSE transport, and --debug, which writes a log under ~/.mcp-auth. On Windows, the README warns that Claude Desktop doesn't escape spaces inside args. Write the header as "Authorization:${AUTH_HEADER}" with no space, and put "AUTH_HEADER": "Bearer <token>" in env. In that pattern mcp-remote does the substitution, not Claude Desktop. If sign-in gets stuck on stale credentials, deleting ~/.mcp-auth resets it.

Which to pick? Use a connector when the server is public and supports OAuth. Use a bridge when the server only exists on your machine or network, when it needs a static header, or when you want the server only in Desktop. Our remote vs local MCP servers explainer covers the underlying difference, and MCP authorization covers what the OAuth sign-in is actually doing.

Making Claude Desktop read your changes

The file is read at startup. Closing the window is not quitting. On Windows the app keeps running in the system tray, and on macOS it can stay in the menu bar. Quit from the tray or menu bar icon (or Cmd+Q), then reopen.

If you iterate a lot, there's a faster path. Anthropic's MCP Apps troubleshooting guide says Help → Troubleshooting → Enable Developer Mode adds a Developer menu with Reload MCP Configuration, which applies config edits without a restart.

To check it worked, open Settings → Developer, which lists each server with its connection status and links to the logs. In a chat, + → Connectors → Manage connectors shows the same servers and their tools.

What your server's process actually gets

The number one reason a server works in your terminal and fails in Claude Desktop is that the two launch it in different environments. The MCP debugging guide is blunt about it:

  • Working directory: "may be undefined (like / on macOS) since the client could be started from anywhere." Relative paths in args or in your server's .env loading will break.
  • Environment: stdio servers "inherit only a limited subset of environment variables automatically (the exact set is platform-dependent)." Anything else goes in env.
  • PATH: don't assume your server sees the same PATH as your terminal. Anthropic says the macOS app reads PATH from your shell profile for its Code sessions, but users still report spawn npx ENOENT for chat-side servers when npx comes from nvm or asdf. On MSIX installs on Windows, a user report (about an extension, but it's the same process environment) says user-level PATH entries are left out, so tools in %USERPROFILE%\.local\bin aren't found.

The fix is the same for all three: absolute paths everywhere. Use the full path to the binary in command (run which npx in the terminal where it works) and full paths in args. If a tool spawns other tools, pass a PATH value in env. With nvm, point command at the versioned binary, such as ~/.nvm/versions/node/v22.x.x/bin/npx, written out in full since ~ won't expand.

Reading the logs

Claude Desktop keeps two kinds of MCP log, in ~/Library/Logs/Claude on macOS and %APPDATA%\Claude\logs on Windows. Linux uses ~/.config/Claude/logs/. Users report that MSIX installs on Windows keep theirs under the Packages folder.

  • mcp.log covers connections: which servers started, which failed, and why.
  • mcp-server-NAME.log captures that server's stderr: Python tracebacks, Node stack traces, "API key missing" messages.
# macOS
tail -n 20 -F ~/Library/Logs/Claude/mcp*.log

# Windows PowerShell
type "$env:AppData\Claude\logs\mcp*.log"

Two rules for anyone writing the server. First, never print to stdout. A stray print() or startup banner corrupts the JSON-RPC stream and the connection dies with a parse error. Log to stderr, which ends up in the per-server log. Second, keep tool calls short. Anthropic's configuration reference for managed (third-party inference) deployments says that unless an admin sets mcpToolTimeoutSec, the desktop limits calls to user-added local servers to 60 seconds. Assume about a minute. Anything slower should return a job ID right away and let the model poll. DialMCP's tools work that way, since a phone call can run ten minutes.

For a closer look than the logs give you, run the server under MCP Inspector with the exact command and args from your config. If it fails there too, the problem is the server, not Claude Desktop.

Troubleshooting table

SymptomLikely causeFix
No servers at all, no errorInvalid JSON: a trailing comma, a missing brace, smart quotes pasted from a web pageRun the file through a JSON validator, fix it, quit fully and reopen
Edits have no effect (Windows)MSIX install reading the virtualized copyEdit the file under %LOCALAPPDATA%\Packages\Claude_*\LocalCache\Roaming\Claude\
Edits have no effect (any OS)App never really quitQuit from the tray or menu bar, or use Reload MCP Configuration
spawn npx ENOENT or "command not found"PATH differs from your shellAbsolute path in command
Server listed, status failedThe process crashed on startupRead mcp-server-NAME.log; run the same command in a terminal
Parse errors in mcp.logServer writes to stdoutSend all logging to stderr
All servers vanished after an update or editThe app rewrote the file, or an invalid entry (often a url) made it drop the blockRestore your backup; move remote servers to a connector or bridge
"Tool call timed out" on long jobsThe per-call limitReturn a job ID and poll
Connector says it can't reach localhostConnectors run from Anthropic's cloudUse mcp-remote in the JSON file instead
Local servers missing or blocked on a work laptopAdmin policy isLocalDevMcpEnabled is offAsk IT; there is no user override

Moving a config to or from other clients

Going to Claude Code is easy. On macOS and WSL, claude mcp add-from-claude-desktop reads this file from its standard location and lets you pick servers to import. Add --scope user to make them global. Our Claude Code MCP setup guide covers scopes and the "type": "http" field Claude Code uses for remote servers.

Hand-pasting between clients is the trap. Cursor accepts url entries under the same mcpServers key, so a Cursor file looks valid to the eye and breaks Claude Desktop. VS Code uses a servers key in mcp.json. Our MCP configuration examples put each client's file shape side by side.

For admins: Desktop Extensions and local servers can each be switched off by policy (isDesktopExtensionEnabled and isLocalDevMcpEnabled, set through the com.anthropic.claudefordesktop preference domain on macOS or HKLM\SOFTWARE\Policies\Claude, or HKCU for per-user policy, on Windows). The older isDxtEnabled key stopped being read at noon Pacific on October 7, 2026, so rename it to isDesktopExtensionEnabled. When a policy is set, nothing in the user's JSON file overrides it.

Further reading

Want a server worth configuring? DialMCP lets Claude place real phone calls from your own verified number and hand back a transcript and a structured outcome. Add https://mcp.dialmcp.com/mcp as a custom connector, or use the dialmcp-connector bridge in claude_desktop_config.json. Free during launch.

Connect DialMCP to Claude

FAQ

Where is claude_desktop_config.json?

On macOS it is ~/Library/Application Support/Claude/claude_desktop_config.json, and on Windows it is %APPDATA%\Claude\claude_desktop_config.json. On some Windows installs packaged as MSIX, the app reads a copy under %LOCALAPPDATA%\Packages instead, according to an open bug report. The reliable way to open the right file is Settings, then Developer, then Edit Config inside Claude Desktop.

Can I put a remote MCP server URL in claude_desktop_config.json?

No. The file only launches local commands that speak MCP over stdio, and users report that url entries cause errors or get the whole server list dropped. Add remote servers as a custom connector under Customize, then Connectors, or run a local bridge such as mcp-remote as the command.

Why is my MCP server not showing up in Claude Desktop?

The usual causes are invalid JSON, editing a file the app does not read, not fully quitting the app, or a command that is not on the app's PATH. Validate the JSON, quit from the tray or menu bar, use absolute paths, then read mcp.log and mcp-server-NAME.log.

Do I have to restart Claude Desktop after editing the config?

Yes, a full quit and reopen, not just closing the window. With Developer Mode turned on under Help, then Troubleshooting, a Developer menu offers Reload MCP Configuration, which applies changes without a restart.

Where are the Claude Desktop MCP logs?

In ~/Library/Logs/Claude on macOS and %APPDATA%\Claude\logs on Windows. mcp.log records connections and failures, and mcp-server-NAME.log holds each server's stderr output.

Can I use environment variables in claude_desktop_config.json?

You can set them per server in the env object, which is how most servers receive API keys. Do not rely on ${VAR} references being expanded: Claude Code documents that for .mcp.json, but no Anthropic documentation says Claude Desktop does it. Values in env are stored in plain text.