ask-marcel-office-cli 2.2.0 → 2.4.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.
Files changed (35) hide show
  1. package/CHANGELOG.md +201 -0
  2. package/README.md +45 -26
  3. package/dist/cli.js +2964 -2446
  4. package/dist/commands.json +254 -727
  5. package/dist/composition/run-registry-command.d.ts +12 -3
  6. package/dist/domain/utilities/base64.d.ts +11 -0
  7. package/dist/index.js +2121 -1737
  8. package/dist/infra/auth.d.ts +30 -4
  9. package/dist/infra/browser-auth.d.ts +21 -1
  10. package/dist/presenter/output-text.d.ts +1 -1
  11. package/dist/presenter/output.d.ts +2 -2
  12. package/dist/presenter/render-to-string.d.ts +42 -2
  13. package/dist/use-cases/commands/command-types.d.ts +1 -20
  14. package/dist/use-cases/commands/create-forward-draft.d.ts +1 -1
  15. package/dist/use-cases/commands/create-reply-draft.d.ts +1 -1
  16. package/dist/use-cases/commands/docs-render.d.ts +0 -1
  17. package/dist/use-cases/commands/docx-metadata.d.ts +32 -2
  18. package/dist/use-cases/commands/draft-comment-splicer.d.ts +8 -1
  19. package/dist/use-cases/commands/include-hidden-folders.d.ts +2 -0
  20. package/dist/use-cases/commands/list-mail-folder-messages-delta.d.ts +10 -2
  21. package/dist/use-cases/commands/list-shared-mailbox-child-folders.d.ts +4 -0
  22. package/dist/use-cases/commands/list-shared-mailbox-folders.d.ts +4 -0
  23. package/dist/use-cases/commands/login-status.d.ts +2 -0
  24. package/dist/use-cases/commands/login.d.ts +18 -8
  25. package/dist/use-cases/commands/next-page.d.ts +1 -0
  26. package/dist/use-cases/commands/ooxml-xml-walker.d.ts +31 -6
  27. package/dist/use-cases/commands/pptx-comments.d.ts +8 -5
  28. package/dist/use-cases/commands/reject-unknown-params.d.ts +16 -0
  29. package/dist/use-cases/commands/resolve-command.d.ts +7 -9
  30. package/dist/use-cases/commands/search-onenote-pages.d.ts +1 -1
  31. package/dist/use-cases/commands/token-tier-capability.d.ts +5 -0
  32. package/dist/use-cases/commands/update-mail-draft.d.ts +4 -0
  33. package/docs/COMMANDS.md +15 -13
  34. package/docs/USAGE.md +2 -2
  35. package/package.json +25 -9
package/CHANGELOG.md CHANGED
@@ -2,6 +2,207 @@
2
2
 
3
3
  All notable changes to `ask-marcel-office-cli` are documented here.
4
4
 
