@chrischall/office-outlook-mcp 0.8.0 → 0.8.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/.claude-plugin/marketplace.json +2 -2
- package/.claude-plugin/plugin.json +1 -1
- package/dist/bundle.js +16 -8
- package/dist/tools/_hints.js +27 -8
- package/dist/tools/mail.js +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
- package/server.json +2 -2
- package/skills/outlook-fpx/SKILL.md +4 -2
|
@@ -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.
|
|
10
|
+
"version": "0.8.1"
|
|
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.
|
|
18
|
+
"version": "0.8.1",
|
|
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.
|
|
4
|
+
"version": "0.8.1",
|
|
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/dist/bundle.js
CHANGED
|
@@ -39086,7 +39086,7 @@ var init_version = __esm({
|
|
|
39086
39086
|
"src/version.ts"() {
|
|
39087
39087
|
"use strict";
|
|
39088
39088
|
PACKAGE_NAME = "office-outlook-mcp";
|
|
39089
|
-
VERSION = "0.8.
|
|
39089
|
+
VERSION = "0.8.1";
|
|
39090
39090
|
}
|
|
39091
39091
|
});
|
|
39092
39092
|
|
|
@@ -50429,7 +50429,7 @@ function workMeta(intent, extra = {}) {
|
|
|
50429
50429
|
return { mint: { domain: "work", intent, ...extra } };
|
|
50430
50430
|
}
|
|
50431
50431
|
var BRIEF_MAX = 120;
|
|
50432
|
-
var BRIEF_NOTE = '"brief": one line per item, `title \u2014 <ISO date or "no date"> \u2014 <status>`, at most 120 chars each, as `data` in the untrusted-content envelope; a last line `-- more` means another page exists (re-ask without "brief" for its nextLink).';
|
|
50432
|
+
var BRIEF_NOTE = '"brief": one line per item, `title \u2014 <ISO date or "no date"> \u2014 <status>`, at most 120 chars each, as `data` in the untrusted-content envelope; a line starting `-- ` is a note (`-- none` for an empty page; a title starting `-- ` or `\\` gets one leading `\\`); a last line `-- more` means another page exists (re-ask without "brief" for its nextLink).';
|
|
50433
50433
|
function briefViewParam(rungs, note) {
|
|
50434
50434
|
const base = viewParam(rungs);
|
|
50435
50435
|
return external_exports.enum([...rungs, "brief"]).optional().describe(`${base.description ?? ""} ${BRIEF_NOTE} ${note}`.trim());
|
|
@@ -50441,15 +50441,23 @@ function flat(s) {
|
|
|
50441
50441
|
function briefDate(dt) {
|
|
50442
50442
|
return flat(dt?.replace(/\.0+(?=Z?$)/, "")) ?? "no date";
|
|
50443
50443
|
}
|
|
50444
|
+
var TITLE_FLOOR = 24;
|
|
50445
|
+
var cut = (s, n) => s.length > n ? `${s.slice(0, Math.max(n - 1, 0))}\u2026` : s;
|
|
50444
50446
|
function briefLine(title, date5, status) {
|
|
50445
|
-
const
|
|
50446
|
-
const shown =
|
|
50447
|
-
const
|
|
50448
|
-
|
|
50447
|
+
const raw = flat(title) ?? "(no subject)";
|
|
50448
|
+
const shown = raw.startsWith("-- ") || raw.startsWith("\\") ? `\\${raw}` : raw;
|
|
50449
|
+
const sep2 = ` \u2014 ${date5} \u2014 `;
|
|
50450
|
+
const room = BRIEF_MAX - sep2.length;
|
|
50451
|
+
if (shown.length + status.length <= room) return `${shown}${sep2}${status}`;
|
|
50452
|
+
const titleRoom = Math.max(room - status.length, Math.min(shown.length, TITLE_FLOOR));
|
|
50453
|
+
const t = cut(shown, titleRoom);
|
|
50454
|
+
return cut(`${t}${sep2}${cut(status, room - t.length)}`, BRIEF_MAX);
|
|
50449
50455
|
}
|
|
50450
50456
|
var BRIEF_MORE = "-- more";
|
|
50457
|
+
var BRIEF_NONE = "-- none";
|
|
50451
50458
|
function briefResult(lines, hasMore = false) {
|
|
50452
|
-
|
|
50459
|
+
const items = lines.length > 0 ? lines : [BRIEF_NONE];
|
|
50460
|
+
return mailboxUntrusted(hasMore ? [...items, BRIEF_MORE] : items);
|
|
50453
50461
|
}
|
|
50454
50462
|
function spaced(value) {
|
|
50455
50463
|
return value.replace(/([a-z])([A-Z])/g, "$1 $2").toLowerCase();
|
|
@@ -50914,7 +50922,7 @@ function registerMailTools(server, client2) {
|
|
|
50914
50922
|
_meta: workMeta("whats-new", { canonical: true, aliases: ["email", "mail", "inbox", "unread", "new mail", "work email"] }),
|
|
50915
50923
|
inputSchema: external_exports.object({
|
|
50916
50924
|
view: external_exports.enum(["brief"]).optional().describe(
|
|
50917
|
-
'Omit for the triage batch above. "brief": one line per message, `<sender>: <subject> \u2014 <received ISO time or "no date"> \u2014 <unread | meeting request | meeting cancelled | meeting response>`, at most 120 chars each, as `data` in the untrusted-content envelope; fetches no body and no invite; a last line `-- more` means another page exists (re-ask without "brief" for its nextLink / next_from).'
|
|
50925
|
+
'Omit for the triage batch above. "brief": one line per message, `<sender>: <subject> \u2014 <received ISO time or "no date"> \u2014 <unread | meeting request | meeting cancelled | meeting response>`, at most 120 chars each, as `data` in the untrusted-content envelope; fetches no body and no invite; a line starting `-- ` is a note (`-- none` for an empty page; a title starting `-- ` or `\\` gets one leading `\\`); a last line `-- more` means another page exists (re-ask without "brief" for its nextLink / next_from).'
|
|
50918
50926
|
),
|
|
50919
50927
|
folder: external_exports.string().min(1).optional().describe('Folder id or well-known name (default "inbox")'),
|
|
50920
50928
|
limit: external_exports.number().int().min(1).max(50).optional().describe("Max messages (default 25, max 50)"),
|
package/dist/tools/_hints.js
CHANGED
|
@@ -20,7 +20,7 @@ export function workMeta(intent, extra = {}) {
|
|
|
20
20
|
}
|
|
21
21
|
/** The longest a brief line may be. */
|
|
22
22
|
export const BRIEF_MAX = 120;
|
|
23
|
-
const BRIEF_NOTE = '"brief": one line per item, `title — <ISO date or "no date"> — <status>`, at most 120 chars each, as `data` in the untrusted-content envelope; a last line `-- more` means another page exists (re-ask without "brief" for its nextLink).';
|
|
23
|
+
const BRIEF_NOTE = '"brief": one line per item, `title — <ISO date or "no date"> — <status>`, at most 120 chars each, as `data` in the untrusted-content envelope; a line starting `-- ` is a note (`-- none` for an empty page; a title starting `-- ` or `\\` gets one leading `\\`); a last line `-- more` means another page exists (re-ask without "brief" for its nextLink).';
|
|
24
24
|
/**
|
|
25
25
|
* The `view` parameter of a canonical read: the tool's own rungs plus
|
|
26
26
|
* `brief`. Absent still means the tool's default.
|
|
@@ -41,26 +41,45 @@ function flat(s) {
|
|
|
41
41
|
export function briefDate(dt) {
|
|
42
42
|
return flat(dt?.replace(/\.0+(?=Z?$)/, '')) ?? 'no date';
|
|
43
43
|
}
|
|
44
|
-
/**
|
|
44
|
+
/** The shortest a title is cut to before the status gives way too. */
|
|
45
|
+
const TITLE_FLOOR = 24;
|
|
46
|
+
const cut = (s, n) => (s.length > n ? `${s.slice(0, Math.max(n - 1, 0))}…` : s);
|
|
47
|
+
/**
|
|
48
|
+
* `title — date — status`, cut to ≤ 120 chars as a WHOLE, title first: the
|
|
49
|
+
* title shortens until the line fits; once it is at its floor the status is
|
|
50
|
+
* cut too (and, past that, the line itself). A title that starts with `-- `
|
|
51
|
+
* or `\` is escaped with one leading `\`, so a subject or sender name can
|
|
52
|
+
* never read as a note — mcp-host strips that one backslash from every item
|
|
53
|
+
* line after its note check.
|
|
54
|
+
*/
|
|
45
55
|
export function briefLine(title, date, status) {
|
|
46
|
-
const
|
|
47
|
-
const shown =
|
|
48
|
-
const
|
|
49
|
-
|
|
56
|
+
const raw = flat(title) ?? '(no subject)';
|
|
57
|
+
const shown = raw.startsWith('-- ') || raw.startsWith('\\') ? `\\${raw}` : raw;
|
|
58
|
+
const sep = ` — ${date} — `;
|
|
59
|
+
const room = BRIEF_MAX - sep.length;
|
|
60
|
+
if (shown.length + status.length <= room)
|
|
61
|
+
return `${shown}${sep}${status}`;
|
|
62
|
+
const titleRoom = Math.max(room - status.length, Math.min(shown.length, TITLE_FLOOR));
|
|
63
|
+
const t = cut(shown, titleRoom);
|
|
64
|
+
return cut(`${t}${sep}${cut(status, room - t.length)}`, BRIEF_MAX);
|
|
50
65
|
}
|
|
51
66
|
/** The note line a brief answer ends with when Outlook holds another page. */
|
|
52
67
|
export const BRIEF_MORE = '-- more';
|
|
68
|
+
/** The single note line a brief answer with no items carries. */
|
|
69
|
+
export const BRIEF_NONE = '-- none';
|
|
53
70
|
/**
|
|
54
71
|
* One line per item, inside the untrusted-data envelope as `data: string[]`
|
|
55
72
|
* (mcp-host's brief-view contract): sender names, subjects and event text are
|
|
56
73
|
* written by other people, so a brief line is fenced like every other rung of
|
|
57
|
-
* these tools. A line starting with `-- ` is a NOTE, not an item: `--
|
|
74
|
+
* these tools. A line starting with `-- ` is a NOTE, not an item: `-- none`
|
|
75
|
+
* answers an empty page, and `-- more`
|
|
58
76
|
* says Outlook has another page (it gives no total, so no `N of M`) — the
|
|
59
77
|
* brief view never silently drops one. Re-ask without `view: "brief"` for the
|
|
60
78
|
* `nextLink` / `next_from` to follow it.
|
|
61
79
|
*/
|
|
62
80
|
export function briefResult(lines, hasMore = false) {
|
|
63
|
-
|
|
81
|
+
const items = lines.length > 0 ? lines : [BRIEF_NONE];
|
|
82
|
+
return mailboxUntrusted(hasMore ? [...items, BRIEF_MORE] : items);
|
|
64
83
|
}
|
|
65
84
|
/** `NotStarted` → `not started`, `TentativelyAccepted` → `tentatively accepted`. */
|
|
66
85
|
export function spaced(value) {
|
package/dist/tools/mail.js
CHANGED
|
@@ -306,7 +306,7 @@ export function registerMailTools(server, client) {
|
|
|
306
306
|
view: z
|
|
307
307
|
.enum(['brief'])
|
|
308
308
|
.optional()
|
|
309
|
-
.describe('Omit for the triage batch above. "brief": one line per message, `<sender>: <subject> — <received ISO time or "no date"> — <unread | meeting request | meeting cancelled | meeting response>`, at most 120 chars each, as `data` in the untrusted-content envelope; fetches no body and no invite; a last line `-- more` means another page exists (re-ask without "brief" for its nextLink / next_from).'),
|
|
309
|
+
.describe('Omit for the triage batch above. "brief": one line per message, `<sender>: <subject> — <received ISO time or "no date"> — <unread | meeting request | meeting cancelled | meeting response>`, at most 120 chars each, as `data` in the untrusted-content envelope; fetches no body and no invite; a line starting `-- ` is a note (`-- none` for an empty page; a title starting `-- ` or `\\` gets one leading `\\`); a last line `-- more` means another page exists (re-ask without "brief" for its nextLink / next_from).'),
|
|
310
310
|
folder: z.string().min(1).optional().describe('Folder id or well-known name (default "inbox")'),
|
|
311
311
|
limit: z.number().int().min(1).max(50).optional().describe('Max messages (default 25, max 50)'),
|
|
312
312
|
sinceHours: z
|
package/dist/version.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@chrischall/office-outlook-mcp",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.1",
|
|
4
4
|
"mcpName": "io.github.chrischall/office-outlook-mcp",
|
|
5
5
|
"description": "Outlook / Microsoft 365 MCP server for Claude — developed and maintained by AI (Claude Code)",
|
|
6
6
|
"author": "Claude Code (AI) <https://www.anthropic.com/claude>",
|
package/server.json
CHANGED
|
@@ -6,12 +6,12 @@
|
|
|
6
6
|
"url": "https://github.com/chrischall/office-outlook-mcp",
|
|
7
7
|
"source": "github"
|
|
8
8
|
},
|
|
9
|
-
"version": "0.8.
|
|
9
|
+
"version": "0.8.1",
|
|
10
10
|
"packages": [
|
|
11
11
|
{
|
|
12
12
|
"registryType": "npm",
|
|
13
13
|
"identifier": "@chrischall/office-outlook-mcp",
|
|
14
|
-
"version": "0.8.
|
|
14
|
+
"version": "0.8.1",
|
|
15
15
|
"transport": {
|
|
16
16
|
"type": "stdio"
|
|
17
17
|
},
|
|
@@ -86,8 +86,10 @@ When the office-outlook-mcp server is hosted on mcp-host, its tools join the
|
|
|
86
86
|
each answered with `view: "brief"` (one line per item,
|
|
87
87
|
`title — <ISO date | no date> — <status>`, returned inside the
|
|
88
88
|
untrusted-content envelope as `data: string[]` because the text is other
|
|
89
|
-
people's; a
|
|
90
|
-
|
|
89
|
+
people's; a line starting `-- ` is a note — `-- none` answers an empty page,
|
|
90
|
+
and a final `-- more` says Outlook has another page, so re-ask without
|
|
91
|
+
`brief` for the `nextLink`; a title starting `-- ` or `\` is escaped with one
|
|
92
|
+
leading `\`). `brief` is additive: on
|
|
91
93
|
`outlook_list_events` and `outlook_list_tasks` it joins the existing
|
|
92
94
|
`compact | full | raw` values, and `outlook_list_unread_messages` takes a
|
|
93
95
|
new optional `view` whose only value is `brief`:
|