How to fix a Cursor MCP server stuck on 'Loading tools'
A Cursor MCP server stuck on "Loading tools" almost never means the server is slow. It means the request Cursor sent, asking the server to list its tools, never got a response, because the server process either failed to start or crashed before it could answer. Cursor is still waiting, and it will keep waiting until something interrupts it.
The fix depends on why the process didn't start, and the two most common reasons are a wrong path in the server's launch command and a stale connection that a simple toggle won't clear. Both are ordinary first-integration mistakes, and both are checkable in under a minute once you know where Cursor logs the failure.
What "loading tools" means
Model Context Protocol is a request-response handshake. When you add a server, Cursor's client sends a tools/list call and waits for the server to answer with its available tools, resources, and prompts. Per Cursor's MCP documentation, a server can be configured two ways: project-scoped in .cursor/mcp.json, or global in ~/.cursor/mcp.json, with either a local command Cursor spawns itself or a remote URL it connects to over HTTP.
For a local command-based server, "the server" is a process Cursor starts on your machine (node, python, uvx, whatever you configured). If that process exits immediately, throws on startup, or was never found on your system's PATH, there's no process to answer the tools/list request, and Cursor has no way to distinguish "still starting" from "already dead." It just keeps spinning. This exact symptom shows up outside Cursor too. A Figma community report describes the identical "stuck at Loading tools" state for a different MCP server. The process behind that connection was never reachable either, the same root cause behind Cursor's version of the freeze.
The four things that cause it
A relative or missing path in the command. mcp.json entries for local servers need a command Cursor can execute, either something already on PATH, or an absolute path to the binary or script. "command": "python" works if python resolves in the shell Cursor spawns from; "command": "./venv/bin/python" usually doesn't, because Cursor doesn't launch the server from your project directory.
A missing or malformed environment variable. Servers that need an API key read it from the env block in mcp.json. Cursor's docs confirm ${env:VARIABLE} interpolation is supported, and a missing variable there often means the server process starts, fails an internal check, and exits. Nothing surfaces in the UI beyond the spinner.
A server that crashed after connecting. Cursor's own troubleshooting guidance points to the Output panel: open it with Cmd+Shift+U (or Ctrl+Shift+U on Windows/Linux), then pick "MCP Logs" from the dropdown. That log is the one place that tells apart three states the tools panel shows identically: never started, started and crashed, and connected but slow.
A stale connection that a toggle won't fix. Editing mcp.json doesn't always get picked up by a running Cursor window. Disabling and re-enabling the server from Cursor Settings → Tools & MCP resolves most of these. When it doesn't, the fix is a full quit and reopen of Cursor, not a window reload. Reloading the window doesn't always restart the MCP client process holding the broken connection, so the same failure survives the reload.
Owen Mercer's Tuesday afternoon
Owen Mercer, a staff engineer at Bracket Labs, added a local MCP server that read from the team's staging Postgres database, so Cursor's agent could check schema questions without him pasting \d output into the chat every time. He copied the example from the library's README:
{
"mcpServers": {
"postgres": {
"command": "mcp-server-postgres",
"args": ["postgresql://localhost/staging"]
}
}
}Cursor showed the server as connecting, then sat on "Loading tools" for several minutes. Owen's first move was toggling it off and on from Tools & MCP. Nothing changed. He almost let it ride another ten minutes as "probably still indexing the schema," until he tried running mcp-server-postgres directly from a plain terminal instead of trusting the toggle. command not found. The library's install had gone into a project virtualenv, not onto his system PATH, so the process Cursor spawned couldn't find it either, no matter how long he waited.
He pointed mcp.json at the virtualenv's absolute path (/Users/owen/bracket/.venv/bin/mcp-server-postgres), but the spinner didn't budge, not from a toggle. Only a full quit and reopen of Cursor cleared it. The client had cached the earlier failed handshake, and no amount of re-enabling the server from Tools & MCP was going to make it forget that.
When hand-rolled MCP config becomes the actual bottleneck
A single local server, on one person's machine, is a five-minute fix once you know to check the logs. The math changes once it's not just Owen's machine. A team of ten engineers each running their own copy of a command-based server means ten different PATHs, ten different places for a typo, and ten separate rounds of "is it slow or is it dead" in a Slack thread. Every new hire repeats the debugging Owen just did, because the fix lived in his terminal history, not in a config anyone else can reuse.
That's the class of problem a hosted, remote MCP server sidesteps rather than solves after the fact. Modem's MCP server is one example built this way, using a single https://mcp.modem.dev/mcp URL added under Cursor Settings → Tools & MCP, Streamable HTTP as the transport, and OAuth for authorization, so there's no local command, no PATH, and no env block to get wrong on any given machine. Setup is a single URL, documented per client, in Modem's MCP docs, and the same URL works whether it's your laptop or a new hire's. It's worth naming plainly that this guide comes from the company that built the Cursor integration it's describing. The point generalizes past Modem specifically, too. A remote server with a documented URL removes an entire category of "stuck loading tools" that local, per-machine commands don't. It doesn't fix a broken local server you already depend on; the four checks above still apply there. It just means the next server your team adds doesn't need them.
For getting Modem's server to answer useful questions once it's connected, the six best tools to give Cursor customer context compares it against .cursor/rules files and single-source servers, and how to give Cursor context about a specific customer bug report walks the exact setup end to end.
The check to run first, every time
Before touching mcp.json again, open MCP Logs (Cmd+Shift+U, then select it from the dropdown), and read what's there. If it's empty, the process never started, so check the path. If it shows a crash, read the error, then check the env vars. If it shows a successful connection and the tools panel still spins, quit Cursor entirely and reopen it. That order costs less time than guessing at which of the three states you're in.