5
+ ## 2.4.0
6
+
7
+ Two community fixes from [@a-tokyo](https://github.com/a-tokyo). Nothing breaks:
8
+ the new flag is optional, and every existing invocation routes exactly as before.
9
+
10
+ ### Fixed — share links whose filename is not ASCII
11
+
12
+ `buildShareToken` fed the raw URL string to `btoa`, which only accepts Latin-1.
13
+ A sharing URL with an accented filename minted a token that resolved to nothing,
14
+ and one with a CJK or emoji filename threw `InvalidCharacterError`, which crashed
15
+ the command from inside `Promise.all`. The URL's UTF-8 bytes are now encoded
16
+ before base64url, which is what Graph's `/shares/{token}` resolver expects.
17
+
18
+ Six commands build that token and all six were affected:
19
+
20
+ | Command | How it reaches the token |
21
+ |---------|--------------------------|
22
+ | `resolve-drive-share-link` | encodes the sharing URL directly |
23
+ | `convert-mail-attachment-to-markdown` | resolves an attachment's source URL |
24
+ | `convert-mail-attachment-to-pdf` | resolves an attachment's source URL |
25
+ | `extract-mail-attachment-images` | resolves an attachment's source URL |
26
+ | `extract-sharepoint-links-in-mail` | one resolve per link found in the body |
27
+ | `extract-sharepoint-links-in-documents` | one resolve per link found in the text |
28
+
29
+ The byte-to-base64 step moved into a shared `bytesToBase64` codec under
30
+ `domain/utilities`, replacing the private copy that lived in `fetch-raw-bytes`.
31
+
32
+ ### Added — `next-page --tenant-id`
33
+
34
+ `next-page` re-signs a cursor to match the identity its originating command used,
35
+ but it knew only two: the home basic token and the elevated chat token. A
36
+ partner-tenant drive listing signs page 1 with a guest token, and the
37
+ `@odata.nextLink` it emits carries no tenant, so page 2 was re-signed with the
38
+ home token and Graph answered `401 invalidAudienceUri`. Anything longer than one
39
+ page in a partner tenant was unreadable past page 1.
40
+
41
+ Pass the same `--tenant-id` you gave the originating command (ultimately from
42
+ `resolve-drive-share-link`) and the cursor is re-signed with a guest token for
43
+ that tenant. The flag reuses the existing `tenant-option` branding, so a
44
+ malformed GUID is rejected at the boundary before any Graph call.
45
+
46
+ The footer carries the flag for you. `next:` and `delta:` both render
47
+ `--tenant-id <guid>` whenever the call that produced the cursor used one, so the
48
+ line stays copy-pasteable rather than becoming a 401 one step later. This is the
49
+ line an MCP agent reads to build its next call, not just a terminal convenience.
50
+
51
+ ### Added — docx tracked changes report replacements as one edit
52
+
53
+ OOXML has no "replace" revision: Word records replacing a span as a deletion
54
+ sitting next to an insertion. Reported as two loose halves, one edit read as an
55
+ unrelated cut plus an unrelated addition somewhere else, with nothing linking
56
+ them. A deletion and an insertion that are adjacent siblings by the same author
57
+ now come back as a single `replacements` entry carrying `before` and `after`,
58
+ and the two halves leave `insertions` / `deletions` so nothing is counted twice.
59
+ The markdown output gains a `### Tracked changes — replacements` section above
60
+ the two existing ones.
61
+
62
+ Adjacency is real document order, not a guess. The default XML parse groups
63
+ same-named siblings per tag, which cannot distinguish del, ins, del, ins from
64
+ del, del, ins, ins, so revisions are re-read through a second order-preserving
65
+ parser. Pairing is scoped to siblings of one parent, requires the same author on
66
+ both halves, and treats Word's glyph-free markers (`w:proofErr`, bookmark and
67
+ comment anchors) as not separating a pair, while any untouched run of prose does.
68
+
69
+ Still unreported, unchanged by this: `w:moveFrom` / `w:moveTo`, `w:rPrChange`,
70
+ `w:pPrChange`, and the table-structure revisions. A document whose only tracked
71
+ edit is a formatting change still reports no tracked changes at all.
72
+
73
+ ### Added — docx moves and formatting changes are reported at all
74
+
75
+ A docx whose only tracked edits were a moved paragraph or a reformat reported
76
+ no tracked changes whatsoever, which reads as a clean document rather than an
77
+ unreviewed one. `w:moveFrom` / `w:moveTo` and `w:rPrChange` / `w:pPrChange` are
78
+ now extracted into two new sections.
79
+
80
+ `moves` joins the two ends of a move through the `w:name` on the range-start
81
+ markers that bracket them, not by matching their text: Word does guarantee the
82
+ halves carry identical content, so text-matching looks free right up to a
83
+ document that moves the same sentence twice and silently cross-pairs four halves
84
+ into two moves that never happened. A half whose partner is missing still gets a
85
+ row, marked `from-only` or `to-only`.
86
+
87
+ `formatChanges` names which properties a reviewer altered, comparing attributes
88
+ as well as tag names. `w:color` sits on both sides of a recolour with only its
89
+ `w:val` moving, so a comparison of tag names alone calls that run unchanged.
90
+ Run-level and paragraph-level changes share one list, separated by `scope`.
91
+
92
+ Table-structure revisions (cell insert / delete / merge, numbering, section and
93
+ table properties) remain unreported, and the `--include-metadata` docs now say
94
+ so rather than leaving it to be discovered.
95
+
96
+ ### Added — `get-mail-signature` empty states carry an `errorCode`
97
+
98
+ Finding no signature used to come back as a validation error with a good
99
+ message and no code, so an agent routing on `errorCode` saw nothing and the
100
+ live QA sweep logged it as `ERR:err`. Two codes now name the two distinct
101
+ misses: `signature_not_found` when the scanned or pinned message carries no
102
+ OWA signature block, and `no_sent_messages` when there is nothing to scan at
103
+ all. The messages are unchanged.
104
+
105
+ ### Fixed — `scopes-check` never opens a browser
106
+
107
+ `scopes-check` obtained the basic token through the same acquiring getter as
108
+ every other command, and in a terminal that getter heals an expired session by
109
+ opening a browser; when the persistent profile is already signed in it also
110
+ clears the session so the OAuth grant can re-fire, which drops the 90-day
111
+ "Stay signed in" cookie. A diagnostic did all of that on 2026-09-02. The basic
112
+ tier is now read straight off the cache like the elevated and Teams tiers
113
+ already were: an expired token reports a negative `expiresInSeconds`, an empty
114
+ cache reports not-signed-in, and `login` remains the command that refreshes.
115
+ Bring-your-own-token managers built with `createGraphClient` are unaffected.
116
+
117
+ ### Added — an `invalidAudienceUri` error hint
118
+
119
+ The one 401 that re-authenticating cannot fix now says so. Graph cannot mint a
120
+ SharePoint token for a tenant you are only a guest in, so an agent told to run
121
+ `login` here loops forever. The hint names `--tenant-id`, points at
122
+ `resolve-drive-share-link` for the GUID, and covers the paginated case where the
123
+ cursor carries no tenant of its own. It sits above the token-expiry rule, which
124
+ would otherwise claim the same 401 and give the wrong advice.
125
+
126
+ ## 2.3.0
127
+
128
+ > **Read this before upgrading.** This release contains breaking changes to the
129
+ > flag surface despite the minor version number. If you pin `^2.2.0` you will
130
+ > receive it automatically. Anything calling the CLI, the MCP gateway, or the
131
+ > library with an old flag spelling will stop working.
132
+
133
+ ### Removed — every flag alias and every deprecated command name
134
+
135
+ One name per flag, one name per command. The alias system is gone: 77 flag
136
+ aliases and 4 deprecated command names. Each alias already pointed at a more
137
+ specific canonical, so nothing was renamed to accommodate the removal.
138
+
139
+ | Gone | Use instead |
140
+ |------|-------------|
141
+ | `--id` (51 commands) | the command's specific id flag (`--message-id`, `--site-id`, …) |
142
+ | `--start` / `--end` (7 date-window commands) | `--start-date-time` / `--end-date-time` |
143
+ | `--body-content` on `create-reply-draft` / `create-forward-draft` | `--comment` |
144
+ | `--task-id` | `--planner-task-id` or `--todo-task-id` |
145
+ | `--folder-id` | `--item-id` |
146
+ | `--item-id` on the SharePoint list commands | `--list-item-id` |
147
+ | `--page-id`, `--section-id` | `--onenote-page-id`, `--onenote-section-id` |
148
+ | `--emails` on `get-schedule` | `--schedules` |
149
+ | `--query` on `search-onenote-pages` | *(now the canonical name, see below)* |
150
+ | `download-onedrive-file-content` | `download-drive-item-content` |
151
+ | `convert-local-file` | `convert-local-file-to-markdown` |
152
+ | `convert-drive-item-zip` | `convert-drive-item-zip-to-markdown` |
153
+ | `convert-mail-attachment-zip` | `convert-mail-attachment-zip-to-markdown` |
154
+
155
+ Why: the same spelling meant different things on sibling commands. That is how
156
+ `--body-content` came to mean "the text above the quote" on the create-draft
157
+ commands and "replace the ENTIRE body, quote included" on `update-mail-draft`,
158
+ a silent data-loss trap fixed in this same release.
159
+
160
+ ### Changed — `search-onenote-pages --title-substring` is now `--query`
161
+
162
+ The last flag naming a shared concept differently from its siblings. All eight
163
+ search commands now take `--query`. (`--query` had already been bolted onto this
164
+ command as an alias for exactly this reason; it is now the only name.) The flag
165
+ still matches page TITLES only, which its description states explicitly.
166
+
167
+ ### Changed — a parameter a command does not declare is now refused
168
+
169
+ Previously the three surfaces disagreed. Commander rejected unknown `--flags` on
170
+ the CLI, but Zod strips unknown keys, so the MCP gateway's `run-command` params
171
+ and direct library `commands[x].execute(...)` calls silently swallowed them and
172
+ returned data that looked like it had obeyed. A live audit found this on 5 of 7
173
+ delta commands. All three surfaces now refuse identically, with
174
+ `errorCode: "unknown_parameter"` and the supported flags named in the message.
175
+
176
+ ### Fixed — `--top` no longer terminates a mail-folder delta sync
177
+
178
+ `list-mail-folder-messages-delta --top 2` on a 67-message Inbox returned 2
179
+ messages and an `@odata.deltaLink` rather than a `nextLink`. Graph reads a
180
+ *satisfied* `$top` as "this sync is complete", so the other 65 messages were
181
+ never delivered and the caller banked a delta token certifying a sync that never
182
+ happened. `--top` is now sent as `Prefer: odata.maxpagesize`, which pages
183
+ normally. `--skip` and `--orderby` are no longer advertised there (Graph ignores
184
+ the first and rejects the second), and `--filter` / `--orderby` are gone from
185
+ the two drive delta commands for the same reason.
186
+
187
+ ### Fixed — a whole-body draft update can no longer drop quoted history
188
+
189
+ `update-mail-draft --body-content` on a threaded draft replaced the entire body
190
+ including the quoted thread, with nothing warning at call time. It now reads the
191
+ draft first and refuses when a quote is present, pointing at `--comment`. Pass
192
+ `--replace-quoted-history true` for the deliberate case. The same read refuses
193
+ non-drafts before the write.
194
+
195
+ ### Fixed — the oversized-response banner only names remedies that exist
196
+
197
+ The `sizeHint` banner called `--output-path` a "universal remedy (works on every
198
+ command)". It is not: plain-JSON commands refuse the flag, and the two commands
199
+ that trip the banner most often (`search-all-files`, `microsoft-search-query`)
200
+ advertise only `--query`, so every remedy it named was a dead end. The banner is
201
+ now derived from the command that produced the payload and the surface asking:
202
+ byte-producing commands keep the `--output-path` wording (`outputPath` on MCP),
203
+ plain-JSON commands on the CLI get a shell redirect, and the same commands on
204
+ MCP get neither, since an MCP client has no shell.
205
+
5
206
  ## 2.2.0
