MCP Servers in Cursor: Setup & Security Guide (2026)
SWATI BARWAL
·11 min read
Cursor ships with native Model Context Protocol (MCP) support, so your agent can call external tools — query a database, search GitHub, read docs — without custom plugins. This guide walks through where to put `mcp.json`, how to wire your first stdio server, when to use remote HTTP transport, and the security rules that keep API keys and filesystem access under control.
If you are new to the protocol itself, start with our MCP explainer first. This post assumes you know what a host, client, and server are.
What you'll learn
Where Cursor reads MCP config (global vs project)
How to add a stdio MCP server with npx
How to connect a remote HTTP/SSE MCP endpoint
Security practices: secrets, filesystem scope, and team sharing
How to verify tools appear in Cursor Agent mode
Common connection errors and fixes
Prerequisites
Cursor installed (MCP is built in — no extension required)
Node.js 18+ for Node-based MCP servers (npx)
Basic JSON editing
Optional: GitHub personal access token for the GitHub server example
Where Cursor loads MCP configuration
Cursor reads server definitions from `mcp.json` in two places (official docs):
Scope | File path | Best for |
|---|---|---|
Project | .cursor/mcp.json at repo root | Team-shared servers tied to one app (DB, internal API) |
Global | ~/.cursor/mcp.json | Personal tools you want in every workspace (GitHub, filesystem) |
Precedence: If the same server name exists in both files, the project entry wins.
You can also add servers from Cursor Settings → MCP (edits the global file) or install marketplace plugins with one click. For reproducible team setups, commit .cursor/mcp.json to git — without secrets.
my-app/
├── .cursor/
│ └── mcp.json ← project MCP servers
├── src/
└── package.jsonStep 1 — Add your first stdio server (filesystem)
Most local MCP servers use stdio: Cursor spawns a child process and talks over stdin/stdout. There is no TCP port unless you explicitly configure a remote url.
Create .cursor/mcp.json in your project root:
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-filesystem",
"/Users/you/projects/sandbox"
]
}
}
}Replace the path with a dedicated sandbox folder — never your home directory or ~/.ssh.
Security note: The filesystem server can read and write every file under the path you pass. Treat that directory like a chroot for the model.
After saving:
1. Open Command Palette → Developer: Reload Window (or restart Cursor) 2. Open Settings → MCP and confirm the server shows as connected 3. In Agent mode, ask: *"List files in my sandbox folder"* — Cursor should call the MCP tool
If the server fails, open the MCP log output in Settings and read the stderr line — spawn ENOENT usually means npx is not on Cursor's PATH (fix with an absolute path to npx).
Step 2 — Global GitHub MCP (optional)
For repos you work on across many projects, put GitHub MCP in ~/.cursor/mcp.json:
{
"mcpServers": {
"github": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "${env:GITHUB_TOKEN}"
}
}
}
}Set GITHUB_TOKEN in your shell profile or use Cursor's ${env:VAR} substitution so the token never lands in committed JSON.
Scopes to grant: repo (private repos) or narrower read-only scopes if you only need issues and search.
Test in Agent mode: *"Search open issues in org/repo mentioning MCP."*
Step 3 — Remote HTTP / SSE servers
When a teammate hosts an MCP server on HTTPS (common for shared internal tools), use the url form instead of command:
{
"mcpServers": {
"internal-runbooks": {
"url": "https://mcp.internal.example.com/mcp",
"headers": {
"Authorization": "Bearer ${env:INTERNAL_MCP_TOKEN}"
}
}
}
}Cursor supports OAuth for some remote servers — see Cursor MCP docs for static OAuth client configuration when dynamic registration is unavailable.
Remote servers are easier to share across a team (one deployment, many IDEs) but expand your attack surface — authenticate at the edge and rotate tokens.
Step 4 — Use MCP tools in Agent vs Chat
Mode | MCP behavior |
|---|---|
Agent | Multi-step tasks; Cursor can call MCP tools automatically when relevant |
Chat | Tool use depends on model and settings; Agent is the reliable path for MCP |
Workflow that works well:
1. Configure servers and reload Cursor 2. Open Agent (Cmd+I / Ctrl+I) 3. Give a goal that requires the tool: *"Using the GitHub MCP server, list my open PRs in trinitytuts/trinity"* 4. Approve tool calls when prompted (first run per session)
If tools never appear, the server is disconnected — fix config before blaming the prompt.
Security checklist (do this before production repos)
1. Least-privilege filesystem paths
Bad | Good |
|---|---|
/Users/you | /Users/you/projects/acme-api-sandbox |
Repository root with .env | Subfolder without secrets |
Add .env, *.pem, and credential files to .gitignore and keep them outside the MCP filesystem root.
2. Never commit secrets in `mcp.json`
Pattern | Safe? |
|---|---|
"API_KEY": "sk-live-..." in committed JSON | No |
"API_KEY": "${env:API_KEY}" | Yes |
envFile: ".env" with .env gitignored | Yes |
Use git-secrets or pre-commit hooks if multiple authors edit .cursor/mcp.json.
3. Pin server package versions
npx -y @scope/[email protected] prevents silent upgrades that change tool schemas or add risky capabilities. Pin in args after you verify a version works.
4. Separate dev and prod tokens
Use read-only database credentials for MCP SQL servers. Never point Agent at production write replicas unless you accept automated mutation risk.
5. Audit tool approvals
Cursor prompts before some tool executions. Read the payload — a compromised or overly broad server could exfiltrate files or run destructive SQL.
6. Remote server TLS and auth
Require HTTPS, short-lived bearer tokens, and network policies (VPN or Zero Trust) for internal MCP gateways.
Project vs global: team workflow
Recommended split for TrinityTuts-style teams:
// ~/.cursor/mcp.json — personal
{
"mcpServers": {
"github": { "...": "..." }
}
}// .cursor/mcp.json — committed to repo
{
"mcpServers": {
"project-docs": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "./docs"]
}
}
}New clones get project servers automatically. Each developer keeps personal tokens in environment variables, not in git.
Example: monorepo with multiple servers
{
"mcpServers": {
"api-schemas": {
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-filesystem",
"./packages/api/openapi"
]
},
"postgres-readonly": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-postgres"],
"env": {
"DATABASE_URL": "${env:DEV_DATABASE_URL}"
}
}
}
}Open the monorepo root in Cursor — nested packages do not inherit a parent .cursor/mcp.json from a subfolder workspace. Open the repo root as the workspace.
Step 5 — Environment variables and `envFile`
Cursor resolves placeholders in command, args, env, url, and headers (Cursor MCP docs). Common patterns:
{
"mcpServers": {
"github": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "${env:GITHUB_TOKEN}"
}
}
}
}Load extra variables from a file:
{
"mcpServers": {
"stripe-dev": {
"command": "node",
"args": ["./tools/stripe-mcp/index.js"],
"envFile": "${workspaceFolder}/.env.local"
}
}
}Keep .env.local in .gitignore. For CI/CD documentation, commit .env.example with empty keys so teammates know which variables to set.
macOS tip: Export tokens in ~/.zshrc *and* verify Cursor inherits them — when ${env:VAR} fails, set the value in Cursor's integrated terminal environment or use envFile instead.
Step 6 — Install from Cursor Marketplace vs manual JSON
Cursor's Customize → MCP page lists official plugins (database connectors, deployment tools, search). One-click install is fastest for evaluation.
Use manual mcp.json when you need:
Exact package versions pinned in args
Custom env / envFile wiring for your org
Project-scoped servers checked into git
Remote url servers behind your VPN
Community listings also appear on cursor.directory — treat third-party servers like any npm dependency: read the source, check permissions, and pin versions.
Security deep dive: what can go wrong
Understanding failure modes helps you configure MCP defensively.
Over-broad filesystem access
An agent asked to "clean up temp files" with filesystem root set to $HOME can delete or read SSH keys, browser profiles, and cloud CLI credentials. Fix: one sandbox directory per project; add a README in that folder describing allowed operations.
SQL write access
Postgres MCP servers execute SQL the model generates. A typo or malicious prompt can DROP TABLE. Fix: connect with a read-only role; use a staging database; require human approval for DDL in runbooks.
Leaked tokens in chat logs
If you paste mcp.json with inline secrets into Chat for debugging, the secret is now in model context. Fix: rotate the token; use ${env:} only; redact before sharing screenshots.
Supply-chain updates
npx -y package@latest pulls the newest release on every cold start. A compromised publish could exfiltrate env vars. Fix: pin semver in args; vendor the server in your repo for high-security environments.
Shared laptops
Global ~/.cursor/mcp.json on a shared machine exposes personal GitHub tokens to anyone who opens Cursor. Fix: per-user OS accounts, or project-only config without global secrets.
Verify the connection (30-second checklist)
1. Settings → MCP — server name shows connected (not red/disabled) 2. Output panel — select MCP log stream; confirm Server started without stack traces 3. Agent prompt — ask for an action only the MCP server can perform 4. Tool approval UI — inspect JSON args before accepting on sensitive servers 5. Revoke test — disable the server toggle and confirm the tool is no longer offered
Repeat after every Cursor upgrade — MCP transport defaults evolve with the spec (July 2026 MCP roadmap).
When to skip MCP in Cursor
MCP is not always the right tool:
Situation | Better approach |
|---|---|
One-off REST call | curl or a small script in the repo |
Static docs already in repo | @docs references or Cursor rules |
Production deploys | CI pipeline, not Agent tool calls |
Highly regulated data | No MCP path to prod; use approved internal portals |
Use MCP when the agent needs repeatable, structured access to systems that change — issues, schemas, logs — not when a single file read suffices.
Troubleshooting
Server shows disconnected after reload
Cause: Invalid JSON, wrong key name (mcpServers is required), or command not found.
Fix: Validate JSON. Run the exact command + args in a terminal. On macOS, replace npx with /usr/local/bin/npx or the output of which npx.
Tools work in terminal but not Cursor
Cause: Cursor does not load shell aliases from .zshrc.
Fix: Use absolute paths in command. Set secrets via env or envFile, not shell-only exports.
Agent ignores MCP tools
Cause: Server disconnected, or prompt does not require external data.
Fix: Confirm green status in Settings → MCP. Rephrase to explicitly reference the server name and action.
Duplicate server names
Cause: Same key in global and project config.
Fix: Rename one entry. Remember project config overrides global for matching keys.
Permission denied on filesystem server
Cause: Path outside allowed root or macOS privacy restrictions.
Fix: Narrow to a subfolder inside the project. Grant Full Disk Access only if absolutely required — prefer a sandbox path.
FAQ
Does Cursor support MCP out of the box?
What is the difference between `.cursor/mcp.json` and `~/.cursor/mcp.json`?
Is stdio or HTTP better for MCP in Cursor?
Can I use the same mcp.json as Claude Desktop?
How do I keep API keys safe when using MCP in Cursor?
Should juniors enable every marketplace MCP server?
Related posts
What Is MCP? A Developer's Guide to Model Context Protocol — protocol basics before Cursor-specific setup
Google NotebookLM Complete Guide for Developers — pair grounded research notebooks with MCP-powered IDE workflows
