affine-mcp-server 1.12.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # AFFiNE MCP Server
2
2
 
3
- A Model Context Protocol (MCP) server that integrates with AFFiNE (self‑hosted or cloud). It exposes AFFiNE workspaces and documents to AI assistants over stdio (default) or HTTP (`/mcp`).
3
+ 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.
4
4
 
5
- [![Version](https://img.shields.io/badge/version-1.12.0-blue)](https://github.com/dawncr0w/affine-mcp-server/releases)
5
+ [![Version](https://img.shields.io/badge/version-2.0.0-blue)](https://github.com/dawncr0w/affine-mcp-server/releases)
6
6
  [![MCP SDK](https://img.shields.io/badge/MCP%20SDK-1.17.2-green)](https://github.com/modelcontextprotocol/typescript-sdk)
7
7
  [![CI](https://github.com/dawncr0w/affine-mcp-server/actions/workflows/ci.yml/badge.svg)](https://github.com/dawncr0w/affine-mcp-server/actions/workflows/ci.yml)
8
8
  [![License](https://img.shields.io/badge/license-MIT-yellow)](LICENSE)
@@ -11,604 +11,257 @@ A Model Context Protocol (MCP) server that integrates with AFFiNE (self‑hosted
11
11
  <img width="380" height="200" src="https://glama.ai/mcp/servers/@DAWNCR0W/affine-mcp-server/badge" alt="AFFiNE Server MCP server" />
12
12
  </a>
13
13
 
14
- ## Overview
15
-
16
- - Purpose: Manage AFFiNE workspaces and documents through MCP
17
- - Transport: stdio (default) and optional HTTP (`/mcp`) for remote MCP deployments
18
- - Auth: Token, Cookie, or Email/Password (priority order)
19
- - Tools: 76 focused tools with WebSocket-based document editing
20
- - Status: Active
21
-
22
- > New in v1.12.0: Added linked documents on database rows, restored MCP CRUD for rows created in the AFFiNE UI, fixed self-hosted table exports, and documented GHCR Docker releases.
23
-
24
- ## Features
14
+ ## Table of Contents
15
+
16
+ - [Overview](#overview)
17
+ - [Choose Your Path](#choose-your-path)
18
+ - [Quick Start](#quick-start)
19
+ - [Compatibility Matrix](#compatibility-matrix)
20
+ - [Tool Surface](#tool-surface)
21
+ - [Documentation Map](#documentation-map)
22
+ - [Verify Your Setup](#verify-your-setup)
23
+ - [Security and Scope](#security-and-scope)
24
+ - [Development](#development)
25
+ - [Release Notes](#release-notes)
26
+ - [License](#license)
27
+ - [Support](#support)
25
28
 
26
- - Workspace: create (with initial doc), read, update, delete
27
- - Documents: list/get/read/publish/revoke + create/append/replace/delete + markdown import/export + tags (WebSocket‑based)
28
- - Sidebar data: collections, folders, and organize links for AFFiNE workspace trees
29
- - Database workflows: create database blocks, inspect schema, add/update/delete rows, and read or update cell values via MCP tools
30
- - Comments: full CRUD and resolve
31
- - Version History: list
32
- - Users & Tokens: current user, sign in, profile/settings, and personal access tokens
33
- - Notifications: list and mark as read
34
- - Blob storage: upload/delete/cleanup
35
-
36
- ## Requirements
29
+ ## Overview
37
30
 
38
- - Node.js 18+
39
- - An AFFiNE instance (self‑hosted or cloud)
40
- - Valid AFFiNE credentials or access token
31
+ AFFiNE MCP Server is designed for three common scenarios:
32
+ - Run a local stdio MCP server for Claude Code, Codex CLI, Cursor, or Claude Desktop
33
+ - Expose a remote HTTP MCP endpoint for hosted or browser-connected clients
34
+ - Automate AFFiNE workspace, document, database, organization, and comment workflows through a stable MCP tool surface
41
35
 
42
- ## Installation
36
+ Highlights:
43
37
 
44
- ```bash
45
- # Global install (recommended)
46
- npm i -g affine-mcp-server
38
+ - Supports AFFiNE Cloud and self-hosted AFFiNE instances
39
+ - Supports stdio and HTTP transports
40
+ - Supports token, cookie, and email/password authentication
41
+ - Exposes 84 canonical MCP tools backed by AFFiNE GraphQL and WebSocket APIs
42
+ - Includes semantic page composition, native template instantiation, database intent composition, capability and fidelity reporting, and workspace blueprint helpers
43
+ - Includes Docker images, health probes, and end-to-end test coverage
47
44
 
48
- # Or run ad‑hoc via npx (no install)
49
- npx -y -p affine-mcp-server affine-mcp -- --version
50
- ```
45
+ Scope boundaries:
51
46
 
52
- The package installs a CLI named `affine-mcp` that runs the MCP server over stdio.
47
+ - This server can access only server-backed AFFiNE workspaces
48
+ - Browser-local workspaces stored only in local storage are not available through AFFiNE server APIs
49
+ - AFFiNE Cloud requires API-token-based access for MCP usage; programmatic email/password sign-in is blocked by Cloudflare
53
50
 
54
- Note: From v1.2.2+ the CLI wrapper (`bin/affine-mcp`) ensures Node runs the ESM entrypoint, preventing shell from misinterpreting JS.
51
+ > New in v2.0.0: Added native edgeless canvas tools and shipped a slimmer 84-tool public surface with least-privilege profiles for read-only, core, and authoring deployments.
55
52
 
56
- ## Configuration
53
+ ## Choose Your Path
54
+ | Goal | Start here |
55
+ | --- | --- |
56
+ | Set up a local stdio server with the least friction | [docs/getting-started.md](docs/getting-started.md) |
57
+ | Run the server in Docker or another OCI runtime | [docs/getting-started.md#path-c-run-from-the-docker-image](docs/getting-started.md#path-c-run-from-the-docker-image) |
58
+ | Configure Claude Code, Claude Desktop, Codex CLI, or Cursor | [docs/client-setup.md](docs/client-setup.md) |
59
+ | Run the server remotely over HTTP or behind OAuth | [docs/configuration-and-deployment.md](docs/configuration-and-deployment.md) |
60
+ | Lock down tool exposure for least-privilege deployments | [docs/configuration-and-deployment.md#least-privilege-tool-exposure](docs/configuration-and-deployment.md#least-privilege-tool-exposure) |
61
+ | Learn common AFFiNE workflows and tool sequences | [docs/workflow-recipes.md](docs/workflow-recipes.md) |
62
+ | Browse the tool catalog by domain | [docs/tool-reference.md](docs/tool-reference.md) |
57
63
 
58
- ### Interactive login (recommended)
64
+ ## Quick Start
59
65
 
60
- The easiest way to configure credentials:
66
+ ### 1. Install the CLI
61
67
 
62
68
  ```bash
63
69
  npm i -g affine-mcp-server
64
- affine-mcp login
70
+ affine-mcp --version
65
71
  ```
66
72
 
67
- This stores credentials in `~/.config/affine-mcp/config` (mode 600). The MCP server reads them automatically — no environment variables needed.
68
-
69
- **AFFiNE Cloud** (`app.affine.pro`): you'll be prompted to paste an API token from Settings → Integrations → MCP Server.
70
-
71
- **Self-hosted instances**: you can choose between email/password (recommended — auto-generates an API token) or pasting a token manually.
72
-
73
- ```
74
- $ affine-mcp login
75
- Affine MCP Server — Login
76
-
77
- Affine URL [https://app.affine.pro]: https://my-affine.example.com
78
-
79
- Auth method — [1] Email/password (recommended) [2] Paste API token: 1
80
- Email: user@example.com
81
- Password: ****
82
- Signing in...
83
- ✓ Signed in as: User Name <user@example.com>
84
-
85
- Generating API token...
86
- ✓ Created token: ut_abc123... (name: affine-mcp-2026-02-18)
87
-
88
- Detecting workspaces...
89
- Found 1 workspace: abc-def-123 (by User Name, 1 member, 2/10/2026)
90
- Auto-selected.
73
+ You can also run the package ad hoc:
91
74
 
92
- ✓ Saved to /home/user/.config/affine-mcp/config (mode 600)
93
- The MCP server will use these credentials automatically.
75
+ ```bash
76
+ npx -y -p affine-mcp-server affine-mcp -- --version
94
77
  ```
95
78
 
96
- Other CLI commands:
97
- - `affine-mcp --help` / `-h` / `help` — show command help
98
- - `affine-mcp status` — show current config and test connection
99
- - `affine-mcp status --json` — machine-readable status output
100
- - `affine-mcp doctor` — run config and connectivity diagnostics
101
- - `affine-mcp show-config` — print the effective config with secrets redacted
102
- - `affine-mcp config-path` — print the config file path
103
- - `affine-mcp snippet <claude|cursor|codex|all> [--env]` — print ready-to-paste client configuration snippets
104
- - `affine-mcp logout` — remove stored credentials
105
- - `affine-mcp --version` / `-v` / `version` — print the installed CLI version and exit
106
-
107
- Non-interactive login helpers:
108
- - `affine-mcp login --url <url> --token <token> --workspace-id <id> --force`
109
-
110
- ### Environment variables
111
-
112
- You can also configure via environment variables (they override the config file):
113
-
114
- - Required: `AFFINE_BASE_URL`
115
- - Auth (choose one): `AFFINE_API_TOKEN` | `AFFINE_COOKIE` | `AFFINE_EMAIL` + `AFFINE_PASSWORD`
116
- - Optional: `AFFINE_GRAPHQL_PATH` (default `/graphql`), `AFFINE_WORKSPACE_ID`, `AFFINE_LOGIN_AT_START` (set `sync` only when you must block startup)
117
- - Tool filtering: `AFFINE_DISABLED_GROUPS`, `AFFINE_DISABLED_TOOLS` (see [Filtering Exposed Tools](#filtering-exposed-tools))
118
-
119
- Authentication priority:
120
- 1) `AFFINE_API_TOKEN` → 2) `AFFINE_COOKIE` → 3) `AFFINE_EMAIL` + `AFFINE_PASSWORD`
121
-
122
- > **Cloudflare note**: `AFFINE_EMAIL`/`AFFINE_PASSWORD` auth requires programmatic access to `/api/auth/sign-in`. AFFiNE Cloud (`app.affine.pro`) is behind Cloudflare, which blocks these requests. Use `AFFINE_API_TOKEN` for cloud, or use `affine-mcp login` which handles this automatically. Email/password works for self-hosted instances without Cloudflare.
123
-
124
- ## Quick Start
125
-
126
- ### Claude Code
127
-
128
- After running `affine-mcp login`, add to your project's `.mcp.json`:
79
+ ### 2. Or run the server in Docker
129
80
 
130
- ```json
131
- {
132
- "mcpServers": {
133
- "affine": {
134
- "command": "affine-mcp"
135
- }
136
- }
137
- }
81
+ ```bash
82
+ docker run -d \
83
+ -p 3000:3000 \
84
+ -e MCP_TRANSPORT=http \
85
+ -e AFFINE_BASE_URL=https://your-affine-instance.com \
86
+ -e AFFINE_API_TOKEN=ut_your_token \
87
+ -e AFFINE_MCP_AUTH_MODE=bearer \
88
+ -e AFFINE_MCP_HTTP_TOKEN=your-strong-secret \
89
+ ghcr.io/dawncr0w/affine-mcp-server:latest
138
90
  ```
139
91
 
140
- No `env` block needed — the server reads `~/.config/affine-mcp/config` automatically.
141
-
142
- If you prefer explicit env vars instead of the config file:
92
+ Then point your client at:
143
93
 
144
94
  ```json
145
95
  {
146
96
  "mcpServers": {
147
97
  "affine": {
148
- "command": "affine-mcp",
149
- "env": {
150
- "AFFINE_BASE_URL": "https://app.affine.pro",
151
- "AFFINE_API_TOKEN": "ut_xxx"
98
+ "type": "http",
99
+ "url": "http://localhost:3000/mcp",
100
+ "headers": {
101
+ "Authorization": "Bearer your-strong-secret"
152
102
  }
153
103
  }
154
104
  }
155
105
  }
156
106
  ```
157
107
 
158
- ### Claude Desktop
159
-
160
- Add to your Claude Desktop configuration:
161
-
162
- - macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`
163
- - Windows: `%APPDATA%\Claude\claude_desktop_config.json`
164
- - Linux: `~/.config/Claude/claude_desktop_config.json`
165
-
166
- ```json
167
- {
168
- "mcpServers": {
169
- "affine": {
170
- "command": "affine-mcp",
171
- "env": {
172
- "AFFINE_BASE_URL": "https://app.affine.pro",
173
- "AFFINE_API_TOKEN": "ut_xxx"
174
- }
175
- }
176
- }
177
- }
178
- ```
108
+ For Docker, health checks, and remote deployment details, see [docs/configuration-and-deployment.md#docker](docs/configuration-and-deployment.md#docker).
179
109
 
180
- Or with email/password for self-hosted instances (not supported on AFFiNE Cloud — see Cloudflare note above):
110
+ ### 3. Save credentials with interactive login
181
111
 
182
- ```json
183
- {
184
- "mcpServers": {
185
- "affine": {
186
- "command": "affine-mcp",
187
- "env": {
188
- "AFFINE_BASE_URL": "https://your-self-hosted-affine.com",
189
- "AFFINE_EMAIL": "you@example.com",
190
- "AFFINE_PASSWORD": "secret!"
191
- }
192
- }
193
- }
194
- }
112
+ ```bash
113
+ affine-mcp login
195
114
  ```
196
115
 
197
- Tips
198
- - Prefer `affine-mcp login` or `AFFINE_API_TOKEN` for zero‑latency startup.
199
- - If your password contains `!` (zsh history expansion), wrap it in single quotes in shells or use the JSON config above.
200
- - `affine-mcp doctor` is the fastest way to confirm that your saved config still works.
201
- - `affine-mcp snippet claude --env` and `affine-mcp snippet codex --env` can generate ready-to-paste client setup from your current config.
202
- - `affine-mcp snippet all --env` prints Claude, Cursor, and Codex setup in one shot.
203
-
204
- ### Codex CLI
205
-
206
- Register the MCP server with Codex:
116
+ This stores credentials in `~/.config/affine-mcp/config` with mode `600`.
207
117
 
208
- - With config file (after `affine-mcp login`):
209
- - `codex mcp add affine -- affine-mcp`
118
+ - For AFFiNE Cloud, use an API token from `Settings -> Integrations -> MCP Server`
119
+ - For self-hosted AFFiNE, you can use either an API token or email/password
210
120
 
211
- - With API token:
212
- - `codex mcp add affine --env AFFINE_BASE_URL=https://app.affine.pro --env AFFINE_API_TOKEN=ut_xxx -- affine-mcp`
121
+ ### 4. Register the server with your client
213
122
 
214
- - With email/password (self-hosted only):
215
- - `codex mcp add affine --env AFFINE_BASE_URL=https://your-self-hosted-affine.com --env 'AFFINE_EMAIL=you@example.com' --env 'AFFINE_PASSWORD=secret!' -- affine-mcp`
216
-
217
- ### Cursor
218
-
219
- Cursor also supports MCP over stdio with `mcp.json`.
220
-
221
- Project-local (`.cursor/mcp.json`) example:
123
+ Claude Code project config:
222
124
 
223
125
  ```json
224
126
  {
225
127
  "mcpServers": {
226
128
  "affine": {
227
- "command": "affine-mcp",
228
- "env": {
229
- "AFFINE_BASE_URL": "https://app.affine.pro",
230
- "AFFINE_API_TOKEN": "ut_xxx"
231
- }
129
+ "command": "affine-mcp"
232
130
  }
233
131
  }
234
132
  }
235
133
  ```
236
134
 
237
- If you prefer `npx`:
135
+ Codex CLI:
238
136
 
239
- ```json
240
- {
241
- "mcpServers": {
242
- "affine": {
243
- "command": "npx",
244
- "args": ["-y", "-p", "affine-mcp-server", "affine-mcp"],
245
- "env": {
246
- "AFFINE_BASE_URL": "https://app.affine.pro",
247
- "AFFINE_API_TOKEN": "ut_xxx"
248
- }
249
- }
250
- }
251
- }
137
+ ```bash
138
+ codex mcp add affine -- affine-mcp
252
139
  ```
253
140
 
254
- ### Docker
141
+ More client-specific setup is in [docs/client-setup.md](docs/client-setup.md).
255
142
 
256
- Pre-built multi-arch images (`linux/amd64`, `linux/arm64`) are published to the GitHub Container Registry on every release tag:
257
-
258
- ```
259
- ghcr.io/dawncr0w/affine-mcp-server:latest # latest release
260
- ghcr.io/dawncr0w/affine-mcp-server:1.12.0 # specific version
261
- ```
262
-
263
- Quick start:
143
+ ### 5. Verify the connection
264
144
 
265
145
  ```bash
266
- docker run -d \
267
- -p 3000:3000 \
268
- -e AFFINE_BASE_URL=https://your-affine-instance.com \
269
- -e AFFINE_API_TOKEN=ut_your_token \
270
- -e AFFINE_MCP_HTTP_TOKEN=your-strong-secret \
271
- ghcr.io/dawncr0w/affine-mcp-server:latest
146
+ affine-mcp status
147
+ affine-mcp doctor
272
148
  ```
273
149
 
274
- Then add to your MCP client config:
150
+ If you want to expose the server remotely over HTTP instead of stdio, start with [docs/configuration-and-deployment.md](docs/configuration-and-deployment.md).
275
151
 
276
- ```json
277
- {
278
- "mcpServers": {
279
- "affine": {
280
- "type": "http",
281
- "url": "http://localhost:3000/mcp",
282
- "headers": { "Authorization": "Bearer your-strong-secret" }
283
- }
284
- }
285
- }
286
- ```
152
+ ## Compatibility Matrix
287
153
 
288
- The container runs as a non-root user and exposes `/healthz` and `/readyz` for liveness/readiness probes.
154
+ | Target | Transport | Recommended auth | Recommended path |
155
+ | --- | --- | --- | --- |
156
+ | Claude Code | stdio | Saved config or API token | [docs/client-setup.md#claude-code](docs/client-setup.md#claude-code) |
157
+ | Claude Desktop | stdio | Saved config or API token | [docs/client-setup.md#claude-desktop](docs/client-setup.md#claude-desktop) |
158
+ | Codex CLI | stdio | Saved config or API token | [docs/client-setup.md#codex-cli](docs/client-setup.md#codex-cli) |
159
+ | Cursor | stdio | Saved config or API token | [docs/client-setup.md#cursor](docs/client-setup.md#cursor) |
160
+ | Containerized remote deployment | HTTP | Bearer token or OAuth | [docs/getting-started.md#path-c-run-from-the-docker-image](docs/getting-started.md#path-c-run-from-the-docker-image) |
161
+ | Remote MCP clients | HTTP | Bearer token or OAuth | [docs/configuration-and-deployment.md#http-mode](docs/configuration-and-deployment.md#http-mode) |
162
+ | AFFiNE Cloud | stdio or HTTP | API token | [docs/configuration-and-deployment.md#auth-strategy-matrix](docs/configuration-and-deployment.md#auth-strategy-matrix) |
163
+ | Self-hosted AFFiNE | stdio or HTTP | API token, cookie, or email/password | [docs/configuration-and-deployment.md#auth-strategy-matrix](docs/configuration-and-deployment.md#auth-strategy-matrix) |
289
164
 
290
- ### Remote Server
165
+ ## Tool Surface
291
166
 
292
- If you want to host the server remotely (e.g., using Render, Railway, Docker, or a VPS) and connect via HTTP MCP (Streamable HTTP on `/mcp`) instead of local `stdio`, run the server in HTTP mode.
167
+ `tool-manifest.json` is the source of truth for canonical tool names. The MCP server exposes those tools through `tools/list` and `tools/call`.
293
168
 
294
- #### Environment variables (HTTP mode)
169
+ Domains:
295
170
 
296
- Required:
297
- - `MCP_TRANSPORT=http`
298
- - `AFFINE_BASE_URL` (example: `https://app.affine.pro`)
299
- - `AFFINE_MCP_AUTH_MODE=bearer` (default) or `AFFINE_MCP_AUTH_MODE=oauth`
171
+ - Workspace: create, inspect, update, delete, and traverse workspaces
172
+ - Organization: collections, collection-rule sync, workspace blueprints, and experimental organize or folder helpers
173
+ - Documents: search, read, create, publish, move, tag, import/export, semantic composition, template inspection and native instantiation, capability and fidelity reporting, and block-level mutation
174
+ - Databases: create columns, add rows, update rows, inspect schema, and compose database structures from intent
175
+ - Comments: list, create, update, delete, and resolve
176
+ - History: version history listing
177
+ - Users and tokens: current user, sign-in, profile/settings, personal access tokens
178
+ - Notifications: list and mark notifications as read
179
+ - Blob storage: upload, delete, and cleanup blobs
300
180
 
301
- Bearer mode backend auth:
302
- - `AFFINE_API_TOKEN` (recommended), or `AFFINE_COOKIE`, or `AFFINE_EMAIL` + `AFFINE_PASSWORD`
181
+ Use `AFFINE_TOOL_PROFILE=read_only`, `core`, or `authoring` when a deployment should expose a smaller surface than the complete `full` default. You can also combine profiles with `AFFINE_DISABLED_GROUPS` such as `docs.database`, `destructive`, or `admin` for finer control.
303
182
 
304
- OAuth mode backend auth:
305
- - `AFFINE_API_TOKEN` (required service credential for AFFiNE backend access)
183
+ For the grouped catalog, notes, and operational caveats, see [docs/tool-reference.md](docs/tool-reference.md).
306
184
 
307
- Recommended for remote/public deployments:
308
- - `AFFINE_MCP_HTTP_HOST=0.0.0.0`
309
- - `AFFINE_MCP_HTTP_ALLOWED_ORIGINS=<comma-separated-origins>` (for browser clients)
185
+ ## Documentation Map
310
186
 
311
- Optional:
312
- - `PORT` (defaults to `3000`; many platforms like Render inject this automatically)
313
- - `AFFINE_WORKSPACE_ID`
314
- - `AFFINE_GRAPHQL_PATH` (defaults to `/graphql`)
315
- - `AFFINE_MCP_HTTP_ALLOW_ALL_ORIGINS=true` (testing only)
187
+ | Document | Purpose |
188
+ | --- | --- |
189
+ | [docs/getting-started.md](docs/getting-started.md) | First-run setup paths and verification |
190
+ | [docs/client-setup.md](docs/client-setup.md) | Client-specific configuration snippets and tips |
191
+ | [docs/configuration-and-deployment.md](docs/configuration-and-deployment.md) | Environment variables, auth modes, Docker, HTTP mode, and deployment guidance |
192
+ | [docs/workflow-recipes.md](docs/workflow-recipes.md) | End-to-end workflows and example tool sequences |
193
+ | [docs/tool-reference.md](docs/tool-reference.md) | Tool catalog grouped by domain |
194
+ | [docs/edgeless-canvas-cookbook.md](docs/edgeless-canvas-cookbook.md) | Edgeless canvas layout helpers and surface elements, worked end-to-end |
195
+ | [CONTRIBUTING.md](CONTRIBUTING.md) | Contributor workflow |
196
+ | [SECURITY.md](SECURITY.md) | Security reporting |
316
197
 
317
- Bearer-mode only:
318
- - `AFFINE_MCP_HTTP_TOKEN=<strong-random-token>` (protects `/mcp`, `/sse`, `/messages`)
198
+ ## Verify Your Setup
319
199
 
320
- OAuth-mode only:
321
- - `AFFINE_MCP_PUBLIC_BASE_URL=https://mcp.yourdomain.com`
322
- - `AFFINE_OAUTH_ISSUER_URL=https://auth.yourdomain.com`
323
- - `AFFINE_OAUTH_SCOPES=mcp` (defaults to `mcp`)
200
+ Useful CLI commands:
324
201
 
325
- #### HTTP auth modes
202
+ - `affine-mcp status` - test the effective configuration
203
+ - `affine-mcp status --json` - machine-readable status output
204
+ - `affine-mcp doctor` - diagnose config and connectivity issues
205
+ - `affine-mcp show-config` - print the effective config with secrets redacted
206
+ - `affine-mcp config-path` - print the config file path
207
+ - `affine-mcp snippet <claude|cursor|codex|all> [--env]` - generate ready-to-paste client config
208
+ - `affine-mcp logout` - remove stored credentials
326
209
 
327
- `AFFINE_MCP_AUTH_MODE=bearer` keeps the current static bearer-token behavior.
210
+ For common failures, see:
328
211
 
329
- ```bash
330
- export MCP_TRANSPORT=http
331
- export AFFINE_MCP_AUTH_MODE=bearer
332
- export AFFINE_API_TOKEN="your_token..."
333
- export AFFINE_MCP_HTTP_HOST="0.0.0.0"
334
- export AFFINE_MCP_HTTP_TOKEN="your-super-secret-token"
335
- export PORT=3000
336
-
337
- npm run start:http
338
- ```
212
+ - [docs/getting-started.md#common-first-run-failures](docs/getting-started.md#common-first-run-failures)
213
+ - [docs/configuration-and-deployment.md#deployment-checklist](docs/configuration-and-deployment.md#deployment-checklist)
339
214
 
340
- `AFFINE_MCP_AUTH_MODE=oauth` turns the MCP endpoint into an OAuth-protected resource for web MCP clients. In this mode:
341
- - the server exposes `/.well-known/oauth-protected-resource`
342
- - unauthenticated `/mcp` requests return `401` with a `WWW-Authenticate` challenge
343
- - `AFFINE_MCP_HTTP_TOKEN` and `?token=` are disabled
344
- - `sign_in` is not registered
345
- - `AFFINE_API_TOKEN` is still required so the server can call AFFiNE as a service credential
215
+ ## Security and Scope
346
216
 
347
- ```bash
348
- export MCP_TRANSPORT=http
349
- export AFFINE_MCP_AUTH_MODE=oauth
350
- export AFFINE_API_TOKEN="your-affine-service-token"
351
- export AFFINE_MCP_HTTP_HOST="0.0.0.0"
352
- export AFFINE_MCP_PUBLIC_BASE_URL="https://mcp.yourdomain.com"
353
- export AFFINE_OAUTH_ISSUER_URL="https://auth.yourdomain.com"
354
- export AFFINE_OAUTH_SCOPES="mcp"
355
- export PORT=3000
356
-
357
- npm run start:http
358
- ```
217
+ - Never commit secrets or long-lived tokens
218
+ - Prefer API tokens over cookies or passwords in production
219
+ - Use HTTPS for non-local deployments
220
+ - Rotate access tokens regularly
221
+ - Restrict exposed tools with `AFFINE_DISABLED_GROUPS` and `AFFINE_DISABLED_TOOLS` for least-privilege setups
222
+ - Use `/healthz` and `/readyz` when running the HTTP server behind a container platform or load balancer
359
223
 
360
- Notes for OAuth mode:
361
- - use HTTPS for non-local deployments
362
- - `AFFINE_MCP_HTTP_ALLOW_ALL_ORIGINS=true` is rejected in OAuth mode
363
- - tokens are validated against the issuer discovery metadata and JWKS
364
- - the protected resource metadata is also served at `/.well-known/oauth-protected-resource/mcp` for path-specific discovery
365
- - `GET /healthz` and `GET /readyz` are available for deployment diagnostics
366
-
367
- #### Recommended presets
368
-
369
- Local testing (HTTP mode):
370
- - `MCP_TRANSPORT=http`
371
- - `AFFINE_MCP_AUTH_MODE=bearer`
372
- - `AFFINE_MCP_HTTP_HOST=127.0.0.1`
373
- - `AFFINE_MCP_HTTP_TOKEN=<token>` (recommended even locally)
374
- - `AFFINE_MCP_HTTP_ALLOWED_ORIGINS=http://localhost:3000` (if testing from a browser app)
375
-
376
- Docker / container runtime:
377
- - `MCP_TRANSPORT=http`
378
- - `AFFINE_MCP_AUTH_MODE=bearer`
379
- - `AFFINE_MCP_HTTP_HOST=0.0.0.0`
380
- - `PORT=3000` (or container/platform port)
381
- - `AFFINE_MCP_HTTP_TOKEN=<strong-token>`
382
- - `AFFINE_MCP_HTTP_ALLOWED_ORIGINS=<your app origin(s)>`
383
-
384
- Render / Railway / VPS (public endpoint):
385
- - `MCP_TRANSPORT=http`
386
- - `AFFINE_MCP_AUTH_MODE=bearer` or `oauth`
387
- - `AFFINE_MCP_HTTP_HOST=0.0.0.0`
388
- - `AFFINE_MCP_HTTP_TOKEN=<strong-token>` (bearer mode)
389
- - `AFFINE_MCP_PUBLIC_BASE_URL=<public base URL>` (OAuth mode)
390
- - `AFFINE_OAUTH_ISSUER_URL=<issuer URL>` (OAuth mode)
391
- - `AFFINE_MCP_HTTP_ALLOWED_ORIGINS=<your client origin(s)>`
392
-
393
- Endpoints currently available:
394
- - `/mcp` - MCP server (Streamable HTTP)
395
- - `/sse` - SSE endpoint (old protocol compatible)
396
- - `/messages` - Messages endpoint (old protocol compatible)
397
- - `/healthz` - HTTP liveness probe
398
- - `/readyz` - HTTP readiness probe
399
-
400
-
401
- ## Available Tools
402
-
403
- ### Workspace
404
- - `list_workspaces` – list all workspaces
405
- - `get_workspace` – get workspace details
406
- - `create_workspace` – create workspace with initial document
407
- - `update_workspace` – update workspace settings
408
- - `delete_workspace` – delete workspace permanently
409
- - `list_workspace_tree` – return the workspace document hierarchy as a tree
410
- - `get_orphan_docs` – find documents that are not linked from any parent doc in the sidebar tree
411
-
412
- ### Organization
413
- - `list_collections` – list workspace collections
414
- - `get_collection` – get a collection by id
415
- - `create_collection` – create a collection
416
- - `update_collection` – rename a collection
417
- - `delete_collection` – delete a collection
418
- - `add_doc_to_collection` – add a document to a collection allow-list
419
- - `remove_doc_from_collection` – remove a document from a collection allow-list
420
- - `list_organize_nodes` – experimental organize/folder tree dump
421
- - `create_folder` – experimental root or nested folder creation
422
- - `rename_folder` – experimental folder rename
423
- - `delete_folder` – experimental recursive folder delete
424
- - `move_organize_node` – experimental folder/link move
425
- - `add_organize_link` – experimental doc/tag/collection link under a folder
426
- - `delete_organize_link` – experimental doc/tag/collection link delete
427
-
428
-
429
- ### Documents
430
- - `list_docs` – list documents with pagination (includes `node.tags`)
431
- - `list_tags` – list all tags in a workspace
432
- - `search_docs` – fast title search with substring/prefix/exact matching, optional tag filtering, and updatedAt sorting
433
- - `list_docs_by_tag` – list documents that contain the requested tag
434
- - `get_docs_by_tag` – discover documents by case-insensitive tag substring and return `availableTags` when nothing matches
435
- - `get_doc` – get document metadata
436
- - `get_doc_by_title` – find a document by title and return its Markdown content
437
- - `read_doc` – read document block content and plain text snapshot (WebSocket)
438
- - `export_doc_markdown` – export document content as markdown
439
- - `publish_doc` – make document public
440
- - `revoke_doc` – revoke public access
441
- - `create_doc` – create a new document (WebSocket)
442
- - `create_doc_from_markdown` – create a document from markdown content
443
- - `create_doc_from_template` – clone a template doc, substitute `{{variables}}`, and optionally link it under a parent doc
444
- - `duplicate_doc` – clone a document into a new doc, optionally under a parent doc
445
- - `create_tag` – create a reusable workspace-level tag
446
- - `add_tag_to_doc` – attach a tag to a document
447
- - `remove_tag_from_doc` – detach a tag from a document
448
- - `update_doc_title` – rename a document in both workspace metadata and the internal page block
449
- - `append_paragraph` – append a paragraph block (WebSocket)
450
- - `append_block` – append canonical block types (text/list/code/media/embed/database/edgeless) with strict validation and placement control (`viewMode=kanban` enables preset-backed data views; `data_view` defaults to kanban)
451
- - `move_doc` – move a document in the sidebar by relinking it under a different parent
452
- - `batch_create_docs` – create up to 20 documents in a single call
453
- - `add_database_column` – add a column to a database block (`rich-text`, `select`, `multi-select`, `number`, `checkbox`, `link`, `date`)
454
- - `add_database_row` – add a row to a database block with values mapped by column name/ID (`title` / `Title` updates the built-in row title)
455
- - `delete_database_row` – delete a row from a database block by row block id
456
- - `read_database_columns` – read database schema metadata including column IDs/types, select options, and table view column mappings
457
- - `read_database_cells` – read row titles plus decoded database cell values with optional row / column filters
458
- - `update_database_cell` – update a single database cell or the built-in row title (`createOption` defaults to `true` for select fields)
459
- - `update_database_row` – batch update multiple cells on a database row (`createOption` defaults to `true` for select fields)
460
- - `append_markdown` – append markdown content to an existing document
461
- - `replace_doc_with_markdown` – replace the main note content with markdown content
462
- - `list_children` – list the direct child docs linked from a document
463
- - `list_backlinks` – list the parent/reference docs that link to a document
464
- - `cleanup_orphan_embeds` – remove linked-doc embeds that point to missing docs
465
- - `find_and_replace` – preview or apply text replacement across a document
466
- - `delete_doc` – delete a document (WebSocket)
467
-
468
- ### Comments
469
- - `list_comments`, `create_comment`, `update_comment`, `delete_comment`, `resolve_comment`
470
-
471
- ### Version History
472
- - `list_histories`
473
-
474
- ### Users & Tokens
475
- - `current_user`, `sign_in`, `update_profile`, `update_settings`
476
- - `list_access_tokens`, `generate_access_token`, `revoke_access_token`
477
-
478
- ### Notifications
479
- - `list_notifications`, `read_all_notifications`
480
-
481
- ### Blob Storage
482
- - `upload_blob`, `delete_blob`, `cleanup_blobs`
483
-
484
- ## Filtering Exposed Tools
485
-
486
- Optional environment variables to narrow the exposed surface.
487
-
488
- ### Group-level — `AFFINE_DISABLED_GROUPS`
489
-
490
- | Group name | Tools included |
491
- |---|---|
492
- | `workspaces` | `list_workspaces`, `get_workspace`, `create_workspace`, `update_workspace`, `delete_workspace` |
493
- | `docs` | `list_docs`, `read_doc`, `search_docs`, `create_doc`, `create_doc_from_markdown`, `create_doc_from_template`, `duplicate_doc`, `append_paragraph`, `append_block`, `append_markdown`, `replace_doc_with_markdown`, `delete_doc`, `publish_doc`, `revoke_doc`, `list_tags`, `list_docs_by_tag`, `create_tag`, `add_tag_to_doc`, `remove_tag_from_doc`, `list_workspace_tree`, `get_orphan_docs`, `list_children`, `update_doc_title`, `get_doc_by_title`, `get_docs_by_tag`, `list_backlinks`, `move_doc`, `batch_create_docs`, `cleanup_orphan_embeds`, `find_and_replace`, `add_database_column`, `add_database_row`, `delete_database_row`, `read_database_columns`, `read_database_cells`, `update_database_cell`, `update_database_row` |
494
- | `comments` | `list_comments`, `create_comment`, `update_comment`, `delete_comment`, `resolve_comment` |
495
- | `history` | `list_histories` |
496
- | `organize` | `list_collections`, `get_collection`, `create_collection`, `update_collection`, `delete_collection`, `add_doc_to_collection`, `remove_doc_from_collection`, `list_organize_nodes`, `create_folder`, `rename_folder`, `delete_folder`, `move_organize_node`, `add_organize_link`, `delete_organize_link` |
497
- | `users` | `current_user`, `sign_in`, `update_profile`, `update_settings` |
498
- | `access_tokens` | `list_access_tokens`, `generate_access_token`, `revoke_access_token` |
499
- | `blobs` | `upload_blob`, `delete_blob`, `cleanup_blobs` |
500
- | `notifications` | `list_notifications`, `read_all_notifications` |
224
+ ## Development
501
225
 
502
- ```json
503
- "env": {
504
- "AFFINE_DISABLED_GROUPS": "comments,history,blobs,users"
505
- }
506
- ```
226
+ Run the main quality gates before opening a PR:
507
227
 
508
- ### Tool-level — `AFFINE_DISABLED_TOOLS`
228
+ ```bash
229
+ npm run build
230
+ npm run test:tool-manifest
231
+ npm run pack:check
232
+ ```
509
233
 
510
- Disables individual tools by exact name (comma-separated).
234
+ Additional validation:
511
235
 
512
- ```json
513
- "env": {
514
- "AFFINE_DISABLED_TOOLS": "delete_workspace,delete_doc"
515
- }
516
- ```
236
+ - `npm run test:comprehensive` boots a local Docker AFFiNE stack and validates the tool surface
237
+ - `npm run test:e2e` runs Docker, MCP, and Playwright together
238
+ - `npm run test:playwright` runs the Playwright suite only
239
+ - Focused runners for the new high-level tool surface include `npm run test:create-placement`, `npm run test:capabilities-fidelity`, `npm run test:native-template`, `node tests/test-database-intent.mjs`, `node tests/test-semantic-page-composer.mjs`, `node tests/test-structured-receipts.mjs`, `node tests/test-organize-tools.mjs`, and `node tests/test-supporting-tools.mjs`
517
240
 
518
- ## Use Locally (clone)
241
+ Local clone flow:
519
242
 
520
243
  ```bash
521
244
  git clone https://github.com/dawncr0w/affine-mcp-server.git
522
245
  cd affine-mcp-server
523
246
  npm install
524
247
  npm run build
525
- # Run directly
526
248
  node dist/index.js
527
-
528
- # Or expose as a global CLI for Codex/Claude without publishing
529
- npm link
530
- # Now use `affine-mcp` like a global binary
531
- ```
532
-
533
- ## Quality Gates
534
-
535
- ```bash
536
- npm run build
537
- npm run test:tool-manifest
538
- npm run pack:check
539
249
  ```
540
250
 
541
- - `tool-manifest.json` is the source of truth for publicly exposed tool names.
542
- - CI validates that `registerTool(...)` declarations match the manifest exactly.
543
- - For full tool-surface verification, run `npm run test:comprehensive` (self-bootstraps a local Docker AFFiNE stack).
544
- - For pre-provisioned environments, use `npm run test:comprehensive:raw`.
545
- - For full environment verification, run `npm run test:e2e` (Docker + MCP + Playwright).
546
- - Additional focused runners: `npm run test:db-create`, `npm run test:db-cells`, `npm run test:db-schema`, `npm run test:supporting-tools`, `npm run test:organize`, `npm run test:bearer`, `npm run test:http-email-password`, `npm run test:http-bearer`, `npm run test:oauth-http`, `npm run test:doc-discovery`, `npm run test:cli-version`, `npm run test:cli-commands`, `npm run test:cli-live`, `npm run test:tool-filtering`, `npm run test:markdown-rich-text-import`, `npm run test:playwright`.
547
-
548
- ## Troubleshooting
549
-
550
- Authentication
551
- - **Cloudflare (403 "Just a moment...")**: AFFiNE Cloud (`app.affine.pro`) uses Cloudflare protection, which blocks programmatic sign-in via `/api/auth/sign-in`. Use `AFFINE_API_TOKEN` instead, or run `affine-mcp login` which guides you through the right method automatically. Email/password auth only works for self-hosted instances.
552
- - Email/Password: only works on self-hosted instances without Cloudflare. Ensure your instance allows password auth and credentials are valid.
553
- - Cookie: copy cookies (e.g., `affine_session`, `affine_csrf`) from the browser DevTools after login
554
- - Token: generate a personal access token; verify it hasn't expired. Run `affine-mcp status` to test.
555
- - Startup timeouts: v1.2.2+ includes a CLI wrapper fix and default async login to avoid blocking the MCP handshake. Set `AFFINE_LOGIN_AT_START=sync` only if needed.
556
-
557
- Connection
558
- - Confirm `AFFINE_BASE_URL` is reachable
559
- - GraphQL endpoint default is `/graphql`
560
- - Check firewall/proxy rules; verify CORS if self‑hosted
561
-
562
- Method not found
563
- - MCP tool names (for example `list_workspaces`) are not JSON-RPC top-level method names.
564
- - Use an MCP client (`tools/list`, `tools/call`) instead of sending direct JSON-RPC calls like `{\"method\":\"list_workspaces\"}`.
565
- - From v1.3.0, only canonical tool names are exposed (legacy `affine_*` aliases were removed).
566
-
567
- Workspace visibility
568
- - This MCP server can access server-backed workspaces only (AFFiNE cloud/self-hosted).
569
- - Browser local-storage workspaces are client-side data, so they are not visible via server GraphQL/WebSocket APIs.
570
-
571
- ## Security Considerations
572
-
573
- - Never commit `.env` with secrets
574
- - Prefer environment variables in production
575
- - Rotate access tokens regularly
576
- - Use HTTPS
577
- - Store credentials in a secrets manager
578
-
579
251
  ## Release Notes
580
252
 
581
- - Changelog: [CHANGELOG.md](CHANGELOG.md)
582
- - Release notes: [RELEASE_NOTES.md](RELEASE_NOTES.md)
583
- - GitHub Releases: [Releases](https://github.com/dawncr0w/affine-mcp-server/releases)
584
-
585
- ## Contributing
586
-
587
- Contributions are welcome!
588
- 1. Read `CONTRIBUTING.md`
589
- 2. Run `npm run ci` locally before opening PR
590
- 3. Keep tool changes synced with `tool-manifest.json`
591
- 4. Use issue/PR templates in `.github/`
592
-
593
- ## Community Health
594
-
595
- - Code of Conduct: `CODE_OF_CONDUCT.md`
596
- - Security policy: `SECURITY.md`
597
- - Contributing guide: `CONTRIBUTING.md`
253
+ - [CHANGELOG.md](CHANGELOG.md)
254
+ - [RELEASE_NOTES.md](RELEASE_NOTES.md)
255
+ - [GitHub Releases](https://github.com/dawncr0w/affine-mcp-server/releases)
598
256
 
599
257
  ## License
600
258
 
601
- MIT License - see LICENSE file for details
259
+ MIT License - see [LICENSE](LICENSE).
602
260
 
603
261
  ## Support
604
262
 
605
- For issues and questions:
606
263
  - Open an issue on [GitHub](https://github.com/dawncr0w/affine-mcp-server/issues)
607
- - Check AFFiNE documentation at https://docs.affine.pro
608
-
609
- ## Author
610
-
611
- **dawncr0w** - [GitHub](https://github.com/dawncr0w)
264
+ - Review AFFiNE product documentation at [docs.affine.pro](https://docs.affine.pro)
612
265
 
613
266
  ## Acknowledgments
614
267