Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,8 @@ A minimal command-line interface that lets you spawn Cursor agents from your ter

Decompose a task into a JSON DAG, fan it out across local subagents, and stream live status into a Cursor Canvas that hot-reloads on every state change. Ships as both a runnable example and a copyable Cursor skill at [`.cursor/skills/dag-task-runner`](.cursor/skills/dag-task-runner).

### [Sverklo (code intelligence over MCP)](sdk/sverklo-mcp)

Wire [sverklo](https://github.com/sverklo/sverklo) — a local-first MCP code-intelligence server (MIT) — into your Cursor SDK agent. The agent gets 37 extra tools alongside Cursor's built-ins: hybrid semantic search ranked by PageRank, recursive blast-radius analysis, symbol graph, bi-temporal memory pinned to git SHAs, and a code-quality audit. Demonstrates the canonical pattern for adding any third-party MCP server to a programmatic Cursor agent.

Learn more in the [Cursor SDK TypeScript docs](https://cursor.com/docs/api/sdk/typescript).
2 changes: 2 additions & 0 deletions sdk/sverklo-mcp/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
node_modules
dist
108 changes: 108 additions & 0 deletions sdk/sverklo-mcp/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
# Cursor SDK + sverklo (code intelligence over MCP)

A Cursor SDK agent with **sverklo** wired in as an MCP server. The agent gets 37 extra tools — semantic search ranked by PageRank, blast-radius analysis, symbol graph, bi-temporal memory pinned to git SHAs, and a code-quality audit — alongside Cursor's built-in `semSearch`, `glob`, `grep`, etc.

[Sverklo](https://github.com/sverklo/sverklo) is a local-first MCP code-intelligence server. MIT-licensed, runs on your laptop, no cloud, no API keys.

## Why this example

The Cursor SDK doesn't expose a custom-tool registration API or a context-provider plug point — extension goes through MCP. This example shows the canonical pattern: declare an MCP server inline in `Agent.create()` and the agent picks the new tools when they fit the task.

The same wiring works for any MCP server (filesystem, github, postgres, etc.). Sverklo is a useful one to start with because it's the difference between an agent that grep-searches your repo and one that understands its symbol graph.

## Getting Started

Use Node.js 22 or newer.

Install sverklo globally (one-time):

```bash
npm install -g sverklo
```

This pulls a small ONNX embedding model (~90 MB) on first run.

Install dependencies:

```bash
pnpm install
```

Set a Cursor API key:

```bash
export CURSOR_API_KEY="crsr_..."
```

Run the example against the cookbook itself:

```bash
pnpm dev
```

Or point it at a specific repository (and override the prompt if you want):

```bash
pnpm dev /path/to/your/project
pnpm dev /path/to/your/project "Find every caller of UserService.validate. Use sverklo_impact for the blast radius."
```

Build and run the compiled example:

```bash
pnpm build
pnpm start
```

## What you'll see

The default prompt asks the agent to build a mental model of the project using `sverklo_overview` (PageRank-ranked) and then run `sverklo_audit`. Output is streamed as the agent decides which tools to call. Every tool call is logged so you can see when the agent reaches for sverklo vs. Cursor's built-ins.

Example trimmed output:

```
[tool] sverklo_overview
[tool] sverklo_audit

This codebase is 12 TypeScript packages organized as a pnpm workspace.
The structurally most important files (PageRank) are:
• sdk/quickstart/src/index.ts
• sdk/coding-agent-cli/src/agent.ts
...
sverklo_audit found 2 medium-severity findings:
• Possible god class: sdk/coding-agent-cli/src/repl.ts (12 methods)
• Hub file: sdk/dag-task-runner/src/runner.ts (8 importers)
```

The agent doesn't call sverklo for every question — it picks the right tool. Ask it "what does this project do?" and it may use Cursor's built-in `semSearch`. Ask it "what breaks if I rename X?" and it'll reach for `sverklo_impact` because the symbol graph is the right substrate.

## File-based variant (`.cursor/mcp.json`)

If your project already has a `.cursor/mcp.json` (because you also use the Cursor IDE on the same project), the SDK can read it directly. Replace the inline `mcpServers` block with `local.settingSources`:

```ts
const agent = await Agent.create({
apiKey: process.env.CURSOR_API_KEY,
name: "Cursor SDK + sverklo",
model: { id: "composer-2" },
local: {
cwd: projectPath,
settingSources: ["project"], // load .cursor/mcp.json from the project
},
})
```

The IDE and the SDK agent then share one MCP config — no drift.

## Notes

- Sverklo's MCP server is local-first; the cloud agent path doesn't apply unless you run sverklo on a host the cloud agent can reach. For cloud-mode agents that need code intelligence, run the SDK locally and use the `local` runtime.
- `npx -y sverklo <path>` is the stdio-mode entrypoint. For long-lived sessions, install sverklo globally (`npm i -g sverklo`) and use `command: "sverklo"` directly to skip the `npx` resolve step on every spawn.
- The Cursor SDK's tool-call event payload schemas are not yet stable; treat tool calls as opaque and don't parse `args` / `result` internals.

## See also

- [Sverklo on GitHub](https://github.com/sverklo/sverklo) — the MCP server (MIT)
- [Sverklo + Cursor SDK recipe (long-form)](https://sverklo.com/recipes/cursor-sdk/)
- [Sverklo's 60-task retrieval benchmark](https://sverklo.com/bench)
- [Cursor SDK TypeScript docs](https://cursor.com/docs/sdk/typescript)
24 changes: 24 additions & 0 deletions sdk/sverklo-mcp/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"name": "sdk-sverklo-mcp",
"version": "0.1.0",
"private": true,
"type": "module",
"packageManager": "pnpm@10.9.0",
"engines": {
"node": ">=22"
},
"scripts": {
"dev": "tsx src/index.ts",
"build": "tsc -p tsconfig.json",
"start": "node dist/index.js",
"typecheck": "tsc -p tsconfig.json --noEmit"
},
"devDependencies": {
"@types/node": "^25.6.0",
"tsx": "^4.21.0",
"typescript": "^6.0.3"
},
"dependencies": {
"@cursor/sdk": "^1.0.7"
}
}
6 changes: 6 additions & 0 deletions sdk/sverklo-mcp/pnpm-workspace.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
packages:
- "."

onlyBuiltDependencies:
- esbuild
- sqlite3
65 changes: 65 additions & 0 deletions sdk/sverklo-mcp/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { Agent } from "@cursor/sdk"

// Wire sverklo as an MCP server for the Cursor SDK agent.
//
// Sverklo (https://github.com/sverklo/sverklo, MIT) is a local-first
// MCP code-intelligence server. It gives the agent 37 extra tools
// alongside Cursor's built-in semSearch / glob / grep:
// sverklo_search — hybrid (BM25 + ONNX embedding + PageRank) search
// sverklo_impact — recursive blast-radius (transitive callers)
// sverklo_refs — exact references to a symbol
// sverklo_overview — PageRank-ranked codebase map
// sverklo_audit — god classes, dead code, security patterns
// sverklo_remember / sverklo_recall — bi-temporal memory pinned to git SHAs
// sverklo_review_diff — risk-scored diff review
// …and 30 more.
//
// One-time setup before running this example:
// npm install -g sverklo
// (Pulls the indexer + a small ONNX embedding model. ~30s, ~90MB.)

const projectPath = process.argv[2] ?? process.cwd()

const agent = await Agent.create({
apiKey: process.env.CURSOR_API_KEY,
name: "Cursor SDK + sverklo (code intelligence over MCP)",
model: { id: process.env.CURSOR_MODEL ?? "composer-2" },
local: { cwd: projectPath },
mcpServers: {
sverklo: {
type: "stdio",
command: "npx",
args: ["-y", "sverklo", projectPath],
cwd: projectPath,
},
Comment thread
cursor[bot] marked this conversation as resolved.
},
})

const prompt =
process.argv[3] ??
"Use sverklo_overview to give me a 5-minute mental model of this codebase " +
"(PageRank-ranked, not file-size-ranked). Then run sverklo_audit and " +
"highlight any high-risk findings I should look at first. Be concrete — " +
"name files and symbols, not generalities."

const run = await agent.send(prompt)

for await (const event of run.stream()) {
if (event.type === "tool_call") {
const { tool } = event as { tool?: string }
Comment thread
cursor[bot] marked this conversation as resolved.
Outdated
if (typeof tool === "string") {
process.stdout.write(`\n[tool] ${tool}\n`)
}
continue
}
if (event.type !== "assistant") continue

for (const block of event.message.content) {
if (block.type === "text") {
process.stdout.write(block.text)
}
}
}

await run.wait()
process.stdout.write("\n")
17 changes: 17 additions & 0 deletions sdk/sverklo-mcp/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"compilerOptions": {
"target": "ES2022",
"lib": ["ESNext"],
"types": ["node"],
"module": "NodeNext",
"moduleResolution": "NodeNext",
"rootDir": "src",
"outDir": "dist",
"strict": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"skipLibCheck": true
},
"include": ["src/**/*.ts"],
"exclude": ["dist", "node_modules"]
}