Notion MCP Server

repository·main·Indexed 26 days ago

https://github.com/makenotion/notion-mcp-server

Official Model Context Protocol (MCP) server for the Notion API, enabling AI agents to query, read, and manipulate Notion pages and databases. It provides tools for interacting with data sources and supports enhanced Markdown for token-efficient page content retrieval and editing. The server supports both STDIO and streamable HTTP transport modes and can be installed via npm or Docker.

Tokens
3.5K
Snippets
8
Records
25
Agent score
88%

What's inside notion-mcp-server

  1. Overview of Notion MCP Server

    main

    The Notion MCP Server implements the Model Context Protocol (MCP) for the Notion API. It provides tools for AI agents to interact with Notion data.

    Note on Remote Notion MCP: Notion has introduced a remote MCP service that offers easier installation via OAuth and optimized tools for AI agents (including Markdown editing). This local repository is a legacy implementation and is not actively monitored. For the most modern experience, refer to the Notion MCP documentation.

  2. Overview of openapi-mcp-server (vendored)

    main
    The openapi-mcp-server directory contains a vendored fork of snaggle-ai/openapi-mcp-server (v1). It is responsible for converting Notion's OpenAPI specification into Model Context Protocol (MCP) tools and executing the underlying API calls. This version is maintained locally to preserve Notion-specific behaviors that standard OpenAPI-to-MCP converters do not support.
  3. Install Notion MCP Server via npm (Cursor, Claude, Zed, Copilot)

    main

    You can install and configure the Notion MCP server using npx. Choose the configuration method based on your client.

    Cursor & Claude

    Add to .cursor/mcp.json or claude_desktop_config.json.

    Option 1: Using NOTION_TOKEN (Recommended)

    {
      "mcpServers": {
        "notionApi": {
          "command": "npx",
          "args": ["-y", "@notionhq/notion-mcp-server"],
          "env": {
            "NOTION_TOKEN": "ntn_****"
          }
        }
      }
    }

    Option 2: Using OPENAPI_MCP_HEADERS (Advanced)

    {
      "mcpServers": {
        "notionApi": {
          "command": "npx",
          "args": ["-y", "@notionhq/notion-mcp-server"],
          "env": {
            "OPENAPI_MCP_HEADERS": "{\"Authorization\": \"Bearer ntn_****\", \"Notion-Version\": \"2025-09-03\" }"
          }
        }
      }
    }

    Zed

    Add to settings.json:

    {
      "context_servers": {
        "some-context-server": {
          "command": {
            "path": "npx",
            "args": ["-y", "@notionhq/notion-mcp-server"],
            "env": {
              "OPENAPI_MCP_HEADERS": "{\"Authorization\": \"Bearer ntn_****\", \"Notion-Version\": \"2025-09-03\" }"
            }
          },
          "settings": {}
        }
      }
    }

    GitHub Copilot CLI

    Use /mcp add interactively, or edit ~/.copilot/mcp-config.json:

    {
      "mcpServers": {
        "notionApi": {
          "command": "npx",
          "args": ["-y", "@notionhq/notion-mcp-server"],
          "env": {
            "NOTION_TOKEN": "ntn_****"
          }
        }
      }
    }
  4. Configure Transport Options

    main

    The Notion MCP Server supports two transport modes:

    STDIO transport (default)

    Used by most clients like Claude Desktop. Communication happens via standard input/output.

    npx @notionhq/notion-mcp-server
    # Or explicitly:
    npx @notionhq/notion-mcp-server --transport stdio

    Streamable HTTP transport

    Used for web-based applications. The server is available at http://127.0.0.1:<port>/mcp by default.

    Common HTTP commands:

    • Custom Port: --transport http --port 8080
    • Custom Host: --transport http --host 0.0.0.0
    • Custom Auth Token: --transport http --auth-token "your-secret-token" or via AUTH_TOKEN env var.
    • Disable Auth (Unsafe): --transport http --unsafe-disable-auth (Use only on isolated networks; enables DNS rebinding protection).

    Authentication for HTTP: All requests must include the bearer token in the Authorization header.

    curl -H "Authorization: Bearer your-token-here" ... http://localhost:3000/mcp
    npx @notionhq/notion-mcp-server --transport http --port 8080
  5. Enable Per-Request Notion Tokens (Multi-tenancy)

    main

    To allow a single server deployment to serve multiple Notion integrations, enable token passthrough. This prevents the server from being locked to a single NOTION_TOKEN at startup.

    1. Enable passthrough: Start the server with the --enable-token-passthrough flag or set ENABLE_TOKEN_PASSTHROUGH=true.

      npx @notionhq/notion-mcp-server --transport http --enable-token-passthrough
    2. Client Request: Clients must send their specific Notion integration token in the Notion-Token header during the initialize request.

    Token Resolution Order:

    1. Notion-Token header (Preferred).
    2. Authorization: Bearer ... (Only if server's own auth is disabled via --unsafe-disable-auth).
    3. Startup environment variable (NOTION_TOKEN or OPENAPI_MCP_HEADERS).
    curl -H "Authorization: Bearer <server-auth-token>" \
         -H "Notion-Token: ntn_****" \
         -H "Content-Type: application/json" \
         -d '{"jsonrpc": "2.0", "method": "initialize", "params": {}, "id": 1}' \
         http://localhost:3000/mcp
  6. Migrate from v1.x to v2.0.0 (Breaking Changes)

    main

    Version 2.0.0 migrates to the Notion API 2025-09-03, which shifts the primary abstraction for databases to data sources.

    Tool Replacements

    If you have hardcoded tool names or prompts, you must update them to the new tool names:

    • Replace post-database-query with query-data-source.
    • Replace update-a-database with update-a-data-source.
    • Replace create-a-database with create-a-data-source.

    Parameter Changes

    • Database IDs: All database operations now require data_source_id instead of database_id.
    • Search Filters: Search filter values have changed from ["page", "database"] to ["page", "data_source"].
    • Page Creation: Supports both page_id and database_id as parents for data sources.

    Migration Effort

    Most AI clients will automatically discover the new tools upon server startup. No code changes are required unless you have hardcoded specific tool names or parameter keys in your prompts or logic.

  7. Install Notion MCP Server via Docker

    main

    Option 1: Using official Docker Hub image

    Add to .cursor/mcp.json or claude_desktop_config.json.

    Using NOTION_TOKEN (Recommended):

    {
      "mcpServers": {
        "notionApi": {
          "command": "docker",
          "args": [
            "run",
            "--rm",
            "-i",
            "-e", "NOTION_TOKEN",
            "mcp/notion"
          ],
          "env": {
            "NOTION_TOKEN": "ntn_****"
          }
        }
      }
    }

    Using OPENAPI_MCP_HEADERS (Advanced):

    {
      "mcpServers": {
        "notionApi": {
          "command": "docker",
          "args": [
            "run",
            "--rm",
            "-i",
            "-e", "OPENAPI_MCP_HEADERS",
            "mcp/notion"
          ],
          "env": {
            "OPENAPI_MCP_HEADERS": "{\"Authorization\":\"Bearer ntn_****\",\"Notion-Version\":\"2025-09-03\"}"
          }
        }
      }
    }

    Option 2: Building the Docker image locally

    Build the image first:

    docker compose build

    Then add to client config (e.g., .cursor/mcp.json) using the local image name:

    {
      "mcpServers": {
        "notionApi": {
          "command": "docker",
          "args": [
            "run",
            "--rm",
            "-i",
            "-e",
            "NOTION_TOKEN=ntn_****",
            "notion-mcp-server"
          ]
        }
      }
    }
  8. Safely modifying the openapi-mcp-server

    main

    Because this server generates tools based on the Notion OpenAPI spec, changes to the code or the spec may alter the public tool surface (names, descriptions, and parameters).

    To verify changes:

    1. The project uses snapshots in openapi/__tests__/notion-spec.snapshot.test.ts to track the generated tool surface.
    2. If a change alters the tool surface, the snapshot test will fail.
    3. Review the diff carefully. Only update the snapshots using vitest -u if the change to the tool surface is intentional.
    vitest -u
  9. Manual publish of @notionhq/notion-mcp-server

    main

    If the automated GitHub Actions publishing workflow is unavailable, you can publish the package manually. This requires npm publish rights. You must run the build command to regenerate bin/cli.mjs to ensure the CLI artifact is in sync with the source code.

    npm ci
    npm run build      # regenerates bin/cli.mjs — do NOT skip
    npm test
    npm publish --access public
  10. Use Authorization fallback for Notion tokens

    main

    If the server is configured to allow it (via allowAuthorizationFallback), it can attempt to resolve a Notion token from the standard Authorization: Bearer <token> header.

    This fallback is only used when:

    1. The notion-token header is absent.
    2. allowAuthorizationFallback is enabled (meaning the server's own gateway authentication is disabled).
    3. The token in the Authorization header carries a valid Notion prefix (ntn_ or secret_).
  11. Pass Notion integration tokens via HTTP headers

    main

    When using the Streamable HTTP transport, you can enable per-request authentication. This allows a single server deployment to serve multiple Notion integrations by having each client supply its own token in the request headers.

    To provide a token explicitly, use the notion-token header. The server validates that the token starts with one of the recognized Notion prefixes:

    • ntn_ (current internal & OAuth integration tokens)
    • secret_ (legacy internal integration tokens)

    If you provide the notion-token header but the value does not match these patterns or fails length requirements (8-300 characters), the server will return an error rather than falling back to the default startup token.