OpenAI- and Anthropic-compatible wrapper around Cursor SDK.
Inspired by Cursor's cookbook: https://github.com/cursor/cookbook.
docker compose up --buildBy default the Cursor agent creates files under ./workspace/ (a subdirectory
of this project). To have files appear in your project directory instead,
set CURSOR_WORKSPACE to that path before starting:
CURSOR_WORKSPACE=/path/to/your/project docker compose up --buildFor server deployment, upload this project or cursor-openai-proxy-deploy.tar.gz,
then run:
tar -xzf cursor-openai-proxy-deploy.tar.gz
cd cursor-openai-proxy-deploy
CURSOR_WORKSPACE=/srv/cursor-workspace docker compose up -d --buildRuntime state is stored in the cursor-state Docker volume under /data.
API keys are not stored by the service; pass the Cursor key on each request.
npm startCopy .env.example to .env and set CURSOR_WORKDIR to the directory where
generated files should appear:
cp .env.example .env
# edit .env: set CURSOR_WORKDIR=/path/to/your/project
npm startCall it with any OpenAI-compatible client:
curl http://localhost:3000/v1/chat/completions \
-H "content-type: application/json" \
-H "authorization: Bearer crsr_xxx" \
-d '{"model":"composer-2","messages":[{"role":"user","content":"hello"}]}'The service stores no API key. Use your Cursor API key as the OpenAI API key:
send it on each /v1/* request as Authorization: Bearer <cursor-api-key>.
GET /v1/models reads the models available to that request key. Pick one of
those id values and pass it as the request model.
Or call it with an Anthropic-compatible client:
curl http://localhost:3000/v1/messages \
-H "content-type: application/json" \
-H "x-api-key: crsr_xxx" \
-H "anthropic-version: 2023-06-01" \
-d '{"model":"composer-2","max_tokens":1024,"messages":[{"role":"user","content":"hello"}]}'Anthropic requests may use x-api-key: <cursor-api-key> or the same bearer
token header.
Step 1: get a Cursor API key from https://cursor.com/dashboard/api?section=user-keys#user-api-keys.
Then install from npm, configure the MCP client to run the stdio server, and pass your Cursor key in the client-side environment:
npm install -g cursor2api-mcpOne-command installer for macOS/Linux:
curl -fsSL https://raw.githubusercontent.com/KnifelfPro/Cursor2API/main/scripts/install-mcp.sh | shWindows cmd installer:
curl -L -o install-mcp.cmd https://raw.githubusercontent.com/KnifelfPro/Cursor2API/main/scripts/install-mcp.cmd && install-mcp.cmdThe installers ask for your Cursor API key, scan common Codex, Clash, OpenCode,
Cursor, and Gemini config locations, then let you install to one target or many
with input like 1, 1,3,5, cursor gemini, or all.
{
"mcpServers": {
"cursor-agent": {
"command": "cursor2api-mcp",
"env": {
"CURSOR_API_KEY": "crsr_xxx"
}
}
}
}To remove cursor2api from your MCP clients and uninstall the global package,
use the one-command uninstaller.
macOS/Linux:
curl -fsSL https://raw.githubusercontent.com/KnifelfPro/Cursor2API/main/scripts/uninstall-mcp.sh | shWindows cmd:
curl -L -o uninstall-mcp.cmd https://raw.githubusercontent.com/KnifelfPro/Cursor2API/main/scripts/uninstall-mcp.cmd && uninstall-mcp.cmdThe uninstaller scans the same Codex, Clash, OpenCode, Cursor, and Gemini config
locations, removes the cursor2api entry from the targets you select (writing a
.bak first), then runs npm uninstall -g cursor2api-mcp.
For development, you can also point the client directly at the checkout:
git clone https://github.com/KnifelfPro/Cursor2API.git
cd Cursor2API
npm install{
"mcpServers": {
"cursor-agent": {
"command": "node",
"args": ["/path/to/Cursor2Api/src/mcp.js"],
"env": {
"CURSOR_API_KEY": "crsr_xxx"
}
}
}
}The MCP server exposes one tool, cursor_agent. On each tool call it asks the
client for MCP roots and uses the first file:// root as the Cursor workspace.
If the client does not support roots, it falls back to the MCP server process
current working directory.
Tool input:
{
"prompt": "Fix the failing tests in the current project",
"model": "composer-2"
}prompt is required. model is optional and selects the default routing model.
For every task, the MCP server fetches the Cursor model list, sends that list,
the MCP tool list, the workspace, and the task to the default model, then lets
that model choose self, delegate, or up to three parallel model agents.
Superpowers and Ponytail are included as local prompt guidance; no server-side
runtime is required.
When the proxy runs on a remote server, files created by the Cursor agent stay on that server. Use the workspace endpoints to list and download them:
# List all files in the workspace
curl -H "Authorization: Bearer crsr_xxx" http://server:3000/workspace
# Download a single file
curl -H "Authorization: Bearer crsr_xxx" http://server:3000/workspace/path/to/file.py \
-o file.pySync everything to the current local directory:
KEY=crsr_xxx SERVER=http://server:3000
for f in $(curl -s -H "Authorization: Bearer $KEY" $SERVER/workspace | jq -r '.files[]'); do
mkdir -p "$(dirname "$f")"
curl -s -H "Authorization: Bearer $KEY" "$SERVER/workspace/$f" -o "$f"
doneSupported endpoints:
GET /healthGET /workspace— list files in the agent workspace (requires auth)GET /workspace/{path}— download a file from the workspace (requires auth)GET /v1/modelsGET /v1/models/:modelPOST /v1/chat/completionsPOST /v1/responsesPOST /v1/completionsPOST /v1/embeddings
Streaming works with "stream": true for the three text endpoints.
MCP:
- stdio server:
npm run mcp - local npm bin:
cursor2api-mcp - tool:
cursor_agent
Anthropic-compatible endpoints:
GET /v1/modelsGET /v1/models/:modelPOST /v1/messagesPOST /v1/messages/count_tokens
Streaming works with "stream": true on /v1/messages.
Hermes compatibility:
- Text responses include estimated
usage. tools,functions, and JSONresponse_formatare accepted and added to the Cursor prompt as instructions.POST /v1/embeddingsreturns stable local hash embeddings. This is enough for clients that require an embedding endpoint to initialize, but it is not a real semantic embedding model.
Anthropic compatibility:
- Messages responses use Anthropic
messageand SSE event shapes. system, text messages,tools,tool_use, andtool_resultinputs are folded into the Cursor prompt.- Cursor SDK returns text, so this proxy does not execute tools or provide real image/file understanding.
All other /v1/* OpenAI endpoints return an OpenAI-shaped not_supported
error with HTTP 501. Cursor SDK can run agent text tasks, but it cannot provide
real OpenAI equivalents for images, audio, files, batches, fine-tuning, vector
stores, realtime, or administration APIs.
This project is fully open under the MIT License. See LICENSE.