---
title: Notion
icon: book
description: Mount Notion pages and databases as a Mirage filesystem.
---

`NotionResource` exposes a Notion workspace as a filesystem. The Node SDK talks to the Notion REST API with an integration token; the Browser SDK talks to Notion's MCP server with an OAuth client provider so secrets stay off the page.

## Node

```bash
pnpm add @struktoai/mirage-node
```

```ts
import { MountMode, NotionResource, Workspace } from '@struktoai/mirage-node'

const notion = new NotionResource({ apiKey: process.env.NOTION_API_KEY! })

const ws = new Workspace({ '/notion': notion }, { mode: MountMode.READ })
await ws.execute('ls /notion/pages/')
```

| Field | Default | Notes |
| --- | --- | --- |
| `apiKey` | required | Notion internal integration token. Redacted in snapshots. |
| `baseUrl` | `https://api.notion.com/v1` | Override for testing against a mock server. |

## Browser

```bash
pnpm add @struktoai/mirage-browser @modelcontextprotocol/sdk
```

```ts
import { MountMode, NotionResource, Workspace } from '@struktoai/mirage-browser'

const notion = new NotionResource({
  authProvider, // OAuthClientProvider from @modelcontextprotocol/sdk
})

const ws = new Workspace({ '/notion': notion }, { mode: MountMode.READ })
await ws.execute('ls /notion/')
```

| Field | Default | Notes |
| --- | --- | --- |
| `authProvider` | required | `OAuthClientProvider` from `@modelcontextprotocol/sdk`. Redacted in snapshots. |
| `serverUrl` | Notion's hosted MCP endpoint | Override if you proxy MCP through your own URL. |

## Mount mode

`read`, `write` (page edits via the MCP server in the browser SDK).

## Resource commands

`notion-search` works on read mounts; the rest require a write mount:

```text
notion-search --query "Roadmap" [--limit 20]
notion-page-create --parent <parent-path> --title "title"
notion-block-append --params '{"block_id":"..."}' --json '{"children":[...]}'
notion-comment-add --json '{"parent":{"page_id":"..."},"rich_text":[{"text":{"content":"Comment"}}]}'
```

## Layout

```text
/notion/
  pages/
    <page-title>__<page-id>/
      page.json
      <child-page-title>__<child-id>/
        page.json
        ...
  databases/
    <database-title>__<database-id>/
      database.json
      <row-page-title>__<page-id>/
        page.json
        ...
```

`database.json` is the database's identity plus its typed column schema,
with no rows inline; `ls` the database directory to enumerate row pages.
The shape is identical to the Python connector:

```json
{
  "database_id": "2c4d6a7f-5bf3-8036-bed2-d1c95826f76b",
  "title": "Item",
  "url": "https://www.notion.so/2c4d6a7f5bf38036bed2d1c95826f76b",
  "created_time": "2025-12-09T23:36:00.000Z",
  "last_edited_time": "2026-04-15T12:30:00.000Z",
  "parent": { "type": "workspace", "workspace": true },
  "archived": false,
  "is_inline": false,
  "properties": {
    "Name": { "id": "title", "type": "title", "title": {} },
    "Number": { "id": "e%5BNQ", "type": "number", "number": { "format": "number" } },
    "Date": { "id": "%3BgQq", "type": "date", "date": {} }
  }
}
```

A database row is itself a page: its `page.json` reports `parent_type` of
`database_id`. For full `page.json` field details and supported edits see
the [Python Notion docs](/python/resource/notion).
