# Notion MCP Server
[](./LICENSE)
[](https://www.typescriptlang.org/)
[](https://apify.com/)
Connect **Claude Desktop** (and other MCP clients) directly to **Notion** using a real MCP server with **SSE** support.
No flaky local scripts. No tokens in URLs. Run it securely in the cloud.
## 🚀 Quick Start (Recommended)
The easiest way to run this securely 24/7 is on **Apify**.
[Deploy to Apify](https://apify.com/piskunlab/notion-mcp-server)
### Connect your MCP client
- **Base URL** (Apify Container URL):
`https://<run-id>.runs.apify.net`
- **SSE endpoint**:
`GET /sse`
- **Client-to-server messages**:
`POST /message?sessionId=...`
Authentication is done via:
- **Authorization header**: `Authorization: Bearer <SECRET_TOKEN>`
## ✨ Features
- **MCP Protocol with SSE**
- **Secure Bearer Authentication**
- **Notion API access (CRUD via OpenAPI tools)**
- **Rate-limiting & basic DDoS protection** (`express-rate-limit`)
- **Security headers** (`helmet`)
## 💻 Local Development (For Geeks)
### Install
```bash
npm install
```
### Build
```bash
npm run build
```
### Run
```bash
npm start
```
### Docker (optional)
If you use Docker locally:
```bash
docker build -t notion-mcp-server .
docker run -p 8080:8080 --env-file .env notion-mcp-server
```
## ⚙️ Configuration
This project is designed to read configuration from environment variables (and Apify Actor input).
### Required ENV variables
- `NOTION_TOKEN`
- Your Notion integration token.
- `SECRET_TOKEN`
- Bearer token required to access `/sse` and `/message`.
Optional (advanced):
- `NOTION_API_VERSION` (default: `2022-06-28`)
- `OPENAPI_MCP_HEADERS` (JSON string of headers; overrides `NOTION_TOKEN` when present)
- `BASE_URL` (override OpenAPI server base URL)
### Claude Desktop configuration
Add (or merge) something like this into `claude_desktop_config.json`:
```json
{
"mcpServers": {
"notion": {
"command": "node",
"args": ["/ABSOLUTE/PATH/TO/dist/start-apify.js"],
"env": {
"NOTION_TOKEN": "YOUR_NOTION_TOKEN",
"SECRET_TOKEN": "YOUR_SECRET_TOKEN"
}
}
}
}
```
On Apify, you typically configure secrets via **Actor input** / **secrets** and use the Container URL as the server endpoint.
## Security Notes
- Never commit `.env` files or Apify `storage/` directories.
- Use a strong `SECRET_TOKEN` and rotate it if it leaks.
## Contributing
PRs are welcome!