Cairn / Docs / MCP Server

MCP Server

Cairn ships a bundled stdio MCP server. Connect Claude Desktop, OpenCode, Cursor, or any MCP-compatible client and give it direct read/write access to your workspace. Changes appear in the Cairn UI instantly.

Server vs. client — two opposite directions

This page is about the built-in MCP server — Cairn exposing your workspace to external AI clients. If you instead want Cairn's own AI to reach out to remote MCP servers and HTTP APIs, that's External Tools (Cairn as an MCP client).

What is MCP?

Model Context Protocol (MCP) is an open standard published by Anthropic for exposing structured tools to AI clients. An MCP server runs as a local process alongside your AI client; the client calls tools from the server to read and write data. Cairn's MCP server exposes your entire workspace — notes, tasks, projects — to any compatible client.

Where the server binary lives

The MCP server is a self-contained binary bundled inside the installed Cairn app. No Node.js required, no separate install.

macOS

/Applications/Cairn.app/Contents/Resources/app.asar.unpacked/dist-mcp/cairn-mcp

Windows

C:\Program Files\Cairn\resources\app.asar.unpacked\dist-mcp\cairn-mcp.exe

Linux

./Cairn.AppImage --appimage-extract
squashfs-root/resources/app.asar.unpacked/dist-mcp/cairn-mcp-linux-x64

Cairn ships for Linux as an AppImage, which mounts itself at a temporary path on every launch, so extract it once (--appimage-extract) and point your client at the extracted binary (cairn-mcp-linux-arm64 on ARM). Pass CAIRN_DB_PATH if it can't find your workspace.

Running from source

/path/to/cairn/dist-mcp/cairn-mcp

Configuring Claude Desktop

Add to ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or the equivalent path on your platform:

{
  "mcpServers": {
    "cairn": {
      "command": "/Applications/Cairn.app/Contents/Resources/app.asar.unpacked/dist-mcp/cairn-mcp"
    }
  }
}

On Windows, use the Windows binary path and ensure the .exe extension is included. Forward slashes work in JSON on Windows. Restart Claude Desktop after saving.

Configuring Cursor

Cursor uses the same mcpServers format as Claude Desktop. Add to ~/.cursor/mcp.json:

{
  "mcpServers": {
    "cairn": {
      "command": "/Applications/Cairn.app/Contents/Resources/app.asar.unpacked/dist-mcp/cairn-mcp"
    }
  }
}

Configuring Cline

Cline (VS Code extension) uses the same format. Add via the Cline settings UI or directly in your VS Code settings.json:

{
  "mcpServers": {
    "cairn": {
      "command": "/Applications/Cairn.app/Contents/Resources/app.asar.unpacked/dist-mcp/cairn-mcp"
    }
  }
}

Configuring OpenCode

In your project repo, create .opencode/config.json:

{
  "mcp": {
    "cairn": {
      "type": "local",
      "command": ["/Applications/Cairn.app/Contents/Resources/app.asar.unpacked/dist-mcp/cairn-mcp"],
      "enabled": true
    }
  }
}

Workspace detection and running while the app is closed

cairn-mcp is a standalone process with its own bundled Node runtime and SQLite — it does not need the Cairn app to be running, so agents can read and write your workspace while Cairn is closed. On start it finds the workspace in this order:

  1. The CAIRN_DB_PATH environment variable, if set — either the workspace folder or the cairn.db file itself.
  2. The workspace folder the app last used (read from its workspace-config.json).

If no workspace is found, the server exits with a message telling you to open Cairn once to choose a workspace folder, or to set CAIRN_DB_PATH. The server never creates or migrates the database — the app owns the schema — so open Cairn at least once against a workspace before connecting. If you switch workspace folders in the app, a running cairn-mcp notices and follows the change within about a second; no restart needed.

To point a client at a specific workspace, add an env block to its config:

{
  "mcpServers": {
    "cairn": {
      "command": "/Applications/Cairn.app/Contents/Resources/app.asar.unpacked/dist-mcp/cairn-mcp",
      "env": { "CAIRN_DB_PATH": "/path/to/your/workspace" }
    }
  }
}

How writes appear instantly

The Cairn app polls the SQLite database using WAL (Write-Ahead Logging) change detection. When the MCP server writes a note or task, the change is committed to the database and the app detects it within milliseconds — no restart required, no manual refresh. The UI updates in place.

MCP notifications

When an MCP tool writes to your workspace, Cairn shows a native OS notification (when the app is not focused) within about a second. The menu bar tray icon shows a badge count for unread MCP updates. Clicking it brings Cairn to front and clears the badge.

All write operations trigger a notification — this includes notes, tasks, projects and Idea Flow tools.

Tool reference

The Cairn MCP server exposes 19 tools. Since v3.1.3 the toolset is consolidated: one tool per intent, with options (mode, filter, action, type) in place of near-duplicate tools. The server also exposes two read-only MCP resources, cairn://workspaces and cairn://projects.

Upgrading from older versions

Before v3.1.3 there were 54 tools with names such as get_cairn_context, get_note, update_task, list_ready_tasks, claim_task and add_task_progress. Those names no longer exist. If you have saved prompts or skills that mention them, switch to the tools below (for example get_context, get_item, update_tasks, search_tasks with filter: "ready", and task_progress). The dashboard tools were removed along with dashboards.

