Skip to main content
Glama
torosent

copilot-outlook-connector

by torosent
README.md
# Outlook.com personal connector

A local, reusable TypeScript STDIO MCP server for **personal Microsoft accounts** such as Outlook.com and Hotmail. Each account has an independent delegated grant and secure credential namespace. This is not an organizational Microsoft 365 connector, an app-only integration, a dashboard, or a native Copilot connector manifest.

## Capabilities and boundaries

| Area | Included | Intentionally absent |
| --- | --- | --- |
| Mail | Structured search/list, message and paginated conversation reads, attachment metadata and bounded inert file bytes, unsent new/reply/reply-all drafts | Send, forwarding, move/archive/delete, categories, arbitrary MIME or header injection |
| Calendar | Discovery, event and instance reads, event creation/updates/deletion, attendee invitations, self-RSVP, whole-series and exact-occurrence operations | Calendar creation/deletion, sharing/ACL changes, contacts, this-and-following series splitting |
| Availability | CalendarView-derived busy/common availability for explicitly selected accessible account/calendar sources | Organizational getSchedule/findMeetingTimes, arbitrary people-directory availability |
| Safety | Durable request receipts, explicit accounts, OS credential storage, generation checks, human WebAuthn approvals | Agent `confirm:true`, approval/enrollment/reset tools, blind write retries |

**This is not unrestricted Outlook parity.** Search is structured Graph filtering, not Gmail syntax or a full-text consumer search promise. Conversations are mailbox-scoped `conversationId` queries, not Gmail thread resources. Pagination is not a consistent snapshot. Only file attachments are downloaded, at most 2 MiB; item/reference attachments and external images are not fetched. Drafts use Graph JSON APIs; Microsoft owns MIME serialization and reply headers.

All recurring edits, deletions, attendee-affecting operations and RSVPs require human approval. **In ordinary Graph v1.0 responses, private creates are gated too:** the provider does not supply the negative-sharing evidence needed to prove an exemption safe. **Updates always remain gated:** Microsoft's event-update documentation does not establish atomic conditional-write enforcement. The connector rechecks versions immediately before dispatch but does not claim an external-edit lock or conditional-write guarantee. See [calendar contracts](docs/calendar-contract.md).

## Local installation

Requires Node.js 22 or later, a desktop browser, and an available OS credential store. Clone and build the source:

```sh
git clone https://github.com/torosent/copilot-outlook-connector.git
cd copilot-outlook-connector
npm ci --registry=https://registry.npmjs.org
npm test
npm pack
node dist/cli.js help
```

For another local installation, install the resulting `copilot-outlook-connector-0.1.0.tgz` into a directory you control:

```sh
npm install --prefix /absolute/path/to/local-install /absolute/path/to/copilot-outlook-connector-0.1.0.tgz
node /absolute/path/to/local-install/node_modules/copilot-outlook-connector/dist/cli.js help
```

The package is marked private to prevent accidental npm publication. Nothing installs or edits Copilot configuration automatically. No repository or package publication is required.

## User-controlled account setup

Use a Microsoft **public desktop client** whose supported account types include personal Microsoft accounts and whose native redirect matches the connector's loopback policy. The recommended native redirect is `http://localhost` under Mobile and desktop applications. Do not add a secret to a desktop client or weaken an unrelated application's settings. If an existing registration is incompatible, create a separate suitable public client or make the specific registration change yourself.

Run `node dist/cli.js help` for the supported registration inspection/configuration and account commands. Registration inspection consumes only allowlisted application metadata; it is **not token import or proof of current portal state**. Configuration does not authenticate. Token-bearing exports and registrations declaring unsupported permissions are rejected. Use a separate least-privilege public client rather than weakening an existing application's configuration.

```sh
node dist/cli.js auth client inspect --file /absolute/path/to/application-manifest.json
node dist/cli.js auth client import --file /absolute/path/to/application-manifest.json
node dist/cli.js accounts add --client-id YOUR_PUBLIC_APPLICATION_ID
node dist/cli.js accounts list
```

Only deliberately invoking `accounts add --client-id` starts sign-in; the client selection is mandatory. `accounts reauth ACCOUNT_ID` may only reauthorize the same stable identity; `accounts remove ACCOUNT_ID` disables local access and cleans up local credential generations, not provider-wide consent. If either reports `cleanupPending`, unlock the credential store and run `accounts cleanup ACCOUNT_ID`. `accounts cleanup` without an ID retries all journaled inactive-generation cleanup.

