uv venv
source .venv/bin/activate
uv pip install -e .[dev]
cp .env.example .envuv run --python 3.12 --with '.[dev]' ruff check .
uv run --python 3.12 --with '.[dev]' ruff format --check .
uv run --python 3.12 --with '.[dev]' pytest -qAll run in CI (GitHub Actions and GitLab CI) on every push and pull/merge request.
None of the test suite talks to a real Exchange server. Tests fake the EWS layer in one of two ways:
tests/conftest.pydefinesFakeExchangeBackend, a stand-in forExchangeBackendused to exercise the MCP tool layer (tests/test_mcp_tools.py,tests/test_registry.py, ...) without touchingexchangelibat all.tests/test_ews_backend.pyandtests/test_backend_edge_cases.pyexerciseEWSExchangeBackenddirectly by assigning aSimpleNamespace/fake object tobackend._account, and by monkeypatchingexchangelibclasses (ResolveNames,FolderCollection, ...) imported intooutlook_mcp.exchange_client.
Follow the same pattern for new tests: build the smallest fake that supports the attributes/methods your code path touches, and assert both the returned model and any request captured from the fake.
- Keep PRs focused — one fix or feature per PR.
- Add or update tests for any behavior change; tests, lint, and format checks must pass.
- Update
README.mdif you change configuration, tool behavior, or the tool catalog. - Describe what real-server behavior prompted the change when fixing an Exchange/EWS-specific bug (timezone handling, address formats, etc.) — these are easy to regress silently.
Open a GitHub issue with the tool name, the request you sent, the error returned (mask any secrets/PII), and your Exchange version if known.