mcpField
N
Notion

Notion

本地服务
foreverworks.github.io生产力1今天更新

关于 Notion

Notion MCP 服务供 AI 助手搜索、读取和修改已共享的 Notion 工作区,并结合 Markdown 页面编辑、类型化数据库查询、视图、评论与文件操作。

主要功能

  1. 01跨工作区搜索页面和数据库
  2. 02以 Markdown 读取和编辑页面
  3. 03查询、计数并检查数据库行
  4. 04创建和修改页面、数据库及列
  5. 05管理评论并传输文件

适用场景

  1. 01查找并总结工作区页面
  2. 02按状态统计任务数量
  3. 03添加或更新数据库条目
  4. 04下载页面或数据库行的附件

MCP 相关

向 MCP 客户端提供 Notion 工作区搜索、页面、数据库、评论和文件操作工具。访问范围取决于配置的工作区令牌及共享给集成的页面。

配置

本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。

mcp.json · 通用配置
{
"mcpServers": {
"com-foreverworks-notion": {
"command": "npx",
"args": [
"-y",
"@foreverworks/mcp-notion"
],
"env": {
"NOTION_TOKENS_DIR": "<NOTION_TOKENS_DIR>"
}
}
}
}
启动命令npx -y @foreverworks/mcp-notion
需要配置的环境变量
NOTION_TOKENS_DIR密钥A folder holding one file per workspace, notion-<label>, each with that workspace's integration token or personal access token.

本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。

安装包
npm@foreverworks/mcp-notion0.1.0

工具

27

收录的工具列表 · 更新于 3 天前

参数类型必填说明
columnobject是
column.namestring是列名;该名称必须尚未被表使用(忽略大小写)。
column.typeenum是列类型。汇总、唯一 ID 和按钮需在 Notion 应用中创建。rich_text | number | select | multi_select | status | date | people | files | checkbox | url | email | phone_number | formula | relation | created_time | created_by | last_edited_time | last_edited_by
column.formatstring否数字:Notion 的格式名称,例如 number、number_with_commas、percent、euro、dollar。
column.optionsarray否选择、 多选或状态:按顺序列出选项。
column.expressionstring否公式:表达式,例如 prop("Hours") * prop("Rate")。
column.descriptionstring否列的用途说明,最多 280 个字符。
column.relation_tostring否关联:指向的数据库(ID 或 URL),必须位于同一工作区。单向关联。
sourcestring否源表,仅当数据库包含多个表时使用(describe_database 会列出这些表):指定表名或 ID。
accountstring否工作区:标签列表 `accounts` 名称(“*”:全部)。很少需要:ID 或 URL 可自行查找。
databasestring是数据库:其 ID、Notion URL,或为其搜索返回的 dataSourceId。

详细介绍

Notion 图标 Notion MCP 服务

通过你的 AI 助手搜索、读取和写入 Notion 工作区;多个工作区可共用一个服务:以 Markdown 格式处理页面,按列查询和统计数据库,查看已保存的视图、人员、评论和文件。它可以创建页面、行、列和数据库,编辑属性和正文,添加评论、上传文件,并将页面移至 Notion 垃圾桶(保留 30 天;restore_page 可将其恢复)。没有工具是 money。

你需要: 每个工作区对应一个 Notion 集成,将其令牌单独存放在一个文件中,并将顶层页面共享给该集成:集成只能看到你共享的内容。上传文件大小上限为 20 MiB(Notion 免费计划为 5 MiB)。

可以询问什么

  • “在我的工作区中找到 Q3 路线图页面并总结。”
  • “Tasks 数据库中每种 Status 有多少行?”
  • “显示我的 Due this week 视图。”
  • “将《Thinking in Systems》添加到 Reading List,状态设为 To read,标签设为 Books。”
  • “在 Onboarding 页面中,将所有 ‘Slack’ 替换为 ‘Mattermost’。”
  • “下载 Contracts 数据库中 Client SRL 行所附的 PDF。”

