Skip to content

MCP Server

The Pensum MCP server exposes your vault to AI agents via the Model Context Protocol. Agents can query your tasks, capture new ones, read project state, search across your vault, drive the weekly review, generate calendar exports, and write back when allowed — all with provenance tracking so you can always tell what an agent did vs. what you did.

This is the bridge between Pensum and the rest of your AI workflow. If you use Claude Desktop, Claude Code, or any other MCP-capable agent, the Pensum MCP server lets that agent participate in your productivity loop instead of just observing it.

The CLI ships a guided install bundle that prints the exact config snippet for your client, with the file path it belongs in and the post-install restart steps:

Terminal window
pensum mcp install --client claude-desktop
pensum mcp install --client claude-code
pensum mcp install --client cursor

Add --read-only to print a read-only bundle (no writes will be possible even if the agent asks). Add --vault=<name> to pin to a specific vault from your multi-vault config.

The bundle includes the file path for your client’s config, the JSON block to paste under mcpServers, and notes on .pensumignore + the audit log so you know what guard rails are in place from the first run.

If you want to wire things up yourself, run Pensum: Print MCP config in the command palette, or pensum mcp config. Either gives you a JSON snippet ready to drop into your MCP client:

{
"mcpServers": {
"pensum": {
"command": "pensum",
"args": ["mcp-serve"],
"env": { "PENSUM_VAULT": "/absolute/path/to/your/vault" }
}
}
}

The PENSUM_VAULT env var points the server at the vault you want it to operate on. Use an absolute path.

To start the server in read-only mode, add PENSUM_MCP_MODE=read-only to the env block. The server will accept every read tool but refuse any write tool with a clear error — useful for sessions where you want context-building without any chance of changes.

ClientWhere the config lives
Claude Desktop~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or %APPDATA%\Claude\claude_desktop_config.json (Windows) — under the mcpServers key
Claude Code~/.config/claude-code/mcp_servers.json or via the claude mcp add command
CursorSettings → Features → Model Context Protocol → Add new
Other clientsWherever your client expects MCP server definitions

Restart the client. The Pensum tools become available to the model.

If you have multiple vaults configured in ~/.config/pensum/config.toml (see CLI multi-vault), register one MCP server per vault:

{
"mcpServers": {
"pensum-personal": {
"command": "pensum",
"args": ["mcp-serve", "--vault=personal"]
},
"pensum-work": {
"command": "pensum",
"args": ["mcp-serve", "--vault=work"]
}
}
}

This is the recommended pattern: one server per vault, each with its own tool namespace. Agents pick which to call based on context.

Pensum’s tools use the form group.action — e.g. plan.today, capture.task, vault.read. The seven groups:

GroupPurpose
system.*Discovery, capabilities, audit, ignore patterns
plan.*Task reads, writes, structured queries, the weekly-review digest
capture.*Lightweight task and stub creation aimed at agent-driven capture
curate.*Wiki entries waiting to be developed
project.*Project listing, dashboards, create, frontmatter update
meet.*Meeting note list / read / create
vault.*Generic file CRUD (read, write, delete, move) + search + ICS export

Every response is wrapped in a shared envelope with optional workflow.suggested_next hints on success and recovery_hints on error, so agents can chain operations without you teaching them the next step.

ToolPurposeArgs
system.summaryVault path, entity counts, last scan timenone
system.capabilitiesServer version, permission mode, tool groups, active ignore patternsnone
system.suggest_nextContext-aware suggestions based on overdue / inbox / stub backlognone
system.auditTail of the MCP audit log (write operations only). Default 50, max 500.count?: number
system.ignore_patternsThe active .pensumignore patterns (defaults + user)none

system.suggest_next is the right first call when an agent isn’t sure what to do — it returns a tool list ranked by what currently needs attention.

The bulk of Pensum’s task model. Reads are unrestricted; writes are subject to read-only mode.

ToolWhat it doesArgs
plan.todayDue / scheduled today + overduenone
plan.inboxTasks in configured inbox files (default Tasks/Inbox.md)inbox_paths?
plan.by_projectOpen tasks for one projectproject
plan.overduePast-due open tasksnone
plan.weekNext 7 daysnone
plan.searchSubstring search across descriptions; paginatedquery, limit?, offset?
plan.getGet a task by ULIDid
plan.waitingTasks in waiting status ([w]). Excluded from the other planning views by design.none
plan.weekly_reviewThe five GTD review zones in one digest: inbox, overdue, waiting, stalled projects, wins since the last reviewinbox_paths?, since?
plan.queryStructured query (status, priority, projects, tags, dates, sort, group, limit)many optional

