Notion

com.foreverworksPublished by foreverworks.comv0.1.1Updated Nov 3, 2026

Search, read and write your Notion workspaces, with pages as Markdown and typed database queries.

The publisher's own server: Notion

Overview

AI-generated overview

Local MCP server that lets an assistant search, read and write several Notion workspaces, with pages as Markdown and typed database queries.

What you can do
  • Search pages and databases by title across all workspaces, list workspaces, users and run a health check
  • Read a page's properties and Markdown body, read blocks, comments and AI meeting-note transcripts
  • Create, update, move, trash and restore pages and rows, and append, find-and-replace or replace page bodies
  • Describe databases, query and count rows, list saved views and templates, and query a view as Notion shows it
  • Add columns and select options, create databases, add comments, upload files and download a page's Notion-hosted files
When to use it
Useful when an assistant should work inside Notion: finding and summarising pages, answering questions about database rows, reading saved views, adding rows or comments, or editing page content. It suits people who keep several Notion workspaces and want one server to reach all of them.
Requirements
Runs locally via npx on Node 22.19 or newer (stdio). Needs a Notion integration token or personal access token per workspace, stored one per file in the folder named by NOTION_TOKENS_DIR (or CREDENTIALS_DIRECTORY). Pages must be shared with the integration. Downloads need NOTION_OUTBOX_DIR; uploads need MCP_FILE_ROOTS. Network access to Notion's API.
Before you install
The token files hold workspace secrets: keep them readable by you alone and never paste tokens into a chat. Write tools change real workspace data: pages and rows are created and edited, comments posted, files uploaded, and pages moved to trash (restorable for 30 days). replace_content cannot be undone through the API. A personal access token acts as you and sees every page you see. Downloads fetch signed file URLs from Notion's storage.

Installation

In SourceWeft

  1. Open Notion in the dashboard and add it to a workspace.
  2. Enable the server for the chats that should use its tools.

Desktop only via STDIO. STDIO servers start a local process, so they need the SourceWeft desktop host.

Other MCP clients

Follow the launch instructions in the repository.

README

[Notion icon] Notion MCP server

Search, read and write your Notion workspaces from your AI assistant, several through one server: pages as Markdown, databases queried and counted by column, saved views, people, comments and files. It creates pages, rows, columns and databases, edits properties and bodies, comments, uploads files, and moves pages to Notion's trash (kept 30 days; restore_page brings them back). No tool is money.