Requested delegated permissions are `User.Read`, `Mail.ReadWrite`, `Calendars.ReadWrite`, `openid`, `profile`, and `offline_access`. **Mail.ReadWrite grants broader mailbox mutation permission at OAuth level even though the connector exposes drafts only. Mail.Send is never requested.** No application permissions, tenant impersonation, password flow or organizational fallback are used.

See [authentication contract](docs/auth-contract.md) for exact commands, cache storage and issuer/account binding. No user-specific client ID, email or credential export belongs in reusable source, examples or test fixtures.

## GitHub Copilot app integration

After local setup, print configuration from the actual installed path:

```sh
node /absolute/path/to/copilot-outlook-connector/dist/cli.js config print
```

Use the emitted ordinary `mcpServers` entry with the GitHub Copilot app's **Customize -> MCP** flow or its supported MCP configuration editor. It contains an absolute Node executable, absolute CLI path, `serve`, and no credentials. Use a distinct server name, `outlook-local`; keep any Google server independent.

The output is inert. Printing configuration, `help`, `doctor`, STDIO discovery and empty-account listing do not start OAuth, enroll an authenticator, read existing vault entries or create account state. `doctor` reports local setup only, not successful Microsoft connectivity.

## Human confirmation and recovery

Bootstrap the authenticator yourself in a trusted CLI, outside an agent workflow:

```sh
node dist/cli.js approvals enroll
```

The separate Outlook enrollment cannot be reset through MCP. A gated operation returns `pending_approval` and a localhost review URL. The human inspects the immutable account, target, resource versions, attendees, recurrence and notification effects, then completes the enrolled authenticator's **user presence and user verification** ceremony. No allow-all setting or SDK elicitation response substitutes for this. Never automate enrollment or approval.

Every write requires an explicit `accountId` and a stable, caller-chosen `requestId`. Repeating the same request returns its durable receipt; reusing the ID for different normalized arguments fails. Use `operation_status` to inspect and `operation_cancel` to cancel only before dispatch. **An `outcome_unknown` operation must not be retried with a new ID.** Inspect Outlook manually first. Microsoft transaction IDs are an additional event-create aid, not permission for automatic retries.

## Storage and threat model

The independent namespace is `copilot-outlook-connector`: macOS Keychain, Windows Credential Manager, or desktop Linux Secret Service through shell-free `secret-tool`. Linux never silently falls back to kernel keyutils. Locked/unavailable vaults fail closed. Install libsecret's tools and unlock a desktop Secret Service on Linux.

MSAL caches are encrypted at rest with per-account/generation authenticated encryption; small encryption keys live in the OS vault, avoiding Windows credential-size limits. Metadata, operation receipts and authenticator public keys live in private local state. Mail bodies and access tokens are not put in receipts. No token is exported or passed as a process argument.

This protects the supported tool boundary and rejects forged approval responses. It cannot protect against arbitrary code already running as the same OS user, a replaced connector binary, compromised server, OS account or authenticator. See [security and operational limitations](docs/security.md).

## Local acceptance

```sh
npm test
npm run smoke:package
```

The package smoke builds a tarball, installs it with production dependencies only in an isolated temporary consumer, and exercises help/config/doctor/real STDIO discovery without credentials. It uses public-registry artifact URLs and integrity-cache installation, **not a claim of fresh network downloads**.

Offline fixtures do not establish native Windows/Linux behavior, physical-authenticator behavior, live app registration state or successful Outlook connectivity. Those require user-controlled platform acceptance. No live draft, invitation, RSVP or event mutation is part of automated acceptance.

TDQS

A3.6/5.0

Scored across 22 tools

Disambiguation4/5

Most tools are clearly separated by domain and action, such as calendar_get_event vs calendar_list_events and mail_read_message vs mail_read_conversation. A few pairs could require attention, like calendar_free_busy vs calendar_find_availability or mail_list_attachments vs mail_read_attachment, but the descriptions clarify the distinctions.

Naming Consistency3/5

The dominant pattern is domain_verb_noun with snake_case, but several names deviate: accounts_list, operation_cancel, operation_status, and calendar_free_busy do not follow the verb-first convention. This makes the naming somewhat mixed despite consistent domain prefixes.

Tool Count3/5

22 tools sits in the upper range and feels slightly heavy for a single connector. The count is defensible because it covers calendar, mail, drafts, attachments, availability, and operations, but it is above the ideal 3-15 range.

Completeness3/5

Calendar lifecycle is well covered including create, update, delete, RSVP, and availability, and mail covers read, search, drafts, and attachments. However, common mail actions such as send, delete, and folder management are absent, and the descriptions repeatedly state these are unsupported, leaving notable gaps in the mail domain.

Maintenance

ActivityMaintained
ResponsivenessNo issues