6
207
 
7
208
  ### Added
package/README.md CHANGED
@@ -4,17 +4,15 @@
4
4
 
5
5
  ### The Microsoft 365 command line built for AI agents
6
6
 
7
- **One sign-in. 180 read-only commands. Every document as clean markdown.**
7
+ **One sign-in. No Azure app registration. Every document as clean markdown.**
8
8
 
9
9
  [![npm version](https://img.shields.io/npm/v/ask-marcel-office-cli.svg?logo=npm&color=cb3837)](https://www.npmjs.com/package/ask-marcel-office-cli)
10
10
  [![license: MIT](https://img.shields.io/npm/l/ask-marcel-office-cli.svg?color=blue)](LICENSE)
11
- [![node ≥20](https://img.shields.io/node/v/ask-marcel-office-cli?logo=node.js&color=339933)](https://nodejs.org)
12
- [![bun ≥1.0](https://img.shields.io/badge/bun-%E2%89%A51.0-14151a?logo=bun)](https://bun.sh)
13
11
  [![types included](https://img.shields.io/npm/types/ask-marcel-office-cli?logo=typescript&color=3178c6)](docs/USAGE.md)
14
12
 
15
13
  Outlook · OneDrive · SharePoint · Calendar · Excel · Teams · Planner · To Do · OneNote · People
16
14
 
17
- [Install](#install-in-60-seconds) · [See it work](#see-it-work) · [What it reaches](#what-your-agent-can-reach) · [Files to markdown](#any-file-becomes-markdown) · [Library](#embed-it-as-a-typescript-library) · [All 184 commands](docs/COMMANDS.md)
15
+ [Install](#install-in-60-seconds) · [See it work](#see-it-work) · [What it reaches](#what-your-agent-can-reach) · [Files to markdown](#any-file-becomes-markdown) · [Library](#embed-it-as-a-typescript-library) · [All 186 commands](docs/COMMANDS.md)
18
16
 
19
17
  </div>
20
18
 
@@ -32,15 +30,38 @@ ask-marcel-office list-mail-messages --top 5
32
30
 
33
31
  That is the whole setup. **No Azure app registration. No tenant-admin consent. No client secrets.** And nothing for a runaway agent to break: the command surface is read-only by design.
34
32
 
33
+ <p align="center">
34
+ <img src="https://raw.githubusercontent.com/ask-marcel/ask-marcel-office-cli/main/docs/demo.gif" alt="ask-marcel-office converting an Outlook .msg file into clean markdown in one command, offline" width="880">
35
+ </p>
36
+
37
+ ## The difference in practice
38
+
39
+ | You need | Raw Microsoft Graph | ask-marcel-office |
40
+ |---|---|---|
41
+ | Access | App registration, admin consent, secret rotation | `login`: one browser sign-in with your own account |
42
+ | An email + attachments | 6+ round trips, HTML-to-text is your problem | `convert-mail-to-markdown`: one call, markdown out |
43
+ | A pptx / pdf / legacy .doc as text | Raw bytes, bring your own converter | `download-drive-item-as-markdown`: one call |
44
+ | A useful error | `BadRequest: Invalid filter clause` | `hint: "string literals MUST use single quotes; embed one by doubling it"` |
45
+ | A 5 MB PDF | Base64 flooding the context window | `--output-path` writes it to disk; the model reads 3 lines |
46
+ | Throttling | HTTP 429, guess the backoff | `retryAfterSeconds` surfaced in the error envelope |
47
+
48
+ And against the tools you already know:
49
+
50
+ | | Microsoft Graph SDKs | CLI for Microsoft 365 (PnP) | ask-marcel-office |
51
+ |---|---|---|---|
52
+ | Sign-in | An Entra app registration, always: every auth flow needs a client id | An Entra app registration; its `setup` command creates one, and the permissions it requests can need admin consent | Your own account, in a browser, once. No app registration |
53
+ | Built for | Backend services | Admins and scripts | Tool-calling LLMs: markdown out, lean fields, a repair hint on every error |
54
+ | Can it break things | Whatever your app's permissions allow | Yes: it creates, changes, and deletes across the tenant | No: read-only by design; the four writes only leave unsent drafts |
55
+
35
56
  ## The three walls it removes
36
57
 
37
58
  ### 🔑 Sign in like a human, not like an app
38
59
 
39
- Microsoft Graph normally means registering an Azure app, chasing tenant-admin consent, and rotating client secrets before the first API call. Here, `login` drives a real browser window through the standard Microsoft sign-in (Playwright under the hood) and captures the same token the Teams web client already uses. Any Microsoft 365 account works, personal or enterprise. Tokens are cached at `~/.ask-marcel/token-cache.json` (0600) and refresh themselves headlessly; `scopes-check` reports per-token scopes and expiry with zero side effects.
60
+ Microsoft Graph normally means registering an Azure app, chasing tenant-admin consent, and rotating client secrets before the first API call. Here, `login` drives a real browser window through the standard Microsoft sign-in (Playwright under the hood) and captures the same token the Teams web client already uses. Any Microsoft 365 account works, personal or enterprise. Tokens are cached at `~/.ask-marcel/token-cache.json` (0600) and refresh themselves headlessly; `scopes-check` reports per-token scopes and expiry without a Graph call and without ever opening a browser: an expired session is reported as expired, not re-captured.
40
61
 
41
62
  ### 🛡️ Safe to hand to an autonomous agent
42
63
 
43
- The 184 commands break down as 176 GET, 4 read-only POST (three searches and a free/busy lookup), and 4 mail-draft operations. No `send-mail`. No `create-event`. No `upload-file`. No `delete-anything`. The worst a hallucinated tool call can do is leave an unsent draft in your Drafts folder. That is the entire blast radius, which is why you can let an agent explore a mailbox without reviewing every call.
64
+ The 186 commands break down as 178 GET, 4 read-only POST (three searches and a free/busy lookup), and 4 mail-draft operations. No `send-mail`. No `create-event`. No `upload-file`. No `delete-anything`. The worst a hallucinated tool call can do is leave an unsent draft in your Drafts folder. That is the entire blast radius, which is why you can let an agent explore a mailbox without reviewing every call. No analytics, either: the only outbound traffic is Microsoft Graph and a periodic npm version check.
44
65
 
45
66
  ### 🧠 Responses budgeted for a context window
46
67
 
@@ -53,17 +74,26 @@ Reading one email with its attachments in raw Graph: GET the message, GET the at
53
74
  ```console
54
75
  $ ask-marcel-office convert-mail-to-markdown --message-id "AAMkAD..."
55
76
 
56
- # Q3 budget review: action needed
77
+ **Subject:** Q3 budget review: action needed
57
78
  **From:** Robin Chen <robin.chen@contoso.com>
79
+ **To:** Alex Kim <alex.kim@contoso.com>
80
+ **Date:** 2026-09-02T08:14:22Z
58
81
 
59
82
  Before Friday's review, the forecast tab still shows last quarter's
60
83
  headcount. Can you sanity-check the attached numbers?
61
84
 
62
- ## Attachments
63
- - Q3-forecast.xlsx (48 KB) · id AAMkAD...
85
+ Robin
86
+
87
+ \[inline image: contoso-signature.png\]
88
+
89
+ _\[Quoted reply chain removed — pass --keep-quoted true to include it\]_
90
+
91
+ **Attachments:**
92
+ - Q3-forecast.xlsx (49.2 KB, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, id: AAMkAD...)
93
+ _Use `convert-mail-attachment-to-pdf` or `get-mail-attachment` with the attachment id to fetch._
64
94
  ```
65
95
 
66
- The quoted chain below the reply is replaced by a one-line marker (restore it with `--keep-quoted true`), inline images become named placeholders, and attachments arrive with the ids ready for the follow-up call:
96
+ Those two bracketed lines are the entire cost of a 40-message thread and a signature logo. Attachments arrive with their ids ready for the follow-up call:
67
97
 
68
98
  ```console
69
99
  $ ask-marcel-office convert-mail-attachment-to-markdown \
@@ -77,22 +107,11 @@ $ ask-marcel-office microsoft-search-query --query "Q3 budget filetype:pptx"
77
107
  $ ask-marcel-office download-drive-item-as-markdown --drive-id "b!abc..." --item-id "01BYE..."
78
108
  ```
79
109
 
80
- ## The difference in practice
81
-
82
- | You need | Raw Microsoft Graph | ask-marcel-office |
83
- |---|---|---|
84
- | Access | App registration, admin consent, secret rotation | `login`: one browser sign-in with your own account |
85
- | An email + attachments | 6+ round trips, HTML-to-text is your problem | `convert-mail-to-markdown`: one call, markdown out |
86
- | A pptx / pdf / legacy .doc as text | Raw bytes, bring your own converter | `download-drive-item-as-markdown`: one call |
87
- | A useful error | `BadRequest: Invalid filter clause` | `hint: "string literals MUST use single quotes; embed one by doubling it"` |
88
- | A 5 MB PDF | Base64 flooding the context window | `--output-path` writes it to disk; the model reads 3 lines |
89
- | Throttling | HTTP 429, guess the backoff | `retryAfterSeconds` surfaced in the error envelope |
90
-
91
110
  ## What your agent can reach
92
111
 
93
112
  | Surface | Commands | In practice |
94
113
  |---|---:|---|
95
- | 📧 Outlook Mail | 36 | Search and read mail as markdown, convert any attachment (down to nested `.zip` and `.msg`), resolve SharePoint links in bodies, extract your signature, find existing drafts on a thread, prepare reply / forward drafts (the only writes) |
114
+ | 📧 Outlook Mail | 38 | Search and read mail as markdown, convert any attachment (down to nested `.zip` and `.msg`), resolve SharePoint links in bodies, extract your signature, find existing drafts on a thread, prepare reply / forward drafts (the only writes) |
96
115
  | 📁 OneDrive + SharePoint | 49 | Discover every drive and site your token can reach, search files, read any document as markdown or PDF, version history, share links resolved even into partner tenants where you're a guest |
97
116
  | 📅 Calendar | 24 | "What's on this week" via relative dates (`today`, `start-of-week`, `+7d`), event details, free/busy lookups |
98
117
  | 👥 People + directory | 16 | People search, user profiles, the directory around you, your own identity and IDs in one round trip |
@@ -178,13 +197,13 @@ claude mcp add --transport stdio --scope user ask-marcel-office -- npx -y ask-ma
178
197
 
179
198
  > **Two things to know.** The first launch downloads the package into npx's cache, so allow it one slow start; every start after that is instant. And GUI apps don't inherit your shell's `PATH`: terminal-launched clients resolve `"npx"` fine, but a client launched from the Dock or Start menu (Claude Desktop) may not find it — if the server won't start, replace `"command": "npx"` with the absolute path `which npx` prints. Bun users: `bunx` works in place of `npx -y`.
180
199
 
181
- You get **five gateway tools**, not one per command — 184 tool schemas would bloat every session, the opposite of the point:
200
+ You get **five gateway tools**, not one per command — a schema per command would bloat every session, the opposite of the point:
182
201
 
183
202
  | Tool | Does |
184
203
  |:--|:--|
185
204
  | `list-commands` | The terse manifest. Start here; `category` narrows it. |
186
205
  | `get-command-docs` | Full docs for one command: options, endpoint, example. |
187
- | `run-command` | The 180 **read** commands. `readOnlyHint: true`, so clients can auto-approve it. |
206
+ | `run-command` | The 182 **read** commands. `readOnlyHint: true`, so clients can auto-approve it. |
188
207
  | `run-write-command` | The 4 mail-draft **write** commands. Separate tool so the read tool's promise stays honest. |
189
208
  | `login` | Sign in / refresh. Opens a browser on this machine. |
190
209
 
@@ -230,14 +249,14 @@ Azure Managed Identity, an on-behalf-of flow, hand-pasted JWTs in tests: the Gra
230
249
 
231
250
  ## Deep docs
232
251
 
233
- - **[All 184 commands](docs/COMMANDS.md)**: per-category tables with required params + Graph endpoint
252
+ - **[All 186 commands](docs/COMMANDS.md)**: per-category tables with required params + Graph endpoint
234
253
  - **[Usage guide](docs/USAGE.md)**: output formats, OData passthrough, `--output-path`, pagination, library API, architecture, configuration
235
254
  - **[Machine-readable manifest](docs/commands.json)**: JSON for programmatic discovery, also importable via `import manifest from 'ask-marcel-office-cli/commands.json'`
236
255
  - **[QA playbook](docs/QA-PLAYBOOK.md)**: the repeatable full-surface health check run before each release
237
256
 
238
257
  ## Roadmap
239
258
 
240
- Read-only stays the default forever. Coverage grows out of real LLM workflows as they come up: suggestions, requests, and pull requests welcome on the [issues page](https://github.com/vdelacou/ask-marcel-office-cli/issues).
259
+ Read-only stays the default forever. Coverage grows out of real LLM workflows as they come up: suggestions, requests, and pull requests welcome on the [issues page](https://github.com/ask-marcel/ask-marcel-office-cli/issues).
241
260
 
242
261
  ## Built with
243
262