You need a Notion integration per workspace, its token in a file of its own, and your top-level pages shared with it: an integration sees only what you share. Uploads take files up to 20 MiB (5 MiB on Notion's Free plan).

What you can ask

  • "Find the Q3 roadmap page in my work workspace and summarise it."
  • "How many rows of the Tasks database are in each Status?"
  • "Show me my Due this week view."
  • "Add 'Thinking in Systems' to the Reading List with status To read and the tag Books."
  • "In the Onboarding page, replace 'Slack' with 'Mattermost' everywhere."
  • "Download the PDFs attached to the Client SRL row of the Contracts database."

Install

[Install in VS Code] [Install in Cursor] [Download for Claude Desktop]

With Claude Code:

bash
claude mcp add notion -e NOTION_TOKENS_DIR="<path to Notion tokens folder>" -- npx -y @foreverworks/mcp-notion

Claude Desktop (Settings, Developer, Edit Config) and most other clients read the same command as JSON:

json
{  "mcpServers": {    "notion": {      "command": "npx",      "args": ["-y", "@foreverworks/mcp-notion"],      "env": {        "NOTION_TOKENS_DIR": "<path to Notion tokens folder>"      }    }  }}

Each runs the published package on Node 22.19 or newer. VS Code and the Claude Desktop bundle ask for NOTION_TOKENS_DIR as they add the server. Cursor reads it from your environment instead (${env:NOTION_TOKENS_DIR}), so set it before you start Cursor. Configuration says what it holds.

From a clone

bash
git clone https://github.com/foreverworks/mcps.git && cd mcpsnpm ci && npm run buildclaude mcp add notion -e NOTION_TOKENS_DIR="<path to Notion tokens folder>" -- node "$PWD/servers/notion/dist/index.js"

In a JSON configuration, the command is node and its one argument the full path of servers/notion/dist/index.js. To share one running copy between several clients over HTTP, see docs/deploying.md.

Over HTTP, a deployment that limits its hosts sets MCP_EGRESS_ALLOW=api.notion.com,prod-files-secure.s3.us-west-2.amazonaws.com,s3.us-west-2.amazonaws.com: Notion's API and the hosts its files are served from.

Configuration

VariableRequiredMeaning
NOTION_TOKENS_DIRyes, or CREDENTIALS_DIRECTORYA folder holding one file per workspace, notion-<label>, each holding that workspace's token and nothing else.
CREDENTIALS_DIRECTORYRead when NOTION_TOKENS_DIR is unset: under systemd, LoadCredential=notion-<label>:<path> puts the same files there, readable by the unit alone.
NOTION_OUTBOX_DIRfor download_filesThe folder downloaded files are saved in, which the server writes and you read. Unset, download_files answers a config error naming it; every other tool works.

Each file is a workspace: notion-personal and notion-work are labelled personal and work, and the server names the labels it found at start. A label is lower-case letters, digits and hyphens; an empty file is skipped. There is no default folder, so a test or a hand-run copy cannot reach a workspace by accident. The files are re-read at most once a minute, and at once after a refused token, so a new token needs no restart. The variables every server shares (transport, limits, MCP_FILE_ROOTS for uploads) are in docs/configuration.md.

Getting a token

For each workspace:

  1. Open https://www.notion.so/profile/integrations, signed in to that workspace, and create a new internal integration.
  2. Turn on the capabilities the assistant needs: read, update and insert content for pages and databases, and the comment capabilities for comments. People's emails appear only if it may read user information with email addresses.
  3. Copy its Internal Integration Secret straight into notion-<label> in your tokens folder, readable by you alone (mode 0600). Do not paste it into a chat.
  4. Share your pages with the integration, which starts out seeing nothing. In Notion, open each top-level page the assistant should reach, then the ••• menu, Connections, and add the integration. Pages under it inherit the access; a new top-level page must be shared the same way.

A personal access token works in the same file instead (made at https://www.notion.so/developers/tokens, signed in to the workspace, with the Notion API capability). It acts as you: it sees every page you see, with nothing to share, and can create private top-level pages, which an integration cannot. It expires within a year.

First run

Ask your assistant to run Notion's health check. Per workspace, it says whether the token is accepted, the workspace and integration names, and whether the integration sees any page yet; if not, do step 4 above.

From a shell, node dist/index.js --health prints one NOTION: line per workspace and exits 0 when all is well, 1 when a person has to act (a refused token, a missing capability), and 2 for a warning (an integration that sees nothing yet, or Notion unwell), which suits a timer.

Tools

read changes nothing; write changes something in a workspace. A tool that takes an id also takes a Notion URL, and finds the workspace itself.

Workspaces and search

ToolAccessWhat it does
list_accountsreadThe workspaces with a token file, by label. No request to Notion.
healthreadPer workspace: the token accepted, the workspace and integration names, whether it sees any page yet.
list_usersreadThe people (and bots) of every workspace: id, name, and email when the token may read it; narrowed by a word.
searchreadPages and databases by title, in every workspace at once, each hit tagged with its workspace.

Pages

ToolAccessWhat it does
read_pagereadA page's properties as plain values and its body as Notion's Markdown.
read_blocksreadThe blocks directly inside a page or a block: id, type, plain text. A meeting-notes block names the blocks holding its summary, notes and transcript.
create_pagewriteA row in a database, checked against its columns (or started from one of its templates), or a child page; either with a Markdown body.
update_pagewriteA page's properties and icon.
append_contentwriteMarkdown at the end, the start, or after a passage.
edit_contentwriteFind and replace in a page's Markdown.
replace_contentwriteA page's whole body; an empty one only with clear. Answers with the page's title and its block count before and after.
move_pagewriteUnder another page or into a database, within one workspace.
trash_page / restore_pagewriteInto Notion's trash (kept 30 days) and back. A database template only with allow_template.

Databases

ToolAccessWhat it does
describe_databasereadA database's tables and columns: types, options, status groups, relation targets, formulas.
query_databasereadRows, filtered by where (typed from the schema) or Notion's own filter, sorted, up to 1,000 in one call.
count_rowsreadHow many rows match, and per value of a column ("tasks per status"), without sending the rows.
list_viewsreadA database's saved views: id, name, type, and the filter and sorts saved in each, columns by name.
query_viewreadThe rows a saved view shows, in its order, filtered exactly as Notion applies it, with the view's total.
list_database_templatesreadA database's page templates: their page ids, names and which is the default.
add_columnwriteA column on a database: a free name, a type and its settings (options, number format, formula, relation), checked against the table first.
add_optionswriteOptions on a select, multi-select or status column; the ones there are kept by id and the column is read back after.
create_databasewriteA database under a page, with its title column and other columns, each checked against the others first.

Comments and files

ToolAccessWhat it does
get_commentsreadA page's open comments.
add_commentwriteA comment on a page, or a reply in a discussion.
upload_filewriteA file by path, uploaded to a row's files column or into a block at the end of a page's body; answers its size and SHA-256.
download_filesreadA page's Notion-hosted files (its files columns and the file blocks of its body) saved to the outbox, each with its SHA-256.

test/tools.snapshot.json pins what a client lists; a diff there is a breaking change.

Troubleshooting

health says "the integration sees no page yet", or a call answers not_shared. Notion answers the same 404 for an id that does not exist and a page not shared with the integration. Check the id, then share the page (step 4 of Getting a token); sharing a top-level page shares everything under it.

auth. The token was refused: revoked, or a personal access token past its expiry. Put a new one in the notion-<label> file; the next call reads it.

forbidden. The integration lacks a capability for this call. Turn it on at https://www.notion.so/profile/integrations (step 2 of Getting a token).

config. No token files where NOTION_TOKENS_DIR points, an unreadable one, or one holding more than one token. For download_files, set NOTION_OUTBOX_DIR.

input from create_page with no parent. Notion refuses a top-level page from an integration; give a parent page, or use a personal access token. Any other input names what to fix, and nothing changed.

outcome_unknown. An append, a find-and-replace, a new page or a comment lost its answer; it is never resent blind. Read the page (or search for a new one) before writing again: the change may be there.

conflict: someone edited the same object at that moment; read it again, then retry. rate_limited: Notion still throttles after the retries (180 requests a minute on the Free plan); wait a minute. api: Notion was unreachable or failed; retry later. With reason: "drift" its answer changed shape: please report it.

How it works

An id finds its own workspace

An id lives in exactly one workspace, so src/app/locate.ts asks each until one answers; a 404 from all is not_shared. Every id found, or revealed by a search or query, is remembered while the process runs, so misses are paid once. A URL may be on notion.so, notion.site or app.notion.com; ?p= names a page open over a database.

A database is named by its own id or its data source's (search gives both). Since API 2025-09-03 a database holds data sources, nearly always one; with several, source names the table, and omitting it is refused with their names.

The values an agent sees

Notion typeOutIn
title, rich_textstringstring, split into 2000-character runs (Notion's limit), never inside a character
numberthe JSON number Notion senta finite number
select, statusoption namean option that exists, matched ignoring case; a new select option only with allow_new_options; a new status never (the API cannot make one)
multi_selectnamesnames, same rule
date{start, end?, timeZone?}YYYY-MM-DD, an ISO date-time, or {start, end, time_zone}
checkboxbooleanboolean
url, email, phone_numberstringstring; empty clears it
relationpage ids, all of thempage ids or URLs, 100 at most
files[{name, url, expiresAt?}]external URLs; a file of your own goes in with upload_file
people, created_by, last_edited_by{id, name}, the name from the workspace's users when the page gave only the idrefused
formula, rollup, created/edited time, unique_id (PREFIX-12)the computed valuerefused: Notion computes it
buttonleft out: it has no valuerefused

Empty values are left out of a page or row (describe_database lists every column). A page object lists at most 25 pages of a relation; read_page reads the rest from the property endpoint (up to 1,000), and a query row lists such a column under truncated. The server does no arithmetic on numbers.

where

Notion's filter keys a condition by the column's type, which agents get wrong. where names the column, an op and a value, and takes the type from the schema:

json
{"where": [{"property": "Status", "op": "equals", "value": ["In progress", "Blocked"]},           {"property": "Due", "op": "next_week"}], "match": "all"}

An op the type lacks, or an option that does not exist, is refused with what exists, before any request. A person column takes a name, an email, a user id or "me". A name is matched against the workspace's users, exactly first, then as part of one person's name; one that two people share or nobody has is refused with who fits. notion_filter takes Notion's own filter object for what where cannot say, ANDed with it.

Templates

Search returns templates as ordinary pages, and a template shapes every future row, so list_database_templates names them and trash_page refuses one without allow_template. create_page with template checks it against that database's templates. Notion fills the row right after making it, so read_page a moment later shows the result. Properties given beside a template are kept; a Markdown body is refused, since it would race the template's.

Changing a database's columns

add_column, add_options and create_database check the request against the table as it is, before sending: a name already taken, an option already there, a setting the type lacks, a formula without its expression, a relation without its target, more than Notion's 100 options. Notion documents a schema update's option list as the options to set, so add_options sends back every current option by id, then the new ones, and reads the column back: an option that went missing fails the call.

Files

upload_file takes a file by path inside MCP_FILE_ROOTS, or as base64 with its SHA-256 from a script, never as text a model types. In a row's files column it joins the files there; otherwise it becomes a block at the end of the body (an image, a PDF, a video or a sound, by its type). Notion's API replaces a files column whole and cannot write back a file it hosts, so a column holding Notion-hosted files needs replace: true, which lets them go; external links are always kept.

download_files saves a page's Notion-hosted files to NOTION_OUTBOX_DIR: its files columns and the file, image, PDF, video and audio blocks of its body, nested ones included (the first 1,000 blocks). Notion's links are signed URLs valid for an hour, fetched over https without the workspace's token or following redirects. External links are listed, never fetched, since they can point anywhere.

Saved views

query_view runs a view as Notion does, quick filters and me included. Notion answers with page ids only and keeps the result about 15 minutes, so query_view reads each row itself (25 by default, up to 100 a call), and nextCursor reads on in the same result. Once that result expires, the tool says to start again; a row trashed or unshared meanwhile is listed under unreadable.

People and meeting notes

On an AI meeting-notes page, read_page with include_transcript answers the summary, notes and transcript as one Markdown text. read_blocks names the blocks behind them, and on transcriptBlockId reads the transcript line by line, each with the block id an AI summary's citations link to.

Replacing a whole body

replace_content cannot be undone through the API, and a model slips on both its arguments: a page id from the wrong row, or a markdown that came out empty. So an empty body needs clear: true, and the answer gives the page's title with blocksBefore and blocksAfter, so a wrong page or a body that shrank to almost nothing shows at once.

The network

  • Version 2026-03-11 in every request: the one with the Markdown endpoints and in_trash.
  • Pacing: an integration gets 180 requests in a fixed minute on the Free plan. A token bucket per workspace (30 at once, then 2.5 a second), shared by every session the process serves, keeps any minute at 180 or under; the workspace-wide limit is left to the 429 backoff and Retry-After.
  • What is resent: a 429 or a 409 conflict_error proves nothing happened, so every request repeats. A 5xx or a lost connection proves nothing either way: reads repeat, and so does whatever lands the same twice (a property update, a move, a whole-body replace); the rest fail as outcome_unknown (notionApi.ts marks which is which). A 401 is retried once, after the token file is read again.
  • Caches: a data source's columns for a minute, a workspace's users for five.

Why REST and not the hosted MCP

Notion scopes every token to one workspace, the hosted MCP's included, so no single sign-in reaches several. The hosted MCP's data-source query depends on the plan, it relays tools this repository does not model, and its refresh token can die and need a person. A personal access token also acts as the user, over REST, for a renewal once a year.

scripts/smoke.ts drives the built server read-only, or writes and trashes one page with --write.

Limitations

  • Columns are added, never renamed or deleted; rollups, unique ids and buttons are made in Notion's app. People columns cannot be written.
  • A meeting transcript does not say who spoke or when. The API gives it as plain paragraph blocks of text (API 2026-03-11, @notionhq/client 5.27.0, whose types have no speaker field), though Notion's app shows speaker turns and timestamps.
  • A page moves only within its workspace; Notion cannot move one between workspaces.
  • query_database answers at most 1,000 rows a call (then nextCursor), and count_rows reads at most Notion's 10,000 per query.
  • Uploads are single-part, at most 20 MiB a file; downloads stop at 50 MiB.
  • Notion-hosted files in a files column cannot be written back, so adding to such a column needs replace: true, or the file goes into the body.

Other servers for Notion

Searched 2026-10-15; Notion's MCP page re-read 2026-10-18.

  • Notion's hosted server (mcp.notion.com, Streamable HTTP) needs an OAuth sign-in in a browser and reaches one workspace per connection; only Enterprise workspaces can sign in without a browser, through their identity provider. Its tool set is the widest (views, file uploads, SQL over data sources, Custom Agent sessions). AI search and unlimited SQL over data sources need a Business or Enterprise plan with Notion AI; querying a saved view works on every plan.
  • @notionhq/notion-mcp-server, Notion's open-source server (stdio or HTTP, one token in an environment variable), is no longer actively maintained.
  • notion-mcp-server on npm, the strongest community server: stdio or HTTP on one token, three tools over 47 operations, typed filters and writes checked against the database's schema, templates, views, file uploads and batched writes.
  • @suekou/mcp-notion-server (stdio, one token) also queries and creates rows from the schema.
  • notion-multi-workspace, the only multi-workspace server found, is archived.

This one exists for several workspaces behind one headless server, each with its own token file: search covers them all at once, and any page or database id or URL finds its own workspace. It also counts matching rows, per value of a column, without sending them, and its whole-body replace refuses an empty body unless asked and answers with the block counts before and after.

Source: servers/notion/README.md at commit cbd1121

Tools

27

add_column

Add a column

Add a column to a database: a name it does not have yet, a type, and that type's settings (options, a number's format, a formula's expression, a relation's target). Checked against the table as it is now before anything is sent; answers the column as Notion made it. Renaming and deleting columns are left to Notion's app.

Parameterscolumnrequiredsourceaccountdatabaserequired

add_comment

Add a comment

A comment on a page, or a reply in one of its discussions, shown in Notion as the workspace's integration. Not resent after a lost answer (outcome_unknown): get_comments says whether it arrived.

Parameterspagerequiredaccountmarkdownrequireddiscussion

add_options

Add options to a column

Add options to a select, multi-select or status column (a status option in a group: To-do, In progress, Complete). The options already there are kept and sent back by id, and the column is read back after: an option that went missing fails the call. Names already there are skipped and listed under alreadyThere. For one new option while writing a row, create_page's allow_new_options is enough.

Parametersgroupcolumnrequiredsourceaccountoptionsrequireddatabaserequired

append_content

Add to a page

Markdown added to a page's body: at the end (default), at the start, or after a passage. Not resent after a lost answer: that is outcome_unknown, and read_page says whether it went through.

Parametersatpagerequiredafteraccountmarkdownrequired

count_rows

Count rows

How many rows match where, and with by, how many hold each value of one column ("how many tasks per status"), most first; an empty value counts as "(empty)", and a multi-select row counts once per option. Reads the matching rows without sending them, up to Notion's 10,000 per query.

Parametersbymatchwheresourceaccountdatabaserequiredin_trashnotion_filter

create_database

Create a database

Create a database under a page, with a title column and the other columns given, each checked against the others before anything is made (and a relation's target found in the same workspace). Answers its id, URL and table. A database is not created twice: if the answer is lost it is outcome_unknown, and search says whether it exists.

Parameterstitlerequiredinlineparentrequiredaccountcolumnstitle_column

create_page

Create a page

A new row in a database, its properties checked against the columns first (an unknown column or option is refused with the ones that exist), a child page under a page, or with no parent a private page at the top of a workspace (a title and a body, no properties). The body is Notion's Markdown. A row can start from one of its database's templates (template): Notion applies it just after the page is made, so read_page a moment later shows what it filled in. Answers the new page's workspace, id and URL. A page is not created twice: if the answer is lost it is outcome_unknown, and search or query_database says whether it exists.

Parametersicontitleparentsourceaccountmarkdowntemplatepropertiesallow_new_options

describe_database

Describe a database

A database's columns: name, type, the options of a select, multi-select or status (with a status's groups), where a relation points, a formula's expression. Read it before writing where, sort or properties: every one of those names these columns. A database holding several tables (data sources) lists each.

Parametersaccountdatabaserequired

download_files

Download a page's files

Save the files Notion hosts for a page to this server's outbox: its files columns and the file blocks of its body (up to 50 MiB each). Answers each file's path, size and SHA-256, and where it was on the page. External links are listed, not fetched. A file that fails is listed with why, beside the others.

Parametersbodypagerequiredcolumnaccountsave_dir

edit_content

Edit a page

Find and replace in a page's body, in its Markdown as read_page shows it. The smallest change that does the job: the rest of the page, its comments and its history stay as they were. Not resent after a lost answer: that is outcome_unknown, and read_page says whether it went through.

Parameterspagerequirededitsrequiredaccountallow_deleting

get_comments

Get comments

The open comments on a page, oldest first, each with its discussion, author, time and text. Resolved ones are not listed by Notion.

Parameterspagerequiredlimitcursoraccount

health

Health

Ask each workspace: is its integration token accepted, which workspace and integration it is, and whether it sees any page at all (a new integration sees nothing until pages are shared with it). One broken workspace never hides the others' answers. Run this before concluding the server is broken.

Parametersaccount

list_accounts

List accounts

The Notion workspaces this server reaches, by label (one per token file), from the token files alone: no request to Notion. Every other tool finds an id's workspace by itself, so a label is needed only to narrow a search. Says nothing about whether a token works; that is health.

Takes no parameters.

list_database_templates

List database templates

The page templates of a database or data source, with their page ids, names and default flags. Use this catalog to distinguish templates from ordinary rows; search can return both. Inspect their pages before editing recurring content. Follow nextCursor when hasMore is true.

Parameterslimitcursorsourceaccountdatabaserequired

list_users

List users

The people (and bots) of every workspace, or of the one account names: each one's id, name, and email when the token may read it. A person column's where takes a name or an email directly, so this is for checking who is who, or for the id when two people share a name.

Parametersqueryaccount

list_views

List a database's views

A database's saved views (table, board, calendar, ...): each one's id, name, type, the table it shows, and the filter and sorts saved in it, in Notion's query grammar with columns by name. Use it to find the view a person means ("my Open tasks"), then query_view to read its rows exactly as Notion shows them.

Parameterssourceaccountdatabaserequired

move_page

Move a page

Under another page, or into a database as a row. Only within the page's own workspace: Notion cannot move a page between workspaces.

Parameterstorequiredpagerequiredsourceaccount

query_database

Query a database

Rows of a database, filtered by where (checked against the columns first), sorted, with the columns asked for. Each row is its id, its title and its non-empty columns as plain values. A relation lists its first 25 pages here (truncated names it); read_page lists them all. nextCursor reads on; Notion stops one query at 10,000 rows (incomplete says so). Works on the Free plan, unlike the hosted connector's SQL query.

Parameterssortlimitmatchwherecursorsourceaccountdatabaserequiredin_trashpropertiesnotion_filter

query_view

Query a saved view

The rows a saved view shows, in its order, filtered and sorted exactly as Notion applies the view (quick filters and 'me' included), with total, the number of rows the view holds. Each row is its id, title and non-empty columns as query_database answers them. Notion keeps a view's result about 15 minutes: nextCursor reads on in that same result, and after that a new call without cursor starts again. A view takes no extra filter: for that, query_database with where.

Parametersviewrequiredlimitcursoraccountproperties

read_blocks

Read blocks

The blocks directly inside a page or a block, in order, one level down: each one's id, type and plain text, and hasChildren when it holds more (read those by its id). An AI meeting-notes block answers its title, status, recording and calendar times, and the ids of the blocks that hold its summary, notes and transcript, each readable here in turn. A type the API does not support says its Notion name under unsupported. For a page's body as one text, read_page is cheaper.

Parametersblockrequiredlimitcursoraccount

read_page

Read a page

One page by id or URL, in whichever workspace has it: its title, parent and properties as plain values (a select is its option's name, a relation its page ids, all of them), and its body as Notion's Markdown. Empty properties are left out. A body past Notion's limit (~20,000 blocks) comes back cut, with contentTruncated and the ids of the parts left out, each readable as a page. A database's id is refused: use describe_database.

Parameterspagerequiredaccountcontentinclude_transcript

replace_content

Replace a page's body

A page's whole body, replaced by this Markdown. Properties are untouched. Child pages and databases in the body are kept unless allow_deleting. An empty body needs clear: true. Answers with the page's title and how many blocks its body held before and after; check both. Prefer edit_content for a change to part of a page.

Parameterspagerequiredclearaccountmarkdownrequiredallow_deleting

restore_page

Restore a page

Out of Notion's trash, back where it was. Notion's API cannot restore a page from the top level of a workspace (it answers a validation error); that one is restored from the Trash in Notion.

Parameterspagerequiredaccount

trash_page

Trash a page

Into Notion's trash, with everything under it. Direct deletion of database templates is refused unless allow_template is explicit. Notion keeps trash 30 days; restore_page brings it back.

Parameterspagerequiredaccountallow_template

update_page

Update a page

Change a page's properties (a row's columns, checked against the database's schema; a page's title as properties: {title: ...}) and its icon. Only the columns named change. Answers the page as read_page does, without the body. The body is changed with append_content, edit_content and replace_content.

Parametersiconpagerequiredaccountpropertiesallow_new_options

upload_file

Upload a file to a page

Upload a file to Notion and attach it to a page: to one of a row's files columns, or as a block at the end of the page's body (an image, PDF, video or sound shows as such). The file goes by path, never as text you type. Answers with its size and SHA-256 as sent: compare them with the source. A column's own Notion-hosted files are kept unless the API cannot write them back, which is refused unless replace says so; nothing is uploaded before every check passes.

Parametersfilerequirednamepagerequiredcolumnaccountreplace

Version history

2
  1. v0.1.1LatestOct 31, 2026
  2. v0.1.0Oct 26, 2026

Score

90% of the applicable checks met

How complete this listing is, computed from the registry entry, the endpoint and public sources. Not a rating of the server and not a statement that it is safe or working today: reachability is a dated check, and no installs or reviews go into the score.

  • Reached in the last 30 days25 pts
  • Auth declared10 pts

    Declare the credential headers in the registry entry, or keep the endpoint answering the probe so its auth can be classified.

  • Tools listedRequired15 pts
  • DescriptionRequired15 pts
  • Logo10 pts
  • Documentation15 pts
  • License10 pts

Other Notion integrations