Capacities MCP
An MCP server for Capacities API 2.0 that enables AI agents to discover, create, read, update, and delete objects, blocks, and daily notes with structured JSON or Markdown, using personal API tokens.
README
Capacities MCP
An agent-oriented MCP server for Capacities API 2.0, built with TypeScript, xmcp, and the official @capacities/api SDK.
- Structural JSON blocks are the default for every write.
get_objectreturns structured JSON by default; its Markdown mode is a compact, read-only proposal/context view.- Separate
*_markdownwrite tools are available for explicit Markdown authoring; agents should choose the structural tools first. - Personal API tokens only (OAuth is not included).
- Strict generated JSON Schemas, live structure/property discovery, verified block mutations, web-resource import, and daily-note support.
Requirements
- Node.js 20+ or Bun 1.3+
- Capacities personal API token with
api:readand/orapi:write
Create a token in Capacities → Settings → Capacities API.
Install
bun install
bun run build
node dist/stdio.js
For development: bun run dev.
Set authentication in the process environment (or pass apiToken for one call):
export CAPACITIES_API_TOKEN="cap-api-..."
$env:CAPACITIES_API_TOKEN = "cap-api-..."
Never commit tokens or include them in shared prompts and logs.
MCP client configuration
Use an absolute path to the built entry point:
{
"mcpServers": {
"capacities": {
"command": "node",
"args": ["/absolute/path/to/capacities-mcp-v2/dist/stdio.js"],
"env": { "CAPACITIES_API_TOKEN": "cap-api-..." }
}
}
}
Tools
| Tool | Purpose | Main inputs |
|---|---|---|
inspect_space |
Discover structures, properties, labels, and collections | structure?, refresh? |
search_objects |
Find objects by title | query, structures?, limit? |
get_object |
Read exact object data (default) or read-only Markdown view | id, format? (structured default) |
create_object |
Create an object with typed properties and optional structural blocks | structure, title, blocks?, fields?, collections? |
create_object_markdown |
Explicitly create an object from Markdown | structure, title, markdown, fields?, collections? |
create_object_from_url |
Import a URL as a web-resource with optional structural notes | url, title?, description?, blocks? |
create_object_from_url_markdown |
Explicitly import a URL with Markdown notes | url, title?, description?, markdown |
update_object |
Patch title, properties, or collections | id, title?, fields?, collections? |
append_content |
Insert structural blocks into an object | id, blocks, insertion options |
append_content_markdown |
Explicitly insert Markdown into an object | id, markdown, insertion options |
delete_object |
Move to trash or permanently delete | id, permanent? |
append_daily_note |
Queue structural blocks for a daily note | blocks, date?, noTimestamp? |
append_daily_note_markdown |
Explicitly queue Markdown for a daily note | markdown, date?, noTimestamp? |
update_block |
Replace one existing block in place using structural JSON | id, blockId, block, propertyId? |
delete_block |
Delete one block and any nested children | id, blockId |
All tools accept an optional apiToken; prefer the environment variable.
Recommended agent workflow
- Call
inspect_space({ structure })before an unfamiliar write and follow itswriteGuide. Property IDs are safest. - Use
search_objectsto find candidates by title, thenget_objectto inspect exact content. Search is title-only, not full-text. - Read with
get_object(structured mode is the default) before updating or deleting. - Use
fieldsfor properties andblocksfor content. Usecreate_object_from_urlfor web resources; ordinary create supports pages, tags, tasks, and custom object types. - Use
update_blockfor precise in-place edits. Its block ID and type stay unchanged. Omittingblockspreserves existing children; supplyingblocksreplaces them. - Use
get_object({ format: "markdown" })only when a compact, non-editing proposal or context view is useful. - Use a
*_markdownwrite tool only when Markdown authoring/conversion is specifically requested; do not use it as the default editing path. - Prefer soft delete; set
permanent: trueonly when irreversible deletion is explicit.
Example structural create:
{
"structure": "Page",
"title": "Meeting notes",
"blocks": [
{
"type": "TextBlock",
"tokens": [
{ "type": "TextToken", "text": "Decisions: ship v1", "style": {} }
],
"hierarchy": { "key": "Base", "val": 0 }
}
]
}
Block inputs are a strict, documented subset of the SDK schema:
- Heading pairs are exactly
Base/0,H1/1,H2/2, orH3/3. LinkTokenhas exactly one target: HTTP(S)urlor CapacitiesentityId.EntityBlock.entityIdis a non-null UUID;GridBlock.columns, when supplied, has at least two columns.- Unknown block/token keys are rejected. New blocks omit IDs.
fields accepts property IDs or exact UI names. The writeGuide reports each field's live type and allowed values. Inputs include primitives, UUID arrays for entity fields, label names/IDs, null to clear, ISO dates or { start, end?, dateResolution? }, rich-text token arrays, and { "type": "emoji" | "iconify", "value": "..." } icons. Unknown, ambiguous, read-only, and invalid values are rejected before a write.
Operational notes
- Structured reads include properties, collections, exact block trees, block IDs, and media metadata.
- Only
TextBlockandGroupBlockaccept appended child blocks. - Synchronous block updates/deletes are checked against the returned object. Daily-note writes alone are queued asynchronously.
- Existing media may expose temporary signed URLs; API 2.0 has no upload endpoint.
- Daily-note
queuedmeans accepted, not immediately readable. - Rate-limit and API errors retain Capacities' stable
cap_*error code. Oncap_rate_limit_exceeded, wait for the endpoint reset window rather than retrying immediately. permanent: truecannot be undone.
Checks
bun run lint
bun run typecheck
bun test
bun run build
bun run verify:tools
With a token, run bun run test:live to exercise discovery, title search, both read modes, structural and Markdown create/append, child-preserving in-place block update, block deletion, URL imports, soft/permanent object deletion, and both daily-note variants. The harness serializes live requests to avoid provider burst limits. Temporary objects are permanently removed; daily-note test markers remain because the API queues those writes.
References
Recommended Servers
playwright-mcp
A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.
Magic Component Platform (MCP)
An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.
Audiense Insights MCP Server
Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.
VeyraX MCP
Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.
graphlit-mcp-server
The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.
Kagi MCP Server
An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.
Neon Database
MCP server for interacting with Neon Management API and databases
E2B
Using MCP to run code via e2b.
Exa Search
A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.
Qdrant Server
This repository is an example of how to create a MCP server for Qdrant, a vector search engine.