@chrischall/office-outlook-mcp 0.8.3 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -7,7 +7,7 @@
7
7
  },
8
8
  "metadata": {
9
9
  "description": "MCP server for Outlook / Microsoft 365 — mail, calendar, contacts and tasks via natural language",
10
- "version": "0.8.3"
10
+ "version": "0.9.0"
11
11
  },
12
12
  "plugins": [
13
13
  {
@@ -15,7 +15,7 @@
15
15
  "displayName": "Outlook (Microsoft 365)",
16
16
  "source": "./",
17
17
  "description": "MCP server for Outlook / Microsoft 365 — triage unread mail, reply, answer meeting invites and schedule meetings, plus folders, calendar, contacts and tasks, with confirmation before anything is sent",
18
- "version": "0.8.3",
18
+ "version": "0.9.0",
19
19
  "author": {
20
20
  "name": "Chris Hall"
21
21
  },
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "office-outlook-mcp",
3
3
  "displayName": "Outlook (Microsoft 365)",
4
- "version": "0.8.3",
4
+ "version": "0.9.0",
5
5
  "description": "Outlook / Microsoft 365 for Claude — triage unread mail, reply, answer meeting invites and schedule meetings, plus folders, calendar, contacts and tasks, with confirmation before anything is sent, using your signed-in browser session",
6
6
  "author": {
7
7
  "name": "Chris Hall",
package/README.md CHANGED
@@ -121,7 +121,7 @@ Everything is optional — with nothing set, the server captures from the browse
121
121
  | `OUTLOOK_CAPTURE_TIMEOUT` | Seconds to wait for the tab to make a readable request. Defaults to `30`. |
122
122
  | `OUTLOOK_TOKEN_CACHE` | `false` to stop caching the token between runs. |
123
123
  | `OUTLOOK_TOKEN_FILE` | Path to the cached token. Defaults to `~/.office-outlook-mcp/token.json`. |
124
- | `OUTLOOK_OUTPUT_DIR` | Absolute directory `outlook_export_messages` and `outlook_export_events` write into. Defaults to `~/Downloads/office-outlook-mcp`. When set, a per-call `dest` must be inside it. See [Bulk export](#bulk-export). |
124
+ | `OUTLOOK_OUTPUT_DIR` | Absolute directory `outlook_export_messages` and `outlook_export_events` write into, and where a local install saves the files `outlook_get_attachment` cannot return inline. Defaults to `~/Downloads/office-outlook-mcp` (for attachments, only when `~/Downloads` exists). When set, a per-call `dest` must be inside it. See [Bulk export](#bulk-export). |
125
125
 
126
126
  ## Tools
127
127
 
@@ -131,13 +131,14 @@ Everything is optional — with nothing set, the server captures from the browse
131
131
  `outlook_list_calendars`, `outlook_find_meeting_times`,
132
132
  `outlook_get_schedule`, `outlook_get_profile`,
133
133
  `outlook_get_mailbox_settings`, `outlook_list_contacts`, `outlook_list_people`,
134
- `outlook_list_categories`, `outlook_list_tasks`
134
+ `outlook_list_categories`, `outlook_list_tasks`, `outlook_list_rules`
135
135
 
136
136
  **Write** (ask you to confirm first — see [Confirmations](#confirmations)) —
137
137
  `outlook_send_message`, `outlook_create_draft`, `outlook_mark_read`,
138
138
  `outlook_update_message`, `outlook_move_message`, `outlook_create_event`,
139
139
  `outlook_update_event`, `outlook_respond_to_invite`, `outlook_delete_event`,
140
- `outlook_reply`.
140
+ `outlook_reply`, `outlook_create_rule`, `outlook_update_rule`,
141
+ `outlook_delete_rule`, `outlook_set_auto_reply`.
141
142
  Some skip the confirmation because nothing reaches anyone else:
142
143
  `outlook_create_draft` (the draft stays in Drafts until you send it from
143
144
  Outlook), `outlook_reply` with `draftOnly: true` (the reply stays in Drafts),
@@ -165,10 +166,23 @@ what that decision needs in every view: `MyResponse`, `ResponseRequested`,
165
166
  `IsOrganizer`, `IsCancelled`, `Type` (SingleInstance, Occurrence, Exception or
166
167
  SeriesMaster), `ShowAs` and `IsAllDay`, plus `SeriesMasterId` in the full view.
167
168
 
169
+ **Rules and automatic replies** — `outlook_list_rules` shows inbox rules in the
170
+ order Outlook applies them. `outlook_create_rule` needs at least one condition
171
+ and one action; a rule that forwards or redirects mail names those recipients in
172
+ its confirmation, because it keeps sending mail out until removed.
173
+ `outlook_update_rule` sends only what you pass, and `conditions`, `exceptions`
174
+ or `actions` replace that whole group. `outlook_set_auto_reply` changes only
175
+ what you pass, and its confirmation shows the exact text that will go out,
176
+ including stored text you did not change. Read the current auto-reply with
177
+ `outlook_get_mailbox_settings`.
178
+
168
179
  **Export** — `outlook_export_messages` (mail) and `outlook_export_events`
169
180
  (calendar) write JSONL or Markdown files, optionally with attachments, and
170
181
  return only where they are; see [Bulk export](#bulk-export).
171
182
 
183
+ **Copilot** — `outlook_ask_copilot` puts a question to Microsoft 365 Copilot
184
+ with your mailbox as context; see [Microsoft 365 Copilot](#microsoft-365-copilot).
185
+
172
186
  **Diagnostics** — `outlook_healthcheck`
173
187
 
174
188
  Every read tool takes `view: compact | full | raw`, defaulting to **compact**.
@@ -192,8 +206,8 @@ the one read a preview makes.)
192
206
  Mail and event text is written by other people, so `outlook_list_messages`,
193
207
  `outlook_get_message`, `outlook_list_unread_messages`, `outlook_get_attachment`,
194
208
  `outlook_list_events`, `outlook_get_event`, `outlook_find_meeting_times`,
195
- `outlook_get_schedule`, `outlook_export_messages` and `outlook_export_events`
196
- wrap every result (all views) in an untrusted-content
209
+ `outlook_get_schedule`, `outlook_export_messages`, `outlook_export_events` and
210
+ `outlook_ask_copilot` wrap every result (all views) in an untrusted-content
197
211
  envelope — `untrusted_content: true` plus a `note` telling the model to treat
198
212
  the text as data, never instructions (a `view: raw` record that carries its
199
213
  own `untrusted_content`/`note` key is nested under `data`, so it cannot
@@ -205,6 +219,37 @@ something the model passes back itself, so keep `MCP_CONFIRM_MODE=ask-user`
205
219
  (the default) and approve each preview in chat — or use a client that asks you
206
220
  before running non-read-only tools — as the real guard on outbound sends.
207
221
 
222
+ ## Microsoft 365 Copilot
223
+
224
+ `outlook_ask_copilot` sends a question to **Microsoft 365 Copilot** and returns
225
+ its answer. Copilot searches your own mail, calendar and files server-side
226
+ (`WorkSearch`) and writes a reply — so this is for *synthesis* across many
227
+ messages ("what needs my attention first", "summarise the thread with X") rather
228
+ than fetching one message, which the read tools already do. Follow-up calls
229
+ continue the same conversation; pass `newConversation: true` to start fresh. Each
230
+ call uses one of a per-conversation quota, reported back, and the answer comes
231
+ back in the untrusted-data envelope like every other mail-derived read.
232
+
233
+ **Setup — a one-time sign-in.** Unlike the mail token (captured from your
234
+ browser), the Copilot token is obtained by MSAL and refreshes silently, but the
235
+ first sign-in needs a browser with MFA. Use the sibling CLI
236
+ [`opencode-m365-copilot`](https://github.com/chrischall/opencode-copilot-plugin):
237
+
238
+ ```sh
239
+ npm install -g opencode-m365-copilot
240
+ opencode-m365 login # one-time browser sign-in; writes an MSAL cache
241
+ ```
242
+
243
+ This MCP reads that cache and refreshes from it. Override its location with
244
+ `OUTLOOK_COPILOT_MSAL_CACHE` if you keep it elsewhere.
245
+
246
+ **What it talks to.** M365 Copilot has no public API; this speaks the same
247
+ undocumented SignalR-over-WebSocket protocol (`substrate.office.com`) that
248
+ Microsoft's own Office web clients use, with the Office web Copilot client id.
249
+ It reaches only Copilot on your own tenant and changes nothing in the mailbox,
250
+ but it is reverse-engineered and may break when Microsoft changes it — and your
251
+ organisation's acceptable-use policy still applies. Use at your discretion.
252
+
208
253
  ## Triage loop
209
254
 
210
255
  An agent can work through new mail end to end without opening Outlook:
@@ -354,6 +399,34 @@ a fresh preview.
354
399
  as a four-hour error on an Eastern mailbox.
355
400
  - Contact phone fields are `MobilePhone1`, not Graph's `MobilePhone`. The v2.0
356
401
  Contact type rejects the Graph name with a 400.
402
+ - `outlook_get_attachment` decodes a text-like file up to 5 MB and returns an
403
+ image up to 5 MB inline. Anything else, up to 50 MB, comes back as the file:
404
+ a signed download link valid for 1 hour when hosted (mcp-host sets
405
+ `MCP_BLOB_BASE_URL` and `MCP_BLOB_SIGNING_KEY`), or a new `0600` file under
406
+ `OUTLOOK_OUTPUT_DIR` (else `~/Downloads/office-outlook-mcp`) on a local
407
+ install. A hosted server never writes to its own disk; nobody in your
408
+ session could open the path.
409
+
410
+ ## Upgrading
411
+
412
+ ### To the next release
413
+
414
+ `outlook_get_attachment` used to return PDFs, Office files and anything over
415
+ 5 MB as metadata only, so the file was unreachable. It now hands the bytes over.
416
+ The existing fields (`name`, `contentType`, `size`, `kind`, `inlined`, `text`,
417
+ `textTruncated`, `hint`) are unchanged. New fields appear when bytes are
418
+ delivered:
419
+
420
+ - `via`: `image`, `resource`, `link` or `disk`.
421
+ - `downloadUrl` and `downloadExpiresAt`: hosted. Treat the link as a secret;
422
+ anyone holding it can download until it expires.
423
+ - `path`: local, where the file was saved.
424
+ - `deliveryNote`: why that route was chosen, when it was not the obvious one.
425
+
426
+ A local install with a `~/Downloads` folder (or `OUTLOOK_OUTPUT_DIR` set) now
427
+ **saves** such attachments to disk instead of returning metadata only. Without
428
+ either, the old metadata-only answer remains. The `hint` text on that path now
429
+ names `OUTLOOK_OUTPUT_DIR`.
357
430
 
358
431
  ## The lightweight alternative
359
432