notion-calendar-mcp
notion-calendar-mcp
Stdio MCP server for Notion Calendar. It talks to the private calendar-api.notion.so HTTP API (no public docs; reverse-engineered).
This project is not affiliated with, endorsed by, or supported by Notion Labs, Inc.
Warning
Use this at your own risk.
The Calendar HTTP API is undocumented and reverse-engineered. Endpoints, payloads, and auth can change or disappear without notice.
Auth is a browser session JWT that typically lasts about 5 hours. After that, calls return 401/403 until you refresh the token from a signed-in calendar.notion.so session.
Using an unofficial API may violate Notion’s Terms of Service. You are responsible for how you use this software.
Never commit session tokens,
credentials.json, or.envfiles. Never paste JWTs into chat, issues, or pull requests.
Licensed under the MIT License.
Requirements
Python 3.10+
A Notion Calendar account signed in at calendar.notion.so
The MCP SDK is pinned to mcp==1.29.1 so Server.list_tools remains available (later 2.x releases removed that registration API).
Install
git clone https://github.com/felipeorlando/notion-calendar-mcp.git
cd notion-calendar-mcp
python3 -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -r requirements.txtAuthentication
Provide a session JWT in one of these ways (file wins for base_url / extra headers; env can supply or override the token).
1. Credentials file (recommended)
mkdir -p ~/.config/notion-calendar
cp credentials.json.example ~/.config/notion-calendar/credentials.json
chmod 600 ~/.config/notion-calendar/credentials.jsonEdit ~/.config/notion-calendar/credentials.json:
{
"authorization": "Bearer YOUR_SESSION_JWT",
"base_url": "https://calendar-api.notion.so",
"headers": {
"x-timezone": "America/New_York",
"x-client-type": "web",
"x-client-platform": "web",
"x-client-os": "linux"
}
}headers is optional. Set x-timezone to your IANA timezone. See credentials.json.example for the full placeholder shape.
How to copy the JWT from the browser:
Sign in at calendar.notion.so.
Open DevTools → Network.
Trigger any calendar load and inspect a request to
calendar-api.notion.so.Copy the
Authorizationvalue (Bearer …).
2. Environment variables
export NOTION_CALENDAR_AUTHORIZATION="Bearer YOUR_SESSION_JWT"
# or a raw token / Bearer value:
# export NOTION_CALENDAR_TOKEN="YOUR_SESSION_JWT"
# optional:
# export NOTION_CALENDAR_BASE_URL="https://calendar-api.notion.so"Do not put real tokens in shell history files you share, or in MCP config that lives inside a git repo.
On 401/403, refresh the JWT. list_tools works without a token; tool calls fail with a clear error if it is missing or expired.
Run
.venv/bin/python server.pyThe process speaks MCP over stdio (no HTTP port).
Claude Desktop
Add the server to the Claude Desktop MCP config:
macOS:
~/Library/Application Support/Claude/claude_desktop_config.jsonWindows:
%APPDATA%\Claude\claude_desktop_config.jsonLinux:
~/.config/Claude/claude_desktop_config.json
{
"mcpServers": {
"notion-calendar": {
"command": "/ABSOLUTE/PATH/TO/notion-calendar-mcp/.venv/bin/python",
"args": ["/ABSOLUTE/PATH/TO/notion-calendar-mcp/server.py"]
}
}
}Replace /ABSOLUTE/PATH/TO/notion-calendar-mcp with the real clone path. Prefer the credentials file above instead of embedding the JWT in this JSON.
Restart Claude Desktop after saving.
Cursor
User config: ~/.cursor/mcp.json. Project config: .cursor/mcp.json (do not commit tokens).
{
"mcpServers": {
"notion-calendar": {
"command": "/ABSOLUTE/PATH/TO/notion-calendar-mcp/.venv/bin/python",
"args": ["server.py"],
"cwd": "/ABSOLUTE/PATH/TO/notion-calendar-mcp"
}
}
}Restart Cursor after saving.
An agent-plugin layout (plugin.json, mcp.json, skills/notion-calendar/SKILL.md) is also included for hosts that load that format.
Tools
Call get_user first, then get_calendar_lists (or get_calendars) before event reads/writes. Prefer title/summary over raw ids when presenting results.
Tool | Kind | Purpose |
| read | Signed-in profile and linked calendar accounts |
| read | Sidebar calendars / |
| read | Calendar metadata (color, role, time zone) |
| read | Events in a time window ( |
| read | One event by id |
| read | Keyword search across accounts/calendars |
| write | Create an event ( |
| write | Patch one or more events |
| destructive | Delete events (confirm first) |
| write |
|
| read | Free/busy blocks before scheduling |
| read | Working hours and defaults (includes |
| write | Update prefs (send |
| read | Paginated directory / attendees |
| read | Contact lookup (prefer |
| read | Color palette |
| read | Mirrored/synced calendars |
| read | Room/resource calendars |
| read | Expand Google group invitees |
| read | Normalize events for export |
| read | Advanced sync tokens; prefer |
| read | Scheduling Holds (booking pages) |
| write | Create or update a Hold |
| destructive | Delete a Hold |
| read | Notion identities tied to this Calendar session |
| write | Rename/recolor calendars |
| write | Subscribe to a calendar |
| destructive | Unsubscribe from the sidebar list |
create_event eventData needs id (uuid hex is fine), summary, start, end, status, provider, accountId, calendarId, and reminders: { "useDefault": true }. Default send_updates to none unless you intend to email guests (all / externalOnly).
Smoke test
With valid credentials:
.venv/bin/python smoke_test.pyCreates a 30-minute probe event two weeks out, then deletes it. It does not print tokens.
Security
See SECURITY.md. Short version: session JWT, ~5 hour TTL, never commit secrets, refresh on 401/403.
Contributing
See CONTRIBUTING.md.
License
MIT © Felipe Orlando
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/felipeorlando/notion-calendar-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server