How to Add a Custom MCP Server to Cursor and Test It Safely
Cursor reads MCP servers from .cursor/mcp.json in the project root for project-scoped servers, or from ~/.cursor/mcp.json for global ones. Add the server block, restart Cursor, then approve the tools in the Tools panel — the editor won’t expose them until you explicitly toggle them on.
That approval step is where most setups appear broken. The config is right, the server runs, and no tools show because nobody clicked.
Where does Cursor look for MCP config?
Two files, two scopes:
| File | Scope | Use for |
|---|---|---|
.cursor/mcp.json |
This project only | Project-specific APIs, committing to the repo |
~/.cursor/mcp.json |
All projects | Personal tools, filesystem access, Git |
If both exist, project-level entries merge with global ones and project takes precedence on name collisions. Name servers distinctly — a global postgres and a project postgres with different connection strings is a debugging afternoon you don’t want.
Step 1: Add the server block
Here is a minimal per-project config with an API key passed as an environment variable:
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "."],
"env": {}
},
"internal-api": {
"command": "node",
"args": ["./mcp-server/dist/index.js"],
"env": { "API_TOKEN": "paste-token-here" }
}
}
}
The . in the filesystem args means “current working directory” — scoped to the project, which is what you want. Never point it at ~.
Step 2: Restart, then enable the tools
Completely quit Cursor and reopen the project. Open the agent panel and look at the tool list — there’s an MCP section where each server shows its tools with individual toggles.
Enable the ones you need. Cursor keeps them disabled by default for a reason: a filesystem server with 11 tools adds 11 function definitions to every request, which costs tokens and dilutes tool selection. Enable three tools and the model picks correctly more often than when all 11 are on.
Step 3: Watch the output for startup errors
Cursor surfaces MCP stderr in the Output pane under the MCP channel. Two errors that come up constantly:
- Server exited before handshake — usually a missing dependency. Run the exact command in your terminal; the real error appears there.
- Tool call failed with 401 — the env var didn’t reach the subprocess. Cursor passes
envverbatim; if your server reads a config file instead, that file may be in the wrong working directory.
Relative paths in args resolve from the workspace root, not from the config file’s folder. That trips people up in monorepos.
Step 4: Decide what the agent is allowed to touch
MCP changes what the agent can do without approval. A Postgres server with write access in an agent that also runs terminal commands is a bad combination — one hallucinated query and a table is gone.
Practical rules that have served me well:
- Read-only database credentials for any MCP server in a coding agent
- Filesystem scope limited to the project folder
- No server with production credentials in a config file that lives in a repo you might push publicly
.cursor/mcp.jsonin.gitignoreif it contains tokens
Step 5: Write your own and test it as a project server
If you build a server, develop it inside the project and point Cursor at ./mcp-server/dist/index.js. Rebuild and restart Cursor to pick up changes — Cursor doesn’t hot reload MCP servers, which surprises people mid-session.
For quick iteration, run it in a terminal first and use the MCP Inspector to confirm it lists tools before wiring it into Cursor. Debugging through the editor’s output pane is slower.
Why do tools disappear after a Cursor update?
Because the tool approval state is tied to the server’s reported tool list. If your server changes its tools — added a parameter, renamed something — Cursor treats them as new and leaves them disabled. Re-enable them after any server update. This is also why version-pinning your MCP server package is worth the small hassle.
Should MCP servers be per-project or global?
The filesystem and shell-adjacent ones per-project, always. A global filesystem server pointed at your home directory means every project you open can read every other project. Database and API servers where the credentials differ per project belong in the project config; ones like a documentation search or a personal notes server work fine globally.
Quick Summary
- Project config lives at
.cursor/mcp.json; global at~/.cursor/mcp.json. - Restart Cursor fully and enable each tool manually in the MCP panel.
- Give filesystem servers the project folder (
.), never your home directory. - Use read-only DB credentials; keep tokens out of committed config files.
- Tools reset to disabled when a server changes its tool list — re-enable after updates.
