kalendia-mcp
Integrates with Google Calendar to list connections, calendars, and events; manage sync rules and scheduling pages.
Integrates with iCloud Calendar to list connections, calendars, and events; manage sync rules and scheduling pages.
Integrates with Zoom Calendar to list connections, calendars, and events; manage sync rules and scheduling pages.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@kalendia-mcp List my sync rules"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
kalendia-mcp
An MCP server for Kalendia. Drive your calendar sync and scheduling from an MCP client (Claude Code, Claude Desktop): list connections and calendars, read your agenda, and create / delete / run sync rules, all from chat.
Tools (24)
The tool surface mirrors what a user can do in the Kalendia web app (everything reachable by an API token; OAuth-redirect actions like connecting Google/Microsoft or Stripe checkout stay in the web UI, and account deletion is intentionally not exposed).
Reads (read-only):
list_connections— connected calendar accounts (Google, Microsoft, iCloud, ICS, Zoom).list_calendars(connection_id)— live provider calendars under one connection (no Kalendia id).list_all_calendars— every persisted calendar across accounts, with the numeric id used by rules/pages.list_sync_rules— all mirror rules.get_agenda(connection_id, calendar_id, from_iso?, to_iso?)— events in a window.list_scheduling_pages/get_scheduling_page(page_id)— booking pages.get_availability(slug, from_iso?, to_iso?)— bookable slots for a page.get_billing/get_billing_overview— plan, usage, limits.get_audit_log(limit?)— recent account activity.
Writes (the client confirms before firing):
Sync rules:
create_sync_rule,run_sync_rule,delete_sync_rule(destructive).Connections/calendars:
connect_icloud,connect_ics,refresh_calendars,discover_calendars,set_active_calendars,rename_calendar,disconnect_connection(destructive).Scheduling pages:
create_scheduling_page,update_scheduling_page,delete_scheduling_page(destructive).
Related MCP server: calendar-mcp
Setup
Mint a personal access token in Kalendia: Settings > API tokens. Copy it (shown once; starts with
kld_).Install deps:
uv sync.Configure the env: copy
.env.exampleto.envand setKALENDIA_TOKEN(andKALENDIA_API_URLif testing against a local backend).
Run
uv run kalendia-mcp # stdio (default)
uv run kalendia-mcp --http # Streamable HTTPRegister in Claude Code
Add to your MCP config (e.g. ~/.claude.json), filling in the token:
{
"mcpServers": {
"kalendia": {
"command": "uv",
"args": ["run", "--directory", "/Users/bogdan-georgebrad/Claude/Code/personal/kalendia-mcp", "kalendia-mcp"],
"env": {
"KALENDIA_TOKEN": "kld_your_token_here",
"KALENDIA_API_URL": "https://api.kalendia.io"
}
}
}
}To test against a local backend instead, set KALENDIA_API_URL to http://localhost:8002 and use a
token minted on that backend.
Remote / multi-user (HTTP)
uv run kalendia-mcp --http runs the server over Streamable HTTP as an OAuth 2.0 resource server, so
ONE deployed instance serves many users: each request authenticates with the caller's own kld_
token (no per-user env var). It serves OAuth Protected Resource Metadata at
/.well-known/oauth-protected-resource (advertising Kalendia as the authorization server), rejects
unauthenticated/invalid tokens with 401 + WWW-Authenticate, validates a presented kld_ token
against the Kalendia API, and forwards it to act as that user. Config via env:
KALENDIA_MCP_HOST / KALENDIA_MCP_PORT (bind), KALENDIA_MCP_URL (public URL in the metadata),
KALENDIA_API_URL (the Kalendia API).
Remaining for a public launch (tracked as Phase 2): hosting/deploy of this HTTP server, and full
OAuth authorization-server discovery (dynamic client registration + auth-code + PKCE) so clients can
mint tokens in-flow instead of pasting a kld_ token. Today a client connects by presenting a
kld_ bearer (minted in Settings > API tokens).
Develop
uv run ruff check . && uv run ruff format --check . && uv run pyright && uv run pytestSecurity
A token has the user's full account access (no scopes yet). Treat it like a password. Revoke a leaked or stale token in Kalendia: Settings > API tokens.
Available Tools
27 toolscancel_eventADestructive
Cancel (delete) one event. Cannot be undone.
connection_id from list_connections; calendar_id from list_calendars; event_id from get_agenda. notify=True (default) sends a cancellation to the attendees. An unknown event returns an error on Google / Microsoft; iCloud treats an already-deleted event as success.
Inputs: event_id (required), calendar_id (required), connection_id (required), notify. Returns: object
connect_icloudA
Connect an Apple iCloud calendar. Requires an app-specific password (NOT your normal Apple password; generate one at appleid.apple.com under Sign-In and Security). Credentials are validated before saving. Returns the new connection.
Inputs: apple_id (required), app_specific_password (required). Returns: object
connect_icsA
Connect a read-only calendar from a public ICS feed URL (an https/webcal .ics link). The feed is fetched and parsed to validate it. An ICS calendar can be a sync source but not a target.
Inputs: feed_url (required). Returns: object
create_eventA
Create a calendar event.
connection_id from list_connections; calendar_id is a writable calendar's provider_calendar_id from list_calendars. start_iso / end_iso are ISO-8601 datetimes (e.g. "2026-06-20T14:00:00Z"; naive is read as UTC). attendees is a list of email addresses; notify=True (default) emails them an invitation. add_conference=True attaches a native video link (Google Meet / Teams). The target must be writable and must NOT be the target of a sync rule. Returns {event: {...}}.
Inputs: title (required), end_iso (required), start_iso (required), calendar_id (required), +7 more. Returns: object
create_scheduling_pageA
Create a scheduling (booking) page.
slug is the public URL suffix (unique per account). availability_window is {"timezone": "<IANA, e.g. Europe/Bucharest>", "weekly": {"mon": [["09:00","17:00"]], "tue": [...]}} where each day key (mon..sun) maps to a list of [start, end] "HH:MM" intervals; omit a day for no availability. source_calendar_ids are checked for conflicts; target_calendar_id (must be writable and active) is where confirmed bookings are created. video_provider is one of none | google_meet | teams | zoom (zoom also needs zoom_connection_id).
Inputs: slug (required), title (required), duration_minutes (required), target_calendar_id (required), +9 more. Returns: object
create_sync_ruleA
Create a sync rule that mirrors events from source_calendar_id onto target_calendar_id.
Calendar ids come from list_calendars; the target must be writable. visibility_mode is one of "busy_only" (hide all details, default), "title_only", or "full_details". mirror_prefix is an optional string prepended to mirrored event titles (e.g. "[Personal]"). Set enabled=False to create it paused. Mirrors the source's current events into the target on creation.
Inputs: source_calendar_id (required), target_calendar_id (required), enabled, mirror_prefix, +1 more. Returns: object
delete_scheduling_pageADestructive
Delete a scheduling page (page_id from list_scheduling_pages). Cannot be undone.
Inputs: page_id (required). Returns: object
delete_sync_ruleADestructive
Delete a sync rule (rule_id from list_sync_rules). The mirrored events it created on the target calendar are cleaned up afterward by Kalendia. This cannot be undone.
Inputs: rule_id (required). Returns: object
disconnect_connectionADestructive
Disconnect a calendar account: permanently deletes the connection and its stored credentials, pauses any booking pages that targeted its calendars, and removes sync rules that used them. The provider OAuth grant is revoked best-effort. Cannot be undone (you would reconnect from scratch). Returns which pages were paused and how many rules were removed.
Inputs: connection_id (required). Returns: object
discover_calendarsA
Re-discover the calendars under one connection (connection_id from list_connections). Newly visible calendars are auto-activated up to the plan's calendar limit.
Inputs: connection_id (required). Returns: result
get_agendaARead-only
Read events from one calendar in a time window.
connection_id comes from list_connections; calendar_id is a calendar's provider_calendar_id from list_calendars (e.g. an email, or "primary"). from_iso / to_iso are ISO-8601 datetimes (e.g. "2026-06-15T00:00:00Z"); omit them to use Kalendia's default window. Returns {events: [...]}.
Inputs: calendar_id (required), connection_id (required), to_iso, from_iso. Returns: object
get_audit_logARead-only
Get recent account audit-log entries, most recent first: id, action, target_type, target_id, payload, created_at. limit is clamped to 1..500.
Inputs: limit. Returns: result
get_availabilityARead-only
Get bookable slots for a scheduling page by its slug, optionally within an ISO-8601 UTC window (from_iso/to_iso). Returns {slug, title, duration_minutes, slots: [ISO datetimes]}. Omit the window for the page's full horizon.
Inputs: slug (required), to_iso, from_iso. Returns: object
get_billingARead-only
Get the current plan and subscription status: plan, tier, subscription_status, current_period_end, is_comp.
Inputs: no named parameters. Returns: object
get_billing_overviewARead-only
Get plan plus current usage and limits: usage {calendars, scheduling_pages} against limits {max_calendars, max_scheduling_pages, teams_app, custom_domain} (null limit = unlimited).
Inputs: no named parameters. Returns: object
get_scheduling_pageARead-only
Get one scheduling (booking) page's full config, including its availability_window. Fetch this before update_scheduling_page, since update is a full replace.
Inputs: page_id (required). Returns: object
list_all_calendarsARead-only
List every calendar across all connected accounts as a flat list (id, connection_id, provider_calendar_id, display_name, custom_name, is_primary, is_writable, sync_enabled). Use the calendar id as a sync-rule source/target or a scheduling-page calendar.
Inputs: no named parameters. Returns: result
list_calendarsARead-only
List the LIVE provider calendars under one connection (a fresh fetch from the provider): each item is name, provider_calendar_id (use this as calendar_id in get_agenda), is_primary, is_writable, is_hidden. This is the provider view and has NO Kalendia calendar id; to get the numeric calendar id needed for sync rules and scheduling pages, use list_all_calendars.
Inputs: connection_id (required). Returns: result
list_connectionsARead-only
List the user's connected calendar accounts (Google, Microsoft, iCloud, ICS, Zoom).
Each item: id, provider, email, status, scopes. Use the id with list_calendars.
Inputs: no named parameters. Returns: result
list_scheduling_pagesBRead-only
List the user's scheduling (booking) pages.
Inputs: no named parameters. Returns: result
list_sync_rulesARead-only
List all sync (mirror) rules. Each rule mirrors events from a source calendar onto a target calendar. Returns id, source_calendar_id, target_calendar_id, visibility_mode, mirror_prefix, enabled.
Inputs: no named parameters. Returns: result
refresh_calendarsA
Re-discover calendars across ALL connected accounts in one call (picks up calendars created since the account was connected). A connection whose provider errors is skipped, not fatal.
Inputs: no named parameters. Returns: result
rename_calendarA
Set a friendly display name for a calendar (calendar_id from list_calendars). Pass null or an empty string to clear the override and fall back to the provider's name.
Inputs: calendar_id (required), custom_name. Returns: object
reschedule_eventA
Reschedule one event to a new time window (the core "move this call" action).
connection_id from list_connections; calendar_id from list_calendars; event_id is the event's provider_event_id from get_agenda. For a recurring meeting, pass the specific occurrence's id (get_agenda returns each occurrence separately) to move just that one. start_iso / end_iso are ISO-8601 datetimes. Only the time changes: title, attendees, location, and the video link are preserved. notify=True (default) emails the attendees about the new time. Returns {event: {...}}.
Inputs: end_iso (required), event_id (required), start_iso (required), calendar_id (required), +2 more. Returns: object
run_sync_ruleA
Run a sync rule now (a full reconcile that backfills the target from the source). Returns counts of events created / updated / deleted, plus any per-event errors.
Inputs: rule_id (required). Returns: object
set_active_calendarsA
Set which calendars under a connection are active (synced and usable in rules/pages). This REPLACES the full active set for that connection. Note: passing an empty list would disconnect the whole account, so this tool rejects an empty list; use disconnect_connection for that.
Inputs: connection_id (required), active_calendar_ids (required). Returns: object
update_scheduling_pageA
Update a scheduling page. This is a FULL REPLACE: call get_scheduling_page first, change the fields you want, and pass every field back (any omitted optional field resets to its default). Set is_active=False to pause the page. Field meanings match create_scheduling_page.
Inputs: slug (required), title (required), page_id (required), duration_minutes (required), +11 more. Returns: object
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 27 tools
Most tools target distinct resources and actions, with clear descriptions. A few pairs overlap slightly (refresh_calendars vs. discover_calendars, get_billing vs. get_billing_overview), but the usage context is explained well enough to avoid major confusion.
All tool names consistently follow a verb_noun pattern in lowercase snake_case (e.g., list_connections, create_event, delete_scheduling_page). The use of provider names in connect_ics/connect_icloud is a natural and predictable deviation.
With 27 tools, the set exceeds the 25-tool threshold considered too many for most servers. While the domain is broad, several tools could be consolidated (e.g., billing tools, refresh/discover), making the count feel inflated rather than well-scoped.
The server provides solid coverage for connections, calendars, sync rules, events, and scheduling pages, with full CRUD for scheduling pages. However, sync rules lack an update endpoint, and event editing is limited to rescheduling (no metadata updates), which are notable gaps for a calendar service.
Maintenance
Related MCP Connectors
Hosted Google Calendar MCP server for AI agents. No self-hosting or Google Cloud setup.
A MCP server that works with Google Calendar to manage event listing, reading, and updates.
Hosted MCP server connecting AI assistants to 9,000+ apps and 40,000+ actions via Zapier.
MCP server that lets your AI assistant build and deploy apps, hosting each one at a live URL.
Related MCP Servers
- AlicenseAqualityDmaintenanceMCP server that connects AI agents to calendars, bookings, and scheduling polls via the Model Context Protocol.227 npmMIT
- AlicenseNot gradedqualityNot gradedmaintenanceMCP server that lets AI agents manage Google Calendar -- create events, check availability, and manage schedules.MIT
- AlicenseNot gradedqualityDmaintenanceAn MCP server that enables AI assistants to manage Google Calendar events, calendars, sharing, and scheduling with full read/write access across multiple Google accounts, supporting natural language creation, recurring events, and Google Meet.40 npmMIT
- FlicenseNot gradedqualityDmaintenanceMCP server for a desktop calendar that allows AI agents to manage events, check schedules, and avoid conflicts via standard MCP tools.2-