morgen-mcp
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., "@morgen-mcpwrite today's diary entry"
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.
morgen-mcp
An MCP server that connects your Morgen calendar to any MCP-compatible AI client.
The idea
Calendar apps give you the technical skeleton of your day; what you did and when. Physical journals capture the feeling of it. This tool lives in between.
morgen-mcp exposes your Morgen schedule as tools that your AI client can call. At the end of the day, start a conversation: the AI fetches your events, reads your existing notes for context, asks you a couple of short questions, and writes something that reads like a real diary and not a meeting log.
Pair it with mcp-obsidian and the entry lands directly in your Obsidian daily note. No extra subscriptions, no extra API keys. Works with whatever AI client you already use.
Related MCP server: Google Calendar MCP Server
How it works
morgen-mcp is an MCP (Model Context Protocol) server. It exposes 3 tools:
Tool | Description |
| Fetch events for a given date across selected calendars |
| List connected Morgen accounts and their IDs |
| List calendars under an account |
The AI client calls these tools to get your schedule. Writing the diary entry and saving it is up to the client and whatever other MCP tools you have connected.
Requirements
Python 3.14+
A Morgen account - get your API key at platform.morgen.so
Any MCP-compatible client (Claude Desktop, Cursor, Windsurf, etc.)
Setup
git clone https://github.com/batoorsayed/morgen-mcp
cd morgen-mcp
uv sync1. Get your Morgen API key
Go to platform.morgen.so > Developers > API Keys.
2. Configure environment
cp .env.example .env
# Add your API key to .envThen run this to fetch your account IDs and get a ready-to-paste env line:
uv run morgen-mcp --list-accountsIt will print something like:
Accounts:
abc123def456 Your Name [icloud]
xyz789ghi012 Your Name [google]
...
Add to your .env:
MORGEN_ACCOUNT_ID=abc123def456,xyz789ghi012,...It also prints a suggested CLAUDE.md snippet you can paste into your project instructions.
Copy the env line into your .env. Include only the accounts whose events you want. See the rate limits note below.
3. Register with your MCP client
Claude Code : Run this from inside the cloned directory:
claude mcp add --scope user morgen-mcp -- uv --directory $(pwd) run morgen-mcpRun once. Available across all projects. Credentials are picked up from .env automatically.
Other clients (Claude Desktop, Cursor, Windsurf, etc.) : Add to your client's MCP config file, replacing /path/to/morgen-mcp with the actual path to your clone. Most clients expand $VAR references from your shell environment. If yours doesn't, paste the actual values directly.
{
"mcpServers": {
"morgen-mcp": {
"command": "uv",
"args": ["--directory", "/path/to/morgen-mcp", "run", "morgen-mcp"],
"env": {
"MORGEN_API_KEY": "$MORGEN_API_KEY",
"MORGEN_ACCOUNT_ID": "$MORGEN_ACCOUNT_ID"
}
}
}
}Usage
Just talk to your AI client:
"Write my diary entry for today"
"What did I have on my calendar yesterday?"
"Summarize my week"The end-of-day ritual
At the end of the day, open your AI client and say something like "write today's diary entry". From there:
The AI fetches your events for the day via
get_eventsIt checks whether today's Obsidian daily note (
YYYY-MM-DD.md) exists, and creates it if notIt reads your morning note and any recent notes you've flagged, to enrich the context
It asks you 2–3 short questions: things the calendar can't tell it (what was hard, what surprised you, what's worth remembering)
It writes a personal diary entry and appends it under a
### End of Dayheading
This workflow requires both morgen-mcp (calendar) and mcp-obsidian (notes) connected to your client. morgen-mcp only handles the events fetch. The AI orchestrates the rest using both MCPs and the system prompt below. Credit to bitbonsai for mcp-obsidian.
System prompt: Add this to your client's project instructions:
When I ask for a diary entry:
1. Fetch my Morgen events for that day using get_events
2. Check if today's Obsidian daily note (YYYY-MM-DD.md) exists — if not, create it
3. Read today's note and any notes I've flagged as important from the past few days
4. Ask me 2-3 short questions to capture what the calendar doesn't show
5. Write a personal diary entry — human, not a bullet list — weaving the events and my answers together
6. Append it to my daily note under a "### End of Day" headingOutput example
### End of Day
Morning focus block finally broke the deadlock on the data layer —
that one took longer than it should have but shipping it felt like
putting down something heavy. Three back-to-back meetings killed the
afternoon momentum. The kind of day where you do more than it felt like.Rate limits
The Morgen API allows 100 points per 15-minute window. Each /list call (calendars, events) costs 10 points.
get_events makes one calendars fetch plus one events fetch per configured account. With 6 accounts that's 70 points, leaving 30 to spare. Fine for a diary tool used a few times a day, but avoid calling it in rapid succession.
If you hit a 429, wait a few minutes and try again.
Privacy
Event data is fetched from Morgen and passed to your AI client for processing. No data is stored or sent anywhere else. Your AI client's own privacy policy applies to how it handles that data.
Contributing
Small tool, open door. PRs welcome — keep it simple.
License
MIT
Available Tools
3 toolsget_eventsA
Fetch events for a given date (YYYY-MM-DD). Defaults to today if empty.
| Name | Required | Description | Default |
|---|---|---|---|
| date | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
There are no annotations, so the description carries the behavioral disclosure burden. It reveals a non-obvious default ('Defaults to today if empty'), but it does not discuss read-only status, authentication needs, or any limitations on returned events.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, front-loaded sentence with no filler. It states the action, the resource, the input format, and the default behavior efficiently.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with one optional parameter and an existing output schema, the description is nearly complete. It could have added whether events come from a specific calendar or across all calendars, but the tool's simple signature makes that omission non-critical.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, but the description fully compensates for the single parameter by specifying both the expected format (YYYY-MM-DD) and the default behavior when the date is empty. This is more meaningful than the raw schema alone.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states a specific verb ('Fetch') and resource ('events'), and adds the date scoping in a standard format. It is immediately distinguishable from sibling tools list_accounts and list_calendars, which target different resources.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear context for when to call the tool: when events for a specific date are needed. It also communicates the behavior when no date is supplied, but it does not explicitly mention when not to use it or direct users to an alternative tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_accountsA
List all connected Morgen accounts and their IDs.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the behavioral disclosure burden. It implies a read-only enumeration by using 'List all', but it does not explicitly address side effects, authentication expectations, or pagination. This is acceptable but not rich.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single sentence with no filler. Every word contributes the action, target, scope, and output content. It is easy to parse and front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter list operation with an output schema, the description fully covers what the agent needs to select and invoke the tool. No pagination or side-effect warnings are necessary for this simplicity level.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters, so the baseline is 4. The description accurately indicates what the output contains (accounts and IDs), which is the only meaning an agent needs beyond the empty schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ('List') with a clear resource ('connected Morgen accounts') and states the output includes their IDs. This unambiguously differentiates it from sibling tools like list_calendars and get_events.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description clearly establishes the tool's purpose: enumerate connected Morgen accounts and retrieve their IDs. It does not explicitly name alternatives or exclusions, but its scope is so distinct from the siblings that usage context is clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_calendarsA
List calendars across all accounts, optionally filtered by account_id.
| Name | Required | Description | Default |
|---|---|---|---|
| account_id | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the burden of explaining behavior. It usefully discloses the broad scope ('across all accounts') and the optional filtering behavior. However, it does not address pagination, permissions, or behavior with invalid account_id values, though these may be less critical for a simple list operation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, efficient sentence that places the core action and scope first and appends the optional filter condition. Every word contributes useful information with no redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with one optional parameter and an output schema, the description covers the key invocation details: what is listed and how the parameter affects scope. It does not mention where account_id values come from (e.g., list_accounts), but that is not strictly necessary for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must add meaning to the lone parameter. It does this by explaining that account_id optionally filters the results across all accounts. This provides essential semantic context beyond the bare schema definition.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ('List') and resource ('calendars'), and clarifies scope ('across all accounts') along with an optional filter. This clearly distinguishes it from sibling tools like list_accounts and get_events, which target different resources.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies this tool is for listing calendars and that account_id can optionally restrict results, but it does not explicitly name alternatives or state when not to use it. An agent could infer the distinction from sibling names, but the guidance is not explicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
3 tool updates
v1.0.0- First observed
get_events - First observed
list_accounts - First observed
list_calendars
TDQS
Scored across 3 tools
The three tools target clearly distinct resources: accounts, calendars, and events. There is no overlap or ambiguity in their purposes.
All tool names follow a consistent list_<resource> pattern: list_accounts, list_calendars, get_events. The slight verb difference (list vs get) is still coherent and predictable.
Three tools is small but reasonable for a read-only calendar/account server. It feels somewhat thin, but each tool serves a distinct need.
The toolkit is entirely read-only: it can list accounts, list calendars, and fetch events, but cannot create, update, delete, or otherwise mutate any calendar data. For a general Morgen integration, this leaves significant gaps.
Related MCP Connectors
Calendar API for AI agents: events, availability, Google/Microsoft setup, scheduling, and iCal.
GDPR-compliant calendar access for AI assistants: read, create, edit, RSVP. Google, MS 365, Apple.
Manage Google, Outlook & Apple calendars and create private sync rules from chat.
Schedule and manage Google Calendar events directly from your workspace. Check availability, view…
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceProvides AI assistants with intelligent access to Google Calendar data, enabling natural language queries about availability, upcoming events, schedule conflicts, and meeting summaries through context-aware calendar integration.-
- AlicenseAqualityFmaintenanceProvides tools to query, search, and list Google Calendar events using the Model Context Protocol. It enables natural language interaction for checking schedules, searching for keywords, and retrieving upcoming meetings.31GPL 3.0
- FlicenseNot gradedqualityCmaintenanceEnables AI assistants to manage Google Calendar by listing, creating, updating, and deleting events. It also includes functionality to find available time slots for scheduling.-
- AlicenseNot gradedqualityDmaintenanceEnables AI assistants to access and interact with macOS Calendar.app events and reminders, including viewing, searching, and filtering calendar data.2MIT