@gongrzhe/server-notion-mcp
v0.0.7
Published
Official MCP server for Notion API with stateless architecture
Maintainers
Readme
Notion MCP Server
[!NOTE]
This is a stateless MCP server for the Notion API with the following improvements:
- Stateless Architecture: Complete request isolation with no session management
- Bearer Token Authentication: Standard Authorization header support
- Fresh Instance Per Request: Each request gets a new server instance
- Horizontal Scaling: Stateless design enables easy load balancing
Learn more about the official Notion MCP here
This project implements an MCP server for the Notion API.
Installation
1. Setting up Integration in Notion:
Go to https://www.notion.so/profile/integrations and create a new internal integration or select an existing one.

While we limit the scope of Notion API's exposed (for example, you will not be able to delete databases via MCP), there is a non-zero risk to workspace data by exposing it to LLMs. Security-conscious users may want to further configure the Integration's Capabilities.
For example, you can create a read-only integration token by giving only "Read content" access from the "Configuration" tab:

2. Connecting content to integration:
Ensure relevant pages and databases are connected to your integration.
To do this, visit the Access tab in your internal integration settings. Edit access and select the pages you'd like to use.


Alternatively, you can grant page access individually. You'll need to visit the target page, and click on the 3 dots, and select "Connect to integration".

