日历管理 MCP 服务器

MorgenMCP 是一个非官方的 MCP 服务器,通过 Model Context Protocol 访问 Morgen 日历 API,提供账号、日历、事件、任务和标签的读写管理,适用于将 Morgen 日历接入 AI 助手和 MCP 客户端的场景。

  • by k3KAW8Pnf7mkmdSMPHz27
  • Python
  • 本地部署
  • 3 星标
  • 更新于
在 GitHub 查看 k3KAW8Pnf7mkmdSMPHz27/MorgenMCP

使用说明

MorgenMCP

An unofficial MCP server for the Morgen calendar API.

[!NOTE] This is an independent, community-maintained project and is not affiliated with, endorsed by, or sponsored by Morgen AG. Morgen is a trademark of Morgen AG.

Requirements

  • uv - Install with curl -LsSf https://astral.sh/uv/install.sh | sh, brew install uv, or winget install astral-sh.uv
  • mise (optional) - Install with curl https://mise.run | sh, brew install mise, or winget install jdx.mise. Convenient for local development: it puts the right Python on PATH in a plain shell and fails fast with setup instructions when MORGEN_API_KEY is unset. Everything works with uv alone — see Environment Setup.
  • A Morgen API key - Get one from Morgen Developer Portal
  • Python 3.12 or newer — Only needed when working from a clone (uv and mise provision this automatically from .python-version). End users running via uvx require no setup.

Installation

No installation required — MCP clients run the server directly via uvx (published on PyPI).

Most clients use the same mcpServers JSON shape. Add this entry to your client's MCP configuration:

{
  "mcpServers": {
    "morgen": {
      "command": "uvx",
      "args": ["morgenmcp"],
      "env": {
        "MORGEN_API_KEY": "your_api_key_here"
      }
    }
  }
}

The server speaks stdio, so no port or URL is involved. If your client asks for a command rather than JSON, it is uvx morgenmcp with MORGEN_API_KEY in the environment. If it cannot find uvx, see Troubleshooting.

To pin to a specific version, pass the version in args (e.g. ["morgenmcp==0.2.1"]). You can also run unreleased commits directly from GitHub: ["--from", "git+https://github.com/k3KAW8Pnf7mkmdSMPHz27/MorgenMCP@main", "morgenmcp"].

Claude Desktop

The config file lives at ~/Library/Application Support/Claude/claude_desktop_config.json on macOS, or %APPDATA%\Claude\claude_desktop_config.json on Windows. Paste the block above, then restart Claude Desktop.

Available Tools

Tools across accounts, calendars, events, tasks, and tags — read-only and mutating:

  • Accounts & calendars: list_accounts, list_calendars, update_calendar_metadata
  • Events: list_events, create_event, update_event, delete_event, batch_update_events, batch_delete_events
  • Tasks: list_tasks, list_task_lists, get_task, create_task, update_task, move_task, complete_task, reopen_task, delete_task, batch_delete_tasks
  • Tags: list_tags, get_tag, create_tag, update_tag, delete_tag

Pass --read-only (or set MORGENMCP_READ_ONLY=1) to expose only the read-only tools. For the exact live list with schemas and annotations, connect any MCP client or run the MCP Inspector.

Configuration

MORGEN_API_KEY is required; everything else is optional. Each setting has an equivalent CLI flag, and the flag wins over the environment variable.

Environment variable CLI flag Default Description
MORGEN_API_KEY — (required) Morgen API key. The server refuses to start without it.
MORGENMCP_READ_ONLY --read-only off Truthy (1/true/yes/on) exposes only the read tools, disabling every mutating one.
MORGENMCP_TASKS_LIMIT --tasks-limit N 100 Default limit sent to /tasks/list. Integer 1–100.
MORGENMCP_TAGS_LIMIT --tags-limit N (unset) Default limit sent to /tags/list. Integer ≥ 1, no upper bound. Unset returns all tags.
MORGENMCP_DISPLAY_TZ — system local IANA timezone (e.g. America/Chicago) for rendering compact event times.
MORGENMCP_DATA_DIR — platform data dir Override the virtual-ID persistence directory.

