Skip to main content
Glama
Capacities MCP Server

Capacities MCP Server

Capacities MCP Server

An MCP server for Capacities: search, property-based object lookup, object CRUD, save weblinks, and daily notes from any MCP-compatible client.

⚠️ Use 2.x. Version 2.x runs on Capacities' current REST API. Version 1.x used the Capacities Beta API, which Capacities scheduled for discontinuation on September 1, 2026; 1.x builds (and any .dxt packaged before v2.0.0) depend on it. Reinstall the current capacities-desktop-extension.dxt (v2.x). See the Capacities API notice.

About the name "v2". Capacities' own docs call the current API "v1" (their Beta was the first API). This repo calls it v2 because it is the second API this server has run on. Same API, two names.

Prerequisites

  • A Capacities account with API access

  • An API token: Capacities desktop app → Settings → Capacities API → Generate new token. Each token is scoped to one space and is either read-only or read-write; tools that write need a read-write token.

  • To run from source: Node.js 22 (the version the Docker image runs)

Related MCP server: Capacities-MCP-Plus

Installation

Choose the option that fits your setup:

Option 1: Claude Desktop Extension (Easiest)

  1. Download capacities-desktop-extension.dxt

  2. In Claude Desktop: Settings → Extensions → Import Extension

  3. Select the .dxt file and enter your API token when prompted

All dependencies are bundled; no additional setup needed.

Option 2: Run from Source

git clone https://github.com/inconceivablelabs/capacitiesMCP.git
cd capacitiesMCP
npm install
npm run build

Then add to your MCP client config (e.g. Claude Desktop's claude_desktop_config.json):

{
  "mcpServers": {
    "capacities": {
      "command": "node",
      "args": ["/path/to/capacitiesMCP/server/dist/index.js"],
      "env": {
        "CAPACITIES_API_TOKEN": "your_token_here"
      }
    }
  }
}

Option 3: Docker Container

For running as a persistent service (e.g. behind an MCP gateway):

# Build from the repo root: the Dockerfile copies from both src/ and server/.
docker build -f server/Dockerfile -t capacities-mcp .
docker run -d \
  -e CAPACITIES_API_TOKEN=your_token_here \
  capacities-mcp

The image is based on node:22-slim. Its runtime stage installs only server/'s production dependencies and the compiled output, with no source or dev dependencies. Since 2.2.3 it also removes the base image's bundled npm/npx, which the server never runs.

Available tools

Tool

Description

search_content

Search objects by title (optionally scoped by structureIds, capped by limit). When Capacities has semantic search enabled, objects related by meaning are also returned, listed after the title matches under a "Related by meaning" label; limit caps the combined list

find_objects

Locate objects of one type by a property the API can't search on — date, label/status, tag/relation, or scalar. Seed by title (title_hint; results limited to titles containing it), by tag, both, or neither, which lists the whole type (paged, page_budget up to 25 pages of 100). A title search that returns 50 results lists the whole type instead. Listed candidates are taken newest first by the date in their title (oldest first when sorting ascending on a date; undated titles last either way). Filters and sorts client-side over typed property values; returns ids + titles + the matched values (no bodies — compose with get_object). With no filters or sort it lists matches without reading each object. Dates are absolute ISO and must start with a real YYYY-MM-DD: a date-only value matches that day, a full timestamp that exact instant, or an {after,before} range. Reading objects stops early on a 403 or 401, or after 3 read errors with no success between them, rather than continuing against a server that is refusing it. A Note: line means the result may be incomplete

list_spaces

Show the space your API token is scoped to

get_space_info

List the space's structures: their properties, label options, and relation targets

create_object

Create an object of any structure with typed properties, labels, and relations (set by name, resolved strictly), plus a markdown body

update_object

Update an existing object's properties/relations (replaces each named property's value) and append a body

get_object

Read an object as Markdown (frontmatter + body), with a Labels: line before it listing every label property (Status, Priority, ...) read from the structured object. Where the two disagree, trust the Labels: line: Capacities' Markdown omits some statuses (Open Question, Backlog, On Hold) and shows Complete as Done

append_to_object

Append markdown content to an object's body without touching its properties

delete_object

Delete an object (moves to trash by default; hard_delete for permanent)

save_weblink

Save a URL as a Weblink, auto-fetching page metadata (override title/description)

add_to_daily_note

Append content to today's daily note

link_to_context

Add a task to another object's Context (a person, project, meeting, ...). Context in Capacities is derived from embeds: an object is in a task's Context when its body embeds the task. This appends that embed, and does nothing if the object already embeds the task

unlink_from_context

Remove a task from another object's Context by deleting every embed of the task in that object's body

Single-space per token. A v2 API token is scoped to exactly one space; list_spaces returns that one space. To work with multiple spaces, use multiple tokens.

