notion-mcp-server

apimlett/notion-mcp-server

3.2

If you are the rightful owner of notion-mcp-server and would like to certify it and/or have it hosted online, please leave a comment on the right or send an email to henry@mcphub.com.

The Notion MCP Server is a Model Context Protocol server that facilitates comprehensive read and write access to Notion workspaces via the Notion API.

Tools
  1. notion_search_pages

    Search for pages across your workspace.

  2. notion_get_page

    Retrieve a specific page with all its content.

  3. notion_create_page

    Create a new page with content.

  4. notion_update_page

    Update an existing page's properties and content.

  5. notion_append_blocks

    Append blocks to an existing page.

  6. notion_query_database

    Query a database with filters and sorting.

  7. notion_create_database_page

    Create a new page in a database.

  8. notion_update_database_page

    Update properties of a database page.

  9. notion_get_blocks

    Get child blocks of a page or block.

  10. notion_update_block

    Update a specific block's content.

  11. notion_delete_block

    Delete a specific block.

  12. notion_get_users

    List all users in the workspace.

  13. notion_get_databases

    List accessible databases.

Notion MCP Server

A Model Context Protocol (MCP) server that provides comprehensive read and write access to Notion workspaces through the Notion API.

Features

  • šŸ” Search and retrieve pages, databases, and blocks
  • šŸ“ Create and update pages with rich content
  • šŸ—ƒļø Database operations - query, create, and update database entries
  • šŸ—ļø Block manipulation - append, update, and delete blocks
  • šŸ”’ Secure authentication using Notion integration tokens
  • šŸ›”ļø Error handling with proper MCP error responses
  • šŸ“Š Comprehensive logging for debugging and monitoring

Quick Start

1. Installation

git clone https://github.com/your-username/notion-mcp-server.git
cd notion-mcp-server
npm install

2. Notion Integration Setup

  1. Go to Notion Developers
  2. Click "New integration"
  3. Fill in basic information:
    • Name: "MCP Server Integration"
    • Associated workspace: Select your workspace
    • Capabilities: Read content, Update content, Insert content
  4. Click "Submit"
  5. Copy the "Internal Integration Token"

3. Configuration

Create a .env file in the project root:

NOTION_TOKEN=your_notion_integration_token_here

Note: The server automatically finds and loads the .env file from the project directory, regardless of where the MCP client runs it from.

4. Grant Page Access

For each Notion page/database you want to access:

  1. Open the page in Notion
  2. Click the "..." menu → "Add connections"
  3. Select your integration

5. Running the Server

# Development
npm run dev

# Production
npm start

Client Integration

Claude Code (CLI)

Add the server to your Claude Code MCP configuration:

{
  "mcpServers": {
    "notion": {
      "command": "node",
      "args": ["/path/to/notion-mcp-server/dist/index.js"]
    }
  }
}

Or using npm:

{
  "mcpServers": {
    "notion": {
      "command": "npx",
      "args": ["-p", "/path/to/notion-mcp-server", "node", "dist/index.js"]
    }
  }
}

The server will automatically read the NOTION_TOKEN from your .env file.

Claude Desktop

Add to your Claude Desktop configuration file:

macOS: ~/Library/Application Support/Claude/claude_desktop_config.json Windows: %APPDATA%/Claude/claude_desktop_config.json

{
  "mcpServers": {
    "notion": {
      "command": "node",
      "args": ["/path/to/notion-mcp-server/dist/index.js"]
    }
  }
}

The server will automatically read the NOTION_TOKEN from your .env file in the project directory.

ChatGPT (via OpenAI)

For ChatGPT integration, you'll need to run the server with a JSON-RPC transport. Create a wrapper script:

notion-mcp-wrapper.js:

#!/usr/bin/env node
const { spawn } = require('child_process');

const server = spawn('node', ['/path/to/notion-mcp-server/dist/index.js'], {
  env: process.env, // Inherits environment variables including NOTION_TOKEN from .env
  stdio: ['pipe', 'pipe', 'pipe'],
  cwd: '/path/to/notion-mcp-server' // Ensures .env file is found
});

process.stdin.pipe(server.stdin);
server.stdout.pipe(process.stdout);
server.stderr.pipe(process.stderr);

