{
  "markdown": "# ox-mcp\n\n[![npm](https://img.shields.io/npm/v/@rheopyrin/ox-mcp?logo=npm)](https://www.npmjs.com/package/@rheopyrin/ox-mcp)\n[![npm downloads](https://img.shields.io/npm/dm/@rheopyrin/ox-mcp)](https://www.npmjs.com/package/@rheopyrin/ox-mcp)\n[![license: MIT](https://img.shields.io/npm/l/@rheopyrin/ox-mcp)](LICENSE)\n[![node](https://img.shields.io/node/v/@rheopyrin/ox-mcp)](package.json)\n\n[![ox-mcp MCP server](https://glama.ai/mcp/servers/Rheopyrin/ox-mcp/badges/card.svg)](https://glama.ai/mcp/servers/Rheopyrin/ox-mcp)\n\nAn MCP server for **Open-Xchange and standards-based mail platforms** — read & search email, send & reply, manage server-side filters, calendar events and invitations, contacts, and other people's availability (free/busy), across one or many accounts.\n\nIt speaks standard **IMAP + SMTP + ManageSieve + CalDAV + CardDAV** with **RFC 6638** free/busy, so it works with any Open-Xchange deployment or standards-compliant host. Authenticate with your **email + app password** (the same credential DAVx5 uses) or OAuth2/OIDC.\n\n> No affiliation with Open-Xchange.\n\n## Install / run\n\n```bash\nnpx -y @rheopyrin/ox-mcp\n# or with a custom config location:\nnpx -y @rheopyrin/ox-mcp --config /path/to/config.json\n```\n\nMCP client config (Claude Desktop / Claude Code):\n\n```jsonc\n{\n  \"mcpServers\": {\n    \"ox\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@rheopyrin/ox-mcp\"],\n      \"env\": {\n        \"OX_MCP_MAIL_SERVER\": \"mail.example.com\",\n        \"OX_MCP_MAIL_USER\": \"you@yourdomain.com\",\n        \"OX_MCP_MAIL_APP_PASSWORD\": \"xxxx-xxxx-xxxx-xxxx\",\n        \"OX_MCP_CALDAV_SERVER\": \"dav.example.com\",\n        \"OX_MCP_CALDAV_USER\": \"you@yourdomain.com\",\n        \"OX_MCP_CALDAV_APP_PASSWORD\": \"yyyy-yyyy-yyyy-yyyy\"\n      }\n    }\n  }\n}\n```\n\nOn first run (without `--config`) it creates `~/.ox-mcp/config.json` (permissions `0600`) with every feature flag listed — **reads enabled, writes disabled** — and empty hosts for you to fill in.\n\n### `--config`\n\n`--config <file>` (or env `OX_MCP_CONFIG`; the flag wins) loads an explicit config file instead of `~/.ox-mcp/config.json`. The file **must exist** — nothing is auto-created when the override is used.\n\n## Tools\n\nTools are grouped by protocol domain. A group's tools appear only when enabled, and the group's server host must be configured (see *Validation*).\n\n| Group | Read (enabled by default) | Write (disabled by default) |\n|---|---|---|\n| `email_*` (IMAP/SMTP/Sieve — `mail` section) | `email_list_folders`, `email_list`, `email_read`, `email_search`, `email_filter_list` | `email_send`, `email_save_draft`, `email_reply`, `email_reply_all`, `email_delete`, `email_move`, `email_flag`, `email_mark_read`, `email_mark_unread`, `email_mark_spam`, `email_archive`, `email_create_folder`, `email_delete_folder`, `email_filter_create`, `email_filter_update` |\n| `calendar_*` (CalDAV — `calDav` section) | `calendar_list`, `calendar_list_events`, `calendar_free_busy` | `calendar_create_event`, `calendar_update_event`, `calendar_delete_event`, `calendar_accept_event`, `calendar_decline_event`, `calendar_tentative_event` |\n| `contact_*` (CardDAV — `cardDav` section) | `contact_list`, `contact_find` | `contact_create` |\n| meta | `list_servers` (always on) | — |\n\n- Every tool (except `list_servers`) accepts an optional `server` argument to target a specific account. A tool is **hidden** from the tool list unless its flag is enabled for at least one account.\n- `email_search` searches **all folders** by default; pass `folder` to narrow it. On the `ox-api` transport, `body`/`text` match only the subject and addresses of recent messages — use `transport: \"imap\"` for true full-text search.\n- `email_mark_spam` / `email_archive` find the Junk/Archive folder via IMAP special-use attributes, with name-based fallbacks.\n- `email_reply` / `email_reply_all` preserve threading (`In-Reply-To`/`References`) and exclude your own address from reply-all recipients.\n- The three RSVP tools (`calendar_accept_event` / `calendar_decline_event` / `calendar_tentative_event`) share **one** feature flag: `respondEvent` (calDav section). They rewrite your `PARTSTAT` on the invitation; the server notifies the organizer.\n- `contact_find` searches contacts **server-side** (CardDAV `addressbook-query`, RFC 6352) with automatic fallback to client-side filtering; `fields` narrows the match to `name`/`email`/`phone`/`org` (default name + email). Handy for resolving a name to an email before `calendar_free_busy`. `contact_list` is plain enumeration.\n\n### Mail filters\n\n`email_filter_create` / `email_filter_update` manage **server-side sieve filters** over ManageSieve (port 4190, STARTTLS; requires basic/app-password auth). Rules support conditions on `from`/`to`/`subject`/any header (AND or OR) and actions `fileinto` (move to folder), `discard`, `markRead`, `redirect`.\n\n> Backend depends on `mail.transport`: with **ox-api** (default), filters go through the OX `mailfilter/v2` module and operate on the account's real webmail rules (rules with tests/actions beyond this model are listed read-only as `other`). With **imap**, ox-mcp manages its own sieve script over ManageSieve (port 4190) and **activates it** — filters from other scripts become inactive while it is active.\n\n## Configuration: per-protocol sections\n\nEach account is made of up to three **self-contained sections** — `mail`, `calDav`, `cardDav` — each with its own `server`, `auth` (incl. its own login `user`), and `features`. This matches servers (like Open-Xchange) that scope app passwords per protocol: your Mail password, CalDAV password, and CardDAV password can all differ.\n\n```jsonc\n{\n  \"defaultServer\": \"default\",\n  \"timeoutSeconds\": 300,                                     // optional; request timeout, default 300\n  \"servers\": {\n    \"default\": {\n      \"mail\": {\n        \"server\": \"webmail.example.com\",                    // OX HTTP API host (default transport)\n        \"transport\": \"ox-api\",                              // optional; \"imap\" for direct IMAP/SMTP\n        \"imap\": { \"host\": \"imap.example.com\", \"port\": 993 }, // optional overrides\n        \"smtp\": { \"host\": \"smtp.example.com\", \"port\": 587, \"secure\": false }, // secure optional; 993/465 = TLS, else STARTTLS\n        \"auth\": { \"type\": \"basic\", \"user\": \"me@example.com\", \"appPassword\": \"mail-scoped-pw\" },\n        \"features\": { \"search\": true, \"send\": false /* per-tool flags */ }\n      },\n      \"calDav\": {\n        \"server\": \"dav.example.com\",\n        \"auth\": { \"type\": \"basic\", \"user\": \"me@example.com\", \"appPassword\": \"caldav-scoped-pw\" },\n        \"features\": { \"respondEvent\": false /* … */ }\n      },\n      \"cardDav\": {\n        \"server\": \"dav.example.com\",\n        \"auth\": { \"type\": \"basic\", \"user\": \"me@example.com\", \"appPassword\": \"carddav-scoped-pw\" }\n      }\n    }\n  }\n}\n```\n\n- **A section you don't configure = its tools are disabled.** A calDav-only config is perfectly valid.\n- **`mail.transport` is optional and defaults to `\"ox-api\"`** — the **Open-Xchange HTTP API** (the webmail backend, `https://<server>/appsuite/api`). OX deployments validate app passwords at this middleware, so it works even where raw IMAP rejects them; `server` is the webmail host. Filter tools use the OX `mailfilter/v2` module — they list and edit the account's **actual webmail rules**. Caveat: search matches subject/addresses (not full bodies).\n- Set **`transport: \"imap\"`** for direct IMAP/SMTP against generic (non-OX) mail hosts — then `server` is the mail host, with optional split `imap`/`smtp` endpoints.\n- `enabled: false` on a section is a config master switch for all its tools.\n- There is **no global features block** — flags live only inside sections (env vars remain global).\n\n## Feature flags\n\nResolution precedence — **env always beats config**, first defined wins:\n\n1. per-account env, tool — `OX_MCP_<ID>_ENABLE_EMAIL_SEND`\n2. per-account env, group — `OX_MCP_<ID>_ENABLE_MAIL`\n3. global env, tool — `OX_MCP_ENABLE_EMAIL_SEND`\n4. global env, group — `OX_MCP_ENABLE_MAIL` / `_CALDAV` / `_CARDDAV`\n5. section config, tool — `servers.<id>.mail.features.send`\n6. section config, master — `servers.<id>.mail.enabled`\n7. default — `true` for reads, `false` for writes\n\n```bash\n# enable sending on all accounts\nOX_MCP_ENABLE_EMAIL_SEND=true\n# turn off the whole calendar section\nOX_MCP_ENABLE_CALDAV=false\n# enable event creation only on the \"work\" account\nOX_MCP_WORK_ENABLE_CALENDAR_CREATE_EVENT=true\n# enable all three RSVP tools at once\nOX_MCP_ENABLE_CALENDAR_RESPOND_EVENT=true\n```\n\nBooleans accept `true/1/yes/on` and `false/0/no/off`.\n\n## Connection & credentials (env)\n\nEvery section field is settable via env: `OX_MCP_[ID_]<SECTION>_<FIELD>` with SECTION ∈ `MAIL | CALDAV | CARDDAV`. The default account uses the non-indexed form.\n\n| Env var | Meaning |\n|---|---|\n| `OX_MCP_MAIL_SERVER` / `OX_MCP_CALDAV_SERVER` / `OX_MCP_CARDDAV_SERVER` | section host |\n| `OX_MCP_MAIL_USER` / `OX_MCP_CALDAV_USER` / `OX_MCP_CARDDAV_USER` | section login user |\n| `OX_MCP_MAIL_APP_PASSWORD` / `OX_MCP_CALDAV_APP_PASSWORD` / … | section app password (basic auth) |\n| `OX_MCP_MAIL_IMAP_HOST` / `_IMAP_PORT` / `_SMTP_HOST` / `_SMTP_PORT` | mail transport overrides (Gmail-style split hosts) |\n| `OX_MCP_MAIL_IMAP_SECURE` / `_SMTP_SECURE` | force TLS (`true`) or STARTTLS (`false`) on a non-standard port |\n| `OX_MCP_MAIL_AUTH_TYPE`, `_CLIENT_ID`, `_REFRESH_TOKEN`, … | per-section OAuth/OIDC fields |\n| `OX_MCP_TIMEOUT_SECONDS` | request timeout for all HTTP/IMAP/SMTP operations (default 300) |\n\nDefault ports: IMAP 993, SMTP 465, DAV 443, ManageSieve 4190. TLS mode derives from the port (993/465 implicit TLS; 143/587 STARTTLS) unless `secure` is set explicitly.\n\n### Validation\n\nConfiguration is validated strictly at startup: every **present** section with enabled tools must have a server (or split imap/smtp hosts for mail) and a login user, or the server exits with an error naming the exact field. Accounts with zero sections error too. Absent sections are simply disabled — no error.\n\n## Authentication types\n\n`basic` (app password) is the default. Other Open-Xchange-aligned mechanisms are supported **per section** via `auth.type` / `OX_MCP_[ID_]<SECTION>_AUTH_TYPE`:\n\n| Type | Extra fields (env: `OX_MCP_[ID_]<SECTION>_…`) |\n|---|---|\n| `basic` | `APP_PASSWORD` |\n| `xoauth2` | `ACCESS_TOKEN` |\n| `oauth2-refresh` | `CLIENT_ID`, `CLIENT_SECRET`, `REFRESH_TOKEN`, `TOKEN_URL`, `SCOPE` |\n| `oauth2-password` | `CLIENT_ID`, `CLIENT_SECRET`, `PASSWORD`, `TOKEN_URL`, `SCOPE` |\n| `oidc` | `ISSUER`, `CLIENT_ID`, `CLIENT_SECRET`, `REFRESH_TOKEN` or `PASSWORD`, `SCOPE` |\n\nTokens are cached and refreshed automatically. Note: mail filters (ManageSieve) require `basic` auth.\n\n## Multiple accounts\n\n```bash\nOX_MCP_ACCOUNTS=work,personal\nOX_MCP_WORK_MAIL_SERVER=mail.work.com\nOX_MCP_WORK_MAIL_USER=me@work.com\nOX_MCP_WORK_MAIL_APP_PASSWORD=...\nOX_MCP_PERSONAL_CALDAV_SERVER=dav.personal.com\nOX_MCP_PERSONAL_CALDAV_USER=me@personal.com\nOX_MCP_PERSONAL_CALDAV_APP_PASSWORD=...\nOX_MCP_DEFAULT_SERVER=work\n```\n\nOr define them in `~/.ox-mcp/config.json` under `servers` (keyed by id). `list_servers` shows what's configured (never secrets); env values override config field-by-field. Feature flags can differ per account (e.g. sending enabled only on `work`).\n\n## Free/busy caveat\n\n`calendar_free_busy` returns **availability windows only** (busy/free), via the CalDAV scheduling outbox — no calendar sharing needed. It does **not** reveal event details, and requires the server to advertise a `schedule-outbox-URL`. To read a colleague's **full** calendar, they must share it with your account; shared calendars then appear in `calendar_list` / `calendar_list_events`.\n\n## Docker\n\n```bash\ndocker build -t ox-mcp .\ndocker run -i --rm \\\n  -e OX_MCP_MAIL_SERVER=mail.example.com \\\n  -e OX_MCP_MAIL_USER=you@yourdomain.com \\\n  -e OX_MCP_MAIL_APP_PASSWORD=xxxx \\\n  ox-mcp\n```\n\n## Development\n\n```bash\nnpm install\nnpm run dev          # run from source\nnpm test             # vitest\nnpm run test:coverage\nnpm run build        # bundle to dist/ (tsup)\n```\n\n## License\n\nMIT\n",
  "bytes": 12065,
  "sha": "174fffb0a333eda744606e2620d2cef6e18e5fd4e06c6a0b009b8b43cef2de5d",
  "repo_slug": "rheopyrin/ox-mcp",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_rheopyrin_ox_mcp_79c6423f/readme"
}