Skip to main content

Notion

Proxy for the Notion REST API through the managed gateway: search, database schema + queries, page read/write, and page content (blocks). All operations are gated by PBAC policy.

The Notion-Version header​

Every Notion API call requires a fixed Notion-Version header alongside Authorization, or Notion rejects the request. Notion's own OAuth passthrough model has no way to attach that extra header per call, so this connector doesn't offer idp_passthrough — Notion's per-user integration tokens (see below) already give the same "act as this specific identity" result without needing a separate IdP.

Finding a database's real id​

A "database" in the Notion UI is often a linked view of a source database that lives elsewhere — connecting the integration on a linked view does not grant access to the source it points at, and get_database/ query_database will 400 against the view's own id ("does not contain any data sources accessible by this API bot"). Likewise, an inline database embedded in a page has its own id, distinct from the page's id — calling get_database with a page's id 400s with "is a page, not a database."

If search with filter_type: "database" doesn't find what you're looking for, use get_block_children on a page you know is shared: an inline database shows up in the results as a child_database block, whose id is the real database id to use. A newly-shared or newly-created database can also take a short while to appear in search results even once access is confirmed — direct get_database/query_database calls by id aren't affected by that lag.

Authentication​

Notion authenticates REST calls with an integration token. This connector supports two auth modes, chosen per managed resource at install time via the Authentication field:

  • Shared integration token (static, default) — every call uses one operator-held token from the token_env secret, with Notion-Version sent alongside it automatically. This matches how Notion access actually works: an integration is shared onto specific pages/databases from each page's ••• menu → Connections, regardless of which person is calling through it, and creating an integration in the first place typically needs workspace-admin permission — not something every individual user can self-serve the way a GitHub or Gitea token is.
  • Per-user integration token (user_secret) — each user links their own Notion integration token once, through a PolicyArc-hosted browser page reached by MCP URL elicitation on the first call. Use this when per-person attribution matters more than the shared-token default, and when each person can create their own integration.

Either way, PolicyArc enforces per-user authorization at the gateway via policy before the request reaches Notion. See Per-user upstream credentials for how the user_secret collection flow works.

Setup​

  • upstream_auth.type — static (default) or user_secret.
  • token_env — static mode only — a secret holding a Notion internal integration token. Hidden when user_secret is selected.

Creating a Notion integration token​

notion.so/my-integrations → New integration → give it the capabilities this connector needs (read content, update content, insert content), then copy its token. Then, on each page or database it should reach, open the page's ••• menu → Connections → connect the integration — an integration with no pages shared to it can authenticate but sees nothing. In user_secret mode each user does this for themselves (their own integration, shared onto whatever they want it to reach) on the collection page; in static mode the operator provisions the shared integration once.

Manifest reference​

  • ID: identos.notion
  • Version: 1.0.0
  • Resource type: urn:connector:identos:notion
  • Capabilities: mcp

Supported auth modes​

TypeDetails
staticscheme bearer; setup fields: token_env
user_secret—

Setup fields​

IDLabelDefaultSecret?Notes
upstream_auth.typeAuthenticationstaticnoNotion's own sharing model is workspace-level, not per-user: one integration is shared onto specific pages/databases regardless of who calls it, and creating an integration itself typically needs workspace-admin permission. static (default) matches that with one shared integration token. user_secret instead has each user link their own integration token, for when you want per-person attribution and each person can create their own integration.
token_envIntegration token—yesUsed only for the static method. A secret holding a Notion internal integration token, created at notion.so/my-integrations and shared onto the pages/databases it should reach. / shown when upstream_auth.type == 'static'

Scopes​

Scope
notion:read
notion:write

Routes​

MethodPatternScopeResource template
POST/searchnotion:read—
GET/databases/{database_id}notion:readnotion://databases/{{database_id}}
POST/databases/{database_id}/querynotion:readnotion://databases/{{database_id}}
GET/pages/{page_id}notion:readnotion://pages/{{page_id}}
POST/pagesnotion:write—
PATCH/pages/{page_id}notion:writenotion://pages/{{page_id}}
GET/blocks/{block_id}/childrennotion:readnotion://blocks/{{block_id}}
PATCH/blocks/{block_id}/childrennotion:writenotion://blocks/{{block_id}}

MCP tools​

NameScopeDescription
searchnotion:readSearch pages and databases the integration has been shared with, by title.
get_databasenotion:readGet a database's schema (properties/columns) and metadata.
query_databasenotion:readQuery a database's rows (pages), with optional filter and sort.
get_pagenotion:readGet a page's properties (not its body content — use get_block_children for that).
create_pagenotion:writeCreate a page, either as a database row (parent.database_id) or as a subpage of another page (parent.page_id).
update_pagenotion:writeUpdate a page's properties, or archive/restore it by setting archived.
get_block_childrennotion:readGet a page's or block's body content as a list of blocks. Pass a page_id as block_id to read a page's top-level content.
append_block_childrennotion:writeAppend new content blocks to the end of a page or block. Pass a page_id as block_id to add to a page's top-level content.