Skip to content

How to See Which MCP Servers Are Actually Running

A server can be configured and not connected, connected in one session and absent from the next, and running as a process long after every client that asked for it has quit. Three checks, in order.

August 8, 20269 min readShift The Culture

“Which MCP servers are running?” is three different questions wearing one coat, and the reason people go in circles on it is that they get an answer to a question they did not ask. A server can be configured and not connected. It can be connected in one session and absent from the one next to it. And it can be running as a process long after every client that asked for it has quit. Here is how to check each one separately, and what to do when the three answers disagree.

The short answer

  • Is it configured, and can it connect? Run claude mcp list in your terminal. It prints a health status per server.
  • Does this session actually have it? Run /mcp inside the session. The terminal command and the session can legitimately disagree.
  • Is a server process alive on this machine right now? Neither of the above tells you. Ask the OS: ps for processes, lsof -nP -iTCP -sTCP:LISTEN for ports.

The rest of this page is why those three can disagree, which is the part that actually costs people an afternoon.

Configured, connected, running are three different states

An MCP server passes through three states, and each one has its own failure mode:

  1. Configured. A line exists in a JSON file somewhere saying this server should be available. Nothing has been launched. Nothing has been checked.
  2. Connected. A client started the server (or reached a remote one), completed the MCP handshake, and pulled its tool list. This is per client and, for stdio servers, per session.
  3. Running. There is a live process on your machine with a pid. For a local stdio server this is the state the OS knows about — and it is the one that outlives everything else when a client exits badly.
Configured is a file. Connected is a session. Running is a process. Most confusion is someone checking one and reasoning about another.

Check 1 — configured: find the file that declares it

Claude Code stores MCP server configuration at three scopes, and they do not live where most people assume:

where each scope is stored
local    →  ~/.claude.json, under the entry for the current project
project  →  .mcp.json in the project root (checked into git)
user     →  ~/.claude.json, at the top level (all your projects)

Two things here trip people constantly. First, local scope is the default — if you ran claude mcp add without --scope, your server was written into ~/.claude.json keyed to the directory you were standing in, which is why it vanishes the moment you open a different project. Second, MCP local scope has nothing to do with .claude/settings.local.json, which is where general local settings live. Same adjective, different file, no relationship.

When the same server name is defined at more than one scope, Claude Code connects once, using the definition from the highest-precedence source — local, then project, then user. The entire entry from that source is used; fields are not merged across scopes. So a stale local-scope entry with the wrong command silently beats the correct project entry your team committed, and nothing about the failure points at the file that caused it.

Check 2 — connected: read the health status, and know what it means

claude mcp list does more than print your config back at you. It health-checks the servers it lists, so each line carries a status:

statuses claude mcp list can print
✔ Connected            handshake completed, tools retrieved
! Needs authentication  reachable, but you are not signed in  → claude mcp login <name>
✘ Failed to connect     Claude Code could not connect to this server
⏸ Pending approval      a project .mcp.json server you have not approved yet

A failure status means that server failed, not that the command failed — an easy misread when one line in a list of ten is red. And ⏸ Pending approval is not an error at all: project-scoped servers from .mcp.json require your approval in an interactive session before Claude Code will connect to them, so they sit in that state until you run claude in the project and approve them.

A green tick from claude mcp list proves the server can start. It does not prove the session you are complaining about has it.

That distinction matters more than it sounds. claude mcp listruns in your terminal, in the directory you are standing in, with your shell's environment. A session running elsewhere has a different working directory (so different local- and project-scope servers), potentially a different environment, and it resolved its server list when it started — before the edit you just made. Inside the session, /mcp is the authoritative view. If claude mcp list says connected and /mcp disagrees, believe /mcp and start restarting things.

Check 3 — running: only the OS knows

Neither command above answers “is there a process alive right now.” For that you go underneath the client:

the two commands that actually answer it
# every process whose command line mentions an MCP server, with parent pid and tty
ps -Ao pid,ppid,tty,etime,command | grep -i '[m]cp'

# every TCP port in LISTEN state, with the process that owns it
lsof -nP -iTCP -sTCP:LISTEN

Read three columns and you have almost everything: ppid tells you who launched it (a ppid of 1 means its parent is gone and the process was reparented to init — an orphan), tty of ?? means it is not attached to any terminal, and etime tells you how long it has been alive. A server with ppid 1 and days of uptime is not serving anyone.

Why the process count is higher than the server count

