Skip to main content

Notion Internal Integration binding for Codex, Claude Code, and other MCP clients.

Project description

Notion Agent Labbook

CI PyPI Python License: MIT

A local MCP server that connects AI coding agents (Codex, Claude Code, OpenCode) to Notion through a Notion Internal Integration secret.

No OAuth, no hosted broker, no cloud worker. The secret lives in your system keychain or 1Password, and the server calls the Notion API directly.

Main Features

  • Open the Notion integrations dashboard and guide the user to the Internal Integration Secret.
  • Detect whether system keychain and 1Password are available, and let the user choose.
  • Store the secret in the local system keychain, in 1Password, or override it with NOTION_AGENT_LABBOOK_TOKEN.
  • Search the pages and data sources the bot can access.
  • Bind only the pages or data sources a project should use.
  • Return access tokens, headers, and bound resource IDs for the official Notion API.
  • Work with Codex, Claude Code, and other MCP-capable clients.

Install

Requirements:

  • Python 3.10 or newer
  • uv
  • a Codex, Claude Code, or another MCP-capable client

Recommended:

codex mcp add labbook -- uvx agent-labbook mcp
claude mcp add --scope project labbook -- uvx agent-labbook mcp

For OpenCode or other MCP clients, add the following to your .mcp.json:

{
  "mcpServers": {
    "labbook": {
      "command": "uvx",
      "args": ["agent-labbook", "mcp"]
    }
  }
}

Or generate this config with:

uvx agent-labbook print-mcp-config

Or use the checked-in .mcp.json for local development from a cloned copy of this repo.

Architecture

┌──────────────┐    MCP (stdio)    ┌──────────────────┐    HTTPS    ┌───────────┐
│  AI Agent    │◄─────────────────►│  agent-labbook   │◄──────────►│ Notion API│
│  (Codex,     │                   │  MCP server      │            └───────────┘
│  Claude Code)│                   └──────┬───────────┘
└──────────────┘                          │
                                          ▼
                                   ┌──────────────┐
                                   │ Secret Store │
                                   │ (keychain /  │
                                   │  1Password / │
                                   │  env var)    │
                                   └──────────────┘

Modules:

Module Responsibility
mcp_server.py MCP tool/resource/prompt definitions, server lifecycle
auth_flow.py Secret detection, storage orchestration, API context assembly
notion_api.py HTTP client for Notion API with retry and backoff
binding_ops.py Binding CRUD: search, discover, bind, unbind, alias management
binding_discovery.py Breadth-first child discovery, resource normalization
binding_browser_page.py HTML template renderer for the local binding chooser UI
binding_ui.py Local HTTP server for browser-based binding selection
state.py .labbook/ project state persistence (session, bindings)
cli.py CLI entry points (mcp, doctor, print-mcp-config)

Recommended Flow

  1. Read labbook://agent-labbook/project/status or run notion_status.
  2. Run notion_prepare_internal_integration to open the Notion integrations dashboard and inspect storage_options, storage_default, and storage_choice_required.
  3. Create a Notion Internal Integration, copy its secret from the Configuration tab, and share the target pages or data sources with the bot in Notion.
  4. Save the secret with notion_configure_internal_integration, choosing storage=keychain or storage=1password, or set NOTION_AGENT_LABBOOK_TOKEN.
  5. If you already know the exact Notion links, use notion_bind_resource_urls.
  6. On desktop machines, use notion_open_binding_browser for a local chooser.
  7. In headless environments, prefer notion_bind_resource_urls when the user can paste exact Notion links. Otherwise combine notion_search_resources, notion_discover_children, and notion_bind_resources.
  8. Read labbook://agent-labbook/project/bindings or run notion_list_bindings to inspect the bound roots.
  9. Run notion_get_api_context and use the returned token, headers, and resource IDs with the official Notion API.

Binding Options

  • Direct URLs -- Use notion_bind_resource_urls when the user already has exact page or data source links.
  • Local browser chooser -- Use notion_open_binding_browser on desktop machines to search, expand child pages, and bind multiple roots visually.
  • Headless MCP flow -- On SSH or other headless environments, use notion_bind_resource_urls when the user can paste exact links. If they cannot, use notion_search_resources, notion_discover_children, and then notion_bind_resources.

Save The Secret

