Atlas / MCP servers / dawncr0w / Affine

AffineCAUTION

mcp/dawncr0w/affine

Model Context Protocol server for AFFiNE. Connect AI assistants to AFFiNE workspaces, documents, databases, and collaboration APIs over stdio or HTTP.

Verdict
CAUTION
Grade
B
Trust score
81 /100
Exposed tools
107 45r · 46w · 16d
Transport
sse · stdio · streamable-http
License
MIT
Stars
297
01

Overview

From the repository's own README, as read at the audited commit. Badges and raw HTML are left out.

A Model Context Protocol (MCP) server for AFFiNE. It exposes AFFiNE workspaces and documents to AI assistants over stdio (default) or HTTP (/mcp) and supports both AFFiNE Cloud and self-hosted deployments.

[](https://github.com/dawncr0w/affine-mcp-server/releases) [](https://github.com/modelcontextprotocol/typescript-sdk) [](https://github.com/dawncr0w/affine-mcp-server/actions/workflows/ci.yml) [](LICENSE)

Table of Contents

  • Overview
  • Choose Your Path
  • Quick Start
  • Compatibility Matrix
  • Tool Surface
  • Documentation Map
  • Verify Your Setup
  • Security and Scope
  • Development
  • Release Notes
  • License
  • Support

Overview

AFFiNE MCP Server is designed for three common scenarios:

  • Run a local stdio MCP server for Claude Code, Codex CLI, Cursor, or Claude Desktop
  • Expose a remote HTTP MCP endpoint for hosted or browser-connected clients
  • Automate AFFiNE workspace, document, database, organization, and comment workflows through a stable MCP tool surface

Highlights:

  • Supports AFFiNE Cloud and self-hosted AFFiNE instances
  • Supports stdio and HTTP transports
  • Coordinates concurrent writes per workspace through one shared MCP server; optional document revisions reject stale edits
  • Supports session-cookie and email/password authentication, plus compa
Read from source at commit 2d13eb0ca77aOBSERVED · 2026-10-06
02

Connect

Built from this server's own package name, version and transport as found in its source — not copied from anyone's documentation, so it cannot drift against a page we do not control. Replace the environment placeholders with a token scoped to the least it needs.

claude-code
claude mcp add affine-mcp-server --env AFFINE_ADMIN_PASSWORD=${AFFINE_ADMIN_PASSWORD} --env AFFINE_MCP_HTTP_ALLOW_QUERY_TOKEN=${AFFINE_MCP_HTTP_ALLOW_QUERY_TOKEN} --env AFFINE_MCP_HTTP_ALLOW_UNAUTHENTICATED=${AFFINE_MCP_HTTP_ALLOW_UNAUTHENTICATED} --env AFFINE_MCP_HTTP_TOKEN=${AFFINE_MCP_HTTP_TOKEN} -- npx -y [email protected]
claude-desktop
{
  "mcpServers": {
    "affine-mcp-server": {
      "command": "npx",
      "args": [
        "-y",
        "[email protected]"
      ],
      "env": {
        "AFFINE_ADMIN_PASSWORD": "${AFFINE_ADMIN_PASSWORD}",
        "AFFINE_MCP_HTTP_ALLOW_QUERY_TOKEN": "${AFFINE_MCP_HTTP_ALLOW_QUERY_TOKEN}",
        "AFFINE_MCP_HTTP_ALLOW_UNAUTHENTICATED": "${AFFINE_MCP_HTTP_ALLOW_UNAUTHENTICATED}",
        "AFFINE_MCP_HTTP_TOKEN": "${AFFINE_MCP_HTTP_TOKEN}"
      }
    }
  }
}
03

Exposed tools (107)

45 read · 46 write · 16 destructive. Blast radius: 16 tools can delete or overwrite — an agent that can be talked into calling a tool can be talked into calling this one.

ToolRiskDescription
add_database_columnwrite
add_database_rowwrite
add_doc_to_collectionwrite
add_mindmap_nodewrite
add_organize_linkwrite
add_surface_elementwrite
add_tag_to_docwrite
analyze_doc_fidelityread
append_blockread
append_markdownread
append_semantic_sectionread
cleanup_blobsread
clear_doc_propertydestructive
compose_database_from_intentread
create_collectionwrite
create_commentwrite
create_custom_propertywrite
create_docwrite
create_doc_from_markdownwrite
create_folderwrite
create_mindmapwrite
create_semantic_pagewrite
create_tagwrite
create_workspacewrite
create_workspace_blueprintwrite
current_userread
delete_blobdestructive
delete_blockdestructive
delete_collectiondestructive
delete_commentdestructive
delete_custom_propertydestructive
delete_database_rowdestructive
delete_docdestructive
delete_folderdestructive
delete_organize_linkdestructive
delete_surface_elementdestructive
delete_tagdestructive
delete_workspacedestructive
export_doc_markdownread
export_with_fidelity_reportread
find_doc_by_titleread
get_capabilitiesread
get_collectionread
get_docread
get_doc_iconread
get_edgeless_canvasread
get_folder_iconread
get_mindmapread
get_orphan_docsread
get_workspaceread
inspect_template_structureread
instantiate_template_nativeread
list_childrenread
list_collectionsread
list_commentsread
list_doc_propertiesread
list_docsread
list_docs_by_tagread
list_historiesread
list_notificationsread
list_organize_nodesread
list_surface_elementsread
list_tagsread
list_workspace_treeread
list_workspacesread
move_blockwrite
move_docwrite
move_organize_nodewrite
publish_docwrite
read_all_notificationsread
read_database_cellsread
read_database_columnsread
read_docread
remove_doc_from_collectiondestructive
remove_tag_from_docdestructive
rename_folderwrite
reparent_mindmap_noderead
replace_doc_with_markdownread
resolve_commentread
restore_docread
revoke_docdestructive
search_docsread
set_doc_journalwrite
set_doc_propertywrite
set_mindmap_layoutwrite
set_mindmap_lockwrite
set_mindmap_stylewrite
sign_inread
trash_docread
update_blockwrite
update_collectionwrite
update_collection_ruleswrite
update_commentwrite
update_database_rowwrite
update_doc_iconwrite
update_doc_titlewrite
update_edgeless_blockwrite
update_folder_iconwrite
update_frame_childrenwrite
update_mindmap_nodewrite
update_profilewrite
update_settingswrite
update_surface_elementwrite
update_table_cellwrite
update_table_column_widthswrite
update_workspacewrite
upload_blobwrite
04

Trust audit

CAUTIONgrade B · trust 81/100 Install with care. The audit found things worth knowing before you trust its output.

LayerWhat it checksResult
L0Provenance & inventoryPASS
L1Static analysis of the codeWARN
L2Instruction surface (what it tells the agent)PASS
L3Class-specific surfaceWARN
L4Behavioural (sandbox)SKIPPED

What the source does

Filesystem
declared (1 observation(s))
Network
declared (8 observation(s))
Shell
declared (2 observation(s))
Dependencies
not all pinned
Secrets in source
none-found

Findings (22)

MEDIUMInformation disclosure · disclose.log_secret · CWE-209, CWE-532
src/cli.ts:1369
if (summary.apiToken) console.log(`API token: ${summary.apiToken} (${summary.sources.apiToken})`);
MEDIUMInformation disclosure · disclose.log_secret · CWE-209, CWE-532
src/cli.ts:1383
console.log(`HTTP auth token: ${summary.http.authToken || "(unset)"} (${summary.sources.httpAuthToken})`);
MEDIUMNetwork egress · net.raw_ip · CWE-200, CWE-319
Dockerfile:44
CMD wget -qO- http://127.0.0.1:${PORT}/healthz || exit 1
MEDIUMNetwork egress · net.raw_ip · CWE-200, CWE-319
src/stdioHttpProxy.ts:6
const DEFAULT_ENDPOINT = `http://127.0.0.1:${process.env.PORT || "3000"}/mcp`;
MEDIUMFilesystem / path · mcp.destructive_tools · CWE-22, CWE-59
clear_doc_property, delete_blob, delete_block, delete_collection, delete_comment, delete_custom_property, delete_database_row, delete_doc, delete_folder, delete_organize_link, delete_surface_element,
Why it matters. 16 tool(s) can delete or overwrite
Fix. prefer a read-only mode or scoped tokens; the page states the blast radius
LOWInventory / provenance · inv.hidden_file · CWE-1104
.coderabbit.yaml
.coderabbit.yaml
Why it matters. hidden member outside the usual dotfiles
Fix. review its purpose
LOWInformation disclosure · disclose.log_secret · CWE-209, CWE-532
tests/test-database-creation.mjs:133
console.log(`Auth mode: email/password (sync login at startup)`);
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
tests/playwright/verify-properties-comments.pw.ts:10
import { connectWorkspaceSocket, joinWorkspace, loadDoc, wsUrlFromGraphQLEndpoint } from '../../dist/ws.js';
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
tests/test-live-test-safety.mjs:97
() => resolveTestRunId({ AFFINE_TEST_RUN_ID: '../../unsafe' }),
LOWNetwork egress · net.raw_ip · CWE-200, CWE-319
docs/client-setup.md:230
"AFFINE_MCP_HTTP_PROXY_URL": "http://127.0.0.1:3000/mcp"
LOWNetwork egress · net.raw_ip · CWE-200, CWE-319
docs/configuration-and-deployment.md:157
| `AFFINE_MCP_HTTP_PROXY_URL` | No | `http://127.0.0.1:${PORT:-3000}/mcp` | Loopback Streamable HTTP endpoint used by `affine-mcp-http-proxy` |
LOWNetwork egress · net.raw_ip · CWE-200, CWE-319
docs/configuration-and-deployment.md:343
`http://127.0.0.1:${PORT:-3000}/mcp` and accepts loopback URLs only.
LOWObfuscation / stealth · obf.homoglyph · CWE-506, CWE-94
tests/test-native-mindmap.mjs:43
f.mutate('update', { mindmapId: f.map.mindmapId, nodeId: c, text: 'Renamed\nЗадача', collapsed: true });
LOWObfuscation / stealth · obf.homoglyph · CWE-506, CWE-94
tests/test-native-mindmap.mjs:50
assert.equal(result.nodes.find(n => n.nodeId === c).text, 'Renamed\nЗадача');
LOWSupply chain · supply.unpinned · CWE-829, CWE-1357
package.json
@modelcontextprotocol/sdk, cors, express, form-data, jose, fractional-indexing, markdown-it, node-fetch
Why it matters. 19 dependency range(s) float
Fix. pin exact versions or ship a lockfile
LOWPrompt injection · prompt.credential_read · CWE-94, CWE-1427
README.md:54
> New in v3.2.1: Scripted cookie login now keeps session secrets out of process arguments, validates workspace access before saving credentials, and restores document pagination for ordinary workspace
Why it matters. asks the agent to read credentials
LOWPrompt injection · prompt.credential_read · CWE-94, CWE-1427
docs/configuration-and-deployment.md:15
config file. Some consumers intentionally read environment variables directly
Why it matters. asks the agent to read credentials
LOWPrompt injection · prompt.transfer_instruction · CWE-94, CWE-1427
CHANGELOG.md:95
- Added `login --save-credentials`, which stores the email/password used to sign in instead of the session cookie, so the server can sign in on its own and renew the session before it expires.
Why it matters. an instruction to move sensitive data to an outside destination
Fix. remove; a skill never needs the user's secrets off the machine
LOWPrompt injection · prompt.transfer_instruction · CWE-94, CWE-1427
CHANGELOG.md:110
- Classify AFFiNE Cloud by complete hostname labels instead of substring-matching `affine.pro`. Self-hosted deployments such as `https://affine.proxy.internal` or `https://affine.pro.example.com` prev
Why it matters. an instruction to move sensitive data to an outside destination
Fix. remove; a skill never needs the user's secrets off the machine
LOWPrompt injection · prompt.transfer_instruction · CWE-94, CWE-1427
CHANGELOG.md:285
- Email/password sign-in and all GraphQL/REST requests now send the `x-affine-version` header (configurable via the new `AFFINE_CLIENT_VERSION`, default `0.26.0`). AFFiNE servers that gate on a minimu
Why it matters. an instruction to move sensitive data to an outside destination
Fix. remove; a skill never needs the user's secrets off the machine
LOWPrompt injection · prompt.transfer_instruction · CWE-94, CWE-1427
README.md:159
With the email/password method, this stores `AFFINE_EMAIL` and `AFFINE_PASSWORD` so the server signs in on its own and renews the session before it expires. The password is written to the mode-`600` c
Why it matters. an instruction to move sensitive data to an outside destination
Fix. remove; a skill never needs the user's secrets off the machine
LOWPrompt injection · prompt.transfer_instruction · CWE-94, CWE-1427
docs/client-setup.md:214
Always send the MCP bearer token in the `Authorization` header. The server
Why it matters. an instruction to move sensitive data to an outside destination
Fix. remove; a skill never needs the user's secrets off the machine

Gates applied: no_behavioural_pass.

Audited 2026-10-06 · audit v0.4.1 · source sha 2d13eb0ca77afull audit observations/trust-audit/mcp-server/dawncr0w__affine.json · Report an issue / request a re-scan
05

Audit history

Every audit this server has had. A grade with a past is a grade somebody is still checking.

DateSourceVerdictGradeScoreChange
2026-10-062d13eb0ca77aCAUTIONB81first audit
06

Questions

What is the Affine MCP server?

Model Context Protocol server for AFFiNE. Connect AI assistants to AFFiNE workspaces, documents, databases, and collaboration APIs over stdio or HTTP.

What tools does Affine expose?

107 in total: 45 read-only, 46 that write, and 16 that can delete or overwrite (clear_doc_property, delete_blob, delete_block, delete_collection, delete_comment). Every one is listed on this page with its risk.

Is Affine safe to connect to an agent?

With care. The audit graded it B (81/100) and found 22 things worth knowing before you trust this server, listed below with the exact line each was found on. Separately from the audit: 16 of its tools can destroy data, so scope the token you give it to what you actually need.

What credentials does Affine need?

It reads AFFINE_ADMIN_PASSWORD, AFFINE_MCP_HTTP_ALLOW_QUERY_TOKEN, AFFINE_MCP_HTTP_ALLOW_UNAUTHENTICATED, AFFINE_MCP_HTTP_TOKEN and AFFINE_PASSWORD from the environment. Give it a token scoped to the least it needs — an agent that can be talked into calling a tool can be talked into calling it with your credentials.

How does Affine run?

It speaks sse, stdio and streamable-http, so it runs as a local process your client starts. It is published on npm as affine-mcp-server at 3.9.0.

How current is this page?

The grade is for one exact copy of the source (2d13eb0ca77a), read on 2026-10-06. The repository is watched and re-audited when it changes.

Advertisement