This is the part that makes people think something is broken when it is working as designed. A local MCP server uses the stdio transport: the client launches the server as a child process and talks to it over that child's stdin and stdout. There is no shared broker, no daemon, no port. It follows that every client connection gets its own copy. Four Claude Code sessions with the same stdio server configured at user scope means four separate server processes, each holding its own memory.

It compounds, because a single logical server is often several processes. Here is a real ps output from the machine this page was written on, filtered to one server:

ps -Ao pid,ppid,command | grep blender-mcp
75398  74931  .../Helpers/disclaimer /opt/homebrew/bin/uv run blender-mcp
75399  75398  /opt/homebrew/bin/uv run blender-mcp
75424  75399  .../blender-mcp/.venv/bin/python ...
75400  74931  .../Helpers/disclaimer /opt/homebrew/bin/uv run blender-mcp
75403  75400  /opt/homebrew/bin/uv run blender-mcp
75474  75403  .../blender-mcp/.venv/bin/python ...

Six processes. Not six servers — two independent chains of three, because a launcher (uv, or npx for Node servers) does not replace itself with the server, it spawns it. So one registration is a wrapper, a launcher, and the actual server. Two registrations of the same server is six processes. If you are counting processes to count servers, divide by the chain depth first, or you will go hunting for a leak that is not there.

When the three answers disagree: a short decision table

  • Configured, but claude mcp list shows nothing. You edited a file at a scope that does not apply here — almost always a local-scope entry under a different project path in ~/.claude.json, or a .mcp.json in a directory that is not the project root.
  • Listed as ⏸ Pending approval. Not broken. Run claude in the project interactively and approve it.
  • claude mcp list is green, the session has no tools. The session resolved its servers at startup. Restart it. If it still disagrees, the session is running in a different directory than your terminal.
  • Nothing is connected, but processes are running. Those are leaked children of dead clients. Check ppid — if it is 1, nobody is talking to that process and it is pure resident memory.
  • Everything green, tools still not called. That is a different problem — connection is not the same as the model choosing to use it. See the full not-loading diagnostic.

Give the agent the same view you just gave yourself

Everything above is a thing you run. The more expensive version of this problem is when the agent gets it wrong: you ask whether a service is up and it answers from a transcript, a CLAUDE.md line, or a memory of a session two weeks ago. Model memory is a cache with no invalidation. It will tell you a server is live because that was true when someone wrote it down.

That is the reason we built whats-running-mcp and gave it away. It is an MIT-licensed MCP server that runs the checks in this article and hands the result to the model instead of to you — agent_sessions (live agent processes, terminal-attached vs detached, with pid, uptime and working directory), listening_ports (every TCP LISTEN socket with its owning process), daemons, and system_stats. Read straight from ps, lsof, launchctl and df, never from documentation.

install — one line, no config
claude mcp add --scope user whats-running -- npx -y whats-running-mcp

It is read-only by construction: every command is a fixed binary with fixed flags via execFile, no shell, and nothing derived from model input is ever executed. Source on GitHub, package on npm. If you want the “which config declares this server” half instead, its sibling whats-loaded-mcp has an mcp_servers tool that lists every MCP server configured across your clients and which file declares each one. Both are free and stay free — the full set is on our agent tools page.

The whole thing on one screen

mcp status check, in order
# 1. configured + reachable?
claude mcp list
claude mcp get <name>          # one server, resolved config + health

# 2. does THIS session have it?
/mcp                           # inside the session, not the terminal

# 3. what is actually alive?
ps -Ao pid,ppid,tty,etime,command | grep -i '[m]cp'
lsof -nP -iTCP -sTCP:LISTEN

# 4. anything with ppid 1 is an orphan — nobody is talking to it

If step 3 turns up a page of processes nobody is connected to, that is its own problem with its own procedure — and the naive fix that most search results give you will kill your live sessions along with the dead ones. That is covered in orphaned Claude Code processes. If a server is configured and simply refuses to appear, work through the not-loading diagnostic instead.

Sources for the client behaviour described here: Anthropic's Claude Code MCP documentation(installation scopes, scope precedence, health statuses, project-server approval) and the MCP specification's stdio transport. The ps output above is from a real machine, not an illustration.

SharePost on X
Free · 13 pages · no upsell inside

Get the Operator Field Kit — free

Six production prompts, the five-step operator setup, and nine rules from our own failure log.

  • 6 complete prompts — printed in full, not previews
  • The five-step setup, each step with a pass/fail test
  • 9 rules from the failure log that produced them

The kit, then the occasional operator note. One click unsubscribes and we never sell the address.

Keep reading