Use notion_configure_internal_integration for persistent storage:

  • storage=keychain -- Default recommendation for local development when system keychain is available.
  • storage=1password -- Use when the op CLI is installed and signed in. You can optionally provide op_vault and op_item_title.
  • NOTION_AGENT_LABBOOK_TOKEN -- Use for CI, temporary runs, or environments where no local secret backend is available.

If more than one local backend is available and you omit storage, the tool will ask the caller to make an explicit choice instead of guessing.

Check The Secret

Use notion_status or agent-labbook doctor to inspect the current setup without retrieving the secret itself.

Important fields:

  • authenticated -- Whether the project currently has a usable Internal Integration secret.
  • storage -- Which persistent backend this project is configured to use.
  • secret_plan -- The recommended secret strategy for this machine right now.
  • storage_options -- The detected local storage backends and their availability.
  • storage_choice_required -- Whether the caller should ask the user to choose between keychain and 1Password.

To verify that the secret also has the correct Notion permissions, prefer notion_search_resources instead of notion_get_api_context.

Guide Users

The recommended user-facing flow for agents is:

  1. Call notion_status.
  2. If authenticated=false, call notion_prepare_internal_integration.
  3. If storage_choice_required=true, ask the user whether they want keychain or 1password.
  4. Tell the user to copy the Internal Integration Secret from Notion's Configuration tab.
  5. Call notion_configure_internal_integration.
  6. Tell the user to share the target pages or data sources with the integration bot.
  7. Prefer notion_bind_resource_urls when the user pastes exact Notion links.
  8. On desktop machines, use notion_open_binding_browser for tree-style selection. In headless environments, prefer notion_bind_resource_urls when the user can paste exact links.
  9. Otherwise call notion_search_resources, optionally notion_discover_children, and then notion_bind_resources.

Do not call notion_get_api_context just to check whether the setup worked. That tool returns the secret and should only be used when the client is ready to make real Notion API calls.

If your content already exists as markdown, prefer Notion's markdown content APIs:

  • POST /v1/pages with markdown
  • GET /v1/pages/{page_id}/markdown
  • PATCH /v1/pages/{page_id}/markdown

Reference: Working with Markdown Content

Contributing

See CONTRIBUTING.md for development setup, testing, and code style guidelines.

Notes

  • .labbook/ should never be committed.
  • This repo handles local configuration and project binding, not general Notion API wrapping.
  • The system keychain is the default recommendation. 1Password is supported when the op CLI is available and signed in.
  • notion_get_api_context returns the secret. Treat it as a last-mile API call step, not a health check.
  • For local setup notes, see docs/self-host.md.
  • For versioning details, see docs/versioning.md.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

agent_labbook-0.17.2.tar.gz (58.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

agent_labbook-0.17.2-py3-none-any.whl (50.2 kB view details)

Uploaded Python 3

File details

Details for the file agent_labbook-0.17.2.tar.gz.

File metadata

  • Download URL: agent_labbook-0.17.2.tar.gz
  • Upload date:
  • Size: 58.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for agent_labbook-0.17.2.tar.gz
Algorithm Hash digest
SHA256 af04880cd512f2ba3f6001a00af6e037f03964e6165b8b79209ff8147bca9ac4
MD5 1c1e4c14fc320bde52e18fd6e15502e1
BLAKE2b-256 b4ef1da093d1a9388588868ffe6190cd00ca5b3bf2d967aa6c4676c0733b9b34

See more details on using hashes here.

Provenance

The following attestation bundles were made for agent_labbook-0.17.2.tar.gz:

Publisher: publish-pypi.yml on binbinsh/agent-labbook

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file agent_labbook-0.17.2-py3-none-any.whl.

File metadata

  • Download URL: agent_labbook-0.17.2-py3-none-any.whl
  • Upload date:
  • Size: 50.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for agent_labbook-0.17.2-py3-none-any.whl
Algorithm Hash digest
SHA256 997d25cd2e3a840d4ed6ad697b49ee66e170a8f7caf2b330fac9065912280f27
MD5 3d3a36293caf9bdd9fb7aa45484db8a4
BLAKE2b-256 5b5d34103e5bbc44e127c4461178baa2a5ec8e10e5bbdb3c92c888aba74e9c3f

See more details on using hashes here.

Provenance

The following attestation bundles were made for agent_labbook-0.17.2-py3-none-any.whl:

Publisher: publish-pypi.yml on binbinsh/agent-labbook

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page