用途
Easy Notion MCP 是一个“Markdown 优先”的 MCP 服务器,用于把 AI 智能体接入 Notion。智能体侧只写 Markdown,由该服务器负责转换成 Notion 的块 API 格式,并支持反向转换回 Markdown。其目标场景是让智能体以“编辑代码文本”的方式编辑 Notion 页面内容:读取页面得到 Markdown,修改字符串后写回。
主要能力
- Markdown 与 Notion 块互转:支持标准 GFM Markdown,保留 24 种块类型,并记录有往返(round-trip)支持。
- 节省 token:读取页面内容约比官方 Notion MCP 少 6–7 倍响应 token。官方服务器返回原始 API JSON,每块携带约 120 token 的元数据;easy-notion-mcp 省去这些内容读取时用不到的元数据,保留页面内容 ≥94%。节省来自元数据省略,而非编码效率;在信息相等时两种格式成本相近,典型省略的是块 UUID、时间戳、作者对象、注解包装等。数据库查询在完整内容下也有约 7 倍收益。
- 43 个工具,分 7 类(HTTP 下有 42 个,不含仅 stdio 的 create_page_from_file),涵盖页面、导航、数据库等多类操作。
- 页面操作:write/read markdown、replace_content、update_section(按标题名定位)、find_replace 等;页面可设置 emoji 图标与封面图。
- 数据库操作:智能体传简单键值对如 { "Status": "Done" },服务器运行时获取数据库 schema 并自动转换;schema 缓存 5 分钟。
- 错误自纠正提示:标题名错误会返回可用标题;页面缺失会建议共享给集成;过滤条件错误会提示先调用 get_database。
- 复杂内容支持:嵌套 toggle、混合内容列、深列表嵌套、完整 Unicode(日文、中文、阿拉伯文、emoji)等均有往返测试覆盖。
- CLI 配置文件模式:适合智能体需要 Notion 访问但不加载完整 MCP 工具面,或为不同权限模式使用不同 Notion 集成。配置文件默认位于 ~/.config/easy-notion-mcp/profiles.json,引用环境变量名而非原始 token;readonly profile 可用于读命令,readwrite profile 用于修改命令。CLI 破坏性命令支持 --dry-run 预检(返回 would_delete_block_ids、would_update、would_archive、would_restore 等计划字段,不修改 Notion)。轻量技能位于仓库 skills/easy-notion-cli/,用于教智能体优先用 CLI 而非注册多个 MCP 服务器。
使用方式
- 创建 Notion 集成,复制 token,并将页面共享给它。
- 接入 MCP 客户端。常见方式:
- Claude Code:以用户级配置注册服务器(-s user),并通过 -e 把 NOTION_TOKEN 直接传给 MCP 子进程;shell 环境与 rcfile 不受影响。可为 create_page 设置默认父页面:加 -e NOTION_ROOT_PAGE_ID=<page-id>。
- 通用 MCP 客户端:在父 shell 环境提供 token(该 export 形式仅对当前 shell 会话持久,除非写入 shell rcfile,需注意安全影响)。
- Claude Desktop / Cursor / Windsurf:在 MCP 配置文件中添加,配置文件位置分别为 claude_desktop_config.json、.cursor/mcp.json、~/.windsurf/mcp.json。
- Claude Desktop 连接器:Settings → Connectors → Add custom connector,输入 http://localhost:3333/mcp,浏览器会打开 Notion 授权页,选择共享页面并 Allow。
- 项目级注册:在项目根目录 .mcp.json 中写入配置(注意不要把带占位凭据的该文件提交到仓库)。
- Dify / n8n / FlowiseAI 等 Docker 平台:在宿主机运行 HTTP 服务器,平台设置里用 host.docker.internal 代替 localhost,并添加 bearer 请求头;HTTP 默认绑定 127.0.0.1,静态 token 模式需要 NOTION_MCP_BEARER,容器访问需设置 NOTION_MCP_BIND_HOST=0.0.0.0。
- 传输方式:
- stdio(API token 模式)。
- HTTP(OAuth 或 API token 模式):运行 npx -p easy-notion-mcp easy-notion-mcp-http 启动带 OAuth 的 HTTP 服务器。OAuth 凭据需在 notion.so/profile/integrations 创建 public integration,并把 http://localhost:3333/callback 配为重定向 URI。OAuth 模式下 create_page 无需 NOTION_ROOT_PAGE_ID,页面默认创建在用户私人工作区。
适用场景
- 让 AI 智能体读写、编辑 Notion 页面与数据库,并以 Markdown 作为操作界面。
- 对上下文预算敏感、希望减少读取页面 token 消耗的智能体工作流。
- 需要按标题定位、局部替换、精细 find_replace 等编辑操作的场景。
- 需要在 Docker 平台(Dify / n8n / FlowiseAI)中以 HTTP 方式接入 Notion 的场景。
- 需要不同权限模式(readonly / readwrite)分离访问 Notion 的场景。
限制
- HTTP 传输面向可信网络:单操作者自托管加 bearer 密钥,或共享部署用 OAuth;未针对直接暴露公网做加固,远程访问需前置带 TLS 的反向代理。
- 静态 token 模式必须设置 bearer;缺失或错误 bearer 返回 401 {"error": "invalid_token"};bearer 使用 crypto.timingSafeEqual 比较;重启服务器并换新值即可轮换密钥。
- 默认绑定 127.0.0.1,仅本地进程可访问;设置 NOTION_MCP_BIND_HOST=0.0.0.0 暴露所有接口,或指定 IP 暴露单一接口;无论绑定如何都要求 bearer。
- /mcp 端点未接入 DNS-rebinding 防护;OAuth 注册/令牌端点(/register、/token、/revoke)的 CORS 较宽松。bearer 或 OAuth 的每用户 bearer 是网络与 Notion 工作区之间唯一的信任边界。
- file:// 上传仅限 stdio:传给 create_page、append_content、replace_content、update_section、update_page.cover 的 file:// URL 在 HTTP 下会被拒绝;本地文件工作流请用 stdio(create_page_from_file 也仅限 stdio),或把文件托管到 HTTPS URL。
- 破坏性工具支持 dry_run: true 预检;dry-run 不会上传或校验本地 file:// Markdown(因为会创建 Notion 上传),replace_content 的 dry-run 也不能暴露 Notion 侧的 unmatched_blocks 或截断字段。
- restore_toggle 按 ID 操作:需传入 archive_toggle 返回的已归档块 ID;Notion 未暴露已归档子项枚举,因此不支持按标题搜索或 read_page include_archived 工作流恢复。
- 数据库写入拒绝未知属性名和不支持的类型,会给出明确错误而非静默丢弃;写入前应先 get_database 确认属性名与类型。
- 支持写入的属性类型:title、rich_text、number、select、multi_select、date、checkbox、url、email、phone、status、relation、people。people 传单个用户 ID 字符串或 ID 数组。计算类型(formula、rollup、unique_id、created_time、last_edited_time、created_by、last_edited_by)由 Notion 生成,不能通过 API 设置;files、verification、place、location、button 的值写入也被拒绝。relation 写入传单个 page-ID 字符串或数组,空数组清除关系。
- 关于 .env 文件(仅贡献者相关):服务器通过 dotenv 从当前工作目录加载 .env,仅在从克隆的仓库检出目录运行(npm install && npm run build 后 node dist/index.js)时方便生效;通过 npx easy-notion-mcp 或任意目录的全局安装调用时不加载。
- 若设置过程中有问题,可在 Discord 社区的 #easy-notion-mcp 频道提问;bug 提交到 GitHub issues。