Notion MCP 接 Claude Code — 官方那個 OAuth 外掛,反而是最不該用的接法
想把 Claude Code 接上 Notion,第一個該做的決定,是跳過 Notion 官方那個 OAuth 外掛。
這句話聽起來不太對。官方推薦的、長得最正規的、會自動幫你管 token 的那個接法,怎麼會是最不該選的?但你真的去接一次就知道了——那條看起來最體面的路,會在三個不同的地方斷給你看,而旁邊那條土到不行、要你自己去後台複製一串鑰匙的路,三步就接上,而且接上之後再也不掉線。
這篇就是要講為什麼。順便把接上之後你還會踩的幾個坑,一次說完。
那個體面的接法,是怎麼一步步斷掉的
先還原現場。你照官方文件走,用 OAuth 外掛(plugin:Notion:notion)連,瀏覽器跳出來叫你授權,你按下「允許」——然後第一個東西就炸了:
Internal Server Error。Notion 的 OAuth 回呼在這一步直接掛掉,連錯誤訊息都懶得給你細節。
你想說可能是一時的,重試。這次走得遠一點,到了 token 交換階段,跳出來的是 MCP OAuth requires a redirect_uri (invalid_grant)。翻成人話:拿授權碼去換正式 token 的時候,那個「換完要把你導回哪裡」的網址對不上,整個交換作廢。
你不死心,繞過外掛,自己用 HTTP transport 把 Bearer Token 塞進去。結果 MCP 回你 Needs authentication——token 明明帶了,它說沒帶。
三次,三個不同的死法。重點來了:這不是你設定錯。你每一步都照做了。問題出在 OAuth 這個機制本身,被硬塞進了一個它根本不適合的場景。
為什麼是機制的問題,不是你的問題
OAuth 的 redirect_uri 那一套,是為「瀏覽器上的網站」設計的。你在網站 A 點「用 Google 登入」,Google 驗證完,要有一個明確的網址把你導回網站 A——那個網址就是 redirect_uri。整套流程預設你有一個跑在固定網址上、隨時能接收回呼的伺服器。
現在把這套搬到你的筆電上。你的 Claude Code 是一個本地的命令列程式,它沒有一個對外的、固定的網址等著被導回去。OAuth 硬要在這種環境裡走完「跳瀏覽器 → 授權 → 拿碼 → 換 token → 導回」這一整圈,每一段都是一個可能斷掉的接點。redirect_uri 對不上、回呼接不到、token 交換失敗——你遇到的三個錯,全都長在這條多出來的迴圈上。
說穿了,OAuth 在這裡解決的是一個你根本沒有的問題:「怎麼讓一個你不完全信任的第三方網站,在不拿到你密碼的情況下臨時借用你的帳號」。但這台機器是你的,這個 Claude Code 是你自己裝的,你要授權的對象就是你自己。為了這件事去跑一整套為陌生人設計的安全握手,剛好就是複雜度的來源——而複雜度一定來自某個你不需要的妥協。
對的接法:把鑰匙直接給它
正確的做法,是繞開 OAuth,用 stdio transport + Internal Integration 的 API Key。一行指令:
1 | claude mcp add notion-local -s user \ |
差別在哪?OAuth 像是去大樓櫃台辦一張會自動續期的感應門禁卡——聽起來方便,但你遇到的是那台發卡機壞了,卡辦不出來。API Key 則是直接給你一把實體鑰匙:它很土,會過期要你自己換,得自己收好別弄丟,但你拿著它,門當場就開。在你自己的大樓裡,要進自己的辦公室,你要的就是這把鑰匙,不是一套門禁系統。
-s user 那個參數順手講一下:它讓這個設定變成全域生效,所有專案、所有 session 自動載入,不用每開一個新資料夾就重設一次。設定一次,到處都在。
接上之後,/mcp 指令會列出來確認 notion-local 是不是 connected。是的話,叫 Claude 隨便搜一頁 Notion,回得了就成了。
接上不是終點,這裡還有四顆地雷
很多教學講到「連上了」就收尾,好像連上就贏了。但 Notion MCP 真正會讓你卡半天、又查不到原因的坑,全在連上之後。先把它們攤開,省得你之後對著螢幕罵髒話。
第一顆,-t 旗標是個騙局。 你可能會直覺地想用 -t <token> 把 token 帶進去。它不會報錯,看起來像吃進去了——然後給你一個 401 Unauthorized。@notionhq/notion-mcp-server 的 -t 旗標實際上會被靜默忽略,token 一定要走 NOTION_TOKEN 環境變數。靜默失敗是最難 debug 的那種失敗,因為它不哭不鬧,只是默默不幹活。記住這條,省下你一個小時。
第二顆,授權要授在最上層的頁面。 Notion 的 Internal Integration 是頁面級授權:你得手動到頁面右上角的「⋯ → Connections」把你的 integration 連上去。關鍵是這個權限是向下繼承的——授權父頁面,所有子頁面自動跟著有權限;只授權某個子頁面,它的兄弟頁面照樣碰不到。所以正確做法是直接在 workspace 最頂層那頁授權,一次蓋住底下所有東西。還有個容易誤判的細節:沒授權的頁面回給你的是 404 object_not_found,不是 403。它不會說「你沒權限」,它會說「查無此頁」,害你以為是 ID 打錯,其實是沒授權。
第三顆,Database ID 不等於 Data Source ID。 這顆最陰。Notion 的 REST API(v2022-06-28)給你的是 Database ID,但 MCP Server(v2025-09-03 那套工具)吃的是 Data Source ID,兩個是不同的東西。你拿 REST API 的 Database ID 丟進 MCP 工具,回你 404,然後你會開始懷疑人生,以為是權限又出問題。其實只是 ID 拿錯版本。要 Data Source ID,得透過 MCP 自己的搜尋功能去取,不能從 REST API 那邊複製過來。
第四顆,MCP 能寫的格式少得可憐。 這個會直接影響你打算拿它做什麼。@notionhq/notion-mcp-server 的 API-patch-block-children 目前只支援兩種區塊:paragraph(段落)和 bulleted_list_item(項目符號)。就這兩種。heading、code、table、callout、toggle、quote、編號清單——全部寫不出來。你想叫 Claude 幫你在 Notion 整理一份帶標題、帶程式碼區塊、帶表格的漂亮筆記?透過純 MCP 辦不到。
這顆地雷踩不踩得到,要看你在哪用:
- 用 Claude Code(CLI):不受限。CLI 可以直接開 Bash 跑 Python 或 curl,繞過 MCP 直接打 Notion REST API,要什麼格式有什麼格式。
- 用 Claude Desktop(例如 cowork 排程):受限。Desktop 環境只能透過 MCP 工具,被卡死在那兩種區塊裡。
如果你剛好是在 Desktop 環境、又非得寫出豐富格式,真正的解法是自己包一層——寫一個小小的自訂 MCP Server,內部直接呼叫 Notion REST API:
1 | # 概念示意:自訂 MCP Server 的核心邏輯 |
當然,要不要為了排版去自建一個 server,得看你寫的頻率。一個月手動排一次版,那就讓 MCP 建好骨架、你事後在 Notion 裡手動調格式就好;天天大量產出,才值得花那個工把 server 包起來。
一個比 Notion 更通用的判準
把這篇從頭到尾看下來,會發現它其實在講一件比「怎麼接 Notion」更大的事。
當一個工具同時給你兩條路——一條「自動、體面、但中間經過很多層」,一條「手動、土、但路很短」——在你自己機器上做本地開發這個場景,選短的那條。體面的自動化(OAuth 自動換 token、回呼、refresh)是為「伺服器上跑、很多人用、要長期無人值守」設計的;那種場景下,多那幾層換來的是省去人工維護。但你一個人在自己的筆電上接一個自己要用的工具,那幾層自動化沒幫你省到任何東西,只是憑空多了三個會斷的接點。
省掉中間商,每砍掉一層,就是少一個半夜會莫名其妙掛掉、又查不出原因的故障點。下次再遇到「官方推薦 vs 看起來很克難」的選擇,先別反射性地選官方那個漂亮的——先問一句:這套自動化解決的問題,是我真的有的問題,還是它預設我會有的問題?
參考資源:
@notionhq/notion-mcp-server(npm)、Notion API 文件、Notion Integrations 管理、Claude Code MCP 文件











































