AFFiNE MCP Server
Server Configuration
Describes the environment variables required to run the server.
| Name | Required | Description | Default |
|---|---|---|---|
| MCP_WS_PORT | No | Host port to expose for WebSocket transport | 7821 |
| AFFINE_EMAIL | No | Email for authentication (self-hosted) | |
| AFFINE_COOKIE | No | Session cookie string (e.g., affine_session=<...>; affine_user_id=<...>) | |
| MCP_TRANSPORT | No | Transport mode: 'stdio' for stdio mode, or 'ws' for WebSocket | ws |
| AFFINE_BASE_URL | No | Base URL of your AFFiNE server, e.g. http://affine.local:3010 | |
| AFFINE_PASSWORD | No | Password for authentication (self-hosted) | |
| AFFINE_API_TOKEN | No | Personal access token for Bearer auth | |
| AFFINE_GRAPHQL_PATH | No | GraphQL endpoint path | /graphql |
| AFFINE_HEADERS_JSON | No | Optional JSON of extra headers to send | |
| AFFINE_WORKSPACE_ID | No | Default workspace id (optional). Tools also accept explicit workspaceId |
Capabilities
Features and capabilities supported by this server
| Capability | Details |
|---|---|
| tools | {
"listChanged": true
} |
Tools
Functions exposed to the LLM to take actions
| Name | Description |
|---|---|
| list_workspacesA | List all available AFFiNE workspaces |
| get_workspaceB | Get details of a specific workspace |
| create_workspaceB | Create a new workspace with initial document (accessible in UI) |
| update_workspaceC | Update workspace settings |
| delete_workspaceB | Delete a workspace permanently |
| list_docsC | List documents in a workspace (GraphQL). |
| search_docsA | Fast search for documents by title using workspace metadata. Much faster than exporting each doc. Returns docId, title, and direct URL for each match. |
| list_tagsA | List all tags in a workspace and the number of docs attached to each tag. |
| list_docs_by_tagB | List documents that contain the requested tag. |
| create_tagB | Create a workspace-level tag entry for future reuse. |
| add_tag_to_docC | Add a tag to a document. |
| remove_tag_from_docC | Remove a tag from a document. |
| get_docA | Get a document by ID (GraphQL metadata). |
| read_docA | Read document block content via WebSocket snapshot (blocks + plain text). Set includeMarkdown: true to also get the rendered markdown — useful when you need to read content without a separate export_doc_markdown call. |
| get_capabilitiesA | Return machine-readable capability flags for this MCP server, including block, database, collaboration, and export support. |
| analyze_doc_fidelityC | Inspect a document for markdown export fidelity risk, including unsupported AFFiNE block flavours and risky content paths. |
| move_docA | Move a doc in the AFFiNE sidebar by embedding it under a new parent. Optionally removes it from the old parent (fromParentDocId). If fromParentDocId is omitted, the doc is added to the new parent but not removed from the old one. |
| publish_docC | Publish a doc (make public). |
| revoke_docC | Revoke a doc's public access. |
| create_docA | Create a new AFFiNE document with optional content. If parentDocId is provided, the new doc is linked into the sidebar tree immediately. |
| create_semantic_pageB | Create an AFFiNE-native page with intentional section structure and native block composition. |
| append_semantic_sectionC | Append a semantic section to an existing AFFiNE document by heading title and native block composition. |
| append_blockB | Append document blocks with canonical types and legacy aliases (supports placement + strict validation). |
| export_doc_markdownC | Export AFFiNE document content to markdown. |
| export_with_fidelity_reportA | Export document markdown together with a structured fidelity report that highlights markdown loss risk and unsupported AFFiNE-native content. |
| create_doc_from_markdownB | Create a new AFFiNE document and import markdown content. Use parentDocId to automatically embed the new doc into a parent, making it visible in the sidebar instead of being an orphan. |
| append_markdownC | Append markdown content to an existing AFFiNE document. |
| replace_doc_with_markdownB | Replace the main note content of a document with markdown content. |
| delete_docC | Delete a document and remove from workspace list |
| list_workspace_treeA | Returns the full document hierarchy as a tree (roots → children → grandchildren). Use depth to limit nesting (default: 3). Note: loads all docs — may be slow on large workspaces. |
| get_orphan_docsB | Find all documents that have no parent (not linked from any other doc via embed_linked_doc). Useful for workspace hygiene. Note: scans all docs — O(n). |
| list_childrenA | List the direct children of a document in the sidebar (embed_linked_doc blocks). Returns docId, title, and URL for each child. |
| update_doc_titleA | Rename a document — updates both the sidebar title (workspace metadata) and the doc's internal page block title. |
| inspect_template_structureB | Inspect a template doc's native structure, tags, and fallback risk before instantiation. |
| instantiate_template_nativeB | Instantiate a template using native AFFiNE block cloning when supported, falling back to markdown materialization only when necessary. |
| add_database_rowA | Add a row to an AFFiNE database block. Provide cell values mapped by column name or column ID. Title column text is stored on the row paragraph block. Select columns auto-create options by label. |
| delete_database_rowB | Delete a row from an AFFiNE database block. |
| read_database_cellsA | Read row titles and database cell values from an AFFiNE database block. |
| read_database_columnsA | Read schema metadata for an AFFiNE database block, including columns, select options, and view column mappings. Useful for empty databases before any rows exist. |
| update_database_rowB | Batch update multiple cells on an existing AFFiNE database row. Include |
| compose_database_from_intentB | Create a useful AFFiNE database/data-view from declarative intent. Supports task_board and issue_tracker presets with starter schema, kanban view, and optional starter rows. |
| add_database_columnB | Add a column to an existing AFFiNE database block. Supports rich-text, select, multi-select, number, checkbox, link, date types. |
| add_surface_elementA | Add a shape, connector, text, or group to the AFFiNE edgeless canvas surface. Shapes support rect/ellipse/diamond/triangle with fill, stroke, and text. Connectors draw arrows between shapes (by id) or between absolute points. Use for building diagrams programmatically. Style fields that don't apply to the chosen element type are reported in the response 'ignored' list (mirrors update_surface_element). |
| list_surface_elementsA | List all shape/connector/text/group elements on the AFFiNE edgeless canvas surface. Returns raw xywh strings plus parsed {x,y,width,height} bounds, with Y.Text fields serialized to plain strings. Optional filters by element type or id. |
| update_surface_elementA | Partially update a surface element by id. x/y/width/height merge with the element's current xywh (move without resizing, or vice versa). text/label/title replace their Y.Text wholesale. Fields that don't apply to the element's type are reported in the response 'ignored' list. |
| delete_surface_elementA | Delete a surface element by id. Set pruneConnectors=true to also delete any connectors whose source or target referenced the deleted element. |
| update_frame_childrenA | Replace a frame block's contents wholesale. Accepts ids of surface elements (shapes/connectors/groups) AND edgeless blocks (notes/frames/edgeless-text) — all go into BlockSuite's prop:childElementIds map, matching what the editor writes when you drag members into a frame. Dragging the frame drags every owned member. Ids that don't resolve come back under 'missing'. By default the frame is resized to fit its new contents (plus padding + title band); set resizeToFit=false to leave xywh untouched. Pass |
| update_edgeless_blockA | Partially update a note/frame/edgeless-text block by id. x/y/width/height merge with current prop:xywh (move without resizing, or vice versa). background replaces prop:background (AFFiNE token or |
| delete_blockA | Delete a block by id. Removes descendants and unlinks from the parent's sys:children by default; set deleteChildren=false to keep descendants orphaned (for re-parenting), or pruneConnectors=true to also drop surface connectors referencing any deleted id. Refuses affine:page — use delete_doc for whole docs. |
| get_edgeless_canvasA | Read the full edgeless canvas: all edgeless-positioned blocks (notes, frames, edgeless-text) with their xywh, plus all surface elements (shapes, connectors, text, groups). Includes aggregate bounding box and per-type element counts. Use this when you need to understand canvas layout end-to-end before placing new elements. |
| list_commentsC | List comments of a doc (with replies). |
| create_commentC | Create a comment on a doc. |
| update_commentC | Update a comment content. |
| delete_commentC | Delete a comment by id. |
| resolve_commentC | Resolve or unresolve a comment. |
| list_historiesC | List doc histories (timestamps) for a doc. |
| list_collectionsC | List AFFiNE collections stored in the workspace sidebar. |
| get_collectionB | Get an AFFiNE collection by id. |
| create_collectionC | Create a new AFFiNE collection in the workspace sidebar. |
| update_collection_rulesB | Replace a collection's rules and rebuild its allow-list from workspace docs. |
| update_collectionC | Rename an AFFiNE collection. |
| delete_collectionC | Delete an AFFiNE collection from the workspace sidebar. |
| add_doc_to_collectionC | Add a document id to an AFFiNE collection allow-list. |
| remove_doc_from_collectionC | Remove a document id from an AFFiNE collection allow-list. |
| list_organize_nodesC | Experimental: list AFFiNE sidebar organize nodes from the folders workspace DB. |
| create_folderC | Experimental: create an AFFiNE organize folder node. |
| create_workspace_blueprintC | Create a simple workspace folder blueprint under the organize tree. |
| rename_folderC | Experimental: rename an AFFiNE organize folder node. |
| delete_folderB | Experimental: delete an AFFiNE organize folder and all nested nodes. |
| move_organize_nodeC | Experimental: move an AFFiNE organize folder or link node. |
| add_organize_linkC | Experimental: add a doc/tag/collection link under an AFFiNE organize folder. |
| delete_organize_linkC | Experimental: delete an AFFiNE organize doc/tag/collection link. |
| current_userB | Get current signed-in user. |
| update_profileB | Update current user's profile information. |
| update_settingsC | Update user settings and preferences. |
| sign_inA | Sign in to AFFiNE using email and password; sets session cookies for subsequent calls. |
| list_access_tokensA | List personal access tokens (metadata). |
| generate_access_tokenC | Generate a personal access token (returns token). |
| revoke_access_tokenC | Revoke a personal access token by id. |
| upload_blobC | Upload a file or blob to workspace storage. |
| delete_blobB | Delete a blob/file from workspace storage. |
| cleanup_blobsC | Permanently remove deleted blobs to free up storage. |
| list_notificationsC | Get user notifications. |
| read_all_notificationsB | Mark all notifications as read. |
Prompts
Interactive templates invoked by user choice
| Name | Description |
|---|---|
No prompts | |
Resources
Contextual data attached and managed by the client
| Name | Description |
|---|---|
No resources | |
Latest Blog Posts
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/DAWNCR0W/affine-mcp-server'
If you have feedback or need assistance with the MCP directory API, please join our Discord server