notion-mcp
MCP (Model Context Protocol) server that wraps ldraney/notion-sdk — a Python SDK for the Notion API v2025-09-03.
Overview
This project exposes the full Notion Python SDK as MCP tools, allowing AI assistants (Claude, etc.) to interact with Notion workspaces through a standardized tool interface.
Why this over the official Notion MCP servers?
The problem
There are two official Notion MCP implementations:
- Open-source
makenotion/notion-mcp-server(TypeScript) — issues and PRs "not actively monitored," may be sunset in the future - Closed-source hosted MCP at
mcp.notion.com— what Claude Desktop's "Connections > Notion" uses
Neither works reliably. This is well-documented in issues like #142 ("Two Notion MCP servers, neither work well"). The open-source server was abandoned for 3.5 months after the v2025-09-03 breaking API change, shipped a broken v2.0.0 (Dec 2025), and still has open showstopper bugs in v2.1.0.
Comparison
| Official open-source | Official hosted | ldraney-notion-mcp |
|
|---|---|---|---|
| Status | "Not actively monitored" | Closed-source | Actively maintained |
| Language | TypeScript | N/A | Python |
| API version | 2025-09-03 (broken) | Unknown | 2025-09-03 (working) |
| Auth | Bearer token (version header trap) | OAuth only | Bearer token (correct headers always) |
| Serialization | Double-stringifies nested objects (#196) | N/A | Accepts both JSON strings and raw objects |
| Property updates | Blocked by additionalProperties: false (#184) |
Unknown | Works correctly |
| Database queries | retrieve-a-database was missing for 5 weeks |
Some tools gated to Enterprise | query_database auto-resolves data sources |
| Tool count | 22 | ~10 | 26 |
| Convenience tools | None | Limited | archive_page, archive_database, query_database |
| Install | npm | Claude Desktop only | PyPI (uvx), .mcpb (planned) |
Key advantages
- Correct API headers always — Built on
ldraney-notion-sdk, which always sends theNotion-Version: 2025-09-03header correctly - LLM-friendly parameter handling —
str | dictunion types so tools don't break when LLMs pass raw objects instead of JSON strings - Convenience tools — Operations like
archive_page,archive_database, andquery_database(with auto data-source resolution) reduce multi-step workflows to single calls - Works everywhere —
uvx,pip, Claude Code, any MCP-compatible client
SDK Coverage
Every method in notion-sdk maps to an MCP tool, organized by module:
Pages
| Tool | SDK Method | Notion Endpoint |
|---|---|---|
create_page |
create_page() |
POST /v1/pages |
get_page |
get_page() |
GET /v1/pages/{id} |
update_page |
update_page() |
PATCH /v1/pages/{id} |
archive_page |
archive_page() |
PATCH /v1/pages/{id} |
move_page |
move_page() |
POST /v1/pages/{id}/move |
Databases
| Tool | SDK Method | Notion Endpoint |
|---|---|---|
create_database |
create_database() |
POST /v1/databases |
get_database |
get_database() |
GET /v1/databases/{id} |
update_database |
update_database() |
PATCH /v1/databases/{id} |
archive_database |
archive_database() |
PATCH /v1/databases/{id} |
query_database |
query_database() |
auto-resolves data source, then POST /v1/data_sources/{id}/query |
Data Sources
| Tool | SDK Method | Notion Endpoint |
|---|---|---|
get_data_source |
get_data_source() |
GET /v1/data_sources/{id} |
update_data_source |
update_data_source() |
PATCH /v1/data_sources/{id} |
query_data_source |
query_data_source() |
POST /v1/data_sources/{id}/query |
list_data_source_templates |
list_data_source_templates() |
GET /v1/data_sources/{id}/templates |
Blocks
| Tool | SDK Method | Notion Endpoint |
|---|---|---|
get_block |
get_block() |
GET /v1/blocks/{id} |
get_block_children |
get_block_children() |
GET /v1/blocks/{id}/children |
append_block_children |
append_block_children() |
PATCH /v1/blocks/{id}/children |
update_block |
update_block() |
PATCH /v1/blocks/{id} |
delete_block |
delete_block() |
DELETE /v1/blocks/{id} |
Users
| Tool | SDK Method | Notion Endpoint |
|---|---|---|
get_users |
get_users() |
GET /v1/users |
get_self |
get_self() |
GET /v1/users/me |
Comments
| Tool | SDK Method | Notion Endpoint |
|---|---|---|
create_comment |
create_comment() |
POST /v1/comments |
get_comments |
get_comments() |
GET /v1/comments |
Search
| Tool | SDK Method | Notion Endpoint |
|---|---|---|
search |
search() |
POST /v1/search |
26 tools total covering the complete Notion API v2025-09-03 surface.
Architecture
notion-mcp/
├── src/
│ └── notion_mcp/
│ ├── server.py # MCP server entry point
│ ├── tools/
│ │ ├── pages.py # Page tools
│ │ ├── databases.py # Database & data source tools
│ │ ├── blocks.py # Block tools
│ │ ├── users.py # User tools
│ │ ├── comments.py # Comment tools
│ │ └── search.py # Search tools
│ └── ...
├── tests/
├── pyproject.toml
└── README.md
Each tool module mirrors the SDK's mixin structure, keeping a clean 1:1 mapping.
Prerequisites
- Python >= 3.10
- A Notion integration API key (
NOTION_API_KEY) notion-sdk(installed as a dependency)
Setup
# Clone
git clone https://github.com/ldraney/notion-mcp.git
cd notion-mcp
# Install
pip install -e .
# Configure
export NOTION_API_KEY="ntn_..."
Usage
With Claude Code
Add to your Claude Code MCP config (~/.claude/settings.json or project settings):
{
"mcpServers": {
"notion": {
"command": "python",
"args": ["-m", "notion_mcp"],
"env": {
"NOTION_API_KEY": "ntn_..."
}
}
}
}
Standalone
python -m notion_mcp
Related
ldraney/notion-sdk— The underlying Python SDK this server wraps
Metadata
Release files for ldraney-notion-mcp 0.1.12
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| ldraney_notion_mcp-0.1.12.tar.gz | 21.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| ldraney_notion_mcp-0.1.12-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 36.4 kB
Release files / ldraney_notion_mcp-0.1.12.tar.gz
| Download URL | ldraney_notion_mcp-0.1.12.tar.gz |
|---|---|
| Size | 21.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
48aed5517eb9dae7dffd5f4b9cdf500a0dff4f9a04caa9ac823b8ddc7754c72d
|
|
BLAKE2b-256 checksum How to use checksums |
5c65f109413ca3b99462688412975d4bd12cf1f120d9a7ab1cd916c1ec7fbebf
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Feb 11, 2026.
Transparency logRelease files / ldraney_notion_mcp-0.1.12-py3-none-any.whl
| Download URL | ldraney_notion_mcp-0.1.12-py3-none-any.whl |
|---|---|
| Size | 15.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
d04edf54f290ff08ba5b6875a99566db943341fb55db707b8c2c5d9d11bcb7f5
|
|
BLAKE2b-256 checksum How to use checksums |
5a8c5421668b0f7384178625a7adc3a962984043645a9b6babe09f81449343f0
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Feb 11, 2026.
Transparency log