EWS Meeting MCP is an MCP server and CLI that schedules meetings through a locally deployed Exchange EWS, primarily aimed at the aforementioned demanding enterprise scenarios: regulated teams, intranet environments, strict security reviews, legacy Exchange deployments, and organizations that cannot directly grant cloud agents broad Microsoft 365 permissions. It provides coding assistants and desktop agents with a secure, structured way to read Outlook inbox messages and availability, discover meeting rooms, suggest meeting times, and create, update, or cancel meetings only after explicit human confirmation.
[Purpose and Positioning] Many teams still run their calendar infrastructure through on-premises Exchange/EWS. General-purpose agents can reason about scheduling, but they should not receive plaintext passwords, guess attendee addresses, or send meeting invitations without a reviewable checkpoint. This project is not a general-purpose Outlook wrapper, nor is it a Microsoft Graph-first calendar connector; instead, it targets stricter enterprise scenarios: on-premises EWS access, room resources, explicit human approval, duplicate-send protection, and meeting lifecycle tooling that is easy to audit.
[Main Capabilities]
- Room-aware scheduling: find overlapping availability times for attendees and filter meeting rooms by Exchange discovery or local policy.
- Human-in-the-loop write operations: create, update, and cancel operations require a preview plus a matching confirmation_id.
- Outlook Show As: when creating or updating a personal appointment, show_as: "out_of_office" (EWS OOF) can be set. Empty attendees and meeting rooms will not send invitations; this feature does not configure email auto-replies.
- Local-first credential handling: reads .env, shell environment, or macOS Keychain; passwords do not pass through the model.
- Structured recovery: initialization failures return machine-readable error codes and user-facing setup commands.
- Auditability: lifecycle previews, confirmed operations, duplicate confirmations, in-progress states, and structured errors are written to a local JSONL audit log.
- Instructions prepared for agents: the MCP server exposes tool descriptions and initialization guidance, and the repository also includes a companion skill.
[How to Use]
- Configure EWS: create a .env in the working directory or provide equivalent environment variables. Use EWS_AU only when IT has confirmed that Basic authentication is enabled and the endpoint is protected by HTTPS.TH_TYPE=BASIC.
- Store the password: for local development, a generic ACCOUNT_PASSWORD can be used as an override, but do not put it in the MCP configuration. On macOS, Keychain is more secure than writing the password into .env or the MCP client configuration. If ACCOUNT_PASSWORD_KEYCHAIN_ACCOUNT is omitted, EWS_USERNAME is used.
- Add the MCP server: either an MCP client installed via npm or a local checkout is supported.
- Verify the setup: the first command prints the configured endpoint and account (without printing the password), and the second command verifies that the account can connect to EWS.
[Typical workflow] When reading inbox mail, first search the configured inbox and then read the selected mail; these mailbox tools are read-only and will not mark as read, send mail, move mail, or change labels. For the Thursday Jira weekly report automation, write the report from the Jira results, then via this MCP call the dedicated self-send email tool ews_send_email_to_self; this tool does not accept recipient, to, cc, or bcc parameters, the recipient is taken from EWS_EMAIL, it is sent via Exchange EWS and by default appends the configured HTML signature, and it does not write the email body or recipient address to the audit log. For automation retries, reuse the same idempotency key; keys that are completed or in progress will not call Exchange again.
Scheduling should follow: preview first, then confirm. Recurring meetings are created by passing a structured recurrence object to the preview and confirm creation calls. If the user only asks for something like "every Monday and Wednesday" without an end date, occurrence count, or an explicit no-end choice, ask before previewing. Modifying an existing meeting should use precise calendar metadata; when multiple candidates exist, the agent must never infer the event from subject text.
[Security and limitations] The design principle is: reads can be automated, and every write must have a narrow safety gate. Inbox reading is limited to explicit read-only search and read tools; meeting writes require preview plus explicit confirmation; only self-send requires configured self-enforcement plus idempotency protection. Authentication failure fast termination (FailFast): after one invalid credential or account lockout response, all subsequent EWS calls in that process are blocked; fix the shared Keychain item and restart MCP before retrying. Confirmed create, update, and cancel tools must pass confirm=true to run, and require a confirmation_id matching the preview; updateCancellation also requires obtaining the exact EWS id and changekey from ews_find_calendar_events or a previously verified result. Duplicate confirmation requests return error_code: "duplicate_confirmation" along with the previous result metadata, and EWS is not called again; an in-progress confirmation returns "confirmation_in_progress" and should not be blindly retried. Preview tools never save, move, delete, or send Exchange notifications. ews_send_email_to_self is the only email write capability, and it is limited to sending to yourself. If ews_setup_check returns ready: false, the agent should display the returned user_message or setup_command as-is and stop, and should not request attendee email addresses to continue scheduling.
[Scheduling Policy] By default, look for ews-meeting-policy.json in the current working directory; EWS_MEETING_POLICY_FILE can point to another file. If there is no policy file, use the built-in defaults: workday 10:00 to 18:00, avoid 12:00-14:00, fallback rooms are 2-11, 2-13, 2-14, 3-1, 3-2, 3-4. For real-time meeting room selection, prefer Exchange room list discovery, then fall back to configured rooms. Policy rooms are merged by alias with the default fallback rooms: matching aliases override the default rooms, and new aliases are appended.
[CLI and Display Status] The npm wrapper starts the MCP server by default; passing --cli runs the Python CLI through the same package. Creating a meeting requires --confirm; otherwise it only prints a dry-run preview and does not call EWS. The preview/confirmation tools for creation and update accept an optional show_as: when creating, omitting it keeps the existing Busy default; when updating, omitting it preserves the stored status. Personal appointments use attendees: [] and rooms: [], and are saved with SendToNone. After calling ews_create_meeting_preview, you should show the user the start/end, time zone offset, show_as, and invitation behavior; after explicit confirmation, call ews_create_meeting_confirmed and pass the same parameters plus confirm: true and the returned confirmation_id. Changing the status after preview invalidates that confirmation. Query/verification tools return the stored show_as and the original legacy_free_busy_status; use ews_verify_meeting to read from the server after saving. This feature only affects calendar status, not email auto-replies.
[Development and Reference] The repository contains the Usage Guide (local setup, Keychain, scheduling policy, smoke checks, CLI examples, MCP configuration, npm wrapper) and the Agent Guide (tool contracts, setup checks, attendee parsing, meeting room selection, preview-confirmation flow, audit logs, verification rules), as well as Publishing (npm package and GitHub Actions release checklist). The companion skill is for agents that support skills.