affine-mcp-server 1.12.0 → 1.13.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 +152 -500
- package/dist/markdown/parse.js +51 -10
- package/dist/tools/comments.js +82 -5
- package/dist/tools/docs.js +1644 -76
- package/dist/tools/organize.js +419 -42
- package/dist/tools/workspaces.js +25 -6
- package/dist/util/mcp.js +26 -2
- package/docs/client-setup.md +174 -0
- package/docs/configuration-and-deployment.md +208 -0
- package/docs/getting-started.md +229 -0
- package/docs/tool-reference.md +171 -0
- package/docs/workflow-recipes.md +147 -0
- package/package.json +7 -2
- package/tool-manifest.json +92 -0
package/README.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# AFFiNE MCP Server
|
|
2
2
|
|
|
3
|
-
A Model Context Protocol (MCP) server
|
|
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
|
-
[](https://github.com/dawncr0w/affine-mcp-server/releases)
|
|
6
6
|
[](https://github.com/modelcontextprotocol/typescript-sdk)
|
|
7
7
|
[](https://github.com/dawncr0w/affine-mcp-server/actions/workflows/ci.yml)
|
|
8
8
|
[](LICENSE)
|
|
@@ -11,604 +11,256 @@ 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
|
+
## 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)
|
|
28
|
+
|
|
14
29
|
## Overview
|
|
15
30
|
|
|
16
|
-
|
|
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.
|
|
31
|
+
AFFiNE MCP Server is designed for three common scenarios:
|
|
23
32
|
|
|
24
|
-
|
|
33
|
+
- Run a local stdio MCP server for Claude Code, Codex CLI, Cursor, or Claude Desktop
|
|
34
|
+
- Expose a remote HTTP MCP endpoint for hosted or browser-connected clients
|
|
35
|
+
- Automate AFFiNE workspace, document, database, organization, and comment workflows through a stable MCP tool surface
|
|
25
36
|
|
|
26
|
-
|
|
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
|
|
37
|
+
Highlights:
|
|
35
38
|
|
|
36
|
-
|
|
39
|
+
- Supports AFFiNE Cloud and self-hosted AFFiNE instances
|
|
40
|
+
- Supports stdio and HTTP transports
|
|
41
|
+
- Supports token, cookie, and email/password authentication
|
|
42
|
+
- Exposes 87 canonical MCP tools backed by AFFiNE GraphQL and WebSocket APIs
|
|
43
|
+
- Includes semantic page composition, native template instantiation, database intent composition, capability and fidelity reporting, and workspace blueprint helpers
|
|
44
|
+
- Includes Docker images, health probes, and end-to-end test coverage
|
|
37
45
|
|
|
38
|
-
|
|
39
|
-
- An AFFiNE instance (self‑hosted or cloud)
|
|
40
|
-
- Valid AFFiNE credentials or access token
|
|
46
|
+
Scope boundaries:
|
|
41
47
|
|
|
42
|
-
|
|
48
|
+
- This server can access only server-backed AFFiNE workspaces
|
|
49
|
+
- Browser-local workspaces stored only in local storage are not available through AFFiNE server APIs
|
|
50
|
+
- AFFiNE Cloud requires API-token-based access for MCP usage; programmatic email/password sign-in is blocked by Cloudflare
|
|
43
51
|
|
|
44
|
-
|
|
45
|
-
# Global install (recommended)
|
|
46
|
-
npm i -g affine-mcp-server
|
|
52
|
+
> New in v1.13.0: Added high-level semantic page, native template, fidelity, and workspace blueprint workflows, plus structured receipts and productized setup docs.
|
|
47
53
|
|
|
48
|
-
|
|
49
|
-
npx -y -p affine-mcp-server affine-mcp -- --version
|
|
50
|
-
```
|
|
54
|
+
## Choose Your Path
|
|
51
55
|
|
|
52
|
-
|
|
56
|
+
| Goal | Start here |
|
|
57
|
+
| --- | --- |
|
|
58
|
+
| Set up a local stdio server with the least friction | [docs/getting-started.md](docs/getting-started.md) |
|
|
59
|
+
| 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) |
|
|
60
|
+
| Configure Claude Code, Claude Desktop, Codex CLI, or Cursor | [docs/client-setup.md](docs/client-setup.md) |
|
|
61
|
+
| Run the server remotely over HTTP or behind OAuth | [docs/configuration-and-deployment.md](docs/configuration-and-deployment.md) |
|
|
62
|
+
| 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) |
|
|
63
|
+
| Learn common AFFiNE workflows and tool sequences | [docs/workflow-recipes.md](docs/workflow-recipes.md) |
|
|
64
|
+
| Browse the tool catalog by domain | [docs/tool-reference.md](docs/tool-reference.md) |
|
|
53
65
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
## Configuration
|
|
57
|
-
|
|
58
|
-
### Interactive login (recommended)
|
|
66
|
+
## Quick Start
|
|
59
67
|
|
|
60
|
-
|
|
68
|
+
### 1. Install the CLI
|
|
61
69
|
|
|
62
70
|
```bash
|
|
63
71
|
npm i -g affine-mcp-server
|
|
64
|
-
affine-mcp
|
|
72
|
+
affine-mcp --version
|
|
65
73
|
```
|
|
66
74
|
|
|
67
|
-
|
|
75
|
+
You can also run the package ad hoc:
|
|
68
76
|
|
|
69
|
-
|
|
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.
|
|
91
|
-
|
|
92
|
-
✓ Saved to /home/user/.config/affine-mcp/config (mode 600)
|
|
93
|
-
The MCP server will use these credentials automatically.
|
|
77
|
+
```bash
|
|
78
|
+
npx -y -p affine-mcp-server affine-mcp -- --version
|
|
94
79
|
```
|
|
95
80
|
|
|
96
|
-
|
|
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`:
|
|
81
|
+
### 2. Or run the server in Docker
|
|
129
82
|
|
|
130
|
-
```
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
83
|
+
```bash
|
|
84
|
+
docker run -d \
|
|
85
|
+
-p 3000:3000 \
|
|
86
|
+
-e MCP_TRANSPORT=http \
|
|
87
|
+
-e AFFINE_BASE_URL=https://your-affine-instance.com \
|
|
88
|
+
-e AFFINE_API_TOKEN=ut_your_token \
|
|
89
|
+
-e AFFINE_MCP_AUTH_MODE=bearer \
|
|
90
|
+
-e AFFINE_MCP_HTTP_TOKEN=your-strong-secret \
|
|
91
|
+
ghcr.io/dawncr0w/affine-mcp-server:latest
|
|
138
92
|
```
|
|
139
93
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
If you prefer explicit env vars instead of the config file:
|
|
94
|
+
Then point your client at:
|
|
143
95
|
|
|
144
96
|
```json
|
|
145
97
|
{
|
|
146
98
|
"mcpServers": {
|
|
147
99
|
"affine": {
|
|
148
|
-
"
|
|
149
|
-
"
|
|
150
|
-
|
|
151
|
-
"
|
|
100
|
+
"type": "http",
|
|
101
|
+
"url": "http://localhost:3000/mcp",
|
|
102
|
+
"headers": {
|
|
103
|
+
"Authorization": "Bearer your-strong-secret"
|
|
152
104
|
}
|
|
153
105
|
}
|
|
154
106
|
}
|
|
155
107
|
}
|
|
156
108
|
```
|
|
157
109
|
|
|
158
|
-
|
|
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
|
-
```
|
|
110
|
+
For Docker, health checks, and remote deployment details, see [docs/configuration-and-deployment.md#docker](docs/configuration-and-deployment.md#docker).
|
|
179
111
|
|
|
180
|
-
|
|
112
|
+
### 3. Save credentials with interactive login
|
|
181
113
|
|
|
182
|
-
```
|
|
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
|
-
}
|
|
114
|
+
```bash
|
|
115
|
+
affine-mcp login
|
|
195
116
|
```
|
|
196
117
|
|
|
197
|
-
|
|
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:
|
|
207
|
-
|
|
208
|
-
- With config file (after `affine-mcp login`):
|
|
209
|
-
- `codex mcp add affine -- affine-mcp`
|
|
118
|
+
This stores credentials in `~/.config/affine-mcp/config` with mode `600`.
|
|
210
119
|
|
|
211
|
-
-
|
|
212
|
-
|
|
120
|
+
- For AFFiNE Cloud, use an API token from `Settings -> Integrations -> MCP Server`
|
|
121
|
+
- For self-hosted AFFiNE, you can use either an API token or email/password
|
|
213
122
|
|
|
214
|
-
|
|
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`
|
|
123
|
+
### 4. Register the server with your client
|
|
216
124
|
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
Cursor also supports MCP over stdio with `mcp.json`.
|
|
220
|
-
|
|
221
|
-
Project-local (`.cursor/mcp.json`) example:
|
|
125
|
+
Claude Code project config:
|
|
222
126
|
|
|
223
127
|
```json
|
|
224
128
|
{
|
|
225
129
|
"mcpServers": {
|
|
226
130
|
"affine": {
|
|
227
|
-
"command": "affine-mcp"
|
|
228
|
-
"env": {
|
|
229
|
-
"AFFINE_BASE_URL": "https://app.affine.pro",
|
|
230
|
-
"AFFINE_API_TOKEN": "ut_xxx"
|
|
231
|
-
}
|
|
131
|
+
"command": "affine-mcp"
|
|
232
132
|
}
|
|
233
133
|
}
|
|
234
134
|
}
|
|
235
135
|
```
|
|
236
136
|
|
|
237
|
-
|
|
137
|
+
Codex CLI:
|
|
238
138
|
|
|
239
|
-
```
|
|
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
|
-
}
|
|
139
|
+
```bash
|
|
140
|
+
codex mcp add affine -- affine-mcp
|
|
252
141
|
```
|
|
253
142
|
|
|
254
|
-
|
|
143
|
+
More client-specific setup is in [docs/client-setup.md](docs/client-setup.md).
|
|
255
144
|
|
|
256
|
-
|
|
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:
|
|
145
|
+
### 5. Verify the connection
|
|
264
146
|
|
|
265
147
|
```bash
|
|
266
|
-
|
|
267
|
-
|
|
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
|
|
148
|
+
affine-mcp status
|
|
149
|
+
affine-mcp doctor
|
|
272
150
|
```
|
|
273
151
|
|
|
274
|
-
|
|
152
|
+
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
153
|
|
|
276
|
-
|
|
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
|
-
```
|
|
154
|
+
## Compatibility Matrix
|
|
287
155
|
|
|
288
|
-
|
|
156
|
+
| Target | Transport | Recommended auth | Recommended path |
|
|
157
|
+
| --- | --- | --- | --- |
|
|
158
|
+
| Claude Code | stdio | Saved config or API token | [docs/client-setup.md#claude-code](docs/client-setup.md#claude-code) |
|
|
159
|
+
| Claude Desktop | stdio | Saved config or API token | [docs/client-setup.md#claude-desktop](docs/client-setup.md#claude-desktop) |
|
|
160
|
+
| Codex CLI | stdio | Saved config or API token | [docs/client-setup.md#codex-cli](docs/client-setup.md#codex-cli) |
|
|
161
|
+
| Cursor | stdio | Saved config or API token | [docs/client-setup.md#cursor](docs/client-setup.md#cursor) |
|
|
162
|
+
| 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) |
|
|
163
|
+
| Remote MCP clients | HTTP | Bearer token or OAuth | [docs/configuration-and-deployment.md#http-mode](docs/configuration-and-deployment.md#http-mode) |
|
|
164
|
+
| AFFiNE Cloud | stdio or HTTP | API token | [docs/configuration-and-deployment.md#auth-strategy-matrix](docs/configuration-and-deployment.md#auth-strategy-matrix) |
|
|
165
|
+
| 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
166
|
|
|
290
|
-
|
|
167
|
+
## Tool Surface
|
|
291
168
|
|
|
292
|
-
|
|
169
|
+
`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
170
|
|
|
294
|
-
|
|
171
|
+
Domains:
|
|
295
172
|
|
|
296
|
-
|
|
297
|
-
-
|
|
298
|
-
-
|
|
299
|
-
-
|
|
173
|
+
- Workspace: create, inspect, update, delete, and traverse workspaces
|
|
174
|
+
- Organization: collections, collection-rule sync, workspace blueprints, and experimental organize or folder helpers
|
|
175
|
+
- Documents: search, read, create, publish, move, tag, import/export, semantic composition, template inspection and native instantiation, capability and fidelity reporting, and text mutation
|
|
176
|
+
- Databases: create columns, add rows, update cells, inspect schema, and compose database structures from intent
|
|
177
|
+
- Comments: list, create, update, delete, resolve, and list unresolved threads
|
|
178
|
+
- History: version history listing
|
|
179
|
+
- Users and tokens: current user, sign-in, profile/settings, personal access tokens
|
|
180
|
+
- Notifications: list and mark notifications as read
|
|
181
|
+
- Blob storage: upload, delete, and cleanup blobs
|
|
300
182
|
|
|
301
|
-
|
|
302
|
-
- `AFFINE_API_TOKEN` (recommended), or `AFFINE_COOKIE`, or `AFFINE_EMAIL` + `AFFINE_PASSWORD`
|
|
183
|
+
For the grouped catalog, notes, and operational caveats, see [docs/tool-reference.md](docs/tool-reference.md).
|
|
303
184
|
|
|
304
|
-
|
|
305
|
-
- `AFFINE_API_TOKEN` (required service credential for AFFiNE backend access)
|
|
185
|
+
## Documentation Map
|
|
306
186
|
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
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
|
+
| [CONTRIBUTING.md](CONTRIBUTING.md) | Contributor workflow |
|
|
195
|
+
| [SECURITY.md](SECURITY.md) | Security reporting |
|
|
310
196
|
|
|
311
|
-
|
|
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)
|
|
197
|
+
## Verify Your Setup
|
|
316
198
|
|
|
317
|
-
|
|
318
|
-
- `AFFINE_MCP_HTTP_TOKEN=<strong-random-token>` (protects `/mcp`, `/sse`, `/messages`)
|
|
199
|
+
Useful CLI commands:
|
|
319
200
|
|
|
320
|
-
|
|
321
|
-
- `
|
|
322
|
-
- `
|
|
323
|
-
- `
|
|
201
|
+
- `affine-mcp status` - test the effective configuration
|
|
202
|
+
- `affine-mcp status --json` - machine-readable status output
|
|
203
|
+
- `affine-mcp doctor` - diagnose config and connectivity issues
|
|
204
|
+
- `affine-mcp show-config` - print the effective config with secrets redacted
|
|
205
|
+
- `affine-mcp config-path` - print the config file path
|
|
206
|
+
- `affine-mcp snippet <claude|cursor|codex|all> [--env]` - generate ready-to-paste client config
|
|
207
|
+
- `affine-mcp logout` - remove stored credentials
|
|
324
208
|
|
|
325
|
-
|
|
209
|
+
For common failures, see:
|
|
326
210
|
|
|
327
|
-
|
|
211
|
+
- [docs/getting-started.md#common-first-run-failures](docs/getting-started.md#common-first-run-failures)
|
|
212
|
+
- [docs/configuration-and-deployment.md#deployment-checklist](docs/configuration-and-deployment.md#deployment-checklist)
|
|
328
213
|
|
|
329
|
-
|
|
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
|
-
```
|
|
214
|
+
## Security and Scope
|
|
339
215
|
|
|
340
|
-
|
|
341
|
-
-
|
|
342
|
-
-
|
|
343
|
-
-
|
|
344
|
-
- `
|
|
345
|
-
- `
|
|
216
|
+
- Never commit secrets or long-lived tokens
|
|
217
|
+
- Prefer API tokens over cookies or passwords in production
|
|
218
|
+
- Use HTTPS for non-local deployments
|
|
219
|
+
- Rotate access tokens regularly
|
|
220
|
+
- Restrict exposed tools with `AFFINE_DISABLED_GROUPS` and `AFFINE_DISABLED_TOOLS` for least-privilege setups
|
|
221
|
+
- Use `/healthz` and `/readyz` when running the HTTP server behind a container platform or load balancer
|
|
346
222
|
|
|
347
|
-
|
|
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
|
-
```
|
|
223
|
+
## Development
|
|
359
224
|
|
|
360
|
-
|
|
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` |
|
|
225
|
+
Run the main quality gates before opening a PR:
|
|
501
226
|
|
|
502
|
-
```
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
227
|
+
```bash
|
|
228
|
+
npm run build
|
|
229
|
+
npm run test:tool-manifest
|
|
230
|
+
npm run pack:check
|
|
506
231
|
```
|
|
507
232
|
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
Disables individual tools by exact name (comma-separated).
|
|
233
|
+
Additional validation:
|
|
511
234
|
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
```
|
|
235
|
+
- `npm run test:comprehensive` boots a local Docker AFFiNE stack and validates the tool surface
|
|
236
|
+
- `npm run test:e2e` runs Docker, MCP, and Playwright together
|
|
237
|
+
- `npm run test:playwright` runs the Playwright suite only
|
|
238
|
+
- 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
239
|
|
|
518
|
-
|
|
240
|
+
Local clone flow:
|
|
519
241
|
|
|
520
242
|
```bash
|
|
521
243
|
git clone https://github.com/dawncr0w/affine-mcp-server.git
|
|
522
244
|
cd affine-mcp-server
|
|
523
245
|
npm install
|
|
524
246
|
npm run build
|
|
525
|
-
# Run directly
|
|
526
247
|
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
248
|
```
|
|
532
249
|
|
|
533
|
-
## Quality Gates
|
|
534
|
-
|
|
535
|
-
```bash
|
|
536
|
-
npm run build
|
|
537
|
-
npm run test:tool-manifest
|
|
538
|
-
npm run pack:check
|
|
539
|
-
```
|
|
540
|
-
|
|
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
250
|
## Release Notes
|
|
580
251
|
|
|
581
|
-
-
|
|
582
|
-
-
|
|
583
|
-
- GitHub 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`
|
|
252
|
+
- [CHANGELOG.md](CHANGELOG.md)
|
|
253
|
+
- [RELEASE_NOTES.md](RELEASE_NOTES.md)
|
|
254
|
+
- [GitHub Releases](https://github.com/dawncr0w/affine-mcp-server/releases)
|
|
598
255
|
|
|
599
256
|
## License
|
|
600
257
|
|
|
601
|
-
MIT License - see LICENSE
|
|
258
|
+
MIT License - see [LICENSE](LICENSE).
|
|
602
259
|
|
|
603
260
|
## Support
|
|
604
261
|
|
|
605
|
-
For issues and questions:
|
|
606
262
|
- Open an issue on [GitHub](https://github.com/dawncr0w/affine-mcp-server/issues)
|
|
607
|
-
-
|
|
608
|
-
|
|
609
|
-
## Author
|
|
610
|
-
|
|
611
|
-
**dawncr0w** - [GitHub](https://github.com/dawncr0w)
|
|
263
|
+
- Review AFFiNE product documentation at [docs.affine.pro](https://docs.affine.pro)
|
|
612
264
|
|
|
613
265
|
## Acknowledgments
|
|
614
266
|
|