3. Adding MCP config to your client:
Using npx (Recommended):
Quick Start:
Run directly without installation:
# STDIO mode (default)
npx @gongrzhe/server-notion-mcp
# Stateless HTTP mode (recommended)
npx @gongrzhe/server-notion-mcp --stateless
# Stateless HTTP mode with custom port
npx @gongrzhe/server-notion-mcp --stateless --port 8080Cursor & Claude:
Add the following to your .cursor/mcp.json or claude_desktop_config.json (MacOS: ~/Library/Application\ Support/Claude/claude_desktop_config.json)
Option 1: Using NOTION_TOKEN (recommended)
{
"mcpServers": {
"notionApi": {
"command": "npx",
"args": ["-y", "@gongrzhe/server-notion-mcp"],
"env": {
"NOTION_TOKEN": "ntn_****"
}
}
}
}Option 2: Using OPENAPI_MCP_HEADERS (for advanced use cases)
{
"mcpServers": {
"notionApi": {
"command": "npx",
"args": ["-y", "@gongrzhe/server-notion-mcp"],
"env": {
"OPENAPI_MCP_HEADERS": "{\"Authorization\": \"Bearer ntn_****\", \"Notion-Version\": \"2022-06-28\" }"
}
}
}
}Zed
Add the following to your settings.json
{
"context_servers": {
"some-context-server": {
"command": {
"path": "npx",
"args": ["-y", "@gongrzhe/server-notion-mcp"],
"env": {
"OPENAPI_MCP_HEADERS": "{\"Authorization\": \"Bearer ntn_****\", \"Notion-Version\": \"2022-06-28\" }"
}
},
"settings": {}
}
}
}Stateless Mode (Recommended)
The server now supports stateless architecture for better scalability, security, and operational simplicity.
Starting the Server in Stateless Mode
# Stateless mode (recommended)
npm run start:stateless
# Or manually with custom options
npx @gongrzhe/server-notion-mcp --stateless --port 8080
# Development mode
npm run dev -- --statelessServer Features in Stateless Mode
- Complete Request Isolation: Each request gets a fresh server instance
- No Session Management: No state stored between requests
- Bearer Token Authentication: Standard Authorization header support
- Fresh Token Validation: Each request validates tokens independently
- Memory Efficient: Automatic cleanup after each request
- Horizontally Scalable: Easy to load balance across multiple instances
API Reference
Base URL
http://localhost:30000/mcpAuthentication All requests require a Bearer token in the Authorization header:
Authorization: Bearer <your_notion_token>Endpoints
POST /mcp: Main MCP endpoint for all operations
- Headers:
Content-Type: application/json,Authorization: Bearer <token> - Body: Standard MCP JSON-RPC request
- Headers:
GET /health: Server health check (no authentication required)
- Returns server status, timestamp, and mode information
Example Usage
# Test tools listing
curl -X POST http://localhost:30000/mcp \
-H "Content-Type: application/json" \
-H "Authorization: Bearer your_notion_token" \
-d '{
"jsonrpc": "2.0",
"id": "test",
"method": "tools/list",
"params": {}
}'
# Test tool call
curl -X POST http://localhost:30000/mcp \
-H "Content-Type: application/json" \
-H "Authorization: Bearer your_notion_token" \
-d '{
"jsonrpc": "2.0",
"id": "test",
"method": "tools/call",
"params": {
"name": "search-database-simple",
"arguments": {"query": "test"}
}
}'Migration from Session-Aware Version
Breaking Changes
- Authentication: Replace custom headers with
Authorization: Bearer <token> - Port: Default port changed from 3000 to 30000 for stateless mode
- Session Management: No longer supported (stateless mode only)
- Endpoints: Only POST /mcp is supported for MCP operations
Migration Steps
- Update client code to use Bearer tokens instead of custom session headers
- Change default port in configurations from 3000 to 30000
- Remove any session management code from clients
- Update error handling for stateless responses (no session state persists)
Legacy Multi-User Session-Aware Mode
The server still supports the legacy session-aware mode for backward compatibility:
# Legacy HTTP transport with multi-user support
npx @gongrzhe/server-notion-mcp --transport http --multi-user --port 3000However, stateless mode is strongly recommended for new deployments due to better scalability, security, and operational simplicity.
Client Connection
When connecting to the legacy multi-user server, clients must:
- Provide the Notion token in the Authorization header:
Bearer ntn_**** - Use the
mcp-session-idheader to maintain session continuity - Connect to the
/mcpendpoint using HTTP POST/GET methods
Example connection headers:
Authorization: Bearer ntn_your_notion_token_here
Content-Type: application/json
mcp-session-id: your-session-id (for subsequent requests)Benefits
- Scalability: Support multiple users without token conflicts
- Security: Tokens are isolated per session, not shared globally
- Flexibility: Each user can have different Notion workspace access
- Monitoring: Real-time visibility into active sessions and usage
Alternative Installation Methods
Global Installation
npm install -g @gongrzhe/server-notion-mcp
# Then run with:
notion-mcp --transport http --multi-userUsing Docker:
There are two options for running the MCP server with Docker:
Option 1: Using the official Docker Hub image:
Add the following to your .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 (for advanced use cases):
{
"mcpServers": {
"notionApi": {
"command": "docker",
"args": [
"run",
"--rm",
"-i",
"-e", "OPENAPI_MCP_HEADERS",
"mcp/notion"
],
"env": {
"OPENAPI_MCP_HEADERS": "{\"Authorization\":\"Bearer ntn_****\",\"Notion-Version\":\"2022-06-28\"}"
}
}
}
}This approach:
- Uses the official Docker Hub image
- Properly handles JSON escaping via environment variables
- Provides a more reliable configuration method
Option 2: Building the Docker image locally:
You can also build and run the Docker image locally. First, build the Docker image:
docker compose buildThen, add the following to your .cursor/mcp.json or claude_desktop_config.json:
Using NOTION_TOKEN (recommended):
{
"mcpServers": {
"notionApi": {
"command": "docker",
"args": [
"run",
"--rm",
"-i",
"-e",
"NOTION_TOKEN=ntn_****",
"notion-mcp-server"
]
}
}
}Using OPENAPI_MCP_HEADERS (for advanced use cases):
{
"mcpServers": {
"notionApi": {
"command": "docker",
"args": [
"run",
"--rm",
"-i",
"-e",
"OPENAPI_MCP_HEADERS={\"Authorization\": \"Bearer ntn_****\", \"Notion-Version\": \"2022-06-28\"}",
"notion-mcp-server"
]
}
}
}Don't forget to replace ntn_**** with your integration secret. Find it from your integration configuration tab:
Installing via Smithery
To install Notion API Server for Claude Desktop automatically via Smithery:
npx -y @smithery/cli install @makenotion/notion-mcp-server --client claudeTransport Options
The Notion MCP Server supports two transport modes:
STDIO Transport (Default)
The default transport mode uses standard input/output for communication. This is the standard MCP transport used by most clients like Claude Desktop.
# Run with default stdio transport
npx @notionhq/notion-mcp-server
# Or explicitly specify stdio
npx @notionhq/notion-mcp-server --transport stdioStreamable HTTP Transport
For web-based applications or clients that prefer HTTP communication, you can use the Streamable HTTP transport:
# Run with Streamable HTTP transport on port 3000 (default)
npx @notionhq/notion-mcp-server --transport http
# Run on a custom port
npx @notionhq/notion-mcp-server --transport http --port 8080
# Run with a custom authentication token
npx @notionhq/notion-mcp-server --transport http --auth-token "your-secret-token"When using Streamable HTTP transport, the server will be available at http://0.0.0.0:<port>/mcp.
Authentication
The Streamable HTTP transport requires bearer token authentication for security. You have three options:
Option 1: Auto-generated token (recommended for development)
npx @notionhq/notion-mcp-server --transport httpThe server will generate a secure random token and display it in the console:
Generated auth token: a1b2c3d4e5f6789abcdef0123456789abcdef0123456789abcdef0123456789ab
Use this token in the Authorization header: Bearer a1b2c3d4e5f6789abcdef0123456789abcdef0123456789abcdef0123456789abOption 2: Custom token via command line (recommended for production)
npx @notionhq/notion-mcp-server --transport http --auth-token "your-secret-token"Option 3: Custom token via environment variable (recommended for production)
AUTH_TOKEN="your-secret-token" npx @notionhq/notion-mcp-server --transport httpThe command line argument --auth-token takes precedence over the AUTH_TOKEN environment variable if both are provided.
Making HTTP Requests
All requests to the Streamable HTTP transport must include the bearer token in the Authorization header:
# Example request
curl -H "Authorization: Bearer your-token-here" \
-H "Content-Type: application/json" \
-H "mcp-session-id: your-session-id" \
-d '{"jsonrpc": "2.0", "method": "initialize", "params": {}, "id": 1}' \
http://localhost:3000/mcpNote: Make sure to set either the NOTION_TOKEN environment variable (recommended) or the OPENAPI_MCP_HEADERS environment variable with your Notion integration token when using either transport mode.
Examples
- Using the following instruction
Comment "Hello MCP" on page "Getting started"AI will correctly plan two API calls, v1/search and v1/comments, to achieve the task
- Similarly, the following instruction will result in a new page named "Notion MCP" added to parent page "Development"
Add a page titled "Notion MCP" to page "Development"- You may also reference content ID directly
Get the content of page 1a6b35e6e67f802fa7e1d27686f017f2Development
Build
npm run buildExecute
npx -y --prefix /path/to/local/notion-mcp-server @notionhq/notion-mcp-serverPublish
npm publish --access public