Troubleshooting MCP Servers in Cursor

MCP servers extend Cursor with external tools, but they are independent processes with their own dependencies, and when they misbehave the symptoms can be confusing: a server that shows red, a tool list that will not refresh, or a disconnect button that appears to do nothing. This guide gives you a systematic way to diagnose MCP problems in Cursor, from the quick triage checklist through the specific fixes for each common failure mode, and shows you how to validate any server outside the IDE so you can tell whether the problem is in the server or in Cursor's connection to it.
Quick Triage Checklist
When an MCP server misbehaves, run through this table from top to bottom. Most issues are resolved in the first three rows.
| Symptom | First thing to check | Typical fix |
|---|---|---|
| Server shows red or fails to start | Run the server command manually in a terminal | Fix command path, missing runtime, or env vars |
| Tools missing or stale | Did you edit mcp.json without restarting? | Restart Cursor or reload the window |
| Disconnect button does nothing | Is the process actually dead? | Kill the process manually, then reconnect |
| Server errors and never retries | Cursor does not auto-retry after some failures | Toggle the server off and on, or restart |
| Requests hang then time out | Server startup or tool runtime is too slow | Pre-warm dependencies, raise the timeout |
| Authentication errors | Token expired or env var missing | Refresh the token, fix the environment |
Server Won't Start
The most common MCP failure is the simplest one: the command Cursor uses to launch the server does not actually work. Cursor spawns exactly the command in your mcp.json, with the environment you gave it, and if that fails the server never appears.
Bad Command Path
Check the command exactly as Cursor would run it. If mcp.json says command": "npx" but your PATH inside the Cursor process does not include npx, the spawn fails. On Windows this is especially common because GUI applications inherit a different PATH than your terminal.
{
"mcpServers": {
"filesystem": {
"command": "C:\\Program Files\\nodejs\\npx.cmd",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "C:\\projects"]
}
}
}
Using the absolute path to the executable is the reliable fix on Windows. On macOS and Linux, which npx tells you the absolute path if the bare command is not being found.
Missing npx or uvx
Many MCP servers ship as npm or Python packages and are launched through npx or uvx. If the runtime is not installed, the server cannot start:
# Verify the runtimes exist
node --version # Node 18+ for npx-based servers
npx --version
python --version
uvx --version # install with: pip install uv
If uvx is missing, install it and restart your terminal and Cursor so the updated PATH is picked up.
Wrong Environment Variables
A server that needs an API key will often start and then immediately exit, or start and return errors on every tool call, when its environment is wrong. Read the server's documentation for the exact variable names, and remember that Cursor passes only what you list in the env block:
{
"mcpServers": {
"github": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "${GITHUB_PAT}"
}
}
}
}
Tools Not Reloading After Editing mcp.json
You edit mcp.json, save it, open the tool list, and the new tools are not there. MCP configuration is read when the server process starts, so edits do not hot-reload in every situation.
- Save the file and confirm it is valid JSON. A trailing comma makes the whole file unparseable and every server can fail.
- Restart Cursor completely, or reload the window if your version offers a reload option in the command palette.
- Open the MCP settings panel and confirm the server shows as connected.
- Start a new chat. An existing conversation may have cached the old tool list, so new tools only appear in fresh sessions.
If toggling the server off and on in the MCP panel does not pick up your changes, do a full window reload or restart Cursor. mcp.json is read at connection time, and a stale process keeps serving its original tool list no matter what the file says now.
Connection and Retry Issues
The Disconnect Button Does Nothing
The disconnect action stops Cursor's client side of the connection, but with stdio servers the actual child process can survive if it does not shut down cleanly. The result is a server that still appears half-alive and refuses a clean reconnect. When the button seems ignored:
# Find and kill a stubborn stdio MCP server process
# macOS / Linux:
ps aux | grep mcp
kill <PID>
# Windows PowerShell:
Get-Process | Where-Object { $_.ProcessName -like "*npx*" -or $_.ProcessName -like "*uvx*" }
Stop-Process -Id <PID> -Force
After the process is gone, reconnect from the MCP panel. The next connection starts a fresh process with your current configuration.
No Retries After a Server Error
If a server returns an error on startup or during initialization, Cursor generally does not keep retrying in the background. The server stays in a failed state until you intervene. The manual restart options, in increasing order of force:
- Toggle the server off and on in the MCP settings panel.
- Reload the Cursor window so all MCP servers reconnect.
- Fully quit and restart Cursor.
- If the process is wedged, kill it as shown above and then reconnect.
Timeouts on Slow Servers
Servers that download dependencies on first run, or tools that call slow external APIs, can exceed the default timeout and report a failure that looks like a broken server. The classic case is an npx-based server on its first invocation, when npm fetches the package before anything can start:
# Pre-warm an npx-based server so the first real connection is fast
npx -y @modelcontextprotocol/server-github --help
For host-level timeouts, many MCP hosts, Cursor included, respect conventional timeout environment variables. Setting them before launching Cursor gives slow servers more room:
# macOS / Linux (add to your shell profile)
export MCP_TIMEOUT=30000 # server startup timeout in ms
export MCP_TOOL_TIMEOUT=120000 # individual tool call timeout in ms
If a server is still too slow, host it differently: run it as a persistent local process and connect over SSE or HTTP instead of spawning it per session.
Transport Types: stdio vs SSE/HTTP
Cursor supports two MCP transport styles, and several troubleshooting steps differ between them.
| Aspect | stdio | SSE / HTTP |
|---|---|---|
| How it runs | Cursor spawns the process | Server runs separately, Cursor connects to a URL |
| Config keys | command, args, env | url (and headers where supported) |
| Common failures | Bad command path, missing runtime | Wrong URL, auth headers, CORS or network issues |
| Restart behavior | Toggling reconnects the process | Reconnect hits the remote endpoint |
| Debugging | Run the command manually | Curl the endpoint, check server logs |
{
"mcpServers": {
"local-stdio-server": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"]
},
"remote-http-server": {
"url": "https://mcp.example.com/sse"
}
}
}
For SSE and HTTP servers, verify the endpoint is reachable before touching Cursor at all:
# A plain GET should return something, even if it is an auth error
curl -i https://mcp.example.com/sse
A 401 or 403 means the transport is fine and your authentication is the problem. A timeout or connection refused means the server is down or the URL is wrong.
Environment Variables and Secrets
Project vs Global mcp.json
Cursor reads MCP configuration from two places:
- Global:
~/.cursor/mcp.json(on Windows:%USERPROFILE%\.cursor\mcp.json). Applies to every project. Put personal servers here: your GitHub token, your database browser, your scraping tools. - Project:
.cursor/mcp.jsoninside the repository. Applies only to that project and is shared with teammates when committed. Put project-specific servers here: a schema MCP for this repo's database, a design tool integration used by this codebase.
When a server is defined in both places, expect the project configuration to govern that project. If tools duplicate or vanish, check both files for an entry with the same name.
Passing Secrets Safely
Cursor expands ${VAR_NAME} placeholders in the env block from your environment, so secrets can live outside mcp.json:
{
"mcpServers": {
"postgres": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-postgres"],
"env": {
"DATABASE_URL": "${MY_DATABASE_URL}"
}
}
}
}
# Set the real value in your shell profile, not in the JSON file
export MY_DATABASE_URL="postgresql://user:password@localhost:5432/appdb"
Project-level .cursor/mcp.json is a regular file in your repo. If it contains a literal API key, every person and every agent that clones the repository gets the key. Use ${VAR} expansion for anything sensitive, and add project mcp.json to .gitignore if it must contain local values.
Reading MCP Logs
When the symptom is unclear, the logs usually name the real problem. Cursor surfaces MCP activity through its output infrastructure:
- Open the command palette and run the command to show the output panel, or use the View menu.
- In the output panel's channel dropdown, select the MCP or Cursor MCP logs channel.
- Trigger the failing action, then read the newest entries. Look for spawn errors, non-zero exit codes, and stack traces from the server's stderr.
Typical log lines and what they mean:
[MCP] spawn npx ENOENT -> the runtime was not found on PATH
[MCP] server exited with code 1 -> the server crashed; run it manually for the real error
[MCP] initialize timed out -> slow startup; pre-warm or raise the timeout
[MCP] tool call rejected: invalid args -> the model sent a bad schema; check the tool input
Server-side stderr is forwarded into these logs, so a Python traceback or a missing-dependency exception from the server itself usually appears here verbatim.
Validating a Server Standalone
The fastest way to prove whether a problem is Cursor's or the server's is to run the server without Cursor.
Run the Command Manually
Copy the command and args from mcp.json and run them in a plain terminal:
# Whatever your mcp.json launches, launch it yourself
npx -y @modelcontextprotocol/server-filesystem /tmp
A healthy stdio MCP server starts and waits silently for JSON-RPC input on stdin. If you instead see a command-not-found error, a crash, or a package installation failure, you have found the problem and Cursor is innocent. Type a few characters and press Enter; a bare protocol error response is actually a good sign, because it proves the process is speaking JSON-RPC.
Use the MCP Inspector
The official MCP inspector connects to a server, lists its tools, and lets you call them interactively:
npx @modelcontextprotocol/inspector npx -y @modelcontextprotocol/server-filesystem /tmp
This opens a local web interface where you can initialize the server, list tools, and invoke one with hand-written arguments. If a tool works in the inspector but not in Cursor, the difference is usually the environment: variables present in your terminal but missing in Cursor's process, or a different working directory. If the tool fails in the inspector too, fix the server first; nothing you change in Cursor will help.
Minimal Working mcp.json
Use this as a reference when your configuration has drifted into something that no longer starts. It shows one stdio server and one remote server, with env expansion:
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-filesystem",
"/Users/you/projects"
]
},
"remote-search": {
"url": "https://mcp.example.com/sse",
"env": {
"API_TOKEN": "${MY_MCP_TOKEN}"
}
}
}
}
Checklist for adapting it to your server:
- Replace the package name and arguments with the ones from the server's documentation.
- Use absolute executable paths on Windows if the bare command is not found.
- Keep secrets as
${VAR}placeholders and set the real values in your shell profile. - Validate the JSON, then restart Cursor and confirm the server shows as connected before opening a chat.
mcp.json is parsed as a single JSON document. A single trailing comma or unquoted value makes the entire file invalid, and every server in it can fail to start together, including the ones that were working fine. If several servers break at once, suspect the file syntax before suspecting each server.
Quick Reference
| Goal | Do this |
|---|---|
| Server red after startup | Run the command manually; fix path, runtime, or env |
| New tools not appearing | Reload the window, then start a fresh chat |
| Disconnect unresponsive | Kill the child process, then reconnect |
| Repeated failures, no retry | Toggle the server off and on, or restart Cursor |
| First-run timeout | Pre-warm the package, raise the timeout env vars |
| Suspect the server, not Cursor | Validate with a manual run or the MCP inspector |
| Suspect Cursor, not the server | Diff your env against a terminal and read the MCP logs channel |