Files
2026-07-13 13:39:12 +08:00

132 lines
6.6 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
title: "Notion Context Source"
version: 3.8.40
lastUpdated: 2026-06-28
---
# Notion Context Source
> **Source of truth:** `src/lib/notion/api.ts` (REST client), `src/lib/db/notion.ts`
> (token persistence), `open-sse/mcp-server/tools/notionTools.ts` (6 MCP tools),
> `src/app/api/settings/notion/route.ts` (settings API). Tool registration and scope
> wiring lives in `open-sse/mcp-server/server.ts`.
## What it is
OmniRoute can connect to a **Notion** workspace as a **context source** — a read/write
knowledge base that agents reach through the built-in MCP server. Once a Notion
integration token is configured, the MCP tools let an LLM search pages and databases,
read page content and block trees, query databases with filters/sorts, and append new
blocks — all proxied through OmniRoute (with retry, timeout, and error classification)
so the model never touches the Notion API directly.
The integration is a thin, hardened wrapper over the official Notion REST API
(`https://api.notion.com/v1`, `Notion-Version: 2026-03-11`). The client
(`src/lib/notion/api.ts`) adds:
- **Retry with exponential backoff** (up to 3 attempts) for `429` and `5xx`.
- **55-second request timeout** via `AbortController`.
- **Typed error classification** — `NotionAuthError` (401/403),
`NotionNotFoundError` (404), `NotionRateLimitError` (429, honors `retry after`
hints), `NotionValidationError` (400/409), `NotionServerError` (5xx),
`NotionTimeoutError`.
- **Message sanitization** that strips stack-trace-like fragments before surfacing.
## Setup
There is **no environment variable** for the Notion token — it is stored in the
SQLite `key_value` table (namespace `notion`, key `integration_token`) via
`src/lib/db/notion.ts`. Configure it from the **Context Sources** tab of the Endpoint
dashboard (`ObsidianSourceCard`'s sibling `NotionSourceCard`), or via the settings REST API.
> [!NOTE]
> The token is a **Notion internal integration token**. Create an integration at
> <https://www.notion.com/my-integrations>, then share the pages/databases you want
> OmniRoute to access with that integration (Notion's permission model is share-based,
> not workspace-wide).
### Configure via REST
```bash
# Save + validate the integration token (POST validates by issuing a test search)
curl -X POST http://localhost:20128/api/settings/notion \
-H "Content-Type: application/json" \
-d '{"token":"ntn_xxx"}'
# Check connection status
curl http://localhost:20128/api/settings/notion
# Disconnect (clears the stored token)
curl -X DELETE http://localhost:20128/api/settings/notion
```
All three methods require dashboard authentication (`isAuthenticated`). On `POST`,
OmniRoute saves the token and immediately runs a 1-result test search; if Notion
returns an error object the token is cleared and the call fails with `400`.
## MCP tools (6)
Defined in `open-sse/mcp-server/tools/notionTools.ts`. The token is resolved at call
time via `getNotionToken()`; if none is configured the tool throws
`"Notion integration token not configured. Set it in Settings > Context Sources."`
| Tool | Scope | Description |
| ---------------------------- | -------------- | --------------------------------------------------------------------------------- |
| `notion_search` | `read:notion` | Search pages and databases by text query (returns titles, IDs, URLs). Paginated. |
| `notion_get_page` | `read:notion` | Get content and metadata of a page by its ID. |
| `notion_list_block_children` | `read:notion` | List all block children of a block or page (the block tree). Paginated. |
| `notion_query_database` | `read:notion` | Query a database with optional `filter` + `sorts` (Notion API format). Paginated. |
| `notion_get_database` | `read:notion` | Get the schema/metadata of a database by ID. |
| `notion_append_blocks` | `write:notion` | Append block children to an existing block or page (max 100 blocks per request). |
### Input parameters
- `notion_search``query` (1500 chars), `pageSize` (1100, default 20),
`startCursor` (optional).
- `notion_get_page``pageId` (32-char hex or UUID).
- `notion_list_block_children``blockId`, `pageSize` (1100, default 50),
`startCursor` (optional).
- `notion_query_database``databaseId`, `filter` (optional, Notion filter format),
`sorts` (optional array), `pageSize` (1100, default 50), `startCursor` (optional).
- `notion_get_database``databaseId`.
- `notion_append_blocks``blockId`, `children` (array of block objects),
`after` (optional position).
### Scopes
The read tools require `read:notion` and the write tool requires `write:notion`.
Scopes are enforced by `withScopeEnforcement()` in
`open-sse/mcp-server/server.ts` only when `OMNIROUTE_MCP_ENFORCE_SCOPES=true`; the
caller's allowed scopes come from `OMNIROUTE_MCP_SCOPES` (comma-separated) or the
authenticated API key's scope context. See [MCP-SERVER.md](./MCP-SERVER.md) for the
full scope model.
## Endpoints
| Method | Path | Purpose |
| -------- | ---------------------- | -------------------------------------- |
| `GET` | `/api/settings/notion` | Return `{ connected, hasToken }`. |
| `POST` | `/api/settings/notion` | Save + validate the integration token. |
| `DELETE` | `/api/settings/notion` | Disconnect (clear the stored token). |
> These are dashboard settings routes. There is **no public `/v1` Notion proxy
> endpoint** — Notion is reached exclusively through the MCP tools above.
## Use cases
- **Knowledge-grounded answers** — let an agent `notion_search` the workspace and
`notion_get_page` the top hit before answering, so responses cite real internal docs.
- **Database-backed workflows** — `notion_query_database` a tasks/CRM database with
filters + sorts, then summarize or triage the rows.
- **Write-back / logging** — `notion_append_blocks` to append meeting notes, run
summaries, or agent output into an existing page (append-only; no destructive edits).
- **Structure exploration** — `notion_list_block_children` to walk a page's block tree,
or `notion_get_database` to discover a database's property schema before querying it.
## Related
- [MCP Server](./MCP-SERVER.md) — transports, scope enforcement, full tool inventory.
- [Obsidian Context Source](./OBSIDIAN_CONTEXT.md) — the other built-in context source.
- [Memory System](./MEMORY.md) — persistent conversational memory (complementary
context layer, injected automatically rather than tool-fetched).