Last verified: June 2026.
There are two ways to connect Notion to Claude over the Model Context Protocol (MCP), and almost every tutorial only covers one of them. Worse, none of them tell you why the connection succeeds but Claude still says it cannot find any of your pages. This guide covers both paths – the hosted OAuth connector and the self-hosted token route – with the exact config, the scopes that matter, the rate limit you will hit, and the specific error strings that show up when something is wrong. It is written from actually running this, not from reading the docs.
Which Notion MCP should you use: hosted or self-hosted?
Short answer: use the hosted MCP at https://mcp.notion.com/mcp for almost everything. It uses OAuth, so you never handle a token, and it respects your existing Notion permissions automatically. Use the self-hosted npm server with an internal integration token only when you need headless, unattended automation (a cron job, a server with no human to click “Allow”), because the hosted server requires an interactive OAuth approval that a background process cannot complete.
| Factor | Hosted (mcp.notion.com) | Self-hosted (npm + token) |
|---|---|---|
| Auth | OAuth (interactive) | Internal integration token (ntn_) |
| Permissions | Inherits your full Notion access | Only pages you explicitly share |
| Setup time | ~2 minutes | ~10 minutes |
| Headless / cron | No (needs a human to approve) | Yes |
| Best for | Claude Desktop, Claude Code, daily use | Servers, scripts, multi-user backends |
How do I connect Notion to Claude using the hosted MCP?
This is the fast path. No token, no npm.
Claude Desktop / Claude.ai: Open Settings > Connectors, click Add custom connector (or pick Notion if it appears in the directory), and paste the URL https://mcp.notion.com/mcp. A Notion OAuth window opens. Approve it, choose which workspace and which top-level pages the connector may see, and you are done. The scope you pick in that OAuth screen is the whole ballgame – see the gotcha below.
Claude Code (CLI): one command.
claude mcp add --transport http notion https://mcp.notion.com/mcp
Then run /mcp inside Claude Code to trigger the OAuth login. After approving, verify it is live:
claude mcp list
You should see notion with a connected status. If it shows failed or needs auth, run /mcp again and complete the browser flow – the CLI cannot proceed past OAuth on its own.
How do I set up the self-hosted Notion MCP with an integration token?
Use this when you need automation that runs without a human. Three steps: create the integration, get the token, then wire it into your MCP config.
1. Create the integration and copy the token
- Go to
https://www.notion.so/my-integrationsand click New integration. You must be a Workspace Owner – if the button is greyed out, that is why. - Name it, select the workspace, and choose Internal integration type.
- On the integration’s settings page, set Capabilities: Read content, plus Update/Insert content if you want Claude to write. If you only grant Read, every write attempt fails with a permission error later – this is a common self-inflicted wound.
- Click Show, then copy the Internal Integration Token. New tokens start with
ntn_(older ones start withsecret_and still work). Treat it like a password.
2. Add it to your MCP config
For Claude Desktop, edit claude_desktop_config.json (macOS: ~/Library/Application Support/Claude/; Windows: %APPDATA%\Claude\). Add:
{
"mcpServers": {
"notion": {
"command": "npx",
"args": ["-y", "@notionhq/notion-mcp-server"],
"env": {
"NOTION_TOKEN": "ntn_your_token_here"
}
}
}
}
Restart Claude Desktop completely (quit, do not just close the window). On Windows, if npx is not found, use the full path to npx.cmd or run via cmd /c – the config does not inherit your shell PATH.
3. The step everyone forgets: share the pages
An internal integration starts with access to nothing. Creating it and pasting the token is not enough. For every page or database you want Claude to touch, open it in Notion, click the … menu (top right), choose Connections (or Add connections), and select your integration. Access is inherited by child pages, so sharing a top-level page covers its whole subtree. Skip this and Claude will connect cleanly and then truthfully report that it cannot see any content.
What are the most common Notion MCP errors and how do I fix them?
These are the failure messages you will actually see, and what each one means.
“Could not find page” / Claude returns zero results from a workspace that clearly has pages
Cause, in order of likelihood: (1) you did not share the page with the integration (self-hosted), or you scoped the OAuth grant too narrowly (hosted); (2) the page is in a different workspace than the one the integration is tied to. Fix: re-check the Connections menu on the specific page, or re-run the OAuth flow and widen the page selection. An integration token is bound to one workspace – it cannot see another.
API token is invalid (HTTP 401 unauthorized)
The token is wrong, was regenerated, or has a stray space/newline from copy-paste. Re-copy it with the Show button, paste it into the env block with no surrounding whitespace, and restart the client. If you rotated the token in Notion, the old one dies immediately – update every config that used it.
Validation error / “body failed validation” (HTTP 400)
Claude tried to write a property type that does not match the database schema – for example sending plain text into a Select, or a malformed date. This is not a connection problem. Tell Claude the exact property names and types, or ask it to fetch the database schema first before writing.
“Rate limited” / HTTP 429
Notion enforces roughly 3 requests per second per integration (averaged, with short bursts tolerated). Bulk operations – “update 200 rows,” “scan every page” – blow straight through this. The fix is pacing, not a bigger plan: have Claude batch in small groups and add a short delay between calls. If you are scripting around the MCP, honor the Retry-After header on a 429 instead of hammering.
spawn npx ENOENT (server will not start, self-hosted)
Node/npx is not on the PATH the client sees. Install Node, then point command at the absolute path to npx (or npx.cmd on Windows). This is the number-one self-hosted startup failure.
MCP server shows “failed” in claude mcp list right after adding it
For the hosted server this almost always means OAuth was never completed – run /mcp and approve in the browser. For the self-hosted server it means the process crashed on launch; run the npx command manually in a terminal to see the real stack trace.
What can Claude actually do with Notion once connected?
With read + write capabilities granted, Claude can search your workspace, read pages and databases, create pages, append blocks, and update properties on existing rows. Practical things that work well: “summarize this Notion doc,” “create a row in my tasks database with these fields,” “find every page mentioning X and list the links,” “turn this conversation into a meeting-notes page.” Things that get awkward: very large pages (the response can get truncated – verify the write actually landed by fetching it back), and bulk edits that trip the rate limit. A reliable habit is to treat Notion as the source of truth and have Claude verify by re-fetching after any write, because timeouts on big pages can commit silently and still return a malformed response.
Security notes from running this in production
- Scope the OAuth grant tightly. The hosted connector inherits whatever you approve. If you only need one project area, share only that top-level page, not the whole workspace.
- Never hardcode the token in a file you might commit. Keep
ntn_tokens in an env var or your OS secret store, and reference them from config. If a token leaks, revoke it in my-integrations immediately – revocation is instant. - Grant the minimum capability. If Claude only needs to read, do not enable insert/update. You can always widen it later.
- Audit which integrations have access to sensitive databases periodically; the Connections menu on each page shows the current list.
If you are wiring up several connectors at once, the mechanics generalize – see our broader Claude MCP setup guide for the config patterns that apply across servers, and the AI operator’s stack for how Notion fits alongside the other tools day to day. If your reason for connecting Notion is to get your own content cited by AI systems, the structure of the pages matters as much as the wiring – see how AI engines cite content.
FAQ
Do I need a paid Notion plan to use the MCP?
No. The API and integrations work on free Notion workspaces. You do need to be a Workspace Owner to create an internal integration.
Why does Claude say it connected but can’t find my pages?
Almost always the page-sharing step. A self-hosted integration has access to nothing until you add it via the page’s Connections menu. For the hosted connector, you scoped the OAuth approval too narrowly – re-run it and select more pages.
What is the Notion API rate limit?
About 3 requests per second per integration, averaged over time with small bursts allowed. Exceeding it returns HTTP 429. Pace bulk operations and respect the Retry-After header.
What does the ntn_ prefix mean on my token?
It is the current internal integration token format. Tokens created today start with ntn_; older secret_ tokens still function and do not need to be replaced.
Can the hosted Notion MCP run in a headless cron job?
No. The hosted server requires interactive OAuth approval, which an unattended process cannot complete. Use the self-hosted npm server with an ntn_ token for headless automation.
How do I let Claude write to Notion, not just read?
Enable Update content and Insert content under the integration’s Capabilities (self-hosted), or approve write scope during OAuth (hosted). Read-only is the default and will reject every write with a permission error.
Where do I put the Notion MCP config for Claude Desktop?
In claude_desktop_config.json – ~/Library/Application Support/Claude/ on macOS, %APPDATA%\Claude\ on Windows. Add a notion entry under mcpServers and fully restart the app.
Can one integration access two workspaces?
No. An internal integration is bound to the single workspace it was created in. For a second workspace, create a second integration (or a second OAuth grant on the hosted connector).
Related reading from operators who run AI tooling daily: Claude Code vs Cursor, Claude Code vs Codex, and Claude in Chrome for LinkedIn automation.
Leave a Reply