An invalid limit fails at startup with a clear error rather than silently returning fewer results:

$ uv run morgenmcp --tasks-limit 500
morgenmcp: error: --tasks-limit must be <= 100 (got 500)

The two list limits are deliberately asymmetric, because Morgen documents the two endpoints differently: /tasks/list documents a default of 1 and a maximum of 100, while /tags/list documents neither and returns all tags when the parameter is omitted. A per-call limit argument on the tool always overrides both the flag and the environment variable.

Note: MORGENMCP_TASKS_LIMIT defaults to 100, which is MorgenMCP's own choice rather than Morgen's. /tasks/list returns a single task when limit is omitted — its documented default is 1, and the API docs tell callers to always set the parameter explicitly, so the server never leaves it to Morgen. This is only a fallback: the tool asks the model to pass a limit suited to the request, and a per-call value always wins. Set this variable to bound what a model can pull in one call, not to express a typical page size.

Troubleshooting

MORGEN_API_KEY is not set — the key goes in the env block of your MCP client's server entry, not in a shell profile: the client launches the server itself and does not inherit your terminal's environment. Get a key from the Morgen Developer Portal.

uvx: command not found, or the server never starts — desktop clients are launched by the OS, not by your shell, so they see a minimal PATH that usually excludes ~/.local/bin, /opt/homebrew/bin, and version-manager shims. Use an absolute path instead:

which uvx   # e.g. /opt/homebrew/bin/uvx
"command": "/opt/homebrew/bin/uvx"

Nothing appears in the client — check the client's MCP log. Both failures above surface there and nowhere else, because a stdio server's stderr goes to the client, not to a terminal.

Development

# Clone the repository
git clone https://github.com/k3KAW8Pnf7mkmdSMPHz27/MorgenMCP.git
cd MorgenMCP

# Install dependencies
uv sync --all-extras

# Run tests
uv run pytest

Environment Setup

The server reads MORGEN_API_KEY from the process environment — it does not load a .env file itself. Either of the following supplies it. Both keep the key in a gitignored file; neither is required if the variable is already exported in your shell.

With uv alone. Put the key in a .env file (already gitignored) and let uv load it:

echo 'MORGEN_API_KEY=your_api_key' > .env
UV_ENV_FILE=.env uv run morgenmcp

Export UV_ENV_FILE=.env in your shell profile to skip the prefix. uv run --env-file .env <cmd> works the same way for one-off commands.

If uv is itself installed through mise (a shim under ~/.local/share/mise/shims/uv), every uv call routes through mise, and mise refuses to run against this repo's untrusted mise.toml — so uv run fails until you mise trust. That is a property of that install, not of this project; a standalone uv (brew install uv) is unaffected.

With mise (optional, recommended if you already use it). This repo ships a mise.toml declaring MORGEN_API_KEY as required, so a missing key fails immediately with setup instructions instead of surfacing on the first tool call. mise set writes to a gitignored mise.local.toml, never the committed config:

mise trust
mise set --file mise.local.toml MORGEN_API_KEY=your_api_key
uv run morgenmcp

mise also puts the interpreter from .python-version on PATH in a plain shell, so a bare python3 in a clone is the right one — useful because the source requires Python 3.12 or newer (see Requirements).

Local Debugging with MCP Inspector

The MCP Inspector provides a web UI for testing tools and inspecting requests/responses:

npx @modelcontextprotocol/inspector uv run morgenmcp

Opens at http://localhost:6274

Releasing

Releases are managed via git tags:

git tag -a v0.2.1 -m "Release v0.2.1"
git push origin v0.2.1

Pushing a tag triggers the GitHub Actions release workflow, which runs tests, builds wheel and sdist distributions, creates a GitHub Release, and publishes to PyPI automatically.

Contributing

See AGENTS.md for environment setup, conventions, and the checks to run before handing off changes.

AI-assisted contributions are welcome and must be disclosed — see AI_POLICY.md, adapted from the Ghostty project's AI policy (MIT).

License

Apache 2.0 - See LICENSE and NOTICE for details.