{"_id":"@emmabyte-eng/affine-mcp","_rev":"2-64070796cd007d10743279bd26f4546a","name":"@emmabyte-eng/affine-mcp","dist-tags":{"latest":"1.0.1"},"versions":{"1.0.0":{"name":"@emmabyte-eng/affine-mcp","version":"1.0.0","keywords":["mcp","model-context-protocol","affine","ai","claude","knowledge-base","wiki"],"author":{"name":"Emmabyte Engineering"},"license":"MIT","_id":"@emmabyte-eng/affine-mcp@1.0.0","maintainers":[{"name":"emma.long","email":"emma@emmabyte.io"}],"homepage":"https://github.com/emmabyte-engineering/affine-mcp#readme","bugs":{"url":"https://github.com/emmabyte-engineering/affine-mcp/issues"},"bin":{"affine-mcp":"dist/index.js"},"dist":{"shasum":"f3f9e50fce283e1c430210f097f6846486a66151","tarball":"https://registry.npmjs.org/@emmabyte-eng/affine-mcp/-/affine-mcp-1.0.0.tgz","fileCount":27,"integrity":"sha512-+rfr0qScny/yorlnoMq+FqAq0YeX/Ld8Lfh8FaNeGzCnvb+WmbnkObXHoWssnBUEgwjSeQSRwAWlP0mhL4kXCA==","signatures":[{"sig":"MEQCIGUXVJyZDPCz5VW5kU4D0lSgh7JCe0rGy0mqa2Gv6aBzAiBNDiEaSviAwrqMeEa7UZHNb6AaMu4Ui6i7a3+Hhr1lpw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":144919},"main":"dist/index.js","type":"module","types":"./dist/index.d.ts","gitHead":"d9de25a1da8b882d92e50bc990cbe32ad95710e2","scripts":{"dev":"tsc --watch","test":"npx tsx test/integration.ts","build":"tsc","start":"node dist/index.js"},"_npmUser":{"name":"emma.long","email":"emma@emmabyte.io"},"repository":{"url":"git+https://github.com/emmabyte-engineering/affine-mcp.git","type":"git"},"_npmVersion":"11.7.0","description":"MCP server for self-hosted AFFiNE instances — read, write, search, and manage docs, tables, diagrams, and comments","directories":{},"_nodeVersion":"22.21.1","dependencies":{"yjs":"^13.6.29","zod":"^4.3.6","markdown-it":"^14.1.1","socket.io-client":"^4.8.3","@modelcontextprotocol/sdk":"^1.27.1"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.21.0","dotenv":"^17.3.1","typescript":"^5.9.3","@types/node":"^25.3.4","@types/markdown-it":"^14.1.2"},"_npmOperationalInternal":{"tmp":"tmp/affine-mcp_1.0.0_1772771189725_0.03452484756754148","host":"s3://npm-registry-packages-npm-production"}},"1.0.1":{"name":"@emmabyte-eng/affine-mcp","version":"1.0.1","description":"MCP server for self-hosted AFFiNE instances — read, write, search, and manage docs, tables, diagrams, and comments","type":"module","main":"dist/index.js","bin":{"affine-mcp":"dist/index.js"},"scripts":{"build":"tsc","dev":"tsc --watch","start":"node dist/index.js","test":"npm run test:unit && npm run test:e2e:all","test:e2e:all":"docker compose -f docker-compose.test.yml up -d && npm run test:e2e:setup && npm run test:e2e; EXIT=$?; docker compose -f docker-compose.test.yml down -v; exit $EXIT","test:unit":"node --import tsx --test test/unit/*.test.ts","test:e2e:setup":"npx tsx test/e2e/setup.ts","test:e2e":"npx tsx test/integration.ts","test:integration":"npx tsx test/integration.ts"},"keywords":["mcp","model-context-protocol","affine","ai","claude","knowledge-base","wiki"],"author":{"name":"Emmabyte Engineering"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/emmabyte-engineering/affine-mcp.git"},"homepage":"https://github.com/emmabyte-engineering/affine-mcp#readme","bugs":{"url":"https://github.com/emmabyte-engineering/affine-mcp/issues"},"dependencies":{"@modelcontextprotocol/sdk":"^1.27.1","markdown-it":"^14.1.1","socket.io-client":"^4.8.3","yjs":"^13.6.29","zod":"^4.3.6"},"devDependencies":{"@types/markdown-it":"^14.1.2","@types/node":"^25.3.4","dotenv":"^17.3.1","tsx":"^4.21.0","typescript":"^5.9.3"},"gitHead":"c2a0fc2364ea7dc7e1c2fd2b09cdabc286f2064b","types":"./dist/index.d.ts","_id":"@emmabyte-eng/affine-mcp@1.0.1","_nodeVersion":"22.22.0","_npmVersion":"11.11.0","dist":{"integrity":"sha512-mKmezko7f/ELX99a9xk/oqqhLAZQnsI2EPLYYDxreztVUpvWYjWFwHM/OW2DbTqEODdOwNcPMuZuqznP0E/ENQ==","shasum":"358b3ba06d50ddac95699065e7707466d74ed729","tarball":"https://registry.npmjs.org/@emmabyte-eng/affine-mcp/-/affine-mcp-1.0.1.tgz","fileCount":27,"unpackedSize":149001,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@emmabyte-eng%2faffine-mcp@1.0.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIE0JZjlFAlTjZ+3aIOwZA9QecDMTbmFtCkcg9SE3xnEZAiBN2LYi3xbp/5tWGqd2EBlj/TZEb5POROdcrxePr04Esw=="}]},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:eec7cd7b-9ef0-41d6-ae67-57d174aa577f"}},"directories":{},"maintainers":[{"name":"emma.long","email":"emma@emmabyte.io"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/affine-mcp_1.0.1_1772829278862_0.44425338032479256"},"_hasShrinkwrap":false}},"time":{"created":"2026-03-06T04:26:29.615Z","modified":"2026-03-06T20:34:39.272Z","1.0.0":"2026-03-06T04:26:29.863Z","1.0.1":"2026-03-06T20:34:38.997Z"},"bugs":{"url":"https://github.com/emmabyte-engineering/affine-mcp/issues"},"author":{"name":"Emmabyte Engineering"},"license":"MIT","homepage":"https://github.com/emmabyte-engineering/affine-mcp#readme","keywords":["mcp","model-context-protocol","affine","ai","claude","knowledge-base","wiki"],"repository":{"type":"git","url":"git+https://github.com/emmabyte-engineering/affine-mcp.git"},"description":"MCP server for self-hosted AFFiNE instances — read, write, search, and manage docs, tables, diagrams, and comments","maintainers":[{"name":"emma.long","email":"emma@emmabyte.io"}],"readme":"# AFFiNE MCP Server\n\nAn open-source [Model Context Protocol (MCP)](https://modelcontextprotocol.io) server that connects AI assistants to your **self-hosted [AFFiNE](https://affine.pro)** instance. Read, write, search, and manage your AFFiNE docs, tables, diagrams, and comments — all from your AI tool of choice.\n\n## Features\n\n| Tool | Description |\n|------|-------------|\n| `list_workspaces` | List all accessible workspaces |\n| `get_workspace` | Get workspace details |\n| `list_docs` | List documents with pagination |\n| `get_doc` | Get document metadata |\n| `read_doc` | Read full document content as markdown |\n| `read_multiple_docs` | Bulk-read multiple documents |\n| `search_docs` | Full-text search across document titles and content |\n| `create_doc` | Create a new document with optional markdown content |\n| `append_to_doc` | Append markdown to an existing document |\n| `replace_doc_content` | Replace a document's entire content |\n| `delete_doc` | Delete a document |\n| `get_mermaid_diagrams` | Extract mermaid diagrams from a document |\n| `insert_mermaid_diagram` | Add a new mermaid diagram |\n| `update_mermaid_diagram` | Update an existing mermaid diagram |\n| `get_doc_link_graph` | Map cross-document links (find orphans, broken links) |\n| `get_tables` | Extract structured table data |\n| `insert_table` | Add a new table |\n| `update_table` | Update an existing table |\n| `get_comments` | Get all comments, replies, and inline anchors |\n\n## Prerequisites\n\n- A **self-hosted AFFiNE** instance (this server connects via AFFiNE's WebSocket and GraphQL APIs)\n- Credentials for your instance (email/password, API token, or session cookie)\n\n> **Note:** This server is designed for self-hosted AFFiNE. It has not been tested with AFFiNE Cloud (`app.affine.pro`).\n\n---\n\n## Quick Start\n\n### Option 1: npx (no install)\n\nThe fastest way to get started. No installation required — just configure your AI tool to run:\n\n```\nnpx @emmabyte-eng/affine-mcp\n```\n\n### Option 2: Docker\n\n```bash\ndocker build -t emmabyteeng/affine-mcp .\n```\n\nThen configure your AI tool to run:\n\n```\ndocker run -i --rm -e AFFINE_BASE_URL -e AFFINE_EMAIL -e AFFINE_PASSWORD emmabyteeng/affine-mcp\n```\n\n### Option 3: Global install\n\n```bash\nnpm install -g @emmabyte-eng/affine-mcp\n```\n\nThen configure your AI tool to run:\n\n```\naffine-mcp\n```\n\n### Option 4: From source\n\n```bash\ngit clone https://github.com/emmabyte-engineering/affine-mcp.git\ncd affine-mcp\nnpm install\nnpm run build\n```\n\nThen configure your AI tool to run:\n\n```\nnode /path/to/affine-mcp/dist/index.js\n```\n\n---\n\n## Configuration\n\nThe server is configured via environment variables:\n\n| Variable | Required | Description |\n|----------|----------|-------------|\n| `AFFINE_BASE_URL` | Yes | Your AFFiNE instance URL (e.g. `https://affine.example.com`) |\n| `AFFINE_EMAIL` | Auth option 1 | Account email |\n| `AFFINE_PASSWORD` | Auth option 1 | Account password |\n| `AFFINE_API_TOKEN` | Auth option 2 | API bearer token |\n| `AFFINE_COOKIE` | Auth option 3 | Session cookie string |\n\nChoose **one** authentication method. Email/password is the simplest for most setups.\n\nCopy `.env.example` to `.env` and fill in your values (used when running from source or for local development):\n\n```bash\ncp .env.example .env\n```\n\n---\n\n## AI Tool Integration\n\nMCP servers communicate over **stdio** — the AI tool launches the server as a subprocess and exchanges JSON messages over stdin/stdout. Each tool below has its own config file where you register MCP servers.\n\n### Claude Desktop\n\nEdit your Claude Desktop config file:\n\n- **macOS:** `~/Library/Application Support/Claude/claude_desktop_config.json`\n- **Windows:** `%APPDATA%\\Claude\\claude_desktop_config.json`\n- **Linux:** `~/.config/Claude/claude_desktop_config.json`\n\n<details>\n<summary><strong>Using npx</strong></summary>\n\n```json\n{\n  \"mcpServers\": {\n    \"affine\": {\n      \"command\": \"npx\",\n      \"args\": [\"@emmabyte-eng/affine-mcp\"],\n      \"env\": {\n        \"AFFINE_BASE_URL\": \"https://affine.example.com\",\n        \"AFFINE_EMAIL\": \"you@example.com\",\n        \"AFFINE_PASSWORD\": \"your-password\"\n      }\n    }\n  }\n}\n```\n\n</details>\n\n<details>\n<summary><strong>Using Docker</strong></summary>\n\n```json\n{\n  \"mcpServers\": {\n    \"affine\": {\n      \"command\": \"docker\",\n      \"args\": [\n        \"run\", \"-i\", \"--rm\",\n        \"-e\", \"AFFINE_BASE_URL\",\n        \"-e\", \"AFFINE_EMAIL\",\n        \"-e\", \"AFFINE_PASSWORD\",\n        \"emmabyteeng/affine-mcp\"\n      ],\n      \"env\": {\n        \"AFFINE_BASE_URL\": \"https://affine.example.com\",\n        \"AFFINE_EMAIL\": \"you@example.com\",\n        \"AFFINE_PASSWORD\": \"your-password\"\n      }\n    }\n  }\n}\n```\n\n</details>\n\n<details>\n<summary><strong>Using global install</strong></summary>\n\n```json\n{\n  \"mcpServers\": {\n    \"affine\": {\n      \"command\": \"@emmabyte-eng/affine-mcp\",\n      \"env\": {\n        \"AFFINE_BASE_URL\": \"https://affine.example.com\",\n        \"AFFINE_EMAIL\": \"you@example.com\",\n        \"AFFINE_PASSWORD\": \"your-password\"\n      }\n    }\n  }\n}\n```\n\n</details>\n\n### Claude Code (CLI)\n\nRun this from your terminal:\n\n```bash\nclaude mcp add affine -- npx @emmabyte-eng/affine-mcp \\\n  --env AFFINE_BASE_URL=https://affine.example.com \\\n  --env AFFINE_EMAIL=you@example.com \\\n  --env AFFINE_PASSWORD=your-password\n```\n\nOr add it to your project's `.claude/settings.json`:\n\n```json\n{\n  \"mcpServers\": {\n    \"affine\": {\n      \"command\": \"npx\",\n      \"args\": [\"@emmabyte-eng/affine-mcp\"],\n      \"env\": {\n        \"AFFINE_BASE_URL\": \"https://affine.example.com\",\n        \"AFFINE_EMAIL\": \"you@example.com\",\n        \"AFFINE_PASSWORD\": \"your-password\"\n      }\n    }\n  }\n}\n```\n\n### Cursor\n\nOpen **Cursor Settings → MCP** and add a server, or edit `~/.cursor/mcp.json`:\n\n```json\n{\n  \"mcpServers\": {\n    \"affine\": {\n      \"command\": \"npx\",\n      \"args\": [\"@emmabyte-eng/affine-mcp\"],\n      \"env\": {\n        \"AFFINE_BASE_URL\": \"https://affine.example.com\",\n        \"AFFINE_EMAIL\": \"you@example.com\",\n        \"AFFINE_PASSWORD\": \"your-password\"\n      }\n    }\n  }\n}\n```\n\n### Windsurf\n\nOpen **Windsurf Settings → MCP** or edit `~/.codeium/windsurf/mcp_config.json`:\n\n```json\n{\n  \"mcpServers\": {\n    \"affine\": {\n      \"command\": \"npx\",\n      \"args\": [\"@emmabyte-eng/affine-mcp\"],\n      \"env\": {\n        \"AFFINE_BASE_URL\": \"https://affine.example.com\",\n        \"AFFINE_EMAIL\": \"you@example.com\",\n        \"AFFINE_PASSWORD\": \"your-password\"\n      }\n    }\n  }\n}\n```\n\n### VS Code (Copilot)\n\nAdd to your VS Code `settings.json` or `.vscode/mcp.json`:\n\n```json\n{\n  \"mcp\": {\n    \"servers\": {\n      \"affine\": {\n        \"command\": \"npx\",\n        \"args\": [\"@emmabyte-eng/affine-mcp\"],\n        \"env\": {\n          \"AFFINE_BASE_URL\": \"https://affine.example.com\",\n          \"AFFINE_EMAIL\": \"you@example.com\",\n          \"AFFINE_PASSWORD\": \"your-password\"\n        }\n      }\n    }\n  }\n}\n```\n\n### Zed\n\nAdd to your Zed settings (`~/.config/zed/settings.json`):\n\n```json\n{\n  \"context_servers\": {\n    \"affine\": {\n      \"command\": {\n        \"path\": \"npx\",\n        \"args\": [\"@emmabyte-eng/affine-mcp\"],\n        \"env\": {\n          \"AFFINE_BASE_URL\": \"https://affine.example.com\",\n          \"AFFINE_EMAIL\": \"you@example.com\",\n          \"AFFINE_PASSWORD\": \"your-password\"\n        }\n      }\n    }\n  }\n}\n```\n\n### Cline (VS Code)\n\nOpen the Cline MCP settings in VS Code, or edit `~/Library/Application Support/Code/User/globalStorage/saoudrizwan.claude-dev/settings/cline_mcp_settings.json`:\n\n```json\n{\n  \"mcpServers\": {\n    \"affine\": {\n      \"command\": \"npx\",\n      \"args\": [\"@emmabyte-eng/affine-mcp\"],\n      \"env\": {\n        \"AFFINE_BASE_URL\": \"https://affine.example.com\",\n        \"AFFINE_EMAIL\": \"you@example.com\",\n        \"AFFINE_PASSWORD\": \"your-password\"\n      }\n    }\n  }\n}\n```\n\n### Roo Code (VS Code)\n\nEdit the Roo Code MCP settings:\n\n```json\n{\n  \"mcpServers\": {\n    \"affine\": {\n      \"command\": \"npx\",\n      \"args\": [\"@emmabyte-eng/affine-mcp\"],\n      \"env\": {\n        \"AFFINE_BASE_URL\": \"https://affine.example.com\",\n        \"AFFINE_EMAIL\": \"you@example.com\",\n        \"AFFINE_PASSWORD\": \"your-password\"\n      }\n    }\n  }\n}\n```\n\n### Amazon Q Developer CLI\n\nEdit `~/.aws/amazonq/mcp.json`:\n\n```json\n{\n  \"mcpServers\": {\n    \"affine\": {\n      \"command\": \"npx\",\n      \"args\": [\"@emmabyte-eng/affine-mcp\"],\n      \"env\": {\n        \"AFFINE_BASE_URL\": \"https://affine.example.com\",\n        \"AFFINE_EMAIL\": \"you@example.com\",\n        \"AFFINE_PASSWORD\": \"your-password\"\n      }\n    }\n  }\n}\n```\n\n### Other MCP Clients\n\nAny MCP-compatible client that supports stdio transport can use this server. The general pattern is:\n\n- **Command:** `npx` (or `node`, `docker`, `@emmabyte-eng/affine-mcp`)\n- **Args:** `[\"@emmabyte-eng/affine-mcp\"]` (for npx)\n- **Transport:** stdio\n- **Environment variables:** `AFFINE_BASE_URL`, `AFFINE_EMAIL`, `AFFINE_PASSWORD`\n\n---\n\n## How It Works\n\nThis server connects to your AFFiNE instance using two protocols:\n\n1. **GraphQL API** — For listing workspaces, documents, fetching metadata, and reading comments\n2. **WebSocket + Yjs** — For reading and writing document content (AFFiNE stores documents as [Yjs](https://yjs.dev) CRDTs)\n\nDocument content is synced via Yjs, then converted to/from Markdown. This gives you full read/write access to document content, including:\n\n- Paragraphs, headings, lists, code blocks, quotes, dividers\n- Tables (native AFFiNE tables, not markdown tables)\n- Mermaid diagrams\n- Embedded linked documents\n- Images and bookmarks\n- Comments and inline comment anchors\n\n---\n\n## Development\n\n```bash\n# Install dependencies\nnpm install\n\n# Build\nnpm run build\n\n# Watch mode\nnpm run dev\n\n# Run integration tests (requires a running AFFiNE instance)\ncp .env.example .env  # then fill in your credentials\nnpm test\n```\n\n### Project Structure\n\n```\nsrc/\n├── index.ts            # MCP server setup and tool registration\n├── config.ts           # Environment variable loading\n├── auth.ts             # Authentication (email/password, token, cookie)\n├── graphql.ts          # GraphQL client and queries\n├── websocket.ts        # WebSocket/Yjs document sync\n├── doc-operations.ts   # All document operations (read, write, search, comments, etc.)\n└── markdown/\n    ├── parse.ts        # Markdown → AFFiNE blocks\n    └── render.ts       # AFFiNE blocks → Markdown\n```\n\n---\n\n## Contributing\n\nContributions are welcome! Here are some areas where help is appreciated:\n\n- **AFFiNE Cloud support** — Testing and adapting for `app.affine.pro`\n- **Additional block types** — Better handling of databases, embeds, and other AFFiNE block types\n- **Write support for comments** — Creating and resolving comments via the MCP server\n- **Rich text fidelity** — Preserving bold, italic, links, and other inline formatting during markdown round-trips\n\nTo contribute:\n\n1. Fork the repository\n2. Create a feature branch\n3. Make your changes\n4. Run `npm run build` to verify the build\n5. Run `npm test` against a test AFFiNE instance if possible\n6. Open a pull request\n\n---\n\n## License\n\nMIT\n","readmeFilename":"README.md"}