安装

在 VS Code 中安装 在 Cursor 中安装 下载 Claude Desktop 版

使用 Claude Code:

claude mcp add notion -e NOTION_TOKENS_DIR="<path to Notion tokens folder>" -- npx -y @foreverworks/mcp-notion

Claude Desktop(Settings、Developer、Edit Config)和大多数其他客户端都通过 JSON 读取相同的命令:

{
  "mcpServers": {
    "notion": {
      "command": "npx",
      "args": ["-y", "@foreverworks/mcp-notion"],
      "env": {
        "NOTION_TOKENS_DIR": "<path to Notion tokens folder>"
      }
    }
  }
}

每种方式都会在 Node 22.19 或更高版本上运行已发布的软件包。VS Code 和 Claude Desktop 安装包会在添加服务时询问 NOTION_TOKENS_DIR。Cursor 则从环境变量中读取该值(${env:NOTION_TOKENS_DIR}),因此请在启动 Cursor 前设置它。配置介绍了该目录的内容。

从克隆版本安装
git clone https://github.com/foreverworks/mcps.git && cd mcps
npm ci && npm run build
claude mcp add notion -e NOTION_TOKENS_DIR="<path to Notion tokens folder>" -- node "$PWD/servers/notion/dist/index.js"

在 JSON 配置中,命令为 node,其唯一参数是 servers/notion/dist/index.js 的完整路径。若要通过 HTTP 在多个客户端之间共享同一个运行中的副本,请参阅 docs/deploying.md。

通过 HTTP 部署时,如果需要限制主机,请设置 MCP_EGRESS_ALLOW=api.notion.com,prod-files-secure.s3.us-west-2.amazonaws.com,s3.us-west-2.amazonaws.com: Notion API 以及托管其文件的主机。

配置

变量必填含义
NOTION_TOKENS_DIR是,或设置 CREDENTIALS_DIRECTORY存放各工作区文件的文件夹,每个文件对应一个工作区,文件名为 notion-<label>,且文件中只包含该工作区的令牌。
CREDENTIALS_DIRECTORY未设置 NOTION_TOKENS_DIR 时读取:在 systemd 下,LoadCredential=notion-<label>:<path> 会将相同的文件放在这里,且只有该单元可以读取。
NOTION_OUTBOX_DIR使用 download_files 时必填保存下载文件的文件夹,服务会写入该文件夹,你可以读取其中的文件。若未设置,download_files 会返回一条指出此变量的 config 错误;其他工具均可正常使用。

每个文件对应一个工作区:notion-personal 和 notion-work 分别标记为 personal 和 work,服务启动时会列出找到的标签。标签只能包含小写字母、 数字和连字符;空文件会被跳过。 没有默认文件夹,因此测试或手动运行的副本不会意外访问工作区。文件最多每分钟 重新读取一次;令牌被拒绝后会立即重新读取,因此新令牌无需重启。所有服务共用的 变量(传输方式、限制、用于上传的 MCP_FILE_ROOTS)见 docs/configuration.md。

获取令牌

对于每个工作区:

  1. 登录对应工作区,打开 https://www.notion.so/profile/integrations,并创建新的内部集成。
  2. 启用助手所需的功能:读取、更新和插入页面与数据库内容,以及评论相关功能。 只有在助手可以读取包含电子邮件地址的用户信息时,才会显示人员的电子邮件地址。
  3. 将其 Internal Integration Secret 直接复制到令牌文件夹中的 notion-<label>, 并确保只有你自己可以读取该文件(权限模式为 0600)。不要将其粘贴到聊天中。
  4. 将页面分享给该集成,因为它起初看不到任何内容。在 Notion 中,打开助手应 访问的每个顶层页面,然后依次选择 ••• 菜单、Connections,并添加该集成。 该页面下的页面会继承访问权限;新的顶层页面必须以相同方式分享。

