Skip to main content
Glama
README.md
# cursor-mcp-server

An MCP server that delegates all code writing to Cursor's Composer 2 (or Grok 4.5) agents. Built so that a PM/orchestrator model - Claude, in the setup this was built for - never writes code directly. It reads context, breaks work into scoped tasks, and calls out to Cursor's agent SDK to actually generate or edit files.

## Why

Claude's context window is the scarce resource in an orchestrator workflow. Every line of code Claude writes directly is a line it has to hold, re-read, and pay for in its own token budget - and that budget scales with the size of the feature, not with the complexity of the task description. Delegating code generation to Cursor decouples the orchestrator's cost from output size: a `cursor_write_code` call costs roughly the same whether Cursor ends up producing 20 lines or 400.

Cursor's per-token pricing is also substantially cheaper than a frontier reasoning model's, so shifting bulk code generation there is a compounding win, not just a context-window trick.

## Architecture

A single MCP server (`@modelcontextprotocol/sdk`) exposing two tools, both backed by `@cursor/sdk`'s `Agent.prompt()`:

- **`cursor_write_code`** - delegate creation of new files/features
- **`cursor_edit_code`** - delegate edits to an existing file

Both tools accept:

| Field | Required | Purpose |
|---|---|---|
| `task` | yes | Clear description of what to build/change |
| `workingDirectory` | no | Absolute path to the project root (defaults to the server's cwd) |
| `files` | write only | Existing files Composer should read for context |
| `targetFile` | edit only | Path to the file being edited |
| `context` | no | Architectural decisions, interfaces, or constraints to respect |
| `model` | no | `"composer"` (default) or `"grok"` |
| `effort` | no | `"low"` \| `"medium"` \| `"high"` - only applies when `model: "grok"` |

The server builds a single prompt from these fields and runs it against Cursor's agent (`local` mode executes on your machine in `workingDirectory`; `cloud` mode runs on Cursor's sandboxed VMs).

## Setup

```bash
npm install
cp .env.example .env
# edit .env: set CURSOR_API_KEY (Cursor dashboard -> Integrations -> API Keys)
npm run build
```

### Environment variables

| Variable | Values | Default |
|---|---|---|
| `CURSOR_API_KEY` | your Cursor API key | required |
| `CURSOR_EXECUTION_MODE` | `local` \| `cloud` | `local` |

### Register with Claude Code / any MCP client

Add to your MCP client config (e.g. `.mcp.json` or `claude mcp add`):

```json
{
  "mcpServers": {
    "cursor-coder": {
      "command": "node",
      "args": ["/absolute/path/to/cursor-mcp-server/dist/index.js"],
      "env": { "CURSOR_API_KEY": "your_cursor_api_key_here" }
    }
  }
}
```

## Model selection

- **`composer`** (default) - Composer 2. Fast and reliable for well-specified, mechanical tasks: CRUD, scaffolding, small edits, following an already-clear pattern.
- **`grok`** - Grok 4.5. More capable, more expensive. Reserve for complex reasoning, tricky refactors, architecture-sensitive changes, or when a Composer run came back wrong/confused. Use `effort: "high"` for the hardest cases.

## Orchestrator contract

This server is meant to be paired with a system prompt / `CLAUDE.md` that hard-gates code generation through it:

```
You are the architect and project manager. Cursor Composer 2 is your
code-writing sub-agent.

- NEVER write code yourself. No code blocks, no file edits.
- For ALL code generation -> call cursor_write_code.
- For ALL code edits -> call cursor_edit_code.
- You MAY read files to understand context before delegating.
- You MAY review Composer's output and ask it to revise via another
  tool call.
```

The orchestrator's job stays: breaking tasks into scoped sub-tasks, defining interfaces/contracts before Composer writes them, reviewing output for correctness, and deciding what to build next. The actual code generation runs entirely inside Cursor's agent loop.

**Always independently re-verify what comes back.** Don't trust a completion message at face value - open the file, run the tests, check the diff. A sub-agent's self-reported "done" is not evidence.

## Scripts

| Command | Purpose |
|---|---|
| `npm run dev` | Run with `tsx watch` for local iteration |
| `npm run build` | Compile TypeScript to `dist/` |
| `npm start` | Run the compiled server |

## License

MIT - see [LICENSE](./LICENSE).