@littlebearapps/outlook-assistant 3.13.0 → 3.14.1
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.
- package/.env.example +30 -3
- package/README.md +67 -27
- package/advanced/index.js +44 -174
- package/auth/auth-errors.js +23 -1
- package/auth/oauth-server.js +7 -1
- package/auth/token-manager.js +7 -3
- package/auth/token-storage.js +28 -30
- package/auth/tools.js +61 -82
- package/calendar/attendees.js +36 -0
- package/calendar/cancel.js +9 -25
- package/calendar/create.js +42 -48
- package/calendar/decline.js +10 -25
- package/calendar/delete.js +10 -25
- package/calendar/index.js +20 -37
- package/calendar/list.js +4 -16
- package/calendar/preview.js +461 -0
- package/calendar/update.js +55 -83
- package/categories/index.js +68 -265
- package/config.js +29 -1
- package/contacts/index.js +72 -128
- package/email/attachments.js +43 -125
- package/email/conversations.js +44 -78
- package/email/delta.js +69 -46
- package/email/draft.js +170 -103
- package/email/export.js +145 -110
- package/email/folder-utils.js +3 -2
- package/email/headers.js +11 -49
- package/email/index.js +86 -110
- package/email/list.js +4 -17
- package/email/mail-tips.js +86 -57
- package/email/mark-as-read.js +13 -49
- package/email/mime.js +39 -51
- package/email/read.js +16 -50
- package/email/search.js +47 -87
- package/email/send.js +82 -48
- package/folder/create.js +6 -25
- package/folder/delete.js +117 -38
- package/folder/index.js +19 -17
- package/folder/list.js +5 -17
- package/folder/move.js +13 -42
- package/folder/resolve.js +11 -6
- package/folder/stats.js +18 -27
- package/index.js +39 -45
- package/llms-install.md +22 -4
- package/llms.txt +20 -11
- package/outlook-auth-server.js +10 -3
- package/package.json +4 -1
- package/request-handler.js +217 -116
- package/rules/create.js +28 -71
- package/rules/index.js +52 -93
- package/rules/list.js +7 -19
- package/rules/rule-builder.js +59 -22
- package/rules/update.js +27 -61
- package/server.js +41 -0
- package/settings/index.js +162 -145
- package/tools.js +30 -0
- package/utils/field-presets.js +4 -2
- package/utils/graph-api.js +65 -22
- package/utils/logger.js +251 -0
- package/utils/mock-data.js +91 -2
- package/utils/read-only.js +59 -0
- package/utils/response-formatter.js +54 -15
- package/utils/risk-classes.js +324 -0
- package/utils/safe-write.js +372 -6
- package/utils/safety.js +247 -42
- package/utils/server-instructions.js +73 -0
- package/utils/tool-error.js +33 -0
package/index.js
CHANGED
|
@@ -38,15 +38,23 @@ Key environment variables:
|
|
|
38
38
|
OUTLOOK_AUTH_METHOD device-code (default) | browser
|
|
39
39
|
OUTLOOK_AUTH_AUDIENCE common | consumers | organizations | <tenant-guid>
|
|
40
40
|
OUTLOOK_SHARED_MAILBOX Opt in to shared mailboxes: read | true (work/school only)
|
|
41
|
+
OUTLOOK_READ_ONLY Set to "true" to refuse every tool call that would change,
|
|
42
|
+
send or delete anything (reads and sign-in still work)
|
|
41
43
|
OUTLOOK_ALLOWED_RECIPIENTS Comma-separated recipient allowlist
|
|
42
44
|
OUTLOOK_MAX_EMAILS_PER_SESSION Default cap per session for every rate-limited tool
|
|
43
|
-
(send-email, draft, manage-rules)
|
|
45
|
+
(send-email, draft, create-event, manage-rules).
|
|
46
|
+
Unset or empty = no cap. 0 BLOCKS those tools; so does
|
|
47
|
+
any value that isn't a whole number (fails closed)
|
|
44
48
|
OUTLOOK_MAX_<TOOL>_PER_SESSION Per-tool cap overriding the default, tool name in upper
|
|
45
49
|
case with _ for -, e.g. OUTLOOK_MAX_SEND_EMAIL_PER_SESSION
|
|
50
|
+
(also covers draft action=send); 0 blocks that tool
|
|
46
51
|
OUTLOOK_DEFAULT_TIMEZONE IANA timezone for event times (default Australia/Melbourne)
|
|
47
52
|
OUTLOOK_IMMUTABLE_IDS Set to "true" for message IDs that survive folder moves
|
|
48
53
|
OUTLOOK_SEARCH_SCAN_LIMIT Local search fallback window (default 500, max 5000)
|
|
49
54
|
OUTLOOK_REQUEST_TIMEOUT_MS Graph request inactivity timeout (default 60000)
|
|
55
|
+
OUTLOOK_DEBUG Set to "true" for detailed stderr logs (addresses redacted)
|
|
56
|
+
OUTLOOK_EXPORT_DIR Extra folder export/attachment downloads may write to
|
|
57
|
+
(besides the temp directory, ~/Downloads, ~/Documents)
|
|
50
58
|
USE_TEST_MODE Set to "true" to run against mock data
|
|
51
59
|
|
|
52
60
|
Documentation: https://github.com/littlebearapps/outlook-assistant`;
|
|
@@ -74,33 +82,40 @@ Documentation: https://github.com/littlebearapps/outlook-assistant`;
|
|
|
74
82
|
process.exit(0);
|
|
75
83
|
}
|
|
76
84
|
|
|
77
|
-
const { Server } = require('@modelcontextprotocol/sdk/server/index.js');
|
|
78
85
|
const {
|
|
79
86
|
StdioServerTransport,
|
|
80
87
|
} = require('@modelcontextprotocol/sdk/server/stdio.js');
|
|
81
88
|
const config = require('./config');
|
|
82
|
-
const {
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
const {
|
|
86
|
-
const {
|
|
87
|
-
const {
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
const { settingsTools } = require('./settings');
|
|
93
|
-
const { advancedTools } = require('./advanced');
|
|
89
|
+
const { createServer } = require('./server');
|
|
90
|
+
|
|
91
|
+
const { setToolCount } = require('./auth');
|
|
92
|
+
const { TOOLS } = require('./tools');
|
|
93
|
+
const { isDebugEnabled } = require('./utils/logger');
|
|
94
|
+
const {
|
|
95
|
+
blockedTools,
|
|
96
|
+
resolveSessionLimit,
|
|
97
|
+
RATE_LIMITED_TOOLS,
|
|
98
|
+
} = require('./utils/safety');
|
|
94
99
|
|
|
95
100
|
// Log startup information
|
|
96
|
-
console.error(
|
|
101
|
+
console.error(
|
|
102
|
+
`STARTING ${config.SERVER_NAME.toUpperCase()} MCP SERVER v${config.SERVER_VERSION}`
|
|
103
|
+
);
|
|
97
104
|
console.error(`Test mode is ${config.USE_TEST_MODE ? 'enabled' : 'disabled'}`);
|
|
105
|
+
if (isDebugEnabled()) {
|
|
106
|
+
console.error(
|
|
107
|
+
'Debug logging is on (OUTLOOK_DEBUG): stderr includes search terms, subjects and Graph errors, with addresses and IDs redacted.'
|
|
108
|
+
);
|
|
109
|
+
}
|
|
98
110
|
|
|
99
111
|
// F-1 / F-48: warn at startup when safety belts are unset. Mirrors the
|
|
100
112
|
// warning surfaced by `auth action=about`. Visible to operators reading
|
|
101
113
|
// stderr; AI clients reading the JSON-RPC stream are unaffected.
|
|
114
|
+
const sessionLimitSet = Object.keys(RATE_LIMITED_TOOLS).some(
|
|
115
|
+
(tool) => resolveSessionLimit(tool).limit !== null
|
|
116
|
+
);
|
|
102
117
|
if (
|
|
103
|
-
!
|
|
118
|
+
!sessionLimitSet &&
|
|
104
119
|
!process.env.OUTLOOK_ALLOWED_RECIPIENTS &&
|
|
105
120
|
!config.USE_TEST_MODE
|
|
106
121
|
) {
|
|
@@ -108,39 +123,18 @@ if (
|
|
|
108
123
|
'⚠ Safety belts not configured. Consider setting OUTLOOK_MAX_EMAILS_PER_SESSION and OUTLOOK_ALLOWED_RECIPIENTS in your .mcp.json env block for safer AI-assisted sending. See `auth action=about` for details.'
|
|
109
124
|
);
|
|
110
125
|
}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
...rulesTools,
|
|
119
|
-
...contactsTools,
|
|
120
|
-
...categoriesTools,
|
|
121
|
-
...settingsTools,
|
|
122
|
-
...advancedTools,
|
|
123
|
-
];
|
|
126
|
+
// #302: say plainly when a session limit of 0 switches a tool off.
|
|
127
|
+
const blocked = blockedTools();
|
|
128
|
+
if (blocked.length > 0) {
|
|
129
|
+
console.error(
|
|
130
|
+
`Session limits block ${blocked.join(', ')} (0 or an unreadable value). Unset the setting for no limit. See \`auth action=about\`.`
|
|
131
|
+
);
|
|
132
|
+
}
|
|
124
133
|
|
|
125
134
|
// Set dynamic tool count for auth about handler
|
|
126
135
|
setToolCount(TOOLS.length);
|
|
127
136
|
|
|
128
|
-
|
|
129
|
-
const server = new Server(
|
|
130
|
-
{ name: config.SERVER_NAME, version: config.SERVER_VERSION },
|
|
131
|
-
{
|
|
132
|
-
capabilities: {
|
|
133
|
-
tools: TOOLS.reduce((acc, tool) => {
|
|
134
|
-
acc[tool.name] = {};
|
|
135
|
-
return acc;
|
|
136
|
-
}, {}),
|
|
137
|
-
},
|
|
138
|
-
}
|
|
139
|
-
);
|
|
140
|
-
|
|
141
|
-
// Handle all requests. Dispatch + error-shaping logic lives in
|
|
142
|
-
// request-handler.js so it is unit-testable without starting the transport.
|
|
143
|
-
server.fallbackRequestHandler = createRequestHandler(TOOLS);
|
|
137
|
+
const server = createServer(TOOLS);
|
|
144
138
|
|
|
145
139
|
// Make the script executable
|
|
146
140
|
process.on('SIGTERM', () => {
|
package/llms-install.md
CHANGED
|
@@ -18,6 +18,16 @@ Add to your MCP client configuration:
|
|
|
18
18
|
}
|
|
19
19
|
```
|
|
20
20
|
|
|
21
|
+
## Plugin Install (Claude Code, GitHub Copilot CLI, Cursor)
|
|
22
|
+
|
|
23
|
+
The plugin in `plugins/outlook-assistant/` runs a pinned server version and adds the `using-outlook-assistant` skill and a safety hook that asks the user before sends, deletes, rules and automatic replies.
|
|
24
|
+
|
|
25
|
+
- Claude Code: `claude plugin marketplace add littlebearapps/outlook-assistant`, then `claude plugin install outlook-assistant@littlebearapps`. The plugin asks for its settings (client ID, read-only mode, confirmation level and others) when enabled.
|
|
26
|
+
- GitHub Copilot CLI: `copilot plugin marketplace add littlebearapps/outlook-assistant`, then `copilot plugin install outlook-assistant@littlebearapps`. No plugin settings: the user gives the client ID at sign-in, and the hook's confirmation level comes from the `OUTLOOK_CONFIRM_LEVEL` environment variable (`outward`, `all-writes` or `off`).
|
|
27
|
+
- Cursor (v3.14.0 plugin or later): loads the folder as a Cursor plugin (`.cursor-plugin/plugin.json`); in Cursor CLI, pass it with `--plugin-dir`. The v3.13.0 plugin fails sign-in in Cursor with `AADSTS900023`; use the manual config instead.
|
|
28
|
+
|
|
29
|
+
Client limits (for example, Cursor's prompt doesn't show the hook's reason): `docs/how-to/getting-started/supported-clients.md`.
|
|
30
|
+
|
|
21
31
|
## Prerequisites
|
|
22
32
|
|
|
23
33
|
1. **Node.js 18.18 or newer** must be installed
|
|
@@ -71,14 +81,19 @@ Add these to the same `env` block if needed:
|
|
|
71
81
|
|----------|---------|
|
|
72
82
|
| `OUTLOOK_AUTH_AUDIENCE` | `consumers` for Azure apps registered as personal-accounts-only (fixes `AADSTS9002331`); `organizations` or a tenant GUID for work-only apps. Default `common` |
|
|
73
83
|
| `OUTLOOK_DEFAULT_TIMEZONE` | IANA timezone for calendar times (default `Australia/Melbourne`) |
|
|
74
|
-
| `OUTLOOK_MAX_EMAILS_PER_SESSION` | Default per-session cap for `send-email
|
|
75
|
-
| `OUTLOOK_ALLOWED_RECIPIENTS` | Comma-separated allowlist of recipient domains/addresses |
|
|
84
|
+
| `OUTLOOK_MAX_EMAILS_PER_SESSION` | Default per-session cap, counted separately per tool, for `send-email` (including `draft` send), `draft` create/update/reply/reply-all/forward, `manage-rules` and `create-event` (override one tool with `OUTLOOK_MAX_<TOOL>_PER_SESSION`, e.g. `OUTLOOK_MAX_SEND_EMAIL_PER_SESSION`). Unset = no limit; `0` blocks the tool |
|
|
85
|
+
| `OUTLOOK_ALLOWED_RECIPIENTS` | Comma-separated allowlist of recipient domains/addresses for sends, drafts, rule forwards and event attendees |
|
|
86
|
+
| `OUTLOOK_READ_ONLY` | `true` refuses every tool call that would change something (sending, drafts, moves, deletes, rules, settings, file writes), dry runs included; reads and sign-in still work |
|
|
76
87
|
| `OUTLOOK_SHARED_MAILBOX` | Opt-in shared-mailbox support, work/school accounts only: `read` or `true` (read and organise). Also add `Mail.Read.Shared` (and `Mail.ReadWrite.Shared` for `true`) in Azure, restart, then run `auth` with `action=authenticate` and `force=true` |
|
|
77
88
|
| `OUTLOOK_SEARCH_SCAN_LIMIT` | Messages scanned by the local search fallback on personal accounts (default 500, max 5000) |
|
|
89
|
+
| `OUTLOOK_EXPORT_DIR` | Extra folder `export` and attachment downloads may write to (besides the temp directory, `~/Downloads` and `~/Documents`) |
|
|
78
90
|
| `OUTLOOK_REQUEST_TIMEOUT_MS` | Per-attempt Graph inactivity timeout in milliseconds (default 60000); not an overall deadline |
|
|
91
|
+
| `OUTLOOK_DEBUG` | `true` for detailed stderr logs while troubleshooting (addresses and IDs redacted). Off by default: one line per tool call, no arguments |
|
|
79
92
|
|
|
80
93
|
Run `npx @littlebearapps/outlook-assistant --help` for the full list of environment variables.
|
|
81
94
|
|
|
95
|
+
`OUTLOOK_CONFIRM_LEVEL` is not a server variable: the plugin's safety hook reads it from the client's environment in GitHub Copilot, VS Code and Cursor. Don't put it in the server's `env` block.
|
|
96
|
+
|
|
82
97
|
## Configuration Files by Client
|
|
83
98
|
|
|
84
99
|
### Claude Desktop
|
|
@@ -86,9 +101,12 @@ File: `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS)
|
|
|
86
101
|
|
|
87
102
|
### Claude Code
|
|
88
103
|
```bash
|
|
89
|
-
claude mcp add outlook -- npx @littlebearapps/outlook-assistant
|
|
104
|
+
claude mcp add outlook -e OUTLOOK_CLIENT_ID=<user-must-provide> -- npx -y @littlebearapps/outlook-assistant
|
|
90
105
|
```
|
|
91
106
|
|
|
107
|
+
### VS Code / GitHub Copilot
|
|
108
|
+
File: `.vscode/mcp.json` in your project root, or the user `mcp.json` (Command Palette → **MCP: Open User Configuration**). VS Code uses a top-level `servers` key instead of `mcpServers`, with `"type": "stdio"` on the entry.
|
|
109
|
+
|
|
92
110
|
### Cursor
|
|
93
111
|
File: `.cursor/mcp.json` in your project root
|
|
94
112
|
|
|
@@ -111,5 +129,5 @@ After authentication, test with:
|
|
|
111
129
|
| Device code "invalid_client" | Enable "Allow public client flows" in Azure → Authentication → Advanced settings |
|
|
112
130
|
| "Shared-mailbox support is turned off" | Set `OUTLOOK_SHARED_MAILBOX`, restart, and re-authenticate with `force=true` (work/school accounts only) |
|
|
113
131
|
| "EADDRINUSE :3333" | Run `npx kill-port 3333` then restart auth server |
|
|
114
|
-
|
|
|
132
|
+
| "Authentication required." | Sign in with `auth` `action=authenticate`; `action=status` shows whether a token is saved |
|
|
115
133
|
| Search returns no results (personal account) | Use `from`, `subject`, `to` filters instead of `query` |
|
package/llms.txt
CHANGED
|
@@ -26,17 +26,23 @@ Built by [Little Bear Apps](https://littlebearapps.com).
|
|
|
26
26
|
- **Progressive search**: Automatically falls back through 4 search strategies when Microsoft's `$search` API is unavailable (personal accounts) — most Graph API wrappers fail silently. Explicit "no results" messaging instead of unfiltered fallback, and `_meta.searchMetadata` reports which strategy answered plus any filter that could not be honoured (`droppedFilters`), so a partially-applied search can never pass as a complete one. Field-scoped `$search` expressions (`from:`/`to:`/`subject:`), which personal accounts reject outright, are translated to equivalent OData filters and retried. Cross-folder search (`searchAllFolders`) reliably returns a superset of inbox results.
|
|
27
27
|
- **Remote-friendly auth**: Device code flow (default) — no auth server, no port forwarding, no SSH tunnels. State persists across MCP server restarts. Works from Untether, mosh, SSH, and headless environments.
|
|
28
28
|
- **Email forensics**: Built-in header analysis for DKIM, SPF, DMARC authentication, delivery chains, and spam scores — useful for phishing investigation and compliance
|
|
29
|
-
- **Delta sync**: Incremental inbox monitoring — returns only new, modified, and deleted emails since last check, with tokens for continuous polling
|
|
29
|
+
- **Delta sync**: Incremental inbox monitoring — returns only new, modified, and deleted emails since last check, with tokens for continuous polling; every page is labelled initial or incremental (`_meta.syncType`)
|
|
30
30
|
- **Batch operations**: Flag, move, export, or categorise multiple emails in a single tool call; search-driven export for batch archiving without collecting IDs
|
|
31
31
|
- **Pre-send intelligence**: Check recipients for out-of-office, mailbox full, delivery restrictions, and moderation before sending — no other Outlook MCP server offers this
|
|
32
32
|
- **Compound automation**: Rules + categories + nested folders (addressable by path or ID) + Focused Inbox for complete inbox management in one conversation
|
|
33
33
|
|
|
34
34
|
## Safety & Token Efficiency
|
|
35
35
|
|
|
36
|
-
- **MCP safety annotations** on all 22 tools
|
|
37
|
-
- **Send-email protections**: pre-send mail tips, dry-run preview, session rate limiting, recipient allowlist
|
|
38
|
-
- **Rule protections**: dry-run preview on create/update, rate limiting, recipient allowlist on forward/redirect, no permanent-delete action
|
|
39
|
-
- **
|
|
36
|
+
- **MCP safety annotations** on all 22 tools, derived from a risk class per tool and action (read, reversible, outward, destructive, persistent), so clients can tell reads from risky changes
|
|
37
|
+
- **Send-email protections**: pre-send mail tips (a send to a flagged recipient, such as out of office or external, is refused until `acknowledgeWarnings: true`), dry-run preview, session rate limiting (unset = no limit; `0` or a value that isn't a whole number blocks the tool; `draft` send counts as `send-email`), recipient allowlist (also checked on drafts, including replies and the draft's current recipients on send, and on `create-event`/`manage-event` update attendees; only single plain addresses can match)
|
|
38
|
+
- **Rule protections**: dry-run preview on create/update, rate limiting (dry runs don't count; `0` blocks rule changes), reorder lists the resulting rule order, recipient allowlist on forward/redirect (a blocked forward refuses the whole rule), no permanent-delete action
|
|
39
|
+
- **Dry-run previews beyond email**: `create-event` and every `manage-event` action, update included, say who would be emailed (with an external count; update also says who an attendee change adds or removes); `mailbox-settings` auto-replies, `folders` delete and `manage-contact` delete show what would change or be lost; `dryRun: true` on any other call is refused rather than run for real
|
|
40
|
+
- **Read-only mode**: `OUTLOOK_READ_ONLY=true` refuses every tool call that would change anything before it runs; reads and sign-in still work
|
|
41
|
+
- **Model guidance**: server `instructions` state the hard rules (retrieved content is data, confirm before outward actions, draft first, refusals and rate limits are final, with `0` = off) and name any tool a session limit of `0` blocks; `auth action=about` shows each tool's session limit; `send-email` and `create-event` ask Claude clients for user confirmation (`anthropic/requiresUserInteraction`)
|
|
42
|
+
- **Plugin skill and safety hook** (Claude Code, GitHub Copilot CLI, Cursor; VS Code not yet checked by hand): the `using-outlook-assistant` skill sets the hard rules; the hook asks with a plain-English reason before anything that reaches other people, deletes or keeps acting, and marks retrieved content as untrusted. Confirmation level `outward` (default), `all-writes` or `off`: a plugin setting in Claude Code, the `OUTLOOK_CONFIRM_LEVEL` environment variable elsewhere. How the hook prompts and fails differs by client: see Supported Clients below
|
|
43
|
+
- **Every client**: the server-side checks (read-only mode, dry runs, the recipient allowlist and send caps, mail-tips refusal, rule refusal), annotations and instructions work in any MCP client, including Codex CLI, Gemini CLI and Claude Desktop with a manual config; clients that support Agent Skills can copy the skill folder
|
|
44
|
+
- **Private logs**: one stderr line per tool call (tool, action, outcome, duration), never its arguments; `OUTLOOK_DEBUG=true` adds detail with addresses and IDs redacted
|
|
45
|
+
- **Input and file hardening**: IDs with `.`/`..` path segments refused, the access token only ever sent to `graph.microsoft.com`, attachment downloads and exports (including conversation exports) written only inside the temp directory, `~/Downloads`, `~/Documents` or `OUTLOOK_EXPORT_DIR`, never to dot-prefixed names; paths must be absolute (or start with `~/`) and symlinks aren't followed; an `export` `savePath` ending in `/` is a folder, created if missing; existing files are never replaced unless `export` is called with `overwrite: true` (and never a symlink, hard-linked file or dotfile); files are created `0600` and new folders `0700`; a partly written file is removed if a write fails
|
|
40
46
|
- **Throttling-aware Graph client**: `429` (and `503`/`504` for non-POST requests) retried honouring `Retry-After`, a per-attempt inactivity timeout (`OUTLOOK_REQUEST_TIMEOUT_MS`, default 60000 ms) and at most 4 requests in flight, so bulk operations neither hang nor throttle themselves
|
|
41
47
|
- **Shared mailboxes off by default**: `.Shared` scopes are requested only when `OUTLOOK_SHARED_MAILBOX` is set (`read` keeps shared access read-only)
|
|
42
48
|
- **Token-optimised**: 22 tools instead of 55 saves ~11,000 tokens per turn (~64% reduction), improving AI accuracy and context efficiency
|
|
@@ -58,18 +64,18 @@ Built by [Little Bear Apps](https://littlebearapps.com).
|
|
|
58
64
|
}
|
|
59
65
|
```
|
|
60
66
|
|
|
61
|
-
`OUTLOOK_CLIENT_SECRET` is only needed for the browser sign-in flow; the default device-code flow uses the client ID alone. Claude Code users can instead install the plugin: `claude plugin marketplace add littlebearapps/outlook-assistant`, then `claude plugin install outlook-assistant@littlebearapps`. Requires an Azure app registration with Microsoft Graph delegated permissions. See README for full setup.
|
|
67
|
+
`OUTLOOK_CLIENT_SECRET` is only needed for the browser sign-in flow; the default device-code flow uses the client ID alone. Claude Code users can instead install the plugin (server, skill and safety hook): `claude plugin marketplace add littlebearapps/outlook-assistant`, then `claude plugin install outlook-assistant@littlebearapps`. The same plugin folder also loads in GitHub Copilot CLI (VS Code not yet checked by hand) and, from v3.14.0, Cursor. Requires an Azure app registration with Microsoft Graph delegated permissions. See README for full setup.
|
|
62
68
|
|
|
63
69
|
## Tool Categories
|
|
64
70
|
|
|
65
71
|
- **Authentication (1 tool)**: `auth` — status, authenticate (device code by default), device-code-complete, about (version, granted scopes, shared-mailbox status)
|
|
66
72
|
- **Email (8 tools)**: `search-emails`, `read-email`, `send-email`, `draft`, `update-email`, `attachments`, `export`, `get-mail-tips`
|
|
67
|
-
- **Calendar (3 tools)**: `list-events` (`startAfter`, `startBefore`, `subject` filters), `create-event
|
|
73
|
+
- **Calendar (3 tools)**: `list-events` (`startAfter`, `startBefore`, `subject` filters), `create-event` (`dryRun`; retry-safe `transactionId`), `manage-event` (update, decline, cancel, delete; `dryRun` on all)
|
|
68
74
|
- **Contacts (2 tools)**: `manage-contact`, `search-people`
|
|
69
75
|
- **Folders (1 tool)**: `folders` — list, create, move, stats, delete; folders addressable by nested path (`Parent/Child`) or ID
|
|
70
|
-
- **Rules (1 tool)**: `manage-rules` — list, create, update, reorder, delete
|
|
76
|
+
- **Rules (1 tool)**: `manage-rules` — list, create, update, reorder, delete (12 conditions including `hasAttachments`, 9 actions, `except*` exceptions)
|
|
71
77
|
- **Categories (3 tools)**: `manage-category`, `apply-category`, `manage-focused-inbox`
|
|
72
|
-
- **Settings (1 tool)**: `mailbox-settings` — get, set auto-replies, set working hours
|
|
78
|
+
- **Settings (1 tool)**: `mailbox-settings` — get, set auto-replies (`dryRun`; schedules shown as UTC plus a labelled local time), set working hours
|
|
73
79
|
- **Advanced (2 tools)**: `access-shared-mailbox` (messages, `listFolders`, `folderId`, nested folder paths), `find-meeting-rooms`
|
|
74
80
|
|
|
75
81
|
## Documentation
|
|
@@ -77,12 +83,15 @@ Built by [Little Bear Apps](https://littlebearapps.com).
|
|
|
77
83
|
- [README](https://raw.githubusercontent.com/littlebearapps/outlook-assistant/main/README.md): Full documentation including setup, Azure configuration, and usage
|
|
78
84
|
- [Tools Reference](https://raw.githubusercontent.com/littlebearapps/outlook-assistant/main/docs/quickrefs/tools-reference.md): All 22 tools with parameters and safety annotations
|
|
79
85
|
- [Connect Outlook to Claude](https://raw.githubusercontent.com/littlebearapps/outlook-assistant/main/docs/how-to/getting-started/connect-outlook-to-claude.md): Step-by-step setup guide for Claude Desktop / Claude Code
|
|
86
|
+
- [Supported Clients](https://raw.githubusercontent.com/littlebearapps/outlook-assistant/main/docs/how-to/getting-started/supported-clients.md): What each client gets — plugin, skill, safety hook and server-side checks — for Claude Code, GitHub Copilot, Cursor, Codex CLI, Gemini CLI and Claude Desktop
|
|
87
|
+
- [Plugin README](https://raw.githubusercontent.com/littlebearapps/outlook-assistant/main/plugins/outlook-assistant/README.md): Plugin settings, the skill and the safety hook in each client
|
|
88
|
+
- [Cross-client Matrix](https://raw.githubusercontent.com/littlebearapps/outlook-assistant/main/docs/cross-client-matrix.md): Which clients and models have been checked against the safety scenarios, and when
|
|
80
89
|
- [Verify Your Connection](https://raw.githubusercontent.com/littlebearapps/outlook-assistant/main/docs/how-to/getting-started/verify-your-connection.md): Test and troubleshoot the connection after installation
|
|
81
90
|
- [Azure Setup](https://raw.githubusercontent.com/littlebearapps/outlook-assistant/main/docs/guides/azure-setup.md): Azure app registration and API permissions walkthrough
|
|
82
91
|
- [Troubleshooting](https://raw.githubusercontent.com/littlebearapps/outlook-assistant/main/docs/troubleshooting.md): Known errors and fixes — auth, search, export, shared mailboxes
|
|
83
92
|
- [FAQ](https://raw.githubusercontent.com/littlebearapps/outlook-assistant/main/docs/faq/faq.md): Frequently asked questions — install, accounts, permissions, tokens, send safety, updates, uninstall (also at <https://littlebearapps.com/help/outlook-assistant/faq/>)
|
|
84
93
|
- [CLAUDE.md](https://raw.githubusercontent.com/littlebearapps/outlook-assistant/main/CLAUDE.md): Quick reference for development
|
|
85
94
|
- [CONTRIBUTING](https://raw.githubusercontent.com/littlebearapps/outlook-assistant/main/CONTRIBUTING.md): Contribution guidelines
|
|
86
|
-
- [CHANGELOG](https://raw.githubusercontent.com/littlebearapps/outlook-assistant/main/CHANGELOG.md): Version history (current: v3.
|
|
87
|
-
- [ROADMAP](https://raw.githubusercontent.com/littlebearapps/outlook-assistant/main/ROADMAP.md): Active milestones (v3.
|
|
95
|
+
- [CHANGELOG](https://raw.githubusercontent.com/littlebearapps/outlook-assistant/main/CHANGELOG.md): Version history (current: v3.14.1 — security and safety release: read-only mode, server instructions, more dry-run previews, mail-tips refusal, the plugin skill and a safety hook for Claude Code, GitHub Copilot and Cursor, and fixes for three advisories covering the recipient allowlist, export file writes and dry runs)
|
|
96
|
+
- [ROADMAP](https://raw.githubusercontent.com/littlebearapps/outlook-assistant/main/ROADMAP.md): Active milestones (v3.14.1 live-test fixes; v3.15.0 structured outputs and paging; v4.0.0 MCP 2026-07-28 and server-side confirmation; the patch-release fix queue; v3.8.x carry-over; v3.16.0+ new Graph APIs)
|
|
88
97
|
- [SECURITY](https://raw.githubusercontent.com/littlebearapps/outlook-assistant/main/SECURITY.md): Security policy (report vulnerabilities privately via GitHub private vulnerability reporting; acknowledged within 7 days), token handling, and MCP safety controls
|
package/outlook-auth-server.js
CHANGED
|
@@ -35,6 +35,9 @@ require('dotenv').config();
|
|
|
35
35
|
|
|
36
36
|
// Import scopes and token path from central config to stay in sync
|
|
37
37
|
const { AUTH_CONFIG: centralAuth } = require('./config');
|
|
38
|
+
// Console output never includes the secret, the CSRF state or an auth code,
|
|
39
|
+
// and Azure error text is redacted (it can carry the user's address) (#278).
|
|
40
|
+
const { redact } = require('./utils/logger');
|
|
38
41
|
|
|
39
42
|
// Log to console
|
|
40
43
|
console.log('Starting Outlook Authentication Server');
|
|
@@ -64,7 +67,9 @@ const server = http.createServer((req, res) => {
|
|
|
64
67
|
|
|
65
68
|
if (query.error) {
|
|
66
69
|
console.error(
|
|
67
|
-
|
|
70
|
+
redact(
|
|
71
|
+
`Authentication error: ${query.error} - ${query.error_description}`
|
|
72
|
+
)
|
|
68
73
|
);
|
|
69
74
|
res.writeHead(400, SECURITY_HEADERS);
|
|
70
75
|
res.end(`
|
|
@@ -147,7 +152,7 @@ const server = http.createServer((req, res) => {
|
|
|
147
152
|
`);
|
|
148
153
|
})
|
|
149
154
|
.catch((error) => {
|
|
150
|
-
console.error(`Token exchange error: ${error.message}`);
|
|
155
|
+
console.error(redact(`Token exchange error: ${error.message}`));
|
|
151
156
|
res.writeHead(500, SECURITY_HEADERS);
|
|
152
157
|
res.end(`
|
|
153
158
|
<html>
|
|
@@ -253,7 +258,9 @@ const server = http.createServer((req, res) => {
|
|
|
253
258
|
// Use the audience from config (defaults to "common"; configurable via
|
|
254
259
|
// OUTLOOK_AUTH_AUDIENCE for personal-only / single-tenant Azure apps).
|
|
255
260
|
const authUrl = `${AUTH_CONFIG.authorizeEndpoint}?${querystring.stringify(authParams)}`;
|
|
256
|
-
console.log(
|
|
261
|
+
console.log(
|
|
262
|
+
`Redirecting to Microsoft sign-in: ${AUTH_CONFIG.authorizeEndpoint}`
|
|
263
|
+
);
|
|
257
264
|
|
|
258
265
|
// Redirect to Microsoft's login page
|
|
259
266
|
res.writeHead(302, { Location: authUrl });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@littlebearapps/outlook-assistant",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.14.1",
|
|
4
4
|
"mcpName": "io.github.littlebearapps/outlook-assistant",
|
|
5
5
|
"description": "Outlook Assistant — MCP server with 22 tools for email, calendar, contacts, and settings via Microsoft Graph API",
|
|
6
6
|
"main": "index.js",
|
|
@@ -60,6 +60,8 @@
|
|
|
60
60
|
"index.js",
|
|
61
61
|
"config.js",
|
|
62
62
|
"request-handler.js",
|
|
63
|
+
"server.js",
|
|
64
|
+
"tools.js",
|
|
63
65
|
"outlook-auth-server.js",
|
|
64
66
|
"auth/",
|
|
65
67
|
"calendar/",
|
|
@@ -86,6 +88,7 @@
|
|
|
86
88
|
"@commitlint/config-conventional": "^20.4.3",
|
|
87
89
|
"@eslint/js": "^10.0.1",
|
|
88
90
|
"@modelcontextprotocol/inspector": "^2.8.0",
|
|
91
|
+
"ajv": "^8.20.0",
|
|
89
92
|
"eslint": "^10.0.2",
|
|
90
93
|
"globals": "^17.4.0",
|
|
91
94
|
"husky": "^9.1.7",
|