Troubleshooting

Copilot MCP Server Not Connecting? Work Through It in Order

An MCP server that shows as failed, or connects and exposes no tools, almost always fails for one of six reasons. Diagnose them in the order they actually occur, with the commands.

Copilot MCP Server Not Connecting? Work Through It in Order/blog/github-copilot-mcp-not-connecting/

Short answer. An MCP server that will not connect is almost always one of six things, and they are worth checking in this order because that is roughly how often each one is the cause: the command cannot be found, the process exits immediately, something is written to stdout that is not protocol, a required environment variable is missing, the client never restarted, or the server started fine and simply exposes no tools.

The last one is the one people misdiagnose, because it does not look like a failure. It looks like Copilot ignoring you.

Get the actual error first

Nearly every MCP question online is answered without the error message, because the error is not in the chat window. It is in the MCP log.

VS Code. Command palette → MCP: List Servers → pick the server → Show Output. That pane holds the server’s stderr, which is where the real message is.

Anything else. Run the server’s command yourself, in a terminal, from the same working directory the client uses:

npx -y @example/some-mcp-server@1.4.2

If it prints a stack trace and exits, you have your answer and the rest of this page is unnecessary. If it sits there apparently doing nothing, that is correct — an MCP server over stdio waits for a client and produces no output on its own.

1. The command cannot be found

The most common cause, and it produces spawn ENOENT or command not found.

The client does not necessarily inherit your shell’s PATH. A GUI application launched from a dock or a launcher gets the login environment, which frequently does not include the PATH additions in your .zshrc — so npx, uvx, node or a version-manager shim that works perfectly in your terminal is genuinely absent from the client’s environment.

Fix it by giving an absolute path:

which npx        # /Users/you/.nvm/versions/node/v22.12.0/bin/npx
{
  "servers": {
    "example": {
      "command": "/Users/you/.nvm/versions/node/v22.12.0/bin/npx",
      "args": ["-y", "@example/some-mcp-server@1.4.2"]
    }
  }
}

An absolute path pinned to a version-manager directory breaks when you upgrade Node. That is a real cost, and it is still better than a server that works for you and not for the person you sent the config to.

2. The process starts and exits immediately

The log shows a start and then a close, with no error you can see.

Run the command by hand. The usual causes, in order:

  • A missing runtime. The server needs Node 20+, or Python 3.11+, and the binary on PATH is older.
  • A package that does not exist at that version. npx -y pkg@2.0.0 will happily fail if 2.0.0 was never published.
  • A crash on startup because a required argument is missing. The server prints usage and exits 1; the client reports a close.

3. Something is being written to stdout

This one is worth understanding because the symptom is bizarre: the server starts, the client connects, and then the connection drops with a parse error.

On stdio transport, stdout is the protocol. Every byte on stdout must be a JSON-RPC message. A single print(), console.log(), a progress bar, a dependency’s banner, or a “listening on…” line corrupts the stream and the client disconnects.

If you are writing the server: everything diagnostic goes to stderr.

import sys
print("connected to database", file=sys.stderr)   # correct
print("connected to database")                    # breaks the protocol
console.error("connected to database");  // correct
console.log("connected to database");    // breaks the protocol

If you are using someone else’s server, a dependency doing this is a bug worth reporting — and npx itself can print an install line the first time it fetches a package, which is why pinning the version and pre-installing it sometimes makes a “flaky” server stop being flaky.

4. A required environment variable is missing

The server starts, connects, and then every tool call fails with an authentication error. Or it exits with something like Error: API_TOKEN is required.

Environment variables in the config are not read from your shell:

{
  "servers": {
    "tracker": {
      "command": "npx",
      "args": ["-y", "@example/tracker-mcp@2.0.1"],
      "env": {
        "TRACKER_TOKEN": "${env:TRACKER_TOKEN}"
      }
    }
  }
}

${env:TRACKER_TOKEN} resolves from the client’s environment, which is the login environment, not your terminal’s. If you exported it in a shell, the client cannot see it. Set it where the client will find it, or use the client’s own secret input prompt if it has one.

5. The client never picked up the change

Editing the config does not always reload the server, and a stale process produces exactly the symptoms of a broken config that you have already fixed.

In VS Code: MCP: List Servers → the server → Restart. If the tool list still does not change, restart the window. If you have edited config in more than one place — a user-level file and a workspace file — check which one is actually in effect; a workspace config that overrides your user config is a common source of “my change did nothing”.

6. It connected, and it has no tools

The server shows as running. Copilot ignores every request that should use it. This is not a connection problem and the connection logs will tell you nothing.

Ask the client what tools it can see — in VS Code agent mode, the tools picker lists them. If the server is there with an empty list, the server started and registered nothing. Causes:

  • The server needs configuration before it exposes anything. Several database and API servers register tools only after a successful connection to the thing they wrap.
  • A capability mismatch. The server implements a protocol version or a capability the client does not use.
  • The tools exist but the model is not choosing them. Different problem entirely: the tools are listed, and Copilot is answering from its own knowledge instead of calling them. Naming the tool explicitly in your prompt is the quickest way to tell these apart.

The check that catches most of it in one go

# 1. Does the command resolve, absolutely?
which npx

# 2. Does the server start by hand, in the right directory?
cd /path/your/client/uses
npx -y @example/some-mcp-server@1.4.2

# 3. Does anything other than the client see its tools?
npx @modelcontextprotocol/inspector npx -y @example/some-mcp-server@1.4.2

If all three work and the client still does not, the problem is in the client’s configuration — which file it read, whether it restarted, and whether a workspace setting is overriding a user one.

Before you add the server at all

An MCP server is a third-party integration that runs inside an agent loop, frequently with your credentials, and it is installed in about forty seconds. That combination deserves a moment’s thought before the connection problem is solved rather than after.

The MCP security lesson covers what to check: read the full tool list rather than the description, scope the credential to the server instead of using a personal token, and pin the version so the thing you reviewed is the thing that runs tomorrow.

Where to go next

Sources

Every version-sensitive claim on this page was checked against first-party documentation. Only sources actually used are listed.

Primary sources

Go deeper in the Academy