Skip to main content
Glama
README.md
# Notion MCP

A secure, open-source Model Context Protocol server for connecting AI agents and apps to Notion.

We built this because the existing hosted/default Notion MCP flow was down or unreliable when we needed it. Instead of waiting on a black-box integration, this project gives teams a simple Notion bridge they can own, run locally, deploy privately, customize, and audit.

Notion MCP is designed to work with any app or team setup:

- No agent architecture yet: use it as a clean local Notion MCP server for search, read, create, and append workflows.
- Intermediate agent setup: connect it to Codex, Claude Desktop, Cursor, or your own assistant as a safe documentation bridge.
- Advanced multi-agent architecture: use it as the Notion knowledge layer behind a lead agent, task agents, product agents, release agents, or app-specific orchestration.

The goal is easy, useful, accommodating infrastructure: Notion stays your source of truth, and agents only get the tools you intentionally expose.

## What It Does

V1 includes:

- Search Notion pages.
- Retrieve Notion page metadata, blocks, and readable plain text.
- Create new Notion pages under a configured root page.
- Append content to existing Notion pages.
- List configured apps/projects.
- Retrieve lightweight app/project context.
- Log decisions to Notion.
- Generate simple Codex-ready prompts from project context.
- Audit-log every tool call.
- Enforce risk levels for every tool.

V1 intentionally does **not** include destructive tools, production-control tools, billing actions, auth changes, email sending, deployments, or unrestricted app control.

## Architecture

```text
AI Client or Agent
   |
   | calls approved MCP tools
   v
Notion MCP
   |
   | uses a scoped Notion integration token
   v
Notion Workspace or Page Tree
```

For more advanced teams, you can add app connectors behind the same permission model:

```text
Lead Agent
   |
   v
Notion MCP / App Gateway
   |
   |-------------------------------
   |          |          |         |
Notion    App API    CI Tool    Support Tool
```

The important rule: agents should call approved MCP tools, not receive unrestricted direct access to every system.

## Quick Start

```bash
npm install
npm run build
cp .env.example .env
```

Create a Notion integration at:

[https://www.notion.com/my-integrations](https://www.notion.com/my-integrations)

Then:

1. Copy the integration secret into `NOTION_TOKEN`.
2. Open the Notion page you want this server to access.
3. Use Notion's page menu to connect/share the page with your integration.
4. Copy the page ID into `NOTION_ROOT_PAGE_ID`.

`.env`:

```text
NOTION_TOKEN=
NOTION_ROOT_PAGE_ID=
SUPABASE_URL=
SUPABASE_SERVICE_ROLE_KEY=
MCP_GATEWAY_API_KEY=
OPENAI_API_KEY=
NODE_ENV=development
AUDIT_LOG_FILE=.audit/tool-calls.jsonl
```

Only `NOTION_TOKEN` and `NOTION_ROOT_PAGE_ID` are required for the core Notion tools. Supabase is optional.

## Run Locally

Development:

```bash
npm run dev
```

Built server:

```bash
npm run build
npm start
```

Stdio wrapper for MCP clients:

```bash
./scripts/run-mcp.sh
```

The wrapper loads `.env` from the repo so you do not need to copy secrets into global client config files.

## Connect To Codex

```bash
./scripts/register-codex-mcp.sh notion_mcp
codex mcp list
```

Restart Codex or open a fresh session after registration.

Equivalent config:

```toml
[mcp_servers.notion_mcp]
command = "/absolute/path/to/notion-mcp/scripts/run-mcp.sh"
args = []
cwd = "/absolute/path/to/notion-mcp"
startup_timeout_sec = 120
```

## Connect To Other MCP Clients

Generic MCP client config:

```json
{
  "mcpServers": {
    "notion-mcp": {
      "command": "/absolute/path/to/notion-mcp/scripts/run-mcp.sh",
      "args": []
    }
  }
}
```

This works best for desktop/local agent clients. Hosted deployments can be added later with HTTP transport, auth, and tenancy controls.

## Tools

### `notion_search`

Search the connected Notion workspace/page tree.

```json
{ "query": "launch checklist" }
```

Returns:

```json
{
  "results": [
    {
      "title": "Launch Checklist",
      "pageId": "notion-page-id",
      "type": "page",
      "url": "https://notion.so/...",
      "lastEditedTime": "timestamp",
      "summary": "Notion page titled \"Launch Checklist\"."
    }
  ]
}
```

### `notion_get_page`

Retrieve a Notion page and block content.

```json
{ "pageId": "notion-page-id" }
```

Returns `pageId`, `title`, `url`, raw `blocks`, and extracted `plainText`.

### `notion_create_page`

Create a new page under `NOTION_ROOT_PAGE_ID` or a provided parent page.

```json
{
  "title": "New Project Decision",
  "content": "Content to add to the page",
  "parentPageId": "optional-page-id"
}
```

Create-only. It does not overwrite existing pages.

### `notion_append_to_page`

Append content to an existing page.

```json
{
  "pageId": "notion-page-id",
  "content": "New decision or note to append"
}
```

Append-only. It does not delete or replace page content.

### `project_list_apps`

Returns project/app names configured in `src/tools/projectTools.ts`.

### `project_get_context`

```json
{ "projectName": "Example App" }
```

Use this to give agents a lightweight local context map before they search deeper in Notion.

### `mission_log_decision`

```json
{
  "projectName": "Example App",
  "decisionTitle": "Use MCP as the documentation bridge",
  "decisionDetails": "Agents can write safe append-only documentation through MCP.",
  "category": "architecture"
}
```

### `codex_generate_prompt`

```json
{
  "projectName": "Example App",
  "goal": "Implement the next safe documentation workflow",
  "constraints": ["Use existing app architecture", "Prioritize safe implementation"]
}
```

## Security Model

Every tool has a risk level.

Executable in V1:

- `read`: search, retrieve, list context.
- `safe_write`: create or append documentation without deleting or replacing content.

Prepared but blocked in V1:

- `operational`: non-destructive live app operations.
- `restricted`: destructive, sensitive, financial, production, auth, access, or security-changing actions.

Human approval should be required before any future tool can:

- Delete content.
- Change user access.
- Change billing or license state.
- Lock users out.
- Send external emails.
- Modify production settings.
- Trigger production deployments.
- Change security policies.
- Change secrets, API keys, or auth settings.

Recommended security practices:

- Use a dedicated Notion integration token for each deployment.
- Share only the specific Notion pages/databases the server needs.
- Keep `.env` out of git.
- Rotate tokens if they are exposed.
- Prefer local/file audit logs for prototypes and Supabase/Postgres audit logs for teams.
- Add new tools behind explicit schemas, risk levels, and tests.

## Audit Logging

Every tool call is logged with:

- `id`
- `timestamp`
- `toolName`
- `riskLevel`
- `inputSummary`
- `success`
- `errorMessage`
- `requestingAgent`
- `projectName`
- `notionPageId`
- `durationMs`

If Supabase is configured, logs are inserted into `tool_calls`. Otherwise logs are written to `.audit/tool-calls.jsonl`.

Optional Supabase table:

```sql
create table if not exists tool_calls (
  id uuid primary key,
  timestamp timestamptz not null,
  tool_name text not null,
  risk_level text not null,
  input_summary text not null,
  success boolean not null,
  error_message text,
  requesting_agent text,
  project_name text,
  notion_page_id text,
  duration_ms integer not null
);
```

## Works With Any App Maturity Level

No app architecture:

- Use Notion MCP as your first bridge between AI and project docs.
- Keep decisions, prompts, checklists, notes, and roadmaps in Notion.

Intermediate app architecture:

- Configure your projects in `src/tools/projectTools.ts`.
- Use `mission_log_decision` and `codex_generate_prompt` to keep implementation work tied to Notion context.

Advanced agent architecture:

- Add connector folders under `src/connectors/`.
- Keep app-specific APIs behind approved tools.
- Require human approval for operational and restricted actions.
- Use audit logs to review what each agent did.

## Customize

Edit:

```text
src/tools/projectTools.ts
```

to define your own apps/projects.

Add future connectors under:

```text
src/connectors/
```

When adding a new tool:

1. Define a Zod input schema.
2. Assign a risk level.
3. Wrap execution with `runLoggedTool`.
4. Keep restricted actions blocked unless you add an explicit human approval workflow.
5. Add focused tests.

## Test

```bash
npm test
npm run typecheck
npm run build
```

Manual tests:

- Run `notion_search` with a known query.
- Run `notion_get_page` with a valid page ID.
- Run `notion_create_page` without `parentPageId` and confirm it appears under `NOTION_ROOT_PAGE_ID`.
- Run `notion_append_to_page` and confirm existing page content is preserved.
- Remove Supabase env vars and confirm `.audit/tool-calls.jsonl` receives entries.
- Remove `NOTION_TOKEN` and confirm Notion tools fail with a clear missing environment error.
- Use an invalid Notion page ID and confirm the tool fails and logs the failure.
- Confirm operational/restricted risk levels throw in tests.

## Deployment Notes

V1 is a local stdio MCP server. That is the simplest and safest first shape for personal agents, desktop clients, and local developer workflows.

For hosted use, add:

- HTTP or Streamable HTTP transport.
- API key or OAuth auth.
- Per-tenant Notion tokens.
- Rate limiting.
- Centralized audit logging.
- Deployment-specific secret management.

Do not deploy a public shared instance with one global Notion token. Each user/team should bring their own Notion integration and credentials.

## License

MIT

TDQS

A3.5/5.0

Scored across 8 tools

Disambiguation5/5

Each tool has a clearly distinct purpose: codex prompt generation, decision logging, Notion page operations (append, create, get, search), and project context retrieval. No overlaps.

Naming Consistency4/5

Names follow snake_case and use a <domain>_<action> pattern, but prefixes vary (codex_, mission_log_, notion_, project_). Within each domain, naming is consistent; overall pattern is readable but not fully uniform.

Tool Count5/5

8 tools is well-scoped for a Notion integration covering core operations (create, get, search, append) plus additional project context and decision logging. No redundancy.

Completeness3/5

Covers create, read, search, and append for Notion pages, but missing update and delete operations. Project context and decision logging are included, but the Notion surface is incomplete for full CRUD.

Maintenance

ActivityInactive
ResponsivenessNo issues