Context and search

ToolRead / WriteDescription
get_contextReadOrientation: workspace, projects, board columns, tags and conventions. With projectId: that project's pinned notes, folders, templates, open tasks and recent activity. Call first to get IDs.
get_itemReadFull content of a note or task card by id — the type is detected from the id.
search_notesReadFind notes. mode is keyword (default) or semantic (meaning-based, local embeddings). An empty query lists notes, newest first. type: "template" lists note templates. Optional projectId, folder, tag, updatedAfter, limit (default 10) and offset.
search_tasksReadFind task cards. mode is keyword (default) or semantic. filter: ready (unblocked, not done), overdue, or due (due within dueWithinDays, default 7, including overdue). Also projectId, columnType, assignee, tag, limit. An empty query lists all matching.

Notes

ToolRead / WriteDescription
ensure_noteWriteIdempotent create-or-update by title + projectId. Omitted content is preserved on update; a drastic shrink is rejected unless overwrite: true. Pass templateId to create from a template (date/title placeholders filled). Also folder, tagNames, isPinned.
edit_noteWriteEdit a note's text. With oldString: replace that exact text (optionally replaceAll). Without oldString: append newString to the end.
update_notesWriteChange one or more notes (noteIds): rename (title, single note only; incoming [[wikilinks]] are updated), move to a folder, tag (tagNames with tagMode add / remove / set), pin, or link / unlink task cards (linkCardIds, unlinkCardIds).

Tasks

ToolRead / WriteDescription
create_taskWriteCreate a task card. Place it with columnType (backlog, todo, in_progress, review, done; default backlog) or an explicit columnId. Also description, priority, dueDate, tagNames, linkNoteIds.
update_tasksWriteUpdate one or more cards (cardIds); only provided fields change. Move with columnType or columnId (moving to done unblocks dependents). Also title, description, priority, due date, assignee, archived (true = archive, false = restore), tags (tagNames + tagMode), linkNoteIds / unlinkNoteIds, and blockedBy / unblockFrom.
task_progressWriteAgent work log on a card. action: "claim" sets the assignee to your agent label and moves Backlog / To Do cards to In Progress (refuses if another agent holds it unless force). action: "log" appends a one-line update under "## Progress"; pass moveTo (in_progress, review, done) when finished. Optional agent and message.

Projects and deletion

ToolRead / WriteDescription
upsert_projectWriteCreate or update a project. Omit projectId to create (requires workspaceId and name; default columns are created automatically); provide projectId to update existing fields (name, description, icon, status, priority).
deleteDeletePermanently delete a note, task card, project (with all its contents), Idea Flow node or Idea Flow edge. type is one of note, task, project, flow_node, flow_edge, plus id. Cannot be undone.

Idea Flow

ToolRead / WriteDescription
get_idea_flowReadThe Idea Flow graph for a project: nodes (with note and task content resolved), edges, spatial bounds and nextPosition. Call before making changes.
edit_idea_flowWriteApply a list of ops in order, then optionally auto-layout (layout: LR or TB). Ops: add_node (types idea, note_ref, task_ref, url, ai_summary, group), update_node (data is merged), add_edge, delete_node, delete_edge. Later ops can refer to an earlier op's ref.

Knowledge Graph

ToolRead / WriteDescription
get_graphReadKnowledge graph. With nodeId (note, card, project or tag id): its N-hop neighbourhood (depth 1–3, default 1); semantic: true instead returns notes similar in meaning. Without nodeId: the whole workspace graph, scoped with projectIds, nodeTypes, edgeTypes; includeAuto (default true) includes auto-discovered edges.

Writing style

ToolRead / WriteDescription
get_user_writing_styleReadYour personal writing persona and style guide, for drafting content in your voice. mode: cheatsheet (default) or full. Returns configured: false if you haven't set one up.
update_user_writing_styleWriteAppend an observation to your style guide, optionally under a numbered section. Intended for when you ask the agent to remember a style preference.

Codebase

ToolRead / WriteDescription
codebase_reindexWriteScan and semantic-index a codebase folder (absolute path). Updates the SQLite cache of file paths, classes, functions, methods, docstrings and call dependencies. Unchanged files are skipped; force: true re-parses everything.
codebase_queryReadQuery the codebase index. action: search (symbols by name or docstring; optional folder, limit), definition (a symbol's signature, lines and docstring), references (callers and callees), file (every symbol in a file, query is the absolute path).
Agent workflow tip

Call get_context once at session start — it returns the workspace, project and column IDs and conventions in one call (pass a projectId for that project's pinned notes and open tasks). Use search_tasks with filter: "ready" to get only tasks with no pending blockers. Use search_notes or search_tasks with an empty query to list everything.

Task dependencies

Use update_tasks with blockedBy to mark cards as blocked by others in the same project. Circular dependencies are rejected automatically. A blocker is treated as resolved as soon as it moves to a done column or is archived. Use unblockFrom to remove a dependency explicitly.

IDs are stable

Note and task IDs are stable across sessions. Fetch them once and reuse them for subsequent tool calls within the same session.