The object model: properties vs. body

Objects in Capacities hold two kinds of content, and the tools treat them differently:

  • Properties — the object's typed fields: title, text, dates, numbers, labels (e.g. a task's Status, a weblink's Category), and entity relations (tags, a meeting's attendees). Set these with the properties / labels / relations inputs on create_object / update_object, keyed by property name or id (get them, plus label options and relation targets, from get_space_info). Relations and labels are set by name and resolved strictly: an unknown name is an error, never a guess; pass create_missing_relations: true to auto-create unmatched relation targets.

  • Body — freeform Markdown, set via the body / notes / content / markdown parameter.

Rule of thumb: set structured things as properties, prose as body. A tag is a property (a relations entry), not a [[link]] typed into the text. One tool call completes one object (all its properties and its body); several distinct, standalone objects take several calls.

Markdown conventions (body)

Any body/notes field supports Capacities' inline conventions:

Syntax

Effect

Creates an object?

() text

Creates a Task and links it into the body

Yes, a Task

#tag

Creates or links a Tag

Yes, a Tag if new

[[Name]]

Links an existing object by title

No; plain text if no such object exists

Use [[Name]] to reference something that already exists; use () / # when you intend to create the task/tag.

save_weblink creates a Weblink from a URL and auto-fetches the page's title and description; you can override title and description at save time. Those are the only properties settable on a weblink. The Capacities API currently treats media objects (weblinks, PDFs, images, audio, files) as create-only: they cannot be updated after creation, so tags, Category, and Topic cannot be set on a weblink through the API. To tag a weblink today, put a #tag in its notes (this associates a Tag via the body).

This is an upstream Capacities API limitation, not a limitation of this server. As soon as the Capacities API allows updating media objects, this server will add full weblink property support (tags / Category / Topic via save_weblink). Until then, #tag-in-notes is the available path.

Rate limits

