Notion MCP Server: Secure & Enterprise Ready
Pricing
Pay per usage
Notion MCP Server: Secure & Enterprise Ready
Connect Claude Desktop and custom AI Agents to your Notion workspace via Model Context Protocol (MCP). Give your AI a "second brain": let it search, read, and write notes securely. Features Enterprise-grade security, SSE transport, and easy setup.
Pricing
Pay per usage
Rating
5.0
(1)
Developer

Illya Piskun
Actor stats
0
Bookmarked
1
Total users
1
Monthly active users
17 hours ago
Last modified
Categories
Share
Notion MCP Server (Apify Actor)
This Actor runs a remote MCP (Model Context Protocol) server for the Notion API on Apify. It exposes an SSE + HTTP message interface that MCP-compatible clients can use to list tools and call Notion operations.
What you get
- An always-on HTTP server inside your Actor run (via Apify Container URL).
- MCP SSE transport:
GET /sseopens an SSE stream and returns asessionId.POST /message?sessionId=...sends JSON-RPC requests.- Responses are delivered back over SSE as
event: message.
Requirements
- A Notion integration token.
- A secret token used to protect your MCP endpoints.
Input
Configured via Apify Actor input (input_schema.json).
notionApiKey(secret)- Notion integration token.
secretToken(secret)- Protects
/sseand/message.
- Protects
notionApiVersion- Default:
2022-06-28.
- Default:
port(optional)- Ignored on Apify Container URL. In Apify Cloud the server must listen on
ACTOR_WEB_SERVER_PORT(usually 4321).
- Ignored on Apify Container URL. In Apify Cloud the server must listen on
How to connect (Container URL)
After the run starts, open the run detail page and copy the Container URL, e.g.
https://<run-id>.runs.apify.net
1) Open SSE and obtain sessionId
Run this in terminal #1 (keep it open):
curl -i -N \-H "Authorization: Bearer <SECRET_TOKEN>" \https://<run-id>.runs.apify.net/sse
You should see:
event: endpointdata: /message?sessionId=<SESSION_ID>
2) Send MCP JSON-RPC messages
In terminal #2, send initialize:
curl -i \-H "Authorization: Bearer <SECRET_TOKEN>" \-H "Content-Type: application/json" \-X POST \--data '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"curl","version":"0.0"}}}' \"https://<run-id>.runs.apify.net/message?sessionId=<SESSION_ID>"
Expected behavior:
- HTTP returns
202 Accepted. - The actual response arrives in terminal #1 as:
{"jsonrpc":"2.0","id":1,"result":{...}}
Endpoints
GET /- Returns
200 OK.
- Returns
GET /health- Returns JSON health status and current session count.
GET /sse- Auth required.
POST /message?sessionId=...- Auth required.
sessionIdmust be taken from the active/sseconnection.
Security notes
- Do not publish or log your
secretToken. - Use
Authorization: Bearer <token>. - If a token leaks, rotate it in Apify input and restart the run.
Troubleshooting
504 from Container URL
If you see 504 Gateway Time-out, the Actor is usually not listening on the expected web server port.
On Apify, Container URL expects the server on ACTOR_WEB_SERVER_PORT (typically 4321).
Session not found
{"error":"Session not found"} means:
- you posted to a different run URL than the one that created the session, or
- the
/sseconnection closed and the session was cleaned up.
Open /sse again and use the new sessionId.
Local development
npm cinpm run buildapify run