Guide intermediate

Cursor SDK Custom Tools vs. MCP Servers: Which Setup Is Right After v3.7 (June 2026)

Published June 6, 2026 · by Pondero Editorial

The short version

Cursor SDK v3.7 added custom tools so you can extend your agent without a separate MCP server. Here is when a custom tool wins, when you still need a server, and when to reach for Make or n8n.

Table of Contents

Cursor SDK Custom Tools vs. MCP Servers: Which Setup Is Right After v3.7 (June 2026)

You just read the Cursor changelog, you want to give your agent one new capability, and you are staring at the same question every Cursor SDK user is asking this week: do you still need an MCP server for this? Short answer: if you were about to stand up a tiny local MCP server just to wrap one function the agent calls during a run, custom tools (shipped in SDK v3.7 on June 4-5, 2026, per Cursor's June 2026 changelog) make that server unnecessary. You pass the function definition straight into Agent.create() and the SDK exposes it to the agent for you. What custom tools do not replace is a shared MCP server your whole team points multiple editors and clients at. Different job, different tool.

Here is the full decision: what custom tools actually are, where custom stores and auto-review fit, and the line where you should stop wiring code and reach for an automation platform like Make or n8n instead.

What custom tools actually are

A custom tool is a function definition you hand to the agent inline. In the TypeScript SDK you pass it through the local.customTools option on Agent.create() (or per send() call). The SDK takes those definitions and registers them behind a built-in MCP server it calls custom-user-tools, per the Cursor SDK docs. The agent sees a normal tool. You never run a server process, write a manifest, or manage a port.

That detail matters more than it sounds. Before v3.7, the smallest unit of "give my agent a new ability" was a standing MCP server, even if the ability was a single five-line function. Custom tools collapse that to a parameter. The tool is scoped to the session, and any nested subagents the run spawns inherit it automatically, so you do not re-register it at every level.

First, install the SDK. The package name follows the Cursor SDK docs:

npm i @cursor/agent-sdk
# or: pnpm add @cursor/agent-sdk
# Python: pip install cursor-agent-sdk

Here is a minimal custom tool passed into a new agent:

import { Agent } from "@cursor/agent-sdk";

const agent = await Agent.create({
  model: "auto",
  local: {
    customTools: [
      {
        name: "parse_invoice_total",
        description: "Extract the grand total from a raw invoice string.",
        inputSchema: {
          type: "object",
          properties: { raw: { type: "string" } },
          required: ["raw"],
        },
        handler: async ({ raw }) => {
          const match = raw.match(/total[:\s]+\$?([\d,.]+)/i);
          return { total: match ? match[1] : null };
        },
      },
    ],
  },
});

The agent can now call parse_invoice_total mid-run with no extra infrastructure. The handler runs in your process, so it has your environment, your secrets, and your imports. That is the whole appeal: a one-off capability that lives and dies with the session.

What custom stores give you

The second v3.7 addition is pluggable persistence. Every SDK run keeps a record of the session (messages, tool calls, state), and v3.7 lets you choose where that record lives. Both the TypeScript and Python SDKs ship two built-in stores: JsonlLocalAgentStore and SqliteLocalAgentStore, per the Cursor SDK docs.

JSONL is the default. It writes an append-only log, one JSON object per line, which diffs cleanly and drops into version control without a binary blob. Good when you want the session history sitting next to the code in a repo. SQLite is the move when you want to query that history. Filtering past runs by tool, time, or outcome is a SQL statement instead of a grep. For anything beyond local files, you implement the public LocalAgentStore interface yourself: a Postgres-backed store for a team, or an in-memory store for CI runs you want to vanish the moment the job ends.

Switching to SQLite is one line:

import { Agent, SqliteLocalAgentStore } from "@cursor/agent-sdk";

const agent = await Agent.create({
  model: "auto",
  local: {
    store: new SqliteLocalAgentStore({ path: "./.cursor/agent-history.db" }),
  },
});

Pick JSONL when the history should travel with the repo. Pick SQLite when you will actually query it. Roll your own when neither local option fits, which in practice means a shared backend or an ephemeral CI run.

How auto-review works

Auto-review is the v3.7 feature aimed squarely at running agents without a human watching every keystroke. It first showed up in v3.6 in late May 2026, which added auto-review for shell, MCP, and fetch tool calls; v3.7 extends and refines it, per Cursor's changelog. The idea: route every tool call through a classifier that decides which calls run on their own and which get held back for a person to approve.

You steer the classifier with a permissions.json file. Two fields carry the weight. autoRun.allow_instructions describes the calls safe to execute immediately. autoRun.block_instructions describes the calls that must stop and wait for a human. These are instructions, not a hardcoded allowlist of exact commands, so the classifier generalizes across calls you did not enumerate.

{
  "autoRun": {
    "allow_instructions": [
      "Read files inside the repo.",
      "Run the test suite and linters.",
      "Call the parse_invoice_total custom tool."
    ],
    "block_instructions": [
      "Any shell command that deletes files or directories.",
      "Any network request to a host outside the allowlist.",
      "Any write to a production database or secrets file."
    ]
  }
}

This is what makes a headless run practical instead of reckless. In a CI job the agent reads, tests, and calls your safe tools on its own, and the moment it reaches for something destructive it stops and surfaces the call for review rather than charging ahead or being blocked from all tool use. The line you draw in those two fields is the line between an agent that ships and an agent you cannot trust unattended.

Custom tool vs. MCP server vs. automation platform

Here is the decision laid out across the five criteria that actually drive the choice. Read it top to bottom for your situation, not left to right.

CriterionCustom tool (SDK)MCP serverAutomation platform (Make / n8n)
Session scopeLives and dies with the agent runPersistent process, outlives any runPersistent service, runs on its own schedule
Multi-client accessSingle session only; not sharedAny MCP-compatible client (other editors, CI, teammates)Any service with an HTTP trigger or connector
Deployment costZero; it is a function parameterYou host and maintain a processHosted by the platform (n8n self-host optional)
Setup timeMinutes; inline definitionHours; manifest, transport, hostingMinutes per scenario in a visual builder
Use in CINative; ephemeral with an in-memory storeWorks, but you run the server in the pipelineTriggered by webhook from the pipeline
Custom tool vs MCP server vs automation platform across session scope, multi-client access, deployment cost, setup time, and CI use.

The pattern is clear once it is on one page. A custom tool wins when the capability is single-session and the cost of a separate process buys you nothing. An MCP server earns its keep the instant a second client needs the same tool, because that is the one thing a custom tool cannot do: it is invisible outside the run that defined it. We hit this line in our own setup the first week of June 2026. We had a small repo-stats function wrapped in a local single-tool MCP server purely so Cursor could call it. Moving it to local.customTools deleted the server, the manifest, and the process management, and the agent behaved identically. The function that we kept as an MCP server was the one our Claude Code sessions also call, because a custom tool would have stranded it inside one SDK run.

When you still need an automation platform

Custom tools and MCP servers both run inside, or are called by, an agent. Neither one schedules anything, and neither one outlives the work it was created for. The day you need a workflow that runs on a clock, branches on conditions, fans out across five services, and keeps an audit trail, you have left the SDK's lane.

That is the Make and n8n layer. Make is the stronger pick when the workflow is scheduled or branching: trigger at 6 a.m., pull yesterday's rows, route each one down a different path based on its status, retry the failures, log every step. Its scenario builder is built for exactly that fan-out, and it carries the highest recurring payout in our roster, which we disclose plainly. n8n is the secondary alternative and the better fit when you want to self-host the orchestration or keep the data on your own infrastructure; its node-based editor covers the same scheduled, multi-step shape.

The clean division of labor: the automation platform owns the schedule, the branching, and the cross-service plumbing. The Cursor SDK owns the reasoning step inside that flow. A Make scenario calls your agent for the one part that needs judgment, and the agent calls a custom tool for the one function that needs your code. You do not pick one. You stack them.

Nested subagents and Design Mode voice

Two smaller v3.7 additions round out the release. Nested subagents let a subagent spawn its own subagents, recursively, each with an independent prompt and model, per Cursor's June 2026 changelog. A reviewer subagent can delegate to a test-writer subagent, which can delegate further down. Because custom tools propagate to nested subagents automatically, a tool you defined at the top is callable all the way down the tree without re-registration. That is what makes the inline-tool model scale past a single flat agent.

Design Mode in the Cursor browser also picked up two changes. Multi-select now lets you click two or more elements at once to see their code and visual relationships together, instead of inspecting one at a time. And voice input lets you narrate changes through the Design Mode overlay while agents are running, so you can describe a UI tweak out loud without breaking out of the canvas. Both are quality-of-life for front-end work rather than architecture, but they reduce the click count on the design side of an agent run.

The verdict, by who you are

If you are writing a one-off function so the agent can parse an API response, transform a file, or do a quick calculation during a run, write a custom tool. It is a parameter on Agent.create(), it inherits down to nested subagents, and it leaves nothing to host. Standing up an MCP server for that is overhead you no longer need to pay.

If you are building a capability that more than one client uses, a tool your teammates call from their own editors, or one both your Cursor SDK runs and your other agents share, set up an MCP server. The whole point of MCP is that the tool outlives any single session and answers to any compatible client. A custom tool structurally cannot do that.

If the thing you are building runs on a schedule, branches on conditions, or wires five services together with an audit trail, that belongs in Make (best for scheduled, branching workflows) or n8n (best if you want to self-host), with the SDK handling only the reasoning step inside the flow.

For developers committed to the SDK across all three patterns, Cursor is the editor that ships these primitives first, and the SDK features land on the paid plans. If you are sorting out which plan unlocks SDK access for a team, our Cursor vs Copilot Teams pricing guide breaks down the current tiers. Start with a custom tool, graduate to an MCP server the moment a second client needs in, and reach for an automation platform when the work needs a clock.