Notion CLI
Agent-First Notion CLI + MCP server (Rust). Fixes @notionhq/notion-mcp-server's create_a_data_source failure on Notion API 2025-09-03+.
Ask AI about Notion CLI
Powered by Claude Β· Grounded in docs
I know everything about Notion CLI. Ask me about installation, configuration, usage, or troubleshooting.
0/500
Reviews
Documentation
notion-cli
An agent-first Notion CLI and MCP server, purpose-built for the Notion API 2025-09-03+ data-source model. Three-tier MCP privilege model: read-only default, runtime writes, admin lifecycle.
Features
- Three-tier MCP β read-only default (7 tools),
--allow-writeruntime CRUD (13 tools),--allow-adminlifecycle ops (18 tools) - Admin lifecycle β
db create,db update(incl. parent move via PATCH),ds update(single-delta: add/remove/rename-property + add-option + bulk),ds add-relation(dual/single/self),page movevia dedicated/moveendpoint - Bot self-identity β
users me(MCPusers_meRO tool) returns the bot's own identity without enumerating workspace PII - Universal
--json <body>β zero-translation agent path on all 7 mutation commands; stdin /@file/ literal modes; mutually exclusive with bespoke flags (exit 2 on mixed) - NDJSON streaming β
--stream/--format=jsonlon 5 paginated commands (ds query,block list,search,users list,comments list) with explicititem/end/errorframes --check-request --costβ API call count + rate-limit window preview without contacting Notion- Field-mask page reads β
page get --properties <ids>(Notionfilter_properties) andpage get-property <page> <prop-id>for paginated relation/rollup/people properties - Observability β per-request UUID v7
request_idpropagated to audit log;tracingsubscriber; OTel exporter behind cargo featureotel - GET response cache β opt-in via
NOTION_CLI_CACHE_TTL; writes auto-invalidate by entity - Idempotency-Key β auto-generated on POST/PATCH; MCP callers can override via
idempotency_keyparam - Token chain β env β file β keychain (macOS) β exec; stderr warning on shadowing
- CLI-only surfaces β
users list/get,comments list/create(not exposed over MCP; privacy / scope) - Page body & icon/cover β
page create --childrenfor one-shot page + body;page update --icon/--covertristate (set / clear / leave) - CLI + MCP β same tool surface accessible via shell commands or as an MCP stdio server
- Agent-friendly output β responses wrapped in an untrusted-source envelope with trust metadata;
--rawfor clean piping - Rate limiting β built-in 3 req/s token bucket with 429
Retry-Afterretry (configurable) - Response size cap β 10 MiB streaming limit prevents OOM on large payloads
- Schema introspection β
notion-cli schema <type>emits JSON Schema for 22 property types, 12 block types, and more - Two-sink audit log β
NOTION_CLI_AUDIT_LOGfor runtime writes +NOTION_CLI_ADMIN_LOGfor admin ops; each entry carries aprivilegefield - Destructive safety gate β TTY-aware prompt on interactive shells; non-TTY requires
--yes. MCP admin destructive ops gated byconfirm=true+NOTION_CLI_ADMIN_CONFIRMED=1env (two-factor) - Actionable error hints β common Notion validation errors get one-line remediation suggestions
- Structured exit codes β stable numeric codes (0/2/3/4/10/64/65/74) for scripting and CI
- Newtype ID validation β accepts 32-hex, dashed UUID, or full Notion URLs; rejects homoglyphs and control characters
--check-requestβ validate and preview request payloads locally without contacting Notion
Quick Start
# Install
cargo install --git https://github.com/0xarkstar/notion-cli
# Set your integration token
export NOTION_TOKEN='ntn_...'
# Search across your workspace
notion-cli search 'meeting notes'
# Query a data source with filters
notion-cli ds query <data-source-id> \
--filter '{"property":"Done","checkbox":{"equals":false}}'
Installation
crates.io
cargo install notion-cli-mcp
(The crate is published as notion-cli-mcp; the installed binary is notion-cli.)
Prebuilt binaries (macOS / Linux, aarch64 + x86_64)
curl -LsSf https://github.com/0xarkstar/notion-cli/releases/latest/download/notion-cli-installer.sh | sh
Homebrew
brew install 0xarkstar/tap/notion-cli
ClawHub (for Hermes / OpenClaw agents)
Published as notion-cli-mcp on ClawHub:
clawhub install 0xarkstar/notion-cli-mcp
The skill describes the full tool surface and example payloads for agent consumption.
From source
cargo install --git https://github.com/0xarkstar/notion-cli
Requires Rust 1.85+. Run notion-cli --version to verify.
Usage
Pages
# Retrieve a page (accepts IDs or full Notion URLs)
notion-cli page get https://notion.so/My-Page-abcdef0123456789abcdef0123456789
# Create a page under a data source
notion-cli page create \
--parent-data-source <data-source-id> \
--properties '{
"Name": {"type":"title","title":[{"type":"text","text":{"content":"New page"}}]},
"Status": {"type":"status","status":{"name":"In Progress"}}
}'
# Update properties
notion-cli page update <page-id> \
--properties '{"Status":{"type":"status","status":{"name":"Done"}}}'
# Archive
notion-cli page archive <page-id>
Data Sources
# Retrieve schema and metadata
notion-cli ds get <data-source-id>
# Query with filter, sort, and pagination
notion-cli ds query <data-source-id> \
--filter '{"property":"Priority","select":{"equals":"High"}}' \
--sorts '[{"property":"Due","direction":"ascending"}]' \
--page-size 25
# Create a new data source in a database container
notion-cli ds create \
--parent <database-id> \
--title 'Tasks' \
--properties '{"Name":{"title":{}},"Done":{"checkbox":{}}}'
Search & Introspection
# Full-text search (filter by object type)
notion-cli search 'onboarding' \
--filter '{"property":"object","value":"page"}'
# Retrieve a database container (lists its data sources)
notion-cli db get <database-id>
# Print JSON Schema for property values (all 22 types)
notion-cli schema property-value --pretty
Request Validation
Preview what would be sent without making an API call:
notion-cli --check-request --pretty page create \
--parent-data-source <id> \
--properties '{"Name":{"type":"title","title":[{"type":"text","text":{"content":"test"}}]}}'
No token required for --check-request.
MCP Server
Start as an MCP stdio server for agent integration:
# Read-only (4 tools: get_page, get_data_source, query_data_source, search)
notion-cli mcp
# Full access (7 tools: above + create_page, update_page, create_data_source)
notion-cli mcp --allow-write
# With audit logging
notion-cli mcp --allow-write --audit-log ./notion-audit.jsonl
Agent configuration example
mcp_servers:
notion:
command: notion-cli
args: [mcp, --allow-write, --audit-log, /var/log/notion-audit.jsonl]
env:
NOTION_TOKEN: ntn_xxx
enabled: true
Output Format
Responses are wrapped in a trust-demarcation envelope by default:
{
"source": "notion",
"trust": "untrusted",
"api_version": "2026-03-11",
"content": { ... }
}
This signals to consuming agents that content originates from an external source and should be treated as data, not instructions. Use --raw to strip the envelope, and --pretty for indented output.
Configuration
| Setting | Source | Description |
|---|---|---|
NOTION_TOKEN | env / --token | Integration token (ntn_...) |
NOTION_CLI_AUDIT_LOG | env / --audit-log | Path for write-operation JSONL audit log |
Create an integration at notion.so/my-integrations, then share target pages/databases with it via the Connections menu.
Exit Codes
| Code | Meaning |
|---|---|
| 0 | Success |
| 2 | Validation error |
| 3 | API error |
| 4 | Rate-limited |
| 10 | Auth / config error |
| 64 | Usage error |
| 65 | JSON parse error |
| 74 | I/O error |
Development
cargo test # 130 tests
cargo clippy --all-targets -- -D warnings
cargo llvm-cov --all-targets --summary-only # 80%+ line coverage
cargo audit # 0 advisories
# Live smoke test against a real workspace
export NOTION_TOKEN='ntn_...'
cargo run --example smoke -- <database-url>
Roadmap
- Block CRUD (page body / children)
- NDJSON streaming for paginated queries
--fieldsresponse field masks- YAML configuration file
- Multi-platform binaries via cargo-dist / Homebrew