plan.search returns { total, offset, limit, count, next_offset, tasks } so agents can walk the result set without re-running the search. next_offset is null on the last page.

ToolWhat it doesArgs
plan.addAdd a task; defaults to agent-suggested-pending provenance so the user reviews itdescription, optional file, due_date, scheduled_date, priority, tags, provenance
plan.completeMark a task complete by ULID; recurring tasks auto-create the next occurrenceid, done_date?
plan.editPatch any subset of fieldsid, optional description, due_date, scheduled_date, priority, tags
plan.rescheduleConvenience for date-only changesid, due_date?, scheduled_date?
plan.deleteDelete a task line. No undo.id
plan.deferSet the 🛫 start date so the task vanishes from planning until then; pass null to clearid, date
plan.add_to_todayToggle a scheduled date of todayid
plan.set_statusChange checkbox status (" " / "/" / "w" / "-" / "x"). Prefer plan.complete for x.id, status

Useful for agent-driven Monday-morning rituals. Returns:

{
"generated_at": "2026-05-17",
"inbox": { "count": 4, "tasks": [...] },
"overdue": { "count": 2, "tasks": [...] },
"waiting": { "count": 1, "tasks": [...] },
"stalled_projects": { "count": 1, "projects": [{ "project": "Launch", "open_count": 3, "days_since_last_activity": 21 }] },
"wins_since": { "since": "2026-05-10", "count": 12, "tasks": [...] }
}

“Stalled” means a project has open work but the last task was completed ≥ 14 days ago (or never). Wins default to a 7-day window; override with since.

ToolWhat it doesArgs
capture.taskHigh-level capture into Tasks/Inbox.md. Always lands as agent-suggested-pending.description, optional project, due_date, priority, tags
capture.stubCreate a wiki stub in Wiki/. Curate view picks it up.title, optional tags, source

capture.task is the right tool when an agent wants to put something on your plate without committing the form of the task. The user accepts, edits, or discards in the Agent Captures view.

ToolWhat it doesArgs
curate.stubsWiki entries, optionally filtered by status (stub / drafted / developed / archived)status?, limit?
ToolWhat it doesArgs
project.listAll project files in the vaultnone
project.dashboardOpen + overdue + recent completions for one projectproject
project.createCreate a project file with Pensum frontmatter at <folder>/<name>.mdname, optional projects_folder, status, priority, target_date, tags
project.updatePatch a project file’s frontmatter (status / priority / target_date / tags). Body untouched.file_path, optional status, priority, target_date, tags
ToolWhat it doesArgs
meet.listMeeting files, filterable by date range / projectoptional after, before, project, limit
meet.readParsed frontmatter + full body for one meetingfile_path
meet.createCreate a meeting note with frontmatter scaffold (Agenda / Notes / Actions sections)title, optional meetings_folder, date, project, attendees, tags

Generic file operations. All vault.* calls are guarded by .pensumignore — if a path matches an ignore pattern the call is refused with an IGNORED error before anything is read or written.

ToolWhat it doesArgs
vault.readRead any file as a stringfile_path
vault.writeWrite a file (overwrite by default, creates parent dirs)file_path, content, optional create_only
vault.deleteDelete a file. Dry-run by default — pass confirm: true to actually delete.file_path, confirm?
vault.moveRename / move a filefrom, to
vault.searchFull-text search across tasks / projects / meetings / wiki; paginated; optional fragment snippetsquery, optional types, limit, offset, fragments, fragment_count, fragment_window
vault.export_icsGenerate an iCalendar .ics string from tasks; default filter = open + in-progress + waiting + completed in last 30doptional status, calendar_name

vault.search with fragments: true returns up to fragment_count snippets of context around each match per file, so an agent can decide whether a file is worth a full vault.read without paying for the full content.

vault.export_ics returns the raw ICS string in data.ics. The matching plugin/CLI command writes it to Pensum/Exports/tasks.ics — for the MCP version, the agent decides where to put the result.

Two tools paginate today: plan.search and vault.search. Both follow the same shape:

{
"total": 142,
"offset": 0,
"limit": 20,
"count": 20,
"next_offset": 20,
"tasks": [...]
}

next_offset is null on the last page. To walk a result set, keep re-calling with the previous next_offset.

Every entity returned by an MCP tool includes a provenance field. Possible values:

  • user-authored
  • ai-suggested-accepted
  • ai-suggested-edited
  • agent-suggested-pending
  • agent-suggested-accepted
  • agent-suggested-edited

See provenance for the full meaning of each.

plan.add defaults to agent-suggested-pending, which lands the task in the Agent Captures view for review. To capture directly to active, pass provenance: "user-authored" — usually inadvisable for agent-initiated content.

