Create pages
notion-create-pages
Creates one or more Notion pages with specified properties and content. Supports applying database templates to pre-populate new pages with content and property values. Each page can optionally have an icon (an emoji character, a custom emoji by name, a Notion icon identifier as returned by fetch such as “icons/pizza_blue”, or an external image URL) and a cover image. Set is_skill: true to create a page as a Notion Skill. If a parent is not specified, a private page will be created.
To create a top-level page in a teamspace, pass parent: {"teamspace_id": "…"} with an ID from notion-get-teams. All pages in the call share that parent. See Teamspace root pages for permissions and an example.
Use creation_mode: "draft" when the user wants a durable page but has not named a destination. Draft mode creates a workspace-level private page and cannot be combined with parent. If the user names a private or shared destination, omit creation_mode and create the page under that parent.
The tool description recommends allow_async: true for most page creates. This is guidance to assistants, not a request default. See Async page create and update.
Markdown in content that is too large or too heavily formatted to parse in one call returns a validation_error, and the call creates no pages. All pages in one call share the same parse limit, so a call that creates several pages can reach it even when no single page would. With allow_async: true, the call still returns an async_task, and the task ends as failed with that error. Retrying the same call fails the same way. Create the pages with part of the content and add the rest with further calls, or split the content into child pages.
Each page in the result has a properties object with the values the page was saved with, under the keys the tool saved them to. Use those keys in later calls. A repaired key appears under its data-source key, and a date sent under its property name appears under its start key, such as date:Due:start. Keys the tool skips, such as id and url, and any key but title on a page outside a database, are left out. Signed file links appear as you sent them.
When the tool repairs a property before it writes a page, the page is still created and the result includes a warnings array. For example, a data source with a “URL” property stores it under the key userDefined:URL, so a URL property in the input is written under that key. Each warning has an index, which points to the page in the input pages array, plus a code and a message. Each message is at most 500 characters. A clean create has no warnings key. A property value that can’t be written still fails the call with a validation_error.
Update a page
notion-update-page
Update a Notion page’s properties, content, icon, or cover. You can also change whether a page is a Skill or apply database templates to an existing page. Icon, cover, and is_skill can be set alongside any update command. To change only the icon or cover, use update_properties and omit properties.
The
update_content command applies each search-and-replace operation whose old_str matches the page and skips the rest. Each skipped operation appears in warnings with code no_match, or indentation_mismatch when the text is on the page with different indentation. If an operation misses and no content-changing operation matches, the call returns a validation error naming the unmatched values and the page is left unchanged. If the connection can read the page, the error also asks you to fetch the page again and base the retry’s old_str on its current text; an update that runs as an async_task fails with the plain no-match error instead. The error never includes page text. An operation whose old_str and new_str are identical doesn’t change the page and doesn’t count as a match. Each old_str must be a non-empty string that matches exactly one location, unless replace_all_matches: true is set for that operation.warnings array. Examples are operations whose old_str matched nothing, lines dropped for incorrect indentation, text auto-corrected to match the page, and a property key repaired before the write, such as URL written as userDefined:URL. Each warning has a code and a message. Each message is at most 500 characters; a longer one is cut and ends with a note giving its original length, such as … (truncated from 12000 characters). Markdown parser warnings also carry category, such as unsupported_tag, and autofix, which is true when the parser changed the content to apply it. A clean update has no warnings key. Read any warnings before you treat the edit as done.
validation_error and the page is left unchanged. Retrying the same call fails the same way. Content that wasn’t loaded appears as <unknown> tags when you fetch the page, so edit only content outside those tags.
The tool description recommends allow_async: true for most page updates. This is guidance to assistants, not a request default. See Async page create and update.
Move pages
notion-move-pages
Move one or more Notion pages or databases to a new parent.
Duplicate a page
notion-duplicate-page
Duplicate a Notion page within your workspace. This action completes asynchronously.
Delete pages
notion-delete-pages
Move up to 20 Notion pages to Trash. Database rows are pages. To move a whole database to Trash, use notion-delete-databases. Items in Trash can be restored with notion-restore-pages or from Trash in Notion. Locked pages can’t be moved to Trash; unlock them in Notion first.
The call must set user_confirmed: true. Without it, nothing is moved to Trash, and the error lists the pages so the MCP client can confirm them with the user. The tool is marked destructive (destructiveHint: true), so MCP clients that honor tool annotations ask before running it. Requires the update content capability.
Get async task status
notion-get-async-task
Retrieves the current status of an async task started by another tool, such as notion-duplicate-page, notion-create-pages with allow_async: true, or notion-update-page whenever it returns an async_task. Returns one of queued, running, retrying, succeeded, or failed. When a task has succeeded, the operation’s result is included in the response; when it has failed, an error is included instead.
Poll this tool with the task_id from the originating tool’s async_task response. Wait briefly between polls — the original response includes a suggested backoff.
Teamspace root pages
notion-create-pages accepts parent.teamspace_id to create pages directly in a teamspace, alongside its other top-level pages. Get the ID from notion-get-teams; IDs with or without dashes are accepted. Pass only one parent ID per call.
Use a connection that acts as a Notion user. Bot-scoped workspace connections don’t support this destination. The user must have permission to edit the teamspace’s pages and add top-level pages. If the teamspace limits top-level page edits to owners, the user must be a teamspace owner. Listing a teamspace with notion-get-teams doesn’t grant permission to create pages there.
New pages inherit the teamspace’s permissions, so people with access to its pages can access the new pages. The teamspace must be active and belong to the connected workspace. Omit creation_mode: draft mode creates private pages and can’t be combined with a teamspace parent.
For example, replace the sample ID with a teamspace ID returned by notion-get-teams:
async_task, wait for it to succeed before using the new pages. This parent option is specific to Notion MCP; it isn’t a parent option for the REST Create a page endpoint.
Async page create and update
Thenotion-create-pages and notion-update-page tools support allow_async: true for page create and update work. Their tool descriptions recommend that assistants pass it for most page writes. This is guidance to assistants, not a schema or server default: omitting allow_async has the same meaning as before. The same validation, permissions, and write operation still apply.
The descriptions recommend allow_async: false when the next step needs the created or updated page right away. They also recommend retrying synchronously when an async attempt is rejected as too large to queue.
A request that is too large to queue returns a validation_error instead of an async_task. Either split it into smaller page writes or retry it with allow_async: false.
When a call returns an async_task handle, poll notion-get-async-task with the returned async_task.id passed as task_id until the task reaches succeeded or failed. Wait for succeeded before any step that depends on the write, such as linking to a new page or adding content to it.
A
succeeded status covers the page write, not template application. When dependent work needs template output, follow the webhook flow in Creating pages from templates. For direct checks, look for the expected content or properties and stop after a bounded number of retries.allow_async is omitted or false, notion-create-pages keeps its synchronous result shape. notion-update-page waits for a synchronous result when it can, but it can still return a pollable async_task if queued execution runs past the synchronous wait deadline, so handle both shapes.
queued, running, or retrying, wait at least the suggested poll_after_seconds before polling again. A succeeded task includes the operation result. For notion-create-pages and notion-update-page, that result includes the same warnings array as a direct call. A failed task includes an error object that the assistant can summarize or use to retry with a corrected request.