Capacities MCP Server
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Capacities MCP Server search my notes for AI trends"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
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
.dxtpackaged before v2.0.0) depend on it. Reinstall the currentcapacities-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)
Download
capacities-desktop-extension.dxtIn Claude Desktop: Settings → Extensions → Import Extension
Select the
.dxtfile 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 buildThen 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-mcpThe 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 objects by title (optionally scoped by |
| Locate objects of one type by a property the API can't search on — date, label/status, tag/relation, or scalar. Seed by title ( |
| Show the space your API token is scoped to |
| List the space's structures: their properties, label options, and relation targets |
| Create an object of any structure with typed properties, labels, and relations (set by name, resolved strictly), plus a markdown body |
| Update an existing object's properties/relations (replaces each named property's value) and append a body |
| Read an object as Markdown (frontmatter + body), with a |
| Append markdown content to an object's body without touching its properties |
| Delete an object (moves to trash by default; |
| Save a URL as a Weblink, auto-fetching page metadata (override |
| Append content to today's daily note |
| 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 |
| 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_spacesreturns 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/relationsinputs oncreate_object/update_object, keyed by property name or id (get them, plus label options and relation targets, fromget_space_info). Relations and labels are set by name and resolved strictly: an unknown name is an error, never a guess; passcreate_missing_relations: trueto auto-create unmatched relation targets.Body — freeform Markdown, set via the
body/notes/content/markdownparameter.
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? |
| Creates a Task and links it into the body | Yes, a Task |
| Creates or links a Tag | Yes, a Tag if new |
| 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.
Weblinks & media objects (current API limitation)
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 |
| |
What it is | Local MCP server (stdio), personal API token | Hosted MCP server at | TypeScript client library, not an MCP server |
Setup |
| Add the URL to your MCP client and sign in. The space must have AI Assistant enabled |
|
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 |
| 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 |
| Yes | — |
| No |
|
| No |
|
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 packagesnpm 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 testsSee 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? |
| Yes | No. Each advisory is scoped to HTTP servers, the HTTP/OAuth client, bearer auth or |
| Yes, via | No. The SDK builds an |
| No | No. |
| No | No. |
| 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 toolsadd_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.
link_to_contextLink Task to ContextA
Add a task to another object's Context. A task's Context in Capacities is derived, not a property: it is the set of objects (people, projects, meetings, ...) whose body embeds the task as an EntityBlock. This appends an EntityBlock embedding the task to the END of the target object's body (POST /blocks/append). Idempotent: if the target already embeds the task anywhere in its body, nothing is written and the existing block id(s) are reported. task_id must be a Task (RootTask).
Inputs: task_id (required), object_id (required).
list_spacesList Capacities SpacesB
Get a list of all your Capacities spaces
Inputs: no named parameters.
save_weblinkSave Weblink to CapacitiesA
Save a URL as a weblink object. Optional title/description override the auto-fetched page metadata (these are the ONLY fields settable on a weblink, and only at save time — weblinks are create-only in the API). To tag or annotate a weblink, put #tag, () tasks, or [[links]] in notes; Category/Topic and other properties cannot be set via the API yet.
Inputs: url (required), notes, title, description.
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.
unlink_from_contextUnlink Task from ContextA
Remove a task from another object's Context. A task's Context in Capacities is derived, not a property: it is the set of objects (people, projects, meetings, ...) whose body embeds the task as an EntityBlock. This deletes EVERY EntityBlock on the target object that embeds the task (at any depth, in any block field), one DELETE /block each; nested content inside a removed block goes with it. If the target does not embed the task, nothing is removed.
Inputs: task_id (required), object_id (required).
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
Scored across 13 tools
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.
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.
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.
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
Related MCP Connectors
Knowledge base MCP for AI agents on iknow.dev. Search, read, and maintain via OAuth.
Official Fibery MCP server: query and update your workspace from any AI client via OAuth.
Connect AI clients to your Dactic work context through a hosted MCP service.
Persistent memory, knowledge graph, task management and more for AI agents via MCP.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceFacilitates integration of PrivateGPT with MCP-compatible applications, enabling chat functionalities and secure management of knowledge sources and user access.-
- AlicenseAqualityDmaintenanceAn 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-compatible615 npm2MIT
- AlicenseCqualityDmaintenanceEnables interaction with the Capacities.io note-taking API via MCP, supporting operations like searching content, saving weblinks, and appending to daily notes.513MIT
- AlicenseNot gradedqualityCmaintenanceEnables 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