Connect AI clients
How to set up MCP servers in Cursor
Cursor reads its MCP servers from a JSON file, either in your home directory or in the project. This covers both files, local and remote servers, keeping keys out of the config, and where to look when a server does not show up.
By the end of this you will have Cursor's agent using two MCP servers: a local one that Cursor starts as a process on your machine, and a remote one it reaches at a URL. You will know which config file to put each in, how to give a server an API key without writing the key into the file, and where to look when a server does not load.
Cursor has no command for adding servers. Everything is a JSON file called mcp.json, so most of this tutorial is about what goes in it.
Prerequisites
- Cursor, recent enough to have the Customize sidebar, which is where MCP servers are switched on and off.
- Node.js 20 or later, for the local server example, which runs through
npx. - A project open in Cursor, if you want project-level servers.
Step 1: Pick global or project config
Cursor looks for mcp.json in two places:
| File | Applies to | Good for |
|---|---|---|
~/.cursor/mcp.json | Every project you open | Servers you want everywhere, with keys that are yours |
.cursor/mcp.json in the project | That project only | Servers the whole team should get from the repository |
Both files have the same shape: one top-level mcpServers object, with one entry per server, keyed by the name you want Cursor to show. Create the file if it does not exist:
{
"mcpServers": {}
}If you put a project file under version control, treat it like any other committed file: no keys in it. Step 4 shows how.
Step 2: Add a local server
A local server, also called stdio, is a program Cursor starts and talks to over standard input and output. The entry names the command and its arguments:
{
"mcpServers": {
"everything": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-everything"]
}
}
}server-everything is the reference server from the MCP project. Its tools exist for testing, so it is a good way to check the setup before you add a server that touches real data.
command is the program, and args is a list with one item per argument. If the server needs environment variables, add an env object next to args.
Step 3: Add a remote server
A remote server runs somewhere else and you reach it at a URL. The entry needs only the url:
{
"mcpServers": {
"everything": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-everything"]
},
"deepwiki": {
"url": "https://mcp.deepwiki.com/mcp"
}
}
}DeepWiki answers questions about public GitHub repositories and needs no key, so it is an easy first remote server. Cursor supports the Streamable HTTP transport that current remote servers use, and the older SSE transport for servers that have not moved yet.
Step 4: Keep keys out of the file
Most servers need a credential, and the easy way to give it one is to paste the key into env or a header. Do not. Cursor can read values from your environment instead.
For a remote server that takes an API key, reference an environment variable in headers:
{
"mcpServers": {
"my-api": {
"url": "https://example.com/mcp",
"headers": {
"Authorization": "Bearer ${env:MY_API_KEY}"
}
}
}
}For a local server, do the same in env:
{
"mcpServers": {
"my-tool": {
"type": "stdio",
"command": "node",
"args": ["tool.js"],
"env": {
"TOKEN": "${env:MY_TOKEN}"
}
}
}
}Cursor fills these in when it starts the server. The syntax is ${env:NAME}, and it works in command, args, env, url and headers. A few other variables are available, such as ${workspaceFolder} for the project root and ${userHome} for your home directory, which help when a path differs between machines.
Local servers can also load a whole file of variables with envFile, for example "envFile": "${workspaceFolder}/.env". That option is only for stdio servers. Keep the .env file out of version control.
For a remote server that supports OAuth, you may not need a key at all. Cursor runs the login flow and stores the token. If the provider wants a pre-registered client, add an auth object with its CLIENT_ID (and CLIENT_SECRET if it is a confidential client).
Step 5: Turn the servers on and check them
Open Customize in the sidebar. Your servers are listed there, and each one can be switched on or off without editing the file. If a server you just added is missing, quit and reopen Cursor. Clients read their MCP config at startup, so an open window may not have seen the change.
Then ask the agent something that needs one of the tools. Cursor uses MCP tools when they are relevant, and by default it asks for your approval before each call. You can let allowlisted tools run without asking, through the same run modes that govern terminal commands. I would leave the prompt on until you know what each tool does.
When a server fails to start, open the Output panel and pick MCP Logs from the dropdown. It shows the server starting up, each tool call, and the error if something broke, which is usually a wrong path in command or a variable that was not set.
Step 6: Put the servers behind Statio
The config above has the usual MCP shortcomings. Each server gets one credential, the key sits on every laptop that uses it, Cursor sees every tool the server offers, and nothing records which calls were made.
With Statio, you install servers once in the dashboard, from the catalog or your own, add the upstream key there, and grant tools one at a time to people and agents. Cursor then points at the Statio desktop app's local proxy instead of at each server. The desktop app writes ~/.cursor/mcp.json for you and keeps it current as your access changes. By hand, the entry is just a URL:
{
"mcpServers": {
"github": {
"url": "http://127.0.0.1:7777/github/mcp"
}
}
}There is no header because the proxy attaches your sign-in to each request, and no key because the GitHub token stays in Statio, encrypted. If the agent calls a tool you were not granted, the gateway refuses it, and the refusal lands in the audit log next to the calls that went through. The client docs cover agents and other clients.
Conclusion
You set up a local server and a remote one in mcp.json, chose between the global and project files, kept keys out of the config with ${env:NAME}, and learned where to switch servers on and where to read their logs.
Where to go next:
- Add MCP servers to Claude Code covers the same servers from the terminal.
- Build an MCP server in Python or in TypeScript if the server you want does not exist.
- Turn an OpenAPI spec into an MCP server if you already have an API.
- Give an AI agent read-only GitHub access for a first real server with a safe set of tools.