Capacities enforces rate limits on its servers, per token and per endpoint (see its rate-limiting docs). In our measurements against /object the window is rolling: slots free up one at a time as each request ages out of the trailing 60 seconds. This server also runs a client-side, per-endpoint limiter, and its multi-call tools (create_object/update_object with many relations, and find_objects' searches and object reads) pace themselves against it. A find_objects listing does not wait: when the window is full it stops as a partial, with a Note: line saying so. That limiter is best-effort: it cannot see other clients using the same token or network. If a tool returns RATE_LIMIT_EXCEEDED, wait and retry rather than trying to predict the window.

The API sits behind Cloudflare, so a server-side rejection can arrive as a Cloudflare "you are being rate limited" page. The one we have captured came on a 429; the server also treats the same page on a 403 as a rate limit, in case a ban arrives that way. Both are reported as RATE_LIMIT_EXCEEDED. Such a ban is per IP address, so it affects every client on the same network for as long as it lasts. Error messages carry the server's response trimmed to fit: a JSON error is kept whole so the model can correct its call, and an HTML page is cut to its first line.

Why this server?

As of 2026-10-21: @capacities/api 1.1.3, and the official MCP server as documented at docs.capacities.io/developer/model-context-protocol. Both are moving, so check them before relying on this table.

This server

Official Capacities MCP server

@capacities/api SDK

What it is

Local MCP server (stdio), personal API token

Hosted MCP server at https://api.capacities.io/mcp, OAuth 2.1

TypeScript client library, not an MCP server

Setup

.dxt, Node, or Docker; token in env

Add the URL to your MCP client and sign in. The space must have AI Assistant enabled

npm install, then write your own code

Coverage

The 13 tools above

Search, read, create (pages, tasks, any type), update properties, append, block-level edits, file upload, list by type/tag/collection, object links

All 22 REST endpoints, plus OAuth with token refresh

Relations and tags on create/update

Set by name, resolved strictly. Unknown or ambiguous names fail before anything is written (auto-create is opt-in)

Properties are set from frontmatter; how relation names are resolved is not documented

You pass ids; name lookup is up to you

Property keys

Property name or id

Frontmatter keys

Ids

Filter by date, label, relation or value

find_objects

List by object type, tag or collection; other filters not documented

Not provided

Search output

Title matches first; semantic hits labelled "Related by meaning"

Title and semantic search ranked together

The raw API response

Client-side rate pacing

Per endpoint, best-effort

n/a (hosted)

None; the only retry is a 401 under OAuth

Pick the official server if you want block-level editing, file uploads, OAuth instead of a token, or a connector that works in hosted chat apps with nothing to install. Pick the SDK if you are writing your own code: it is the complete client. Note that 1.1.3 needs zod 4 at runtime even though its peer range also allows zod 3 (under zod 3.25 its import fails with .meta is not a function). Pick this server if your MCP client does typed, relation-heavy writes that must be validated before anything is saved, or needs to find objects by property value.

Configuration

Environment Variable

Required

Default

CAPACITIES_API_TOKEN

Yes

—

CAPACITIES_API_BASE_URL

No

https://api.capacities.io

LOG_LEVEL

No

info

Project structure

capacitiesMCP/
├── src/                  # TypeScript source (single source of truth)
├── server/               # Runtime packaging
│   ├── Dockerfile        # Container build
│   ├── package.json      # Runtime dependencies only
│   └── dist/             # Compiled output (built from root src/)
├── tsconfig.json         # Builds src/ → server/dist/
├── manifest.json         # DXT extension manifest
└── *.dxt                 # Pre-built extension packages

npm run build compiles src/ directly into server/dist/. There is one source, one build step, and one output location used by all three installation methods.

Development

npm install
npm run build        # Compile TypeScript
npm run dev          # Watch mode
npm run inspector    # MCP Inspector for debugging
npm test             # Run tests

See CLAUDE.md for architecture details.

Security advisories and reachability

This server speaks MCP over stdio only. It imports two modules from @modelcontextprotocol/sdk (server/mcp.js and server/stdio.js); the SDK's HTTP transports, OAuth client/server code and Express/Hono middleware are installed as dependencies but never loaded. Most advisories that Dependabot raises against this repo therefore cannot be reached at runtime. We still patch them, because the lockfiles ship in the Docker image and the extension.

As of 2.1.2 (SDK 1.32.1), npm audit reports 0 in both lockfiles. Reachability of the advisories cleared in that release, checked against a module-resolution trace of a live stdio session (initialize, tools/list, tools/call, resources/list):

Package

Loaded on our path?

Reachable?

@modelcontextprotocol/sdk (5 advisories)

Yes

No. Each advisory is scoped to HTTP servers, the HTTP/OAuth client, bearer auth or taskStore, none of which we use. The SDK's own advisory text says stdio-only servers are not affected by the memory-exhaustion one.

fast-uri

Yes, via ajv

No. The SDK builds an ajv instance at startup, but only calls it to validate form-elicitation replies (elicitInput), which this server never sends. Instrumented, a session that included tool calls with malformed URIs in their arguments made zero fast-uri calls; a control that compiled a schema with an $id through the same ajv instance made 15.

proxy-addr, qs (via Express)

No

No.

hono

No

No.

ip-address (via express-rate-limit)

No

No.

Image scanners also used to flag ip-address 10.1.0 inside the npm CLI bundled with the node:22-slim base image. That copy is in no lockfile, so Dependabot cannot see it, and the server never runs npm. Since 2.2.3 the runtime image no longer contains npm at all.

License

MIT. See LICENSE.

Available Tools

13 tools
add_to_daily_noteAdd to Daily NoteA

Add content to today's daily note in Capacities. Supports markdown. Each call appends to the existing daily note.

Inputs: content (required), no_timestamp.

append_to_objectAppend to Capacities ObjectA

Append markdown to the END of an existing object's body (POST /blocks/append) — additive, never removes, and never touches typed properties. This is the body counterpart to update_object, which replaces typed properties (scalars/labels/relations) via PATCH /object. Use update_object to change properties; use this to add notes/body.

Inputs: markdown (required), objectId (required).

create_objectCreate Capacities ObjectA

Create a new object of any structure in your Capacities space. Call get_space_info first to get structure_id, property ids, label options, and relation target types. Scalar properties (text/url/number/boolean/date) go in properties keyed by property NAME or id; dates are ISO-8601 strings. Labels go in labels (keyed by property NAME or id, values are option NAMES) and relations go in relations (keyed by property NAME or id, values are entity NAMES). Relations and labels are set by NAME and resolved strictly — an unknown name is an error, never a guess. Pass create_missing_relations: true to auto-create unmatched relation targets. update_object (not this tool) replaces; this creates.

Inputs: title (required), structure_id (required), body, labels, +4 more.

delete_objectDelete Capacities ObjectA

Delete an object. By default (hard_delete=false) it moves to trash and is recoverable in Capacities. Pass hard_delete=true to permanently delete — this cannot be undone.

Inputs: objectId (required), hard_delete.

find_objectsFind Capacities ObjectsA

Locate objects of one structure (NAME or id from get_space_info), then filter and sort client-side on properties the API cannot search. Seed by title_hint, by tag (a tag NAME), both, or neither — omit title_hint to list by tag or list the whole type. Results are limited to objects whose title contains title_hint (case, accents and punctuation ignored; it needs a letter or digit); short numeric hints also match dates ("1:1" matches 2024-11-12). A title search that returns 50 results lists the whole type instead. A listing reads up to page_budget pages of 100 (default 12, max 25) and orders candidates by the date in their title, newest first (oldest first for an ascending date sort; undated titles last), before fetch_cap (default 30, max 50) cuts them. With no filters and no sort, matches are listed without fetching each object (up to limit, default 30). Per call: at most 5 relation filters, and a call that lists makes at most 45 requests. filters are keyed by property NAME or id: a date is an absolute ISO string (a date-only value matches that day, a full timestamp that exact instant) or {after,before}; a label is an option NAME; a relation/tag is an object NAME; text/number/boolean are equals. sort is {by, order}; missing values sort last. A line starting "Note:" means the result may be incomplete; seed_complete and candidates_complete (in the result's second text block, a JSON object) say which part, and it is the full answer only when both are true and matched equals returned. Returns ids + titles + filtered/sorted values, NO bodies (use get_object); cannot follow backlinks.

Inputs: structure (required), tag, sort, limit, +4 more.

get_objectGet Capacities Object (Markdown)A

Read an object rendered as Markdown (YAML frontmatter of its properties + body). A Labels: line before the markdown lists every label property (e.g. Status, Priority) read from the STRUCTURED object, as <propertyId>: <Option>[, <Option>] entries separated by ; ((none) when empty). Where it disagrees with the frontmatter, the Labels line is authoritative: Capacities' markdown render omits some statuses (e.g. Open Question, Backlog, On Hold) and shows Complete as Done.

Inputs: objectId (required).

get_space_infoGet Space StructuresB

Get the structures (object types), their writable properties, and collections for your Capacities space.

Inputs: no named parameters.

list_spacesList Capacities SpacesB

Get a list of all your Capacities spaces

Inputs: no named parameters.

search_contentSearch Capacities ContentA

Search Capacities objects in your space by title. When Capacities has semantic search enabled for the account, it also returns objects related by meaning; those are listed after the title matches under a "Related by meaning" label. limit caps the combined list. Optionally scope by structureIds (from get_space_info).

Inputs: query (required), limit, structureIds.

update_objectUpdate Capacities ObjectA

Replace typed properties of an existing object (PATCH /object). Only the properties you name are changed; unnamed properties are left intact. WARNING: for a named property this REPLACES its value — it does NOT append. Naming a multi-value relation/label drops the prior list and sets exactly what you pass. To ADD to a relation, first read the current values (this tool reports them) and pass the full desired list. The optional body param is a convenience: after the PATCH, it also appends markdown to the object's body (POST /blocks/append) — the same additive write append_to_object performs on its own. Labels and relations are set by NAME and resolved strictly — an unknown name is an error. properties/labels/relations map keys accept a property NAME or id. Pass create_missing_relations: true to auto-create unmatched relation targets.

Inputs: objectId (required), body, title, labels, +4 more.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    A3.9/5.0

    Scored across 13 tools

    Disambiguation4/5

    Most tools are clearly distinct: create/update/append/delete act on different object aspects, and link/unlink are paired opposites. The main overlap is search_content versus find_objects, both used to locate objects; the descriptions distinguish global title/semantic search from structure-scoped filtering, but an agent may still hesitate between them.

    Naming Consistency4/5

    Names are consistently snake_case and verb-led (list_, get_, create_, update_, append_, delete_, search_, find_, link_/unlink_). A few use prepositions such as add_to_daily_note and link_to_context rather than strict verb_noun, but the overall pattern remains predictable.

    Tool Count5/5

    13 tools is well within the ideal range and each maps to a distinct capability: space discovery, object CRUD/append, search/listing, daily notes, weblinks, and task context linking. The set does not feel padded or thin.

    Completeness4/5

    Core lifecycle coverage is strong: spaces/info, object read/create/update/delete/append, search/find, daily note appends, weblinks, and context link/unlink. Gaps are minor and partly API-imposed: weblinks are create-only, and there is no full-text body search or bulk operation, but agents can work around these with existing tools.

    Maintenance

    ActivityNo data
    ResponsivenessOutdated data

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      A
      quality
      D
      maintenance
      An enhanced MCP server for the Capacities knowledge management app. Features * List and explore spaces * Search content with full-text and title modes * Read full object content by ID (unique feature) * Save weblinks with tags and metadata * Add content to daily notes * Windows-compatible
      6
      15 npm
      2
      MIT
    • A
      license
      C
      quality
      D
      maintenance
      Enables interaction with the Capacities.io note-taking API via MCP, supporting operations like searching content, saving weblinks, and appending to daily notes.
      5
      13
      MIT
    • A
      license
      Not graded
      quality
      C
      maintenance
      Enables MCP clients that support remote servers, such as ChatGPT, to securely search, fetch, list, and optionally create or update objects in a self-hosted Anytype space over HTTPS.
      MIT