Two server modes, set via the PENSUM_MCP_MODE env var:

ModeSet withBehavior
allow (default)unset, or PENSUM_MCP_MODE=allowAll tools available. Writes still subject to .pensumignore.
read-onlyPENSUM_MCP_MODE=read-onlyWrite tools refuse with READ_ONLY and a recovery hint. Reads work normally.

system.capabilities returns the active mode under permission_mode, so agents can check before they try.

For a stronger guarantee, run a separate stdio server entry (e.g. pensum-readonly) with PENSUM_MCP_MODE=read-only in its env block — the mode is locked at process start.

A .pensumignore file at the vault root lists paths the MCP server must never read or write. Syntax is a subset of .gitignore:

  • # comments and blank lines
  • *, **, ? wildcards
  • Trailing / matches directories only
  • Leading / anchors to the vault root
  • Negation (!pattern) is not supported — the file is deny-only on purpose, so the security model stays trivially auditable

The server always merges these defaults on top of your file:

.pensum/secrets/**
**/.git/**
**/.obsidian/workspace*

Use system.ignore_patterns to see the merged list. Any vault.* call against a matched path is refused with an IGNORED error before the call reaches the filesystem.

Every write tool the server exposes appends a one-line JSON entry to .pensum/mcp-audit.jsonl. Read tools are skipped to keep the log small — they’re the bulk of traffic and they don’t change state.

A typical entry:

{"ts":"2026-05-17T15:22:11.043Z","tool":"plan.add","status":"ok","args_summary":{"description":"draft Q3 plan","file":"Tasks/Inbox.md"}}

status is one of ok / error / denied. denied covers read-only refusals and .pensumignore matches. args_summary is a trimmed version of the inputs — long strings are truncated, arrays and objects are placeheld so the log stays grep-friendly.

Tail the log from inside an agent session with system.audit (default last 50, max 500). Or just tail -f .pensum/mcp-audit.jsonl from a terminal.

The MCP server runs over stdio by default. The client launches the server as a subprocess and communicates via stdin/stdout. Every snippet on this page assumes stdio; it’s what every MCP client expects and has no auth surface.

An HTTP transport is also available (localhost-only, token-authenticated) for cases where stdio isn’t workable — e.g. a long-running agent process talking to the same server across multiple sessions, or a containerised agent that can’t spawn the binary itself. Configure under Settings → Agents → Transport.

For v1.0, stdio is recommended. HTTP is there for advanced cases.

When an agent captures a task with agent-suggested-pending provenance (the default for capture.task and plan.add), the task lands in the Agent Captures view rather than going directly into your active task graph.

Open the view: Pensum: Open agent captures. For each pending capture:

  • Accept — task moves into active, provenance flips to agent-suggested-accepted
  • Edit — open the edit modal, modify, then accept (provenance: agent-suggested-edited)
  • Discard — drop the suggestion

This is the safety mechanism for agent-originated content. The expectation: agents capture freely, you triage on your schedule.

To turn off the review queue (allow agent captures to land directly): Settings → Agents → Agent capture review → off. Only do this if you trust your agents to write meaningful tasks; otherwise the review step is valuable.

In allow mode with no .pensumignore overrides, agents can:

  • Read any file in the vault (vault.read, all plan.*/project.*/meet.*/curate.* reads)
  • Add tasks (defaulting to pending review)
  • Mark tasks complete, edit them, reschedule, defer, change status, delete
  • Create projects, meeting notes, wiki stubs
  • Patch project frontmatter
  • Write or move arbitrary files
  • Delete files only with confirm: true (default is dry-run)

Agents cannot:

  • Touch paths matched by .pensumignore (default includes .pensum/secrets/**, .git/**, Obsidian workspace state)
  • Bypass read-only mode once it’s been set in the env

If you want stricter limits, run in read-only mode for sensitive sessions, or add to .pensumignore.

If MCP is off (Settings → Agents → Enable MCP server → off), the binary still runs but reports unavailability for tool calls. If the Pensum plugin isn’t loaded, the binary can still read the vault directly (it shares the engine with the CLI). For most users, leave MCP on.

Server-side logs go to stderr (visible in your MCP client’s logs). For most users this is invisible; if you’re debugging an agent that doesn’t seem to be getting the right responses, check your client’s MCP log.

The MCP server ships with the Pensum CLI. Update via npm install -g @pensum/cli@latest (or Homebrew if installed that way). The plugin’s MCP integration is decoupled — you can update the CLI without updating the plugin.

system.capabilities returns the running version. Agents can check it if they care about version-specific behavior.