也可以在同一个文件中使用个人访问令牌(登录工作区后,在 https://www.notion.so/developers/tokens 创建,并启用 Notion API 功能)。 该令牌以你的身份运行:它可以查看你能查看的所有页面,无需分享页面;还可以创建 私有顶层页面,而集成无法做到这一点。令牌会在一年内过期。

首次运行

请助手运行 Notion 的 health 检查。它会针对每个工作区说明令牌是否有效、工作区 和集成的名称,以及集成是否已能看到页面;如果还看不到,请执行上面的第 4 步。

在 shell 中,运行 node dist/index.js --health 会为每个工作区输出一行 NOTION:,并在一切正常时以状态码 0 退出;需要人工处理时(令牌被拒绝、缺少功能) 以状态码 1 退出;出现警告时(集成尚看不到任何内容,或 Notion 状态异常)以状态码 2 退出,适用于定时任务。

工具

read 不会进行任何更改;write 会更改工作区中的内容。接受 ID 的工具也接受 Notion URL,并会自行查找工作区。

工作区与搜索
工具访问权限功能
list_accounts读取列出有令牌文件的工作区及其标签。不向 Notion 发送请求。
health读取针对每个工作区,检查令牌是否有效、工作区和集成的名称,以及是否已能看到页面。
list_users读取列出所有工作区中的人员(和机器人):ID、名称,以及令牌获准读取时的电子邮件地址;可按关键词筛选。
search读取一次搜索所有工作区中标题匹配的页面和数据库,并在每条结果上标注其所属工作区。
页面
工具访问权限功能
read_page读取以纯值形式返回页面属性,并以 Notion 的 Markdown 格式返回正文。
read_blocks读取返回页面或区块内的直接子区块:id、类型、纯文本。会议记录区块会标出保存其摘要、笔记和转录内容的区块。
create_page写入创建数据库中的一行(根据其列进行校验,或基于其中一个模板创建),或创建子页面;两者都可以包含 Markdown 正文。
update_page写入更新页面属性和图标。
append_content写入在末尾、开头或某段内容之后追加 Markdown。
edit_content写入在页面的 Markdown 中查找并替换内容。
replace_content写入替换页面的整个正文;仅当使用 clear 时才能替换为空正文。返回页面标题以及替换前后的区块数。
move_page写入在同一工作区内,将页面移至其他页面下或移入数据库。
trash_page / restore_page写入将页面移入 Notion 回收站(保留 30 天)或恢复页面。数据库模板仅在使用 allow_template 时可操作。
数据库
工具访问权限功能
describe_database读取返回数据库的表和列:类型、选项、状态组、关联目标和公式。
query_database读取返回行;可按 where(根据架构指定类型)或 Notion 自带的筛选条件进行筛选、排序;单次调用最多返回 1,000 行。
count_rows读取返回符合条件的行数,以及某列各值对应的行数(例如“各状态的任务数”),而不发送行数据。
list_views读取返回数据库已保存的视图:id、名称、类型,以及每个视图中已保存的筛选条件和排序方式、列名。
query_view读取按照 Notion 应用筛选条件的方式,按视图顺序返回已保存视图显示的行,并包含视图的总数。
list_database_templates读取返回数据库的页面模板:页面 id、名称,以及哪个模板为默认模板。
add_column写入向数据库添加列:可自定义名称、类型及其设置(选项、数字格式、公式、关联);先根据表进行校验。
add_options写入向单选、多选或状态列添加选项;现有选项按 id 保留,之后会重新读取该列。
create_database写入在页面下创建数据库,包含标题列和其他列;添加每列前都会先与其他列进行校验。
评论和文件
工具访问权限功能
get_comments读取获取页面中未解决的评论。
add_comment写入在页面上添加评论,或在讨论中回复。
upload_file写入按路径上传文件,将其上传到某行的文件列,或上传到页面正文末尾的区块中;返回文件大小和 SHA-256。
download_files读取将页面托管在 Notion 上的文件(文件列和正文中的文件区块)保存到 outbox,并返回每个文件的 SHA-256。

test/tools.snapshot.json 固定了客户端列出的内容;其中的差异属于不兼容变更。

故障排查

health 显示“集成尚未看到页面”,或调用返回 not_shared。 对于不存在的 ID 和未与集成共享的页面,Notion 会返回相同的 404。请检查 ID,然后共享页面(获取令牌的第 4 步);共享顶层页面会一并共享其下的所有内容。

auth。 令牌被拒绝:可能已撤销,或个人访问令牌已过期。请在 notion-<label> 文件中放入新令牌;下次调用时会读取该令牌。

forbidden。 集成缺少执行此调用所需的权限。请在 https://www.notion.so/profile/integrations 中启用相应权限(获取令牌的第 2 步)。

config。 NOTION_TOKENS_DIR 指向的位置没有令牌文件、令牌文件不可读,或其中包含多个令牌。对于 download_files,请设置 NOTION_OUTBOX_DIR。

create_page 未提供父页面时返回 input。 Notion 不允许集成创建顶层页面;请指定父页面,或使用个人访问令牌。其他 input 会指出需要修复的内容,且不会做出任何更改。

outcome_unknown。 追加内容、查找并替换、新建页面或评论的调用未能收到响应;系统绝不会在未确认的情况下重新发送。再次写入前,请先读取页面(新建页面则使用 search):更改可能已经生效。

conflict:有人同时编辑了同一对象;请重新读取,然后重试。rate_limited:重试后 Notion 仍在限流(Free 计划每分钟 180 次请求);请等待一分钟。api:Notion 无法访问或发生故障;请稍后重试。若 reason: "drift",表示其响应结构发生变化:请报告此问题。

工作原理

ID 定位其所属工作区

一个 ID 只属于一个工作区,因此 src/app/locate.ts 会逐个询问,直到其中一个工作区响应;若全部返回 404,则为 not_shared。进程运行期间会记住找到的 ID,以及搜索或查询返回的 ID,因此每次未找到都只需查找一次。URL 可以来自 notion.so、notion.site 或 app.notion.com;?p= 表示数据库中打开的页面。

数据库由其自身 ID 或其数据源的 ID 标识(搜索会返回两者)。从 API 2025-09-03 开始,数据库包含数据源,通常只有一个;若有多个,source 用于指定表;若省略,则会拒绝请求并列出数据源名称。

Agent 可见的值
Notion 类型输出输入
title, rich_text字符串字符串,拆分为每段 2000 个字符(Notion 的限制),且不会从字符中间截断
numberNotion 发送的 JSON 数字有限数值
select, status选项名称已存在的选项(忽略大小写进行匹配);只有在使用 allow_new_options 时才能创建新的 select 选项;status 选项不可新建(API 无法创建)
multi_select名称名称,规则相同
date{start, end?, timeZone?}YYYY-MM-DD、ISO 日期时间,或 {start, end, time_zone}
checkbox布尔值布尔值
url, email, phone_number字符串字符串;留空会清除该值
relation页面 ID,包含全部页面 ID 或 URL,最多 100 个
files[{name, url, expiresAt?}]外部 URL;自己的文件需通过 upload_file 上传
people, created_by, last_edited_by{id, name};若页面只提供 ID,则名称取自工作区用户拒绝
formula, rollup, created/edited time, unique_id (PREFIX-12)计算出的值拒绝:由 Notion 计算
button省略:它没有值拒绝

空值会从页面或行中省略(describe_database 会列出每一列)。页面对象最多列出关联中的 25 个页面;read_page 会通过属性端点读取其余页面(最多 1,000 个),查询行则会在 truncated 下列出此类列。服务不会对数字进行算术运算。

where

Notion 的筛选条件按列类型确定,而 Agent 常会弄错。 where 指定列名、操作符和值,并从架构中获取类型:

{"where": [{"property": "Status", "op": "equals", "value": ["In progress", "Blocked"]},
           {"property": "Due", "op": "next_week"}],
 "match": "all"}

如果类型不支持某个操作符,或某个选项不存在,工具会在发送任何请求前拒绝操作,并告知现有内容。人员列接受姓名、电子邮件、用户 ID 或 "me"。姓名会与工作区用户匹配:先精确匹配,再匹配某个人姓名中的部分内容;如果有多人同名或无人匹配,工具会拒绝操作,并告知符合条件的人员。对于 where 无法表达的条件,notion_filter 接受 Notion 自己的筛选对象,并与 where 的条件进行 AND 运算。

模板

搜索会将模板作为普通页面返回,而模板会影响此后创建的每一行,因此 list_database_templates 会列出模板,trash_page 则会拒绝处理未设置 allow_template 的模板。create_page 使用 template 时,会检查模板是否属于该数据库。Notion 会在创建行后立即填充内容,因此稍后调用 read_page 即可查看结果。模板旁边提供的属性会保留;Markdown 正文则会被拒绝,以免与模板发生竞争。

更改数据库列

add_column、add_options 和 create_database 会在发送前根据表格当前状态检查请求:名称已被占用、选项已存在、类型不支持某项设置、公式缺少表达式、关联缺少目标,或选项超过 Notion 的 100 项上限。Notion 将架构更新中的选项列表定义为要设置的全部选项,因此 add_options 会先发送所有现有选项的 ID,再发送新增选项,并在之后读取该列;如果有选项消失,此次调用就会失败。

文件

upload_file 可从 MCP_FILE_ROOTS 内的路径上传文件,也可由脚本以 base64 和其 SHA-256 上传,绝不会将模型输入的文本当作文件。如果数据库行中有文件列,文件会添加到该列已有文件中;否则会根据文件类型将其作为内容末尾的区块插入(图片、PDF、视频或音频)。Notion 的 API 会整体替换文件列,且无法重新写入由 Notion 托管的文件,因此,包含 Notion 托管文件的列需要设置 replace: true,这会移除这些文件;外部链接则始终保留。

download_files 会将页面中由 Notion 托管的文件保存到 NOTION_OUTBOX_DIR:包括文件列,以及正文中的文件、图片、PDF、视频和音频区块,也包括嵌套区块(最多读取前 1,000 个区块)。Notion 的链接是有效期为一小时的签名 URL,通过 https 获取时不会使用工作区令牌,也不会跟随重定向。外部链接只会列出,不会获取,因为它们可能指向任意位置。

已保存的视图

query_view 会像 Notion 一样运行视图,包括快速筛选条件和 me。Notion 只会返回页面 ID,且结果会保留约 15 分钟,因此 query_view 会自行读取每一行(默认 25 行,每次最多 100 行),并通过 nextCursor 在同一结果中继续读取。结果过期后,工具会提示重新开始;期间被移至废纸篓或取消共享的行会列在 unreadable 下。

人员和会议记录

对于 AI 会议记录页面,使用 include_transcript 调用 read_page 会以一段 Markdown 文本返回摘要、笔记和文字记录。read_blocks 会列出这些内容对应的区块;对于 transcriptBlockId,它会逐行读取文字记录,每行都带有区块 ID,供 AI 摘要中的引用链接使用。

替换整个正文

replace_content 无法通过 API 撤销,而且模型可能会在它的两个参数上出错:使用错误行的页面 ID,或得到空的 markdown。因此,若正文为空,必须设置 clear: true;返回结果会提供页面标题以及 blocksBefore 和 blocksAfter,这样一来,页面选错或正文几乎被清空都会立即显现。

网络
  • 版本:每个请求都使用 2026-03-11,这是包含 Markdown 端点和 in_trash 的版本。
  • 请求节奏:Free 计划下,集成每分钟可发送 180 个请求。每个工作区使用一个令牌桶(一次最多 30 个,之后每秒 2.5 个),由进程服务的所有会话共享,确保每分钟请求数不超过 180;工作区级别的限制则交由 429 退避和 Retry-After 处理。
  • 重发规则:429 或 409 conflict_error 能证明请求没有产生任何影响,因此每个请求都会重试。5xx 或连接中断则无法证明请求是否产生影响:读取请求会重试,同一操作重复执行结果相同的请求(属性更新、移动、整页内容替换)也会重试;其余请求会以 outcome_unknown 失败(notionApi.ts 标明了哪些请求属于哪一类)。401 会重试一次,重试前会重新读取令牌文件。
  • 缓存:数据源的列缓存 1 分钟,工作区的用户缓存 5 分钟。
为什么使用 REST,而不使用托管 MCP

Notion 会将每个令牌限定在一个工作区内,托管 MCP 也不例外,因此单次登录无法访问多个工作区。托管 MCP 的数据源查询取决于计划,它会转发本仓库未建模的工具,而且其刷新令牌可能失效,需要人工处理。个人访问令牌也可以通过 REST 以用户身份操作,每年续期一次。

scripts/smoke.ts 以只读方式运行已构建的服务;添加 --write 则会写入并移至垃圾桶一个页面。

限制

  • 列只能添加,不能重命名或删除;汇总、唯一 ID 和按钮需在 Notion 应用中创建。无法写入人员列。
  • **会议转录文本不会标明发言者或发言时间。**API 会将其作为纯文本 paragraph 块提供(API 2026-03-11,@notionhq/client 5.27.0,其类型定义中没有发言者字段),但 Notion 应用会显示发言轮次和时间戳。
  • 页面只能在自己的工作区内移动;Notion 不支持在工作区之间移动页面。
  • query_database 每次最多返回 1,000 行(之后使用 nextCursor),count_rows 每次查询最多读取 Notion 的 10,000 行限制。
  • 上传采用单部分传输,每个文件最多 20 MiB;下载上限为 50 MiB。
  • 无法将托管在 Notion 上的文件写回文件列,因此向此类列添加内容需要设置 replace: true,否则文件会进入正文。

其他 Notion 服务

检索日期:2026-10-15;重新查阅 Notion 的 MCP 页面日期:2026-10-18。

  • Notion 的托管服务(mcp.notion.com,Streamable HTTP)需要在浏览器中通过 OAuth 登录,且每个连接只能访问一个工作区;只有 Enterprise 工作区可以通过其身份提供商免浏览器登录。其工具集最全面(视图、文件上传、数据源上的 SQL、Custom Agent 会话)。AI 搜索和数据源上的无限 SQL 需要配备 Notion AI 的 Business 或 Enterprise 计划;所有计划均可查询已保存的视图。
  • @notionhq/notion-mcp-server 是 Notion 的开源服务(stdio 或 HTTP,通过环境变量传入一个令牌),目前已不再积极维护。
  • npm 上的 notion-mcp-server 是功能最强的社区服务:通过一个令牌使用 stdio 或 HTTP,提供 3 个工具,涵盖 47 种操作;支持类型化筛选器,写入操作会根据数据库架构进行检查,还支持模板、视图、文件上传和批量写入。
  • @suekou/mcp-notion-server(stdio,一个令牌)也可以根据架构查询和创建行。
  • notion-multi-workspace 是唯一找到的多工作区服务,目前已归档。

此服务适用于在一个无头服务后接入多个工作区,每个工作区各自使用一个令牌文件:搜索可以一次覆盖所有工作区,输入任意页面或数据库 ID 或 URL 都能找到对应的工作区。它还可以按列值统计匹配的行数,而无需发送这些行;执行整页内容替换时,除非收到明确要求,否则不会接受空正文,并会返回替换前后的块数量。

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。