notion-mcp-server
An MCP server for Notion API with optimized token efficiency and full database property filtering, enabling AI assistants to manage pages, databases, and blocks.
README
notion-mcp-server
English | 日本語
MCP (Model Context Protocol) server for Notion API. Enables AI assistants to interact with Notion pages, databases, and blocks.
API Version: 2025-09-03 (latest)
Why this repository?
Why I Built This
I wanted to use AI agents to process tasks from my Notion database with specific conditions:
"Get tasks where Status = 'Not Started' AND Assignee = 'Alice', sorted by Priority"
Here's what I found with existing options:
| MCP Option | Property Filtering | Token Efficiency | Plan Required |
|---|---|---|---|
| Official Notion MCP | Metadata only (created_at, created_by) / Full (Enterprise+AI) | Good | Notion AI |
@notionhq/notion-mcp-server |
✅ Full support | Large responses | None |
| This repository | ✅ Full support | Optimized | None |
The gap I wanted to fill:
- Full database property filtering (AND/OR, select, checkbox, date, etc.)
- Optimized response sizes for LLM token efficiency
- No plan restrictions
This repository provides property filtering with fields parameter for 90% token reduction.
Quick Start
1. Get a Notion Token
- Go to Notion Integrations
- Click "New integration"
- Give it a name and select the workspace
- Copy the "Internal Integration Token" (starts with
ntn_) - Share the pages/databases you want to access with your integration
2. Configure Your AI Client
Claude Desktop
Add to your configuration (~/.config/claude/claude_desktop_config.json on macOS):
{
"mcpServers": {
"notion": {
"command": "npx",
"args": ["-y", "@atikk-co-jp/notion-mcp-server"],
"env": {
"NOTION_TOKEN": "ntn_xxxxxxxxxxxx"
}
}
}
}
Claude Code
Add to your .mcp.json:
{
"mcpServers": {
"notion": {
"command": "npx",
"args": ["-y", "@atikk-co-jp/notion-mcp-server"],
"env": {
"NOTION_TOKEN": "ntn_xxxxxxxxxxxx"
}
}
}
}
That's it! Restart your AI client and start using Notion.
Features
- Page Operations: Create, retrieve, update, and move Notion pages
- Database Operations: Create, retrieve, update, and query databases with filters and sorts
- Block Operations: Retrieve, update, delete, and append blocks
- Search: Search across pages and databases
- Comments: Create and list comments
- Users: List users and retrieve user info
- Token-Efficient Output: Markdown/simple format reduces token usage by ~96%
- Markdown Input: Create and append content using Markdown (80% fewer input tokens)
API Coverage
⭐ = Markdown input supported (reduces input tokens by ~80%)
📤 = Minimal response (id/url only) - reduces output tokens by ~90%
| Category | Notion API | MCP Tool | Input | Output (default) |
|---|---|---|---|---|
| Pages | ||||
| Create page | create-page 📤 |
JSON | {id, url} |
|
create-page-simple ⭐📤 |
Markdown | {id, url} |
||
| Retrieve page | retrieve-page |
JSON | simple/json | |
| Update page | update-page 📤 |
JSON | {id, url} |
|
| Retrieve page property | retrieve-page-property |
JSON | json | |
| Move page | move-page 📤 |
JSON | {id, url} |
|
| Archive page | archive-page 📤 |
JSON | {id} |
|
| Databases | ||||
| Create database | create-database 📤 |
JSON | {id, url} |
|
| Retrieve database | retrieve-database |
JSON | simple/json | |
| Update database | update-database 📤 |
JSON | {id, url} |
|
| Archive database | archive-database 📤 |
JSON | {id} |
|
| Data Sources | ||||
| Retrieve data source | retrieve-data-source |
JSON | simple/json | |
| Query data source | query-data-source |
JSON | simple/json | |
| Update data source | update-data-source 📤 |
JSON | {id} |
|
| Blocks | ||||
| Retrieve block | retrieve-block |
JSON | markdown/json | |
| Update block | update-block 📤 |
JSON | {id} |
|
update-block-simple ⭐📤 |
Markdown | {id} |
||
| Delete block | delete-block 📤 |
JSON | {id} |
|
delete-blocks-batch 📤 |
JSON | {deleted_count, failed_count} |
||
clear-page-content 📤 |
JSON | {deleted_count, failed_count} |
||
| Retrieve block children | get-block-children |
JSON | markdown/simple/json | |
| Append block children | append-block-children 📤 |
JSON | {block_ids} |
|
append-blocks-simple ⭐📤 |
Markdown | {block_ids} |
||
replace-page-content ⭐📤 |
Markdown | {deleted_count, created_count} |
||
find-and-replace-in-page ⭐📤 |
Markdown | {updated_count, updated_block_ids} |
||
| Comments | ||||
| Create comment | create-comment 📤 |
JSON | {id} |
|
create-comment-simple ⭐📤 |
Markdown | {id} |
||
| List comments | list-comments |
JSON | json | |
| Users | ||||
| List users | list-users |
JSON | json | |
| Retrieve user | retrieve-user |
JSON | json | |
| Retrieve bot user | retrieve-bot-user |
JSON | json | |
| Search | ||||
| Search | search |
JSON | simple/json |
Available Tools
retrieve-page
Retrieve a Notion page by its ID.
Parameters:
page_id(required): The ID of the page to retrieveformat(optional): Output format -"simple"(default) or"json"simple: Returns simplified property values with reduced token usagejson: Returns raw Notion API response
include_content(optional): Include page content as markdown (default: true)
{
"page_id": "page-uuid-here",
"format": "simple",
"include_content": true
}
create-page
Create a new page. Supports two parent types:
- Child page: Use
parent.page_idto create a page under an existing page - Database entry: Use
parent.data_source_idto create a page in a database
Create a child page:
{
"parent": { "page_id": "parent-page-uuid-here" },
"properties": {
"title": {
"title": [{ "text": { "content": "Child Page Title" } }]
}
}
}
Create a database entry:
{
"parent": { "data_source_id": "data-source-uuid-here" },
"properties": {
"Name": {
"title": [{ "text": { "content": "New Page Title" } }]
},
"Status": {
"status": { "name": "In Progress" }
}
}
}
create-page-simple ⭐
Create a new page using Markdown. ~80% fewer input tokens compared to create-page.
Supports two parent types:
- Child page: Use
parent.page_idto create a page under an existing page - Database entry: Use
parent.data_source_idto create a page in a database
Parameters:
parent(required): Either{ page_id }or{ data_source_id }title(required): Page title as a simple stringcontent(optional): Page content in Markdownproperties(optional): Additional Notion propertiesicon(optional): Emoji icon (e.g., "🐛")
Supported Markdown:
- Headings:
# ## ###(#### and beyond → heading_3) - Lists:
-or*(bulleted),1.(numbered) - Checkboxes:
- [ ]/- [x] - Code blocks:
```with language - Quotes:
> - Dividers:
--- - Images:
 - Tables:
| col1 | col2 |with header separator|---|---| - Inline:
**bold**,*italic*,~~strike~~,`code`,[link](url)
Extended Markdown (bidirectional):
- Toggle:
<details><summary>title</summary>content</details> - Callout:
> [!NOTE],> [!WARNING],> [!TIP],> [!IMPORTANT],> [!CAUTION] - Equation:
$$E = mc^2$$(inline/block) - Underline:
<u>text</u>or++text++ - Color:
{color:red}text{/color},{bg:yellow}text{/bg} - Bookmark:
[bookmark](url)or[bookmark:caption](url) - Columns:
:::columns/:::column/::: - Media:
@[embed](url),@[video](url),@[audio](url),@[file](url),@[pdf](url) - Table of contents:
[TOC]
Create a child page:
{
"parent": { "page_id": "parent-page-uuid-here" },
"title": "Meeting Notes",
"content": "## Agenda\n\n1. Review progress\n2. Next steps"
}
Create a database entry:
{
"parent": { "data_source_id": "data-source-uuid-here" },
"title": "Bug Report",
"content": "## Steps to Reproduce\n\n1. Login\n2. Open settings\n\n## Expected Behavior\n\nShould display correctly",
"properties": {
"Status": { "status": { "name": "Open" } }
},
"icon": "🐛"
}
Token Comparison:
| Method | Tokens | Reduction |
|---|---|---|
| create-page (blocks) | ~152 | - |
| create-page-simple (markdown) | ~26 | 83% |
update-page
Update a page's properties, icon, cover, archive status, or lock status.
Parameters:
page_id(required): The ID of the page to updateproperties(optional): Properties to updateicon(optional): Icon (set to null to remove)cover(optional): Cover image (set to null to remove)archived(optional): Set to true to archiveis_locked(optional): Lock the page to prevent edits in the UI
{
"page_id": "page-uuid-here",
"properties": {
"Status": {
"status": { "name": "Done" }
}
},
"is_locked": true
}
query-data-source
Query a data source with optional filters and sorts.
Parameters:
data_source_id(required): The ID of the data source to queryfilter(optional): Filter conditions as a JSON objectsorts(optional): Sort conditions as an arraystart_cursor(optional): Cursor for paginationpage_size(optional): Number of results to return (1-100)format(optional): Output format -"simple"(default) or"json"simple: Returns simplified property values with reduced token usagejson: Returns raw Notion API response
{
"data_source_id": "data-source-uuid-here",
"filter": {
"property": "Status",
"status": { "equals": "In Progress" }
},
"sorts": [
{ "property": "Created", "direction": "descending" }
],
"format": "simple"
}
create-database
Create a new database as a subpage of an existing page.
Parameters:
parent_page_id(required): The ID of the parent pageproperties(required): Database schema with at least one title propertytitle(optional): Database title as rich text arrayicon(optional): Icon for the databasecover(optional): Cover image for the databaseis_inline(optional): If true, creates an inline database
{
"parent_page_id": "parent-page-uuid",
"properties": {
"Name": { "title": {} },
"Status": { "select": { "options": [{ "name": "Todo" }, { "name": "Done" }] } },
"Priority": { "number": {} }
},
"title": [{ "type": "text", "text": { "content": "Task Database" } }]
}
update-database
Update an existing database container (title, description, icon, cover).
Note: For schema (properties/columns) updates, use update-data-source instead.
Parameters:
database_id(required): The ID of the database to updatetitle(optional): New title as rich text arraydescription(optional): New description as rich text arrayicon(optional): Icon (set to null to remove)cover(optional): Cover image (set to null to remove)is_inline(optional): If true, creates an inline databasearchived(optional): Set to true to archiveis_locked(optional): Lock the database to prevent edits in the UI
{
"database_id": "database-uuid-here",
"title": [{ "type": "text", "text": { "content": "New Title" } }],
"is_locked": true
}
retrieve-data-source
Retrieve a data source schema by its ID.
Parameters:
data_source_id(required): The ID of the data sourceformat(optional): Output format -"simple"(default) or"json"
{
"data_source_id": "data-source-uuid-here",
"format": "simple"
}
update-data-source
Update a data source schema (properties/columns).
Parameters:
data_source_id(required): The ID of the data source to updateproperties(optional): Properties to add, update, or delete (set to null)
{
"data_source_id": "data-source-uuid-here",
"properties": {
"NewColumn": { "rich_text": {} },
"OldColumn": null
}
}
search
Search across all pages and data sources.
{
"query": "search term",
"filter": { "value": "page", "property": "object" }
}
Filter values: "page" or "data_source"
get-block-children
Get the child blocks of a page or block.
Parameters:
block_id(required): The ID of the block or page to get children fromstart_cursor(optional): Cursor for paginationpage_size(optional): Number of results to return (1-100)format(optional): Output format -"markdown"(default),"simple", or"json"markdown: Returns human-readable markdown with significantly reduced token usage (~96% reduction)simple: Returns ID + type + markdown content (lightweight, for deletion target selection)json: Returns raw Notion API response
fetch_nested(optional): Whenformat="markdown", fetch nested children blocks recursively (default: false)
{
"block_id": "page-or-block-uuid-here",
"format": "markdown",
"fetch_nested": true
}
Get block IDs for deletion:
{
"block_id": "page-or-block-uuid-here",
"format": "simple"
}
Returns:
{
"blocks": [
{ "id": "abc123", "type": "heading_1", "content": "# Title" },
{ "id": "def456", "type": "paragraph", "content": "Some text" }
],
"has_more": false
}
append-block-children
Append new blocks to a page or block.
{
"block_id": "page-or-block-uuid-here",
"children": [
{
"type": "paragraph",
"paragraph": {
"rich_text": [{ "text": { "content": "New paragraph" } }]
}
}
]
}
append-blocks-simple ⭐
Append blocks using Markdown. ~80% fewer output tokens compared to append-block-children.
Parameters:
block_id(required): The page or block ID to append tocontent(required): Content in Markdownafter(optional): Insert after this block ID
Same Markdown support as create-page-simple.
{
"block_id": "page-or-block-uuid-here",
"content": "# New Section\n\nThis is **important** content with a [link](https://example.com).\n\n- Item 1\n- Item 2\n\n```javascript\nconst x = 1;\n```"
}
Token Comparison:
| Method | Tokens | Reduction |
|---|---|---|
| append-block-children (blocks) | ~201 | - |
| append-blocks-simple (markdown) | ~42 | 79% |
replace-page-content ⭐
Replace all content of a page with new Markdown content. Automatically preserves child_database and child_page blocks.
Parameters:
page_id(required): The page ID to updatecontent(required): New content in Markdowndry_run(optional): Preview which blocks will be deleted without making changes (default: false)
⚠️ Warning: Blocks not representable in Extended Markdown (table_of_contents, synced_block, etc.) will be DELETED. Use dry_run: true to preview before executing.
Use when: You want to completely rewrite page content without finding individual block IDs.
Same Markdown support as create-page-simple.
{
"page_id": "page-uuid-here",
"content": "# New Page Title\n\nThis is the new content.\n\n## Section 1\n\n- Item 1\n- Item 2"
}
Preview deletions (dry run):
{
"page_id": "page-uuid-here",
"content": "# New content",
"dry_run": true
}
find-and-replace-in-page ⭐
Find text in a page and replace it with new content. Supports regex patterns for advanced matching.
Parameters:
page_id(required): The page ID to search infind(required): Text to find (string or regex pattern)replace(required): Replacement text (supports Markdown:**bold**,*italic*, etc.)use_regex(optional): If true, treatfindas a regex pattern (default: false)
Use when: You want to update specific text without rewriting the entire page.
{
"page_id": "page-uuid-here",
"find": "old text",
"replace": "**new text**"
}
With regex:
{
"page_id": "page-uuid-here",
"find": "item\\d+",
"replace": "updated item",
"use_regex": true
}
delete-blocks-batch
Delete multiple blocks by their IDs. Blocks are deleted sequentially to respect API rate limits (3 req/s).
Parameters:
block_ids(required): Array of block IDs to delete (max 100)
Use when: You want to delete specific blocks. Use get-block-children with format="simple" to get block IDs first.
{
"block_ids": ["block-uuid-1", "block-uuid-2", "block-uuid-3"]
}
Returns:
{
"deleted_count": 3,
"failed_count": 0,
"deleted": ["block-uuid-1", "block-uuid-2", "block-uuid-3"]
}
clear-page-content
Delete all content from a page. By default, preserves child_database and child_page blocks.
Parameters:
page_id(required): The page ID to clearpreserve_types(optional): Block types to preserve (default:["child_database", "child_page"]). Set to[]to delete all.
Use when: You want to delete all content from a page without selecting individual blocks.
{
"page_id": "page-uuid-here"
}
Delete everything (including child databases/pages):
{
"page_id": "page-uuid-here",
"preserve_types": []
}
Returns:
{
"deleted_count": 15,
"failed_count": 0
}
create-comment
Add a comment to a page.
{
"page_id": "page-uuid-here",
"rich_text": [{ "type": "text", "text": { "content": "This is a comment" } }]
}
create-comment-simple ⭐
Add a comment using Markdown. Simpler than create-comment.
Parameters:
page_id(required): The ID of the pagecontent(required): Comment in Markdowndiscussion_id(optional): Reply to existing thread
{
"page_id": "page-uuid-here",
"content": "This is **important** with a [link](https://example.com)"
}
Development
# Install dependencies
pnpm install
# Run in development mode
pnpm dev
# Build for production
pnpm build
# Type check
pnpm typecheck
# Lint
pnpm lint
# Format code
pnpm format
# Run tests
pnpm test
# Run tests in watch mode
pnpm test:watch
License
MIT
推荐服务器
Baidu Map
百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。
Playwright MCP Server
一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。
Magic Component Platform (MCP)
一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。
Audiense Insights MCP Server
通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。
VeyraX
一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。
graphlit-mcp-server
模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。
Kagi MCP Server
一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。
e2b-mcp-server
使用 MCP 通过 e2b 运行代码。
Neon MCP Server
用于与 Neon 管理 API 和数据库交互的 MCP 服务器
Exa MCP Server
模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。