server.on('exit', (code) => {
  process.exit(code);
});

Then configure ChatGPT to use:

{
  "tools": [
    {
      "type": "mcp_server",
      "mcp_server": {
        "command": "node",
        "args": ["/path/to/notion-mcp-wrapper.js"]
      }
    }
  ]
}

Alternative: Global Installation

For easier configuration, you can install the server globally:

# Make the server globally available
npm link

# Or install globally if published
npm install -g notion-mcp-server

Then use in configurations:

{
  "mcpServers": {
    "notion": {
      "command": "notion-mcp-server"
    }
  }
}

Note: When using global installation, ensure your .env file is in the working directory where the client runs, or set the NOTION_TOKEN as a system environment variable.

Security Best Practices

āœ… DO: Keep your Notion token in the .env file

NOTION_TOKEN=secret_your_notion_integration_token_here

āŒ DON'T: Put tokens directly in MCP client configurations

// AVOID THIS - tokens exposed in config files
{
  "mcpServers": {
    "notion": {
      "env": {
        "NOTION_TOKEN": "secret_token_here"
      }
    }
  }
}

System Environment Variables (Optional)

If you prefer system-wide environment variables instead of .env files:

# Add to your shell profile (.bashrc, .zshrc, etc.)
export NOTION_TOKEN="your_notion_integration_token_here"

This approach works well with global installations and containerized deployments.

MCP Tools Available

Page Operations

notion_search_pages

Search for pages across your workspace.

{
  "query": "meeting notes",
  "filter": "page",
  "sort": "last_edited_time"
}
notion_get_page

Retrieve a specific page with all its content.

{
  "page_id": "page-uuid-here"
}
notion_create_page

Create a new page with content.

{
  "parent": {
    "type": "page_id",
    "page_id": "parent-page-uuid"
  },
  "title": "New Page Title",
  "content": "# Heading\n\nThis is some content."
}
notion_update_page

Update an existing page's properties and content.

{
  "page_id": "page-uuid-here",
  "title": "Updated Title",
  "content": "Updated content here"
}
notion_append_blocks

Append blocks to an existing page.

{
  "block_id": "page-or-block-uuid",
  "content": "Additional content to append"
}

Database Operations

notion_query_database

Query a database with filters and sorting.

{
  "database_id": "database-uuid-here",
  "filter": {
    "property": "Status",
    "select": {
      "equals": "In Progress"
    }
  },
  "sorts": [
    {
      "property": "Created",
      "direction": "descending"
    }
  ]
}
notion_create_database_page

Create a new page in a database.

{
  "database_id": "database-uuid-here",
  "properties": {
    "Name": {
      "title": [
        {
          "text": {
            "content": "New Task"
          }
        }
      ]
    },
    "Status": {
      "select": {
        "name": "To Do"
      }
    }
  },
  "content": "Task description here"
}
notion_update_database_page

Update properties of a database page.

{
  "page_id": "page-uuid-here",
  "properties": {
    "Status": {
      "select": {
        "name": "Completed"
      }
    }
  }
}

Block Operations

notion_get_blocks

Get child blocks of a page or block.

{
  "block_id": "block-uuid-here"
}
notion_update_block

Update a specific block's content.

{
  "block_id": "block-uuid-here",
  "content": "Updated block content"
}
notion_delete_block

Delete a specific block.

{
  "block_id": "block-uuid-here"
}

Utility Operations

notion_get_users

List all users in the workspace.

notion_get_databases

List accessible databases.

Configuration

Environment Variables

VariableDescriptionRequired
NOTION_TOKENNotion integration tokenYes
LOG_LEVELLogging level (debug, info, warn, error)No (default: info)
PORTServer port for health checksNo (default: 3000)

Integration Capabilities

When creating your Notion integration, ensure you enable:

  • āœ… Read content - Required for all read operations
  • āœ… Update content - Required for updating pages/blocks
  • āœ… Insert content - Required for creating pages/blocks
  • āœ… Read user information - Required for user operations

Error Handling

The server implements comprehensive error handling:

  • Authentication errors - Invalid or missing Notion token
  • Permission errors - Access denied to specific pages/databases
  • Rate limiting - Automatic retry with exponential backoff
  • Validation errors - Invalid parameters or malformed requests
  • Network errors - Connection timeouts and retries

Development

Project Structure

notion-mcp-server/
ā”œā”€ā”€ src/
│   ā”œā”€ā”€ index.ts              # Main server entry point
│   ā”œā”€ā”€ types.ts              # TypeScript type definitions
│   ā”œā”€ā”€ tools/                # MCP tool implementations
│   │   ā”œā”€ā”€ pages.ts          # Page-related tools
│   │   ā”œā”€ā”€ databases.ts      # Database-related tools
│   │   ā”œā”€ā”€ blocks.ts         # Block-related tools
│   │   └── utils.ts          # Utility tools
│   ā”œā”€ā”€ notion/               # Notion API wrappers
│   │   ā”œā”€ā”€ client.ts         # Notion client setup
│   │   ā”œā”€ā”€ converters.ts     # Content converters
│   │   └── validators.ts     # Input validation
│   └── utils/
│       ā”œā”€ā”€ logger.ts         # Logging utilities
│       └── errors.ts         # Error handling
ā”œā”€ā”€ tests/                    # Test files
ā”œā”€ā”€ docs/                     # Additional documentation
ā”œā”€ā”€ package.json
ā”œā”€ā”€ tsconfig.json
ā”œā”€ā”€ .env.example
└── README.md

Building

npm run build

Testing

# Run all tests
npm test

# Run tests with coverage
npm run test:coverage

# Run integration tests (requires valid Notion token)
npm run test:integration

Linting

npm run lint
npm run lint:fix

Contributing

  1. Fork the repository
  2. Create a feature branch: git checkout -b feature/amazing-feature
  3. Commit your changes: git commit -m 'Add amazing feature'
  4. Push to the branch: git push origin feature/amazing-feature
  5. Open a Pull Request

Development Guidelines

  • Follow TypeScript best practices
  • Add tests for new features
  • Update documentation for API changes
  • Use conventional commit messages
  • Ensure all tests pass before submitting PR

Security

  • Never commit .env files or tokens to the repository
  • Use environment variables for sensitive configuration
  • Regularly rotate your Notion integration tokens
  • Follow the principle of least privilege when granting access

Troubleshooting

Common Issues

"Cannot use import statement outside a module" Error

This project uses ES modules. Make sure your package.json includes:

{
  "type": "module"
}
"Expected ',' or ']' after array element in JSON" Error

This error occurs when logs are sent to stdout instead of stderr, interfering with MCP JSON communication. The server has been fixed to send all logs to stderr, but if you encounter this:

  1. Ensure you're using the latest version
  2. Check that no console.log statements are in the code
  3. Restart Claude Desktop after updating the server
"Missing required environment variable: NOTION_TOKEN" Error

The server automatically loads the .env file from the project directory. If you see this error:

  1. Ensure the .env file exists in the project root with your token:
    NOTION_TOKEN=your_notion_integration_token_here
    
  2. Verify the token is valid and not expired
  3. Check that there are no extra spaces or quotes around the token
"Cannot find module" Error
  • Verify the path in your MCP client configuration points to the correct location
  • Ensure you've built the project: npm run build
  • Check that the dist/ folder exists and contains index.js
"Unauthorized" Error
  • Verify your NOTION_TOKEN is correct in the .env file
  • Ensure the integration has been added to the pages/databases you're accessing
  • Check that your integration has the required capabilities
"Object not found" Error
  • Verify the page/database ID is correct
  • Ensure the integration has access to the specific object
  • Check if the object has been deleted or moved
Rate Limiting
  • The server automatically handles rate limits with exponential backoff
  • If you encounter persistent rate limiting, consider reducing request frequency

Debug Mode

Enable debug logging:

LOG_LEVEL=debug npm start

This will output detailed information about API calls and responses.

Testing the Server

To verify the server works correctly:

# Build the project
npm run build

# Test TypeScript compilation
npm run typecheck

# Run the server (will start and wait for MCP connections)
npm start

Changelog

See for a detailed list of changes.

License

This project is licensed under the MIT License - see the file for details.

Acknowledgments

Support


Made with ā¤ļø by the open-source community