- name
- affine-mcp-server-integration
- description
- Connect AI assistants to AFFiNE workspaces, documents, databases, and collaboration APIs using the Model Context Protocol.
- triggers
- ["connect to my AFFiNE workspace","set up AFFiNE MCP server","configure MCP for AFFiNE Cloud","create and manage AFFiNE documents with AI","integrate Claude with AFFiNE","access my AFFiNE knowledge base","use AFFiNE database with MCP","deploy AFFiNE MCP server"]
# AFFiNE MCP Server Integration
> Skill by [ara.so](https://ara.so) — MCP Skills collection.
## Overview
AFFiNE MCP Server is a Model Context Protocol server that exposes AFFiNE workspaces, documents, databases, and collaboration features to AI assistants. It supports both AFFiNE Cloud and self-hosted deployments, offering 85+ tools across workspace management, document operations, database manipulation, and organizational features.
**Key capabilities:**
- Connect AI assistants (Claude Code, Cursor, Codex CLI, Claude Desktop) to AFFiNE
- Read, create, update, and delete documents programmatically
- Manage databases, collections, and organizational structures
- Access via stdio (local) or HTTP (remote) transports
- Semantic page composition and template instantiation
- Block-level document mutation and structured data handling
## Installation
### Global CLI Installation
```bash
# Install globally via npm
npm i -g affine-mcp-server
# Verify installation
affine-mcp --version
```
### Ad-hoc Execution
```bash
# Run without installing
npx -y -p affine-mcp-server affine-mcp -- --version
```
### Docker Deployment
```bash
# Pull the official image
docker pull ghcr.io/dawncr0w/affine-mcp-server:latest
# Run with environment variables
docker run -d \
-p 3000:3000 \
-e MCP_TRANSPORT=http \
-e AFFINE_BASE_URL=https://app.affine.pro \
-e AFFINE_API_TOKEN=${AFFINE_API_TOKEN} \
-e AFFINE_MCP_AUTH_MODE=bearer \
-e AFFINE_MCP_HTTP_TOKEN=${MCP_HTTP_TOKEN} \
ghcr.io/dawncr0w/affine-mcp-server:latest
```
## Authentication Setup
### Interactive Login (Recommended for Local Use)
```bash
# Store credentials securely (~/.config/affine-mcp/config with mode 600)
affine-mcp login
# Interactive prompts will ask for:
# - AFFiNE base URL (default: https://app.affine.pro)
# - Authentication method (token, cookie, or email/password)
# - Credentials
```
### Environment Variables
```bash
# For AFFiNE Cloud (token required)
export AFFINE_BASE_URL=https://app.affine.pro
export AFFINE_API_TOKEN=ut_your_token_here
# For self-hosted with email/password
export AFFINE_BASE_URL=https://your-affine-instance.com
export AFFINE_EMAIL=user@example.com
export AFFINE_PASSWORD=${AFFINE_PASSWORD}
# For self-hosted with cookie
export AFFINE_BASE_URL=https://your-affine-instance.com
export AFFINE_COOKIE=${AFFINE_COOKIE}
```
### Getting an API Token
**AFFiNE Cloud:**
1. Sign in to https://app.affine.pro
2. Go to Settings → Integrations → MCP Server
3. Generate an API token
**Self-hosted:**
1. Sign in to your AFFiNE instance
2. Navigate to Settings → Account → Personal Access Tokens
3. Create a new token with appropriate scopes
## Client Configuration
### Claude Code
Add to your `.claude/project_config.json`:
```json
{
"mcpServers": {
"affine": {
"command": "affine-mcp"
}
}
}
```
Or with explicit environment variables:
```json
{
"mcpServers": {
"affine": {
"command": "affine-mcp",
"env": {
"AFFINE_BASE_URL": "https://app.affine.pro",
"AFFINE_API_TOKEN": "${AFFINE_API_TOKEN}"
}
}
}
}
```
### Claude Desktop
Add to `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS):
```json
{
"mcpServers": {
"affine": {
"command": "affine-mcp"
}
}
}
```
### Cursor
Add to `~/.cursor/mcp_config.json`:
```json
{
"mcpServers": {
"affine": {
"command": "affine-mcp"
}
}
}
```
### Codex CLI
```bash
# Add the server
codex mcp add affine -- affine-mcp
# Verify
codex mcp list
```
### HTTP Mode (Remote Deployment)
Client configuration:
```json
{
"mcpServers": {
"affine": {
"type": "http",
"url": "https://your-mcp-server.com/mcp",
"headers": {
"Authorization": "Bearer ${MCP_HTTP_TOKEN}"
}
}
}
}
```
Server environment:
```bash
export MCP_TRANSPORT=http
export MCP_HTTP_PORT=3000
export AFFINE_MCP_AUTH_MODE=bearer
export AFFINE_MCP_HTTP_TOKEN=${MCP_HTTP_TOKEN}
```
## CLI Commands
### Configuration Management
```bash
# Show current configuration (secrets redacted)
affine-mcp show-config
# Get config file path
affine-mcp config-path
# Generate client configuration snippets
affine-mcp snippet claude
affine-mcp snippet cursor
affine-mcp snippet codex
affine-mcp snippet all
# Generate with environment variables
affine-mcp snippet claude --env
# Logout (remove stored credentials)
affine-mcp logout
```
### Health Checks
```bash
# Test effective configuration
affine-mcp status
# Machine-readable status
affine-mcp status --json
# Diagnose configuration and connectivity
affine-mcp doctor
```
### Running the Server
```bash
# Start stdio server (default)
affine-mcp
# Start HTTP server
MCP_TRANSPORT=http MCP_HTTP_PORT=3000 affine-mcp
# With custom log level
LOG_LEVEL=debug affine-mcp
```
## Tool Surface Overview
The server exposes 85 tools organized by domain:
### Workspace Tools
```typescript
// List all workspaces
list_workspaces()
// Get workspace details
get_workspace({ workspaceId: "workspace-id" })
// Create workspace
create_workspace({
name: "My New Workspace",
description: "Project workspace"
})
// Update workspace
update_workspace({
workspaceId: "workspace-id",
name: "Updated Name"
})
// Delete workspace
delete_workspace({ workspaceId: "workspace-id" })
```
### Document Tools
```typescript
// Search documents
search_docs({
workspaceId: "workspace-id",
query: "meeting notes",
limit: 10
})
// Get document by exact title
get_doc_by_title({
workspaceId: "workspace-id",
title: "Project Roadmap"
})
// Read document content
read_doc({
workspaceId: "workspace-id",
docId: "doc-id"
})
// Create document
create_doc({
workspaceId: "workspace-id",
title: "New Document",
text: "Initial content",
folderId: "folder-id" // Optional, new in v2.1.0
})
// Update document
update_doc({
workspaceId: "workspace-id",
docId: "doc-id",
text: "Updated content"
})
// Delete document
delete_doc({
workspaceId: "workspace-id",
docId: "doc-id"
})
// Move document to trash
trash_doc({
workspaceId: "workspace-id",
docId: "doc-id"
})
// Restore from trash
restore_doc({
workspaceId: "workspace-id",
docId: "doc-id"
})
```
### Template Tools
```typescript
// List available templates
list_templates({ workspaceId: "workspace-id" })
// Inspect template structure
inspect_template({
workspaceId: "workspace-id",
templateId: "template-id"
})
// Create document from template
create_doc_from_template({
workspaceId: "workspace-id",
templateId: "template-id",
title: "Q1 Report",
folderId: "folder-id" // Optional
})
```
### Database Tools
```typescript
// Create database
create_database({
workspaceId: "workspace-id",
docId: "doc-id",
blockId: "block-id", // Optional
name: "Project Tracker"
})
// Add database column
add_database_column({
workspaceId: "workspace-id",
docId: "doc-id",
databaseId: "database-id",
name: "Status",
type: "select",
options: ["Todo", "In Progress", "Done"]
})
// Add database row
add_database_row({
workspaceId: "workspace-id",
docId: "doc-id",
databaseId: "database-id",
values: {
"Task": "Implement feature",
"Status": "In Progress"
}
})
// Update database row
update_database_row({
workspaceId: "workspace-id",
docId: "doc-id",
databaseId: "database-id",
rowId: "row-id",
values: {
"Status": "Done"
}
})
// Inspect database schema
inspect_database_schema({
workspaceId: "workspace-id",
docId: "doc-id",
databaseId: "database-id"
})
```
### Collection Tools
```typescript
// List collections
list_collections({ workspaceId: "workspace-id" })
// Create collection
create_collection({
workspaceId: "workspace-id",
name: "Project Docs"
})
// Add document to collection
add_doc_to_collection({
workspaceId: "workspace-id",
collectionId: "collection-id",
docId: "doc-id"
})
// Remove document from collection
remove_doc_from_collection({
workspaceId: "workspace-id",
collectionId: "collection-id",
docId: "doc-id"
})
```
### Comment Tools
```typescript
// List comments on document
list_comments({
workspaceId: "workspace-id",
docId: "doc-id"
})
// Create comment
create_comment({
workspaceId: "workspace-id",
docId: "doc-id",
text: "Great point!",
quote: "original text" // Optional
})
// Update comment
update_comment({
workspaceId: "workspace-id",
docId: "doc-id",
commentId: "comment-id",
text: "Updated comment"
})
// Delete comment
delete_comment({
workspaceId: "workspace-id",
docId: "doc-id",
commentId: "comment-id"
})
```
## Common Workflow Patterns
### Creating a Project Structure
```typescript
// 1. Create workspace
const workspace = await create_workspace({
name: "Q1 Project",
description: "Project tracking workspace"
});
// 2. Create main document
const mainDoc = await create_doc({
workspaceId: workspace.id,
title: "Project Overview",
text: "# Project Overview\n\nKey objectives..."
});
// 3. Create database for task tracking
const database = await create_database({
workspaceId: workspace.id,
docId: mainDoc.id,
name: "Task Tracker"
});
// 4. Add columns
await add_database_column({
workspaceId: workspace.id,
docId: mainDoc.id,
databaseId: database.id,
name: "Priority",
type: "select",
options: ["High", "Medium", "Low"]
});
// 5. Add initial tasks
await add_database_row({
workspaceId: workspace.id,
docId: mainDoc.id,
databaseId: database.id,
values: {
"Task": "Define requirements",
"Priority": "High"
}
});
```
### Document Search and Update
```typescript
// 1. Search for documents
const results = await search_docs({
workspaceId: "workspace-id",
query: "meeting notes",
limit: 5
});
// 2. Find specific document by exact title
const doc = await get_doc_by_title({
workspaceId: "workspace-id",
title: "Weekly Standup - 2024-01-15"
});
// 3. Read current content
const content = await read_doc({
在 GitHub 查看