@juvantlabs/m365-graph-mcp-server 0.4.0 → 0.4.3

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/ARCHITECTURE.md CHANGED
@@ -290,9 +290,9 @@ security smell (handbook anti-pattern S1).
290
290
 
291
291
  | Dependency | Version | Why |
292
292
  |---|---|---|
293
- | `@modelcontextprotocol/sdk` | `^1.25.2` | MCP framing; ≥1.25.2 required (ReDoS + DNS rebinding fixes — audit C7) |
293
+ | `@modelcontextprotocol/sdk` | `^1.32.2` | MCP framing; ≥1.25.2 required (ReDoS + DNS rebinding fixes — audit C7); ≥1.32 clears the late-2026 `npm audit` advisories on the SDK and its transitive HTTP stack. |
294
294
  | `@microsoft/microsoft-graph-client` | `^3.0.7` | Microsoft's official Graph SDK — handles batching, retries, types |
295
- | `@azure/msal-node` | `^5.0.0` | OAuth — never roll auth. v5+ avoids transitive `uuid <14` GHSA-w5hq-g745-h8pq. |
295
+ | `@azure/msal-node` | `^7.1.2` | OAuth — never roll auth. v5+ avoids transitive `uuid <14` GHSA-w5hq-g745-h8pq; v7.1.2 clears the high-severity advisory affecting 5.0.0-beta.0 – 7.0.2. The v6/v7 majors only change `PublicClientApplication.acquireTokenInteractive` (unused here); the confidential-client auth-code flow, `getAuthCodeUrl` defaults and the token-cache format are unchanged — pinned by `tests/unit/msal_contract.test.ts`, including a cache fixture written by 5.1.5. |
296
296
  | `@napi-rs/keyring` | `^1.3.0` | OS keychain for token persistence; replaces archived `keytar`. |
297
297
  | `isomorphic-fetch` | `^3.0.0` | Peer dep of the Graph SDK. |
298
298
 
package/CHANGELOG.md CHANGED
@@ -11,7 +11,168 @@ project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
11
11
 
12
12
  ## [Unreleased]
13
13
 
14
- ## [0.4.0] - unreleased — SharePoint sites RW + permission-surface invariants
14
+ ## [0.4.3] - unreleased — publish-workflow fix; first npm release of the 0.4.2 content
15
+
16
+ Ships everything listed under `[0.4.2]` below (that version was tagged
17
+ but never reached npm). No tool, schema or behaviour change.
18
+
19
+ ### Fixed — release pipeline
20
+
21
+ - **`publish.yml`: pin the npm upgrade to `npm@^11.5.1`** instead of
22
+ `npm@latest`. npm 12 dropped Node 20 (engines `^22.22.2 || ^24.15.0
23
+ || >=26`), so `npm install -g npm@latest` failed with `EBADENGINE` on
24
+ the Node 20 publish job and the `v0.4.2` run published nothing.
25
+ 11.5.1 is the npm Trusted Publishing minimum, and npm 11 supports
26
+ Node `^20.17.0` (the job runs Node 20.20.x). `ci.yml` does not upgrade
27
+ npm and is unaffected.
28
+
29
+ ## [0.4.2] - tagged, never published — dependency security remediation
30
+
31
+ > **Not on npm.** The `v0.4.2` tag exists, but its publish run failed at
32
+ > the npm-upgrade step (see `[0.4.3]`) before anything was published.
33
+ > The tag was deliberately not moved; this content first ships in
34
+ > **0.4.3**.
35
+
36
+ No tool, schema or behaviour change. Clears every `npm audit` advisory
37
+ (34 → 0: 3 critical, 13 high, 17 moderate, 1 low) so the CI and publish
38
+ audit gate (`--audit-level=moderate`, unchanged) passes again. No
39
+ advisory is ignored.
40
+
41
+ ### Security — runtime dependencies (shipped)
42
+
43
+ - **`@azure/msal-node` `^5.0.0` → `^7.1.2`** (high; affected range
44
+ 5.0.0-beta.0 – 7.0.2; resolved 5.1.5 → 7.1.2; `@azure/msal-common`
45
+ stays on the 16.x line, 16.5.2 → 16.15.0). Migration review:
46
+ - v6 / v7 breaking changes are confined to
47
+ `PublicClientApplication.acquireTokenInteractive` (`form_post`
48
+ default, then `responseMode` removed; custom `loopbackClient` /
49
+ `ILoopbackClient` removed; loopback GET callbacks rejected). This
50
+ server uses `ConfidentialClientApplication` with a manually hosted
51
+ authorization-code flow (`getAuthCodeUrl` + own localhost listener +
52
+ `acquireTokenByCode`), `acquireTokenSilent`, and a custom
53
+ `ICachePlugin` on the OS keychain — none of which changed contract.
54
+ No device-code or interactive (`acquireTokenInteractive`) path
55
+ exists here.
56
+ - `getAuthCodeUrl` on a confidential client still defaults to
57
+ `response_mode=query`, which the setup listener reads.
58
+ - Since 5.6 / 6.0.1, `acquireTokenByCode` validates the ID-token nonce
59
+ strictly. Setup sends no nonce, so Entra issues none and the
60
+ exchange passes; the two setup requests are now built by
61
+ `authCodeUrlRequest()` / `authCodeTokenRequest()` in
62
+ `src/auth/msal.ts` so they cannot drift apart.
63
+ - 7.0.2 / 7.1.0 sanitize the auth-code payload and reject
64
+ `instanceAware` for confidential clients — not used here.
65
+ - 7.0.0 coalesces concurrent identical silent-token requests
66
+ (beneficial for parallel tool calls).
67
+ - Token-cache format: a cache serialized by 5.1.5 is read by 7.1.2
68
+ and refreshes with its refresh token — existing keychain entries
69
+ keep working; no re-run of `setup` expected.
70
+ - **`@modelcontextprotocol/sdk` `^1.25.2` → `^1.32.2`** (high; also
71
+ clears transitive `hono`, `@hono/node-server`, `express-rate-limit`,
72
+ `body-parser`, `proxy-addr` (critical), `qs`, `fast-uri`, `zod`,
73
+ `ip-address`).
74
+
75
+ ### Security — development toolchain (not shipped)
76
+
77
+ - `vitest` / `@vitest/coverage-v8` `^3` → `^4.1.12` (critical via
78
+ `vitest`, `tinypool`; also `vite`, `esbuild`, `postcss`, `nanoid`,
79
+ `source-map-js`, `glob`, `test-exclude`, `js-yaml`). Vitest 5 was not
80
+ taken: it requires Node ≥ 22 and this package supports Node ≥ 20.
81
+ - `eslint` `^9` → `^10.14.0`, `@typescript-eslint/*` → `^8.72.1`,
82
+ `tsx` → `^4.23.15`.
83
+ - `overrides.minimatch: ^11.0.1` (moderate, GHSA-g3hv-75wg-m249). Every
84
+ current ESLint / typescript-eslint release still depends on
85
+ minimatch 10.x and there is no 10.x backport, so the patched major is
86
+ forced. Its consumers here only use `new Minimatch(pattern, { dot })`,
87
+ `Minimatch#match` and the named `minimatch()` — all retained in 11.x
88
+ (11.0 removed `makeRe`, `regexp`, `AST`, `debug`, none of which they
89
+ call).
90
+
91
+ ### Tests
92
+
93
+ - Vitest 4: constructor mocks (`new Entry(...)`) now use `function`
94
+ implementations (arrow functions are not constructible under v4).
95
+ - `@vitest/coverage-v8` 4 counts lines and branches more strictly; the
96
+ per-file thresholds (unchanged) are met by new tests rather than by
97
+ lowering them: plain streaming download (`download_file_stream`),
98
+ resumable large-file upload (`upload_file_large`), and search result
99
+ mapping.
100
+ - New `msal_contract.test.ts` runs the **real** msal-node offline (fake
101
+ keychain + fake token endpoint): setup URL (`response_mode=query`, no
102
+ nonce), code exchange → keychain → silent token after restart, strict
103
+ nonce rejection, and a keychain cache written by msal-node 5.1.5
104
+ (fixture + generator in `tests/fixtures/msal-legacy-cache/`) yielding
105
+ its token and refreshing with its refresh token. The fixture stores a
106
+ placeholder instead of the JWT-shaped synthetic ID token (secret
107
+ scanning treats it as a credential); the test rebuilds it at load.
108
+ - `makeMsalClient()` accepts optional offline-metadata / network-module
109
+ overrides (test seam; production passes none).
110
+
111
+ ## [0.4.1] - 2026-07-04 — folder creation + confirmation-token expiry semantics
112
+
113
+ > Release-hygiene note: `[0.4.0]` was tag-published on 2026-06-26 from
114
+ > commit `5235c78`. Three subsequent PRs (#9, #11, #12) merged to `main`
115
+ > **without** a version bump on `package.json`, so the source tree
116
+ > drifted from what's on npm. This `0.4.1` restores that alignment. See
117
+ > the root-cause writeup in `docs/adr/` (forthcoming) and the follow-up
118
+ > to add a CI guard that fails a merge when `package.json.version`
119
+ > matches a version already in `npm view … versions`.
120
+
121
+ ### Added — Files
122
+
123
+ - **`m365-graph:create_folder`** — new tool for creating folders in
124
+ OneDrive personal drives and SharePoint document libraries. Wraps
125
+ `POST /drives/{drive-id}/items/{parent-id}/children` with the
126
+ `folder: {}` facet. Parameters: `name` (required), `parent_item_id?`
127
+ (defaults to drive root), `drive_id?` (defaults to `/me/drive`),
128
+ `conflict_behavior?` — **restricted to `fail` (default) | `rename`
129
+ by design**. `replace` is intentionally NOT exposed: Graph accepts
130
+ it, but replacing an existing folder is a near-destructive intent
131
+ (the existing folder — potentially with content — is displaced)
132
+ that would push this tool from `write_idempotent` toward
133
+ `write_irreversible` semantics and force a two-phase confirmation
134
+ gate. Callers that truly need replacement compose it from
135
+ `delete_file` (already two-phase-gated) + `create_folder`.
136
+ Returns the created folder's item ID so agents can chain
137
+ `upload_file(parent_item_id=<new_id>, …)` without a round-trip
138
+ through `list_items`. Categorized `write_idempotent` — repeated
139
+ calls with the default `fail` behavior converge on a single
140
+ effective state, and the created folder is reversible via
141
+ `delete_file`. No new Graph scope required: `Files.ReadWrite`
142
+ (OneDrive) and `Sites.ReadWrite.All` (SharePoint) already granted
143
+ in 0.4.0. Filed as issue #10; motivated by real friction archiving
144
+ invoices into the `finance-invoices` SharePoint library where
145
+ destination folders (`Aruba/`, `_SDI-ufficiali/`, `Namecheap/`,
146
+ `_Personal-pre_startup/`) had to be created by hand in the web UI
147
+ before the server could upload into them. Total tool count is now
148
+ 20 (5 write on files: upload, create_folder, copy, move, delete).
149
+
150
+ ### Fixed
151
+
152
+ - **`consumeConfirmation` — expired token now reports `token_expired`,
153
+ not `token_unknown`** (`src/auth/confirmation_tokens.ts`). Pre-fix, the
154
+ periodic `gc()` pass ran BEFORE the entry lookup, so an expired-but-
155
+ still-recorded entry was garbage-collected first and the subsequent
156
+ `pending.get(token)` returned `undefined` — the caller saw
157
+ `token_unknown` and the `token_expired` code path was effectively
158
+ unreachable from wall-clock expiry. The two states are semantically
159
+ distinct (expired = "you're late"; unknown = "there's no such token")
160
+ and both are audit-relevant on a security-relevant two-phase gate
161
+ (`delete_file`, `cancel_event`, `decline_event`). Fix: look up the
162
+ entry FIRST, distinguish expired vs unknown, then run `gc()` on the
163
+ rest of the store. A new `_injectExpiredConfirmation` test helper and
164
+ two unit tests assert the distinct outcomes without racing wall-clock
165
+ time. Surfaced by a sibling MCP server (`m365-mail`) while porting the
166
+ same confirmation-token module. No behavior change on any other
167
+ outcome (`ok`, `token_wrong_tool`, `spec_mismatch` all unchanged).
168
+ This fix was originally listed under `[0.4.0]` in the pre-audit
169
+ changelog, but did NOT make it into the npm-published 0.4.0 tarball
170
+ (verified by tarball inspection on 2026-07-04); it lands in the user-
171
+ visible surface only with this 0.4.1.
172
+
173
+ ---
174
+
175
+ ## [0.4.0] - 2026-06-26 — SharePoint sites RW + permission-surface invariants
15
176
 
16
177
  ### Added
17
178
 
@@ -53,6 +214,11 @@ project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
53
214
 
54
215
  Reference: decisions#210 (per-agent legal-ip enforcement architecture).
55
216
 
217
+ Published from tag `v0.4.0` → commit `5235c78`. **Note**: the fix
218
+ `consumeConfirmation reports token_expired distinctly from
219
+ token_unknown` was originally targeted for this release but landed on
220
+ `main` after the tag was cut; it ships in `0.4.1`.
221
+
56
222
  ---
57
223
 
58
224
  ## [0.3.0] - 2026-06-22 — Long Teams transcript paging + cap fix
@@ -410,7 +576,11 @@ the Juvant OS instance level — see juvant-os-pm FEAT-018 / 019 /
410
576
 
411
577
  ---
412
578
 
413
- [Unreleased]: https://github.com/juvantlabs/m365-graph-mcp-server/compare/v0.3.0...HEAD
579
+ [Unreleased]: https://github.com/juvantlabs/m365-graph-mcp-server/compare/v0.4.3...HEAD
580
+ [0.4.3]: https://github.com/juvantlabs/m365-graph-mcp-server/compare/v0.4.2...v0.4.3
581
+ [0.4.2]: https://github.com/juvantlabs/m365-graph-mcp-server/compare/v0.4.1...v0.4.2
582
+ [0.4.1]: https://github.com/juvantlabs/m365-graph-mcp-server/compare/v0.4.0...v0.4.1
583
+ [0.4.0]: https://github.com/juvantlabs/m365-graph-mcp-server/compare/v0.3.0...v0.4.0
414
584
  [0.3.0]: https://github.com/juvantlabs/m365-graph-mcp-server/compare/v0.2.1...v0.3.0
415
585
  [0.2.1]: https://github.com/juvantlabs/m365-graph-mcp-server/compare/v0.2.0...v0.2.1
416
586
  [0.2.0]: https://github.com/juvantlabs/m365-graph-mcp-server/compare/v0.1.4...v0.2.0
package/README.md CHANGED
@@ -32,10 +32,13 @@ See [CHANGELOG.md](CHANGELOG.md) for the full change list.
32
32
 
33
33
  ## Status
34
34
 
35
- **Published.** v0.3.0 on npm
36
- ([`@juvantlabs/m365-graph-mcp-server`](https://www.npmjs.com/package/@juvantlabs/m365-graph-mcp-server)).
37
- 19 tools across files (OneDrive + SharePoint), Outlook Calendar, and
38
- Teams meeting transcripts. Published via npm **Trusted Publishing**
35
+ **Published.** v0.4.0 on npm
36
+ ([`@juvantlabs/m365-graph-mcp-server`](https://www.npmjs.com/package/@juvantlabs/m365-graph-mcp-server)),
37
+ released 2026-06-26. 19 tools across files (OneDrive + SharePoint),
38
+ Outlook Calendar, and Teams meeting transcripts. v0.4.1 is prepared
39
+ on `main` — adds `create_folder` (bringing the tool count to 20) and
40
+ fixes the `consumeConfirmation` gc-ordering bug; pending manual tag +
41
+ release trigger. Published via npm **Trusted Publishing**
39
42
  (OIDC-based auth from GitHub Actions; no static `NPM_TOKEN`) with
40
43
  provenance attestation; manual approval gate on the `production`
41
44
  GitHub Environment guards the publish step.
@@ -96,7 +99,7 @@ The Juvant OS adopter binds this server in `.juvant/config.json`:
96
99
  {
97
100
  "m365-graph": {
98
101
  "provider": "microsoft",
99
- "mcp_server": "npx @juvantlabs/m365-graph-mcp-server@0.3.0",
102
+ "mcp_server": "npx @juvantlabs/m365-graph-mcp-server@0.4.0",
100
103
  "scope": "rw"
101
104
  }
102
105
  }
@@ -122,6 +125,7 @@ Step 8.5 cross-check semantics.
122
125
  | `m365-graph:search_events` | Searches events by subject substring (Graph $search isn't supported on Events; subject-only via `contains()`). Returns recurrence series masters, not occurrences. | `query` (required), `limit?` (1–50, default 20) | `{ count, results: [] }` (same event shape). | `Calendars.Read` |
123
126
  | `m365-graph:get_event` | Fetches full details for a single event — body (capped at 8000 chars), attendees with response statuses, location, recurrence rule, online-meeting join URL when applicable. | `event_id` (required) | event summary + `body` / `body_content_type` / `body_truncated` / `recurrence` / `online_meeting_join_url`. | `Calendars.Read` |
124
127
  | `m365-graph:upload_file` | Uploads a local file to a drive. Auto-routes between single PUT (≤ 4 MB) and resumable upload session (> 4 MB, 10 MB chunks). 200 MB hard cap. | `local_path` (required), `drive_id?`, `parent_item_id?`, `name?`, `conflict_behavior?` (`fail`/`replace`/`rename`, default `fail`) | `{ uploaded: { id, name, size, webUrl, upload_path } }` | `Files.ReadWrite` |
128
+ | `m365-graph:create_folder` | Creates a folder in a drive (OneDrive primary by default; SharePoint document library via `drive_id`). Synchronous POST to `/children`. Returns the new folder's item ID so it can be passed as `parent_item_id` to a subsequent `upload_file` / `create_folder` call. `replace` conflict behavior is intentionally not exposed (compose `delete_file` + `create_folder` if truly needed). | `name` (required), `parent_item_id?`, `drive_id?`, `conflict_behavior?` (`fail`/`rename`, default `fail`) | `{ created: { id, name, webUrl, parent_id, child_count } }` | `Files.ReadWrite` |
125
129
  | `m365-graph:create_event` | Creates a new event on the user's primary calendar (or a specified calendar). Sends invitations to attendees by Graph default. | `subject` + `start` + `end` (required), `timezone?` (default UTC), `body?`, `body_content_type?` (`text`/`html`), `location?`, `attendees?`, `is_all_day?`, `calendar_id?` | `{ created: <event summary> }` | `Calendars.ReadWrite` |
126
130
  | `m365-graph:update_event` | Updates an existing event. All fields except `event_id` are optional; only provided fields are PATCHed. **Attendees: full replacement, not merge** — pass the full intended list. | `event_id` (required), then any subset of `subject`/`start`+`end`+`timezone`/`body`+`body_content_type`/`location`/`attendees`/`is_all_day` | `{ updated: <event summary> }` | `Calendars.ReadWrite` |
127
131
  | `m365-graph:copy_file` | Async copy with polling. POSTs to `/items/{id}/copy`, polls the monitor URL with exponential backoff (1s → 2s → … capped at 30s) until completion. Falls back to `list-by-name` if the monitor's completed response omits `resourceLocation` (common Graph quirk). | `item_id` + `target_parent_id` (required); `source_drive_id?`, `target_drive_id?`, `new_name?`, `wait_max_seconds?` (1–1800, default 300) | `{ status: "completed", copied: { id, name, ... } }` | `Files.ReadWrite` |
@@ -135,7 +139,7 @@ Step 8.5 cross-check semantics.
135
139
 
136
140
  ¹ **Admin consent required.** `OnlineMeetings.Read` and `OnlineMeetingTranscript.Read.All` must be granted in the Entra app registration under **API permissions → Add a permission → Microsoft Graph → Delegated → Grant admin consent**. Without admin consent these tools return 403 Forbidden.
137
141
 
138
- That's 4 read + 4 write on files, 5 read + 4 write on calendars, 2 read on meeting transcripts — **19 tools total**. Read tools exercise delegated `Files.Read` + `Calendars.Read`; write tools require `Files.ReadWrite` + `Calendars.ReadWrite`; transcript tools require `OnlineMeetings.Read` + `OnlineMeetingTranscript.Read.All` (all separately granted + admin-consented in the Entra app).
142
+ That's 4 read + 5 write on files, 5 read + 4 write on calendars, 2 read on meeting transcripts — **20 tools total**. Read tools exercise delegated `Files.Read` + `Calendars.Read`; write tools require `Files.ReadWrite` + `Calendars.ReadWrite`; transcript tools require `OnlineMeetings.Read` + `OnlineMeetingTranscript.Read.All` (all separately granted + admin-consented in the Entra app).
139
143
 
140
144
  ## Local development
141
145
 
@@ -35,4 +35,5 @@ export type ConsumeResult = {
35
35
  };
36
36
  export declare function consumeConfirmation(token: string, toolName: string, spec: Record<string, unknown>): ConsumeResult;
37
37
  export declare function _resetConfirmationTokens(): void;
38
+ export declare function _injectExpiredConfirmation(token: string, toolName: string, spec: Record<string, unknown>): void;
38
39
  //# sourceMappingURL=confirmation_tokens.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"confirmation_tokens.d.ts","sourceRoot":"","sources":["../../src/auth/confirmation_tokens.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAmCH,MAAM,WAAW,WAAW;IAC1B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,kBAAkB,EAAE,MAAM,CAAC;CAC5B;AAED,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,WAAW,CAcb;AAED,MAAM,MAAM,YAAY,GACpB,eAAe,GACf,eAAe,GACf,kBAAkB,GAClB,eAAe,CAAC;AAEpB,MAAM,MAAM,aAAa,GACrB;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,GACZ;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,YAAY,CAAA;CAAE,CAAC;AAEvC,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,aAAa,CAiBf;AAID,wBAAgB,wBAAwB,IAAI,IAAI,CAE/C"}
1
+ {"version":3,"file":"confirmation_tokens.d.ts","sourceRoot":"","sources":["../../src/auth/confirmation_tokens.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAmCH,MAAM,WAAW,WAAW;IAC1B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,kBAAkB,EAAE,MAAM,CAAC;CAC5B;AAED,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,WAAW,CAcb;AAED,MAAM,MAAM,YAAY,GACpB,eAAe,GACf,eAAe,GACf,kBAAkB,GAClB,eAAe,CAAC;AAEpB,MAAM,MAAM,aAAa,GACrB;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,GACZ;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,YAAY,CAAA;CAAE,CAAC;AAEvC,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,aAAa,CA4Bf;AAID,wBAAgB,wBAAwB,IAAI,IAAI,CAE/C;AAID,wBAAgB,0BAA0B,CACxC,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,IAAI,CAMN"}
@@ -59,14 +59,24 @@ export function issueConfirmation(toolName, spec) {
59
59
  };
60
60
  }
61
61
  export function consumeConfirmation(token, toolName, spec) {
62
- gc();
62
+ // Look up the token BEFORE the periodic GC pass so an expired-but-
63
+ // still-recorded entry reports as `token_expired`, not `token_unknown`
64
+ // — the two states are semantically distinct (expired says "you're
65
+ // late"; unknown says "there's no such token"). Only after this
66
+ // lookup do we GC other stale entries. For a security-relevant two-
67
+ // phase gate (delete_file, cancel_event, decline_event) this matters
68
+ // for the caller-facing UX and for audit signal fidelity.
63
69
  const entry = pending.get(token);
64
- if (!entry)
70
+ if (!entry) {
71
+ gc();
65
72
  return { ok: false, error: "token_unknown" };
73
+ }
66
74
  if (entry.expiresAt <= Date.now()) {
67
75
  pending.delete(token);
76
+ gc();
68
77
  return { ok: false, error: "token_expired" };
69
78
  }
79
+ gc();
70
80
  if (entry.toolName !== toolName) {
71
81
  return { ok: false, error: "token_wrong_tool" };
72
82
  }
@@ -82,4 +92,13 @@ export function consumeConfirmation(token, toolName, spec) {
82
92
  export function _resetConfirmationTokens() {
83
93
  pending.clear();
84
94
  }
95
+ // Test helper — inject a pre-expired token so expiry paths can be
96
+ // exercised deterministically without racing wall-clock time.
97
+ export function _injectExpiredConfirmation(token, toolName, spec) {
98
+ pending.set(token, {
99
+ toolName,
100
+ specHash: hashSpec(spec),
101
+ expiresAt: Date.now() - 1_000,
102
+ });
103
+ }
85
104
  //# sourceMappingURL=confirmation_tokens.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"confirmation_tokens.js","sourceRoot":"","sources":["../../src/auth/confirmation_tokens.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"confirmation_tokens.js","sourceRoot":"","sources":["../../src/auth/confirmation_tokens.ts"],"names":[],"mappings":"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"}
@@ -9,7 +9,7 @@
9
9
  * Tokens persist in the OS keychain via `src/auth/keyring.ts`. The MSAL
10
10
  * cache plugin pattern is: load on first access, save when it changes.
11
11
  */
12
- import { ConfidentialClientApplication, type ICachePlugin } from "@azure/msal-node";
12
+ import { ConfidentialClientApplication, type AuthorizationCodeRequest, type AuthorizationUrlRequest, type Configuration, type ICachePlugin } from "@azure/msal-node";
13
13
  /**
14
14
  * Delegated scopes the MCP server requests. Order is irrelevant; MSAL
15
15
  * normalizes. `offline_access` is required to get a refresh token.
@@ -25,13 +25,39 @@ export declare const DELEGATED_SCOPES: string[];
25
25
  * app registration. See README § Local development.
26
26
  */
27
27
  export declare const REDIRECT_URI = "http://localhost:3000/auth/callback";
28
+ /**
29
+ * Authorization-URL request used by `setup`. Deliberately no `nonce`
30
+ * and no `responseMode`:
31
+ * - the confidential-client `getAuthCodeUrl` defaults to
32
+ * `response_mode=query`, which is what the setup localhost listener
33
+ * reads (GET `?code=`);
34
+ * - `acquireTokenByCode` (msal-node ≥ 5.6) validates the ID-token
35
+ * nonce strictly — if a nonce were sent here it would also have to be
36
+ * passed to the code exchange, otherwise the exchange fails with
37
+ * `nonce_mismatch`. Sending none keeps the two requests consistent.
38
+ * Pinned by tests/unit/msal_contract.test.ts.
39
+ */
40
+ export declare function authCodeUrlRequest(): AuthorizationUrlRequest;
41
+ /** Code-exchange request used by `setup`; mirrors authCodeUrlRequest(). */
42
+ export declare function authCodeTokenRequest(code: string): AuthorizationCodeRequest;
28
43
  /**
29
44
  * Build the MSAL cache plugin for a given tenant. Exported so tests
30
45
  * can drive the load/save lifecycle directly with a fake
31
46
  * TokenCacheContext + spied keychain store.
32
47
  */
33
48
  export declare function makeCachePlugin(tenantId: string): ICachePlugin;
34
- export declare function makeMsalClient(): ConfidentialClientApplication;
49
+ /**
50
+ * Optional, additive overrides. Production calls `makeMsalClient()` with
51
+ * none; tests pass offline authority/cloud-discovery metadata and a fake
52
+ * network module so the real MSAL code paths run without a tenant.
53
+ * Credentials, authority and cache plugin are never overridable here.
54
+ */
55
+ export interface MsalClientOverrides {
56
+ authorityMetadata?: string;
57
+ cloudDiscoveryMetadata?: string;
58
+ system?: Configuration["system"];
59
+ }
60
+ export declare function makeMsalClient(overrides?: MsalClientOverrides): ConfidentialClientApplication;
35
61
  /**
36
62
  * Acquire an access token silently from the cache. Refreshes via the
37
63
  * cached refresh token if the access token is expired. Throws if no
@@ -1 +1 @@
1
- {"version":3,"file":"msal.d.ts","sourceRoot":"","sources":["../../src/auth/msal.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EACL,6BAA6B,EAE7B,KAAK,YAAY,EAElB,MAAM,kBAAkB,CAAC;AAI1B;;;;;;;GAOG;AAcH,eAAO,MAAM,gBAAgB,UAQ5B,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,YAAY,wCAAwC,CAAC;AAElE;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,YAAY,CAe9D;AAED,wBAAgB,cAAc,IAAI,6BAA6B,CAa9D;AAED;;;;;GAKG;AACH,wBAAsB,cAAc,CAClC,MAAM,EAAE,6BAA6B,GACpC,OAAO,CAAC,MAAM,CAAC,CAoBjB"}
1
+ {"version":3,"file":"msal.d.ts","sourceRoot":"","sources":["../../src/auth/msal.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EACL,6BAA6B,EAC7B,KAAK,wBAAwB,EAC7B,KAAK,uBAAuB,EAC5B,KAAK,aAAa,EAClB,KAAK,YAAY,EAElB,MAAM,kBAAkB,CAAC;AAI1B;;;;;;;GAOG;AAcH,eAAO,MAAM,gBAAgB,UAQ5B,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,YAAY,wCAAwC,CAAC;AAElE;;;;;;;;;;;GAWG;AACH,wBAAgB,kBAAkB,IAAI,uBAAuB,CAM5D;AAED,2EAA2E;AAC3E,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,wBAAwB,CAM3E;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,YAAY,CAe9D;AAED;;;;;GAKG;AACH,MAAM,WAAW,mBAAmB;IAClC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,MAAM,CAAC,EAAE,aAAa,CAAC,QAAQ,CAAC,CAAC;CAClC;AAED,wBAAgB,cAAc,CAAC,SAAS,GAAE,mBAAwB,GAAG,6BAA6B,CAoBjG;AAED;;;;;GAKG;AACH,wBAAsB,cAAc,CAClC,MAAM,EAAE,6BAA6B,GACpC,OAAO,CAAC,MAAM,CAAC,CAoBjB"}
package/dist/auth/msal.js CHANGED
@@ -47,6 +47,33 @@ export const DELEGATED_SCOPES = [
47
47
  * app registration. See README § Local development.
48
48
  */
49
49
  export const REDIRECT_URI = "http://localhost:3000/auth/callback";
50
+ /**
51
+ * Authorization-URL request used by `setup`. Deliberately no `nonce`
52
+ * and no `responseMode`:
53
+ * - the confidential-client `getAuthCodeUrl` defaults to
54
+ * `response_mode=query`, which is what the setup localhost listener
55
+ * reads (GET `?code=`);
56
+ * - `acquireTokenByCode` (msal-node ≥ 5.6) validates the ID-token
57
+ * nonce strictly — if a nonce were sent here it would also have to be
58
+ * passed to the code exchange, otherwise the exchange fails with
59
+ * `nonce_mismatch`. Sending none keeps the two requests consistent.
60
+ * Pinned by tests/unit/msal_contract.test.ts.
61
+ */
62
+ export function authCodeUrlRequest() {
63
+ return {
64
+ scopes: DELEGATED_SCOPES,
65
+ redirectUri: REDIRECT_URI,
66
+ prompt: "select_account",
67
+ };
68
+ }
69
+ /** Code-exchange request used by `setup`; mirrors authCodeUrlRequest(). */
70
+ export function authCodeTokenRequest(code) {
71
+ return {
72
+ code,
73
+ scopes: DELEGATED_SCOPES,
74
+ redirectUri: REDIRECT_URI,
75
+ };
76
+ }
50
77
  /**
51
78
  * Build the MSAL cache plugin for a given tenant. Exported so tests
52
79
  * can drive the load/save lifecycle directly with a fake
@@ -68,17 +95,24 @@ export function makeCachePlugin(tenantId) {
68
95
  },
69
96
  };
70
97
  }
71
- export function makeMsalClient() {
98
+ export function makeMsalClient(overrides = {}) {
72
99
  const tenantId = process.env.M365_TENANT_ID ?? "";
73
100
  const config = {
74
101
  auth: {
75
102
  clientId: process.env.M365_CLIENT_ID ?? "",
76
103
  clientSecret: process.env.M365_CLIENT_SECRET ?? "",
77
104
  authority: `https://login.microsoftonline.com/${tenantId}`,
105
+ ...(overrides.authorityMetadata !== undefined
106
+ ? { authorityMetadata: overrides.authorityMetadata }
107
+ : {}),
108
+ ...(overrides.cloudDiscoveryMetadata !== undefined
109
+ ? { cloudDiscoveryMetadata: overrides.cloudDiscoveryMetadata }
110
+ : {}),
78
111
  },
79
112
  cache: {
80
113
  cachePlugin: makeCachePlugin(tenantId),
81
114
  },
115
+ ...(overrides.system !== undefined ? { system: overrides.system } : {}),
82
116
  };
83
117
  return new ConfidentialClientApplication(config);
84
118
  }
@@ -1 +1 @@
1
- {"version":3,"file":"msal.js","sourceRoot":"","sources":["../../src/auth/msal.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EACL,6BAA6B,GAI9B,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAE7C;;;;;;;GAOG;AACH,oEAAoE;AACpE,oEAAoE;AACpE,iEAAiE;AACjE,uCAAuC;AACvC,EAAE;AACF,uEAAuE;AACvE,+DAA+D;AAC/D,sEAAsE;AACtE,wEAAwE;AACxE,uEAAuE;AACvE,qEAAqE;AACrE,gEAAgE;AAChE,+DAA+D;AAC/D,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,WAAW;IACX,iBAAiB;IACjB,qBAAqB;IACrB,qBAAqB;IACrB,qBAAqB;IACrB,kCAAkC;IAClC,gBAAgB;CACjB,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,qCAAqC,CAAC;AAElE;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAAC,QAAgB;IAC9C,MAAM,KAAK,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAC;IACtC,OAAO;QACL,KAAK,CAAC,iBAAiB,CAAC,YAA+B;YACrD,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;YAC1B,IAAI,IAAI,EAAE,CAAC;gBACT,YAAY,CAAC,UAAU,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;YAC5C,CAAC;QACH,CAAC;QACD,KAAK,CAAC,gBAAgB,CAAC,YAA+B;YACpD,IAAI,YAAY,CAAC,eAAe,EAAE,CAAC;gBACjC,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,UAAU,CAAC,SAAS,EAAE,CAAC,CAAC;YAClD,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,cAAc;IAC5B,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,EAAE,CAAC;IAClD,MAAM,MAAM,GAAkB;QAC5B,IAAI,EAAE;YACJ,QAAQ,EAAE,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,EAAE;YAC1C,YAAY,EAAE,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,EAAE;YAClD,SAAS,EAAE,qCAAqC,QAAQ,EAAE;SAC3D;QACD,KAAK,EAAE;YACL,WAAW,EAAE,eAAe,CAAC,QAAQ,CAAC;SACvC;KACF,CAAC;IACF,OAAO,IAAI,6BAA6B,CAAC,MAAM,CAAC,CAAC;AACnD,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,MAAqC;IAErC,MAAM,KAAK,GAAG,MAAM,CAAC,aAAa,EAAE,CAAC;IACrC,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,cAAc,EAAE,CAAC;IAC9C,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CACb,mEAAmE;YACjE,iEAAiE,CACpE,CAAC;IACJ,CAAC;IACD,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,kBAAkB,CAAC;QAC7C,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC;QACpB,MAAM,EAAE,gBAAgB;KACzB,CAAC,CAAC;IACH,IAAI,CAAC,MAAM,EAAE,WAAW,EAAE,CAAC;QACzB,MAAM,IAAI,KAAK,CACb,iEAAiE;YAC/D,iEAAiE,CACpE,CAAC;IACJ,CAAC;IACD,OAAO,MAAM,CAAC,WAAW,CAAC;AAC5B,CAAC"}
1
+ {"version":3,"file":"msal.js","sourceRoot":"","sources":["../../src/auth/msal.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../src/auth/setup.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAkFH,wBAAsB,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAoC9C"}
1
+ {"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../src/auth/setup.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAuFH,wBAAsB,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CA4B9C"}
@@ -17,7 +17,7 @@
17
17
  import { exec } from "node:child_process";
18
18
  import http from "node:http";
19
19
  import { URL } from "node:url";
20
- import { DELEGATED_SCOPES, REDIRECT_URI, makeMsalClient } from "./msal.js";
20
+ import { REDIRECT_URI, authCodeTokenRequest, authCodeUrlRequest, makeMsalClient, } from "./msal.js";
21
21
  const CALLBACK_PORT = 3000;
22
22
  const CALLBACK_TIMEOUT_MS = 5 * 60 * 1000; // 5 minutes
23
23
  function openInBrowser(url) {
@@ -78,11 +78,7 @@ function waitForAuthCode() {
78
78
  }
79
79
  export async function runSetup() {
80
80
  const client = makeMsalClient();
81
- const authUrl = await client.getAuthCodeUrl({
82
- scopes: DELEGATED_SCOPES,
83
- redirectUri: REDIRECT_URI,
84
- prompt: "select_account",
85
- });
81
+ const authUrl = await client.getAuthCodeUrl(authCodeUrlRequest());
86
82
  console.error("[setup] Starting OAuth flow against tenant:", process.env.M365_TENANT_ID);
87
83
  console.error("[setup] If your browser does not open automatically, visit:");
88
84
  console.error("");
@@ -93,11 +89,7 @@ export async function runSetup() {
93
89
  openInBrowser(authUrl);
94
90
  const code = await waitForAuthCode();
95
91
  console.error("[setup] Authorization code received. Exchanging for tokens…");
96
- const tokenResponse = await client.acquireTokenByCode({
97
- code,
98
- scopes: DELEGATED_SCOPES,
99
- redirectUri: REDIRECT_URI,
100
- });
92
+ const tokenResponse = await client.acquireTokenByCode(authCodeTokenRequest(code));
101
93
  if (!tokenResponse?.account) {
102
94
  throw new Error("Token acquisition succeeded but no account info was returned.");
103
95
  }
@@ -1 +1 @@
1
- {"version":3,"file":"setup.js","sourceRoot":"","sources":["../../src/auth/setup.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"setup.js","sourceRoot":"","sources":["../../src/auth/setup.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Tool: m365-graph:create_folder
3
+ *
4
+ * Create a folder in a drive (OneDrive primary by default; SharePoint
5
+ * document library via `drive_id`). Wraps Graph's synchronous
6
+ * children-POST:
7
+ *
8
+ * POST /me/drive/root/children (root of primary OneDrive)
9
+ * POST /me/drive/items/{parent-id}/children (nested)
10
+ * POST /drives/{drive-id}/root/children (non-default drive)
11
+ * POST /drives/{drive-id}/items/{parent-id}/children (nested)
12
+ *
13
+ * Body:
14
+ * {
15
+ * "name": "<name>",
16
+ * "folder": {},
17
+ * "@microsoft.graph.conflictBehavior": "fail" | "replace" | "rename"
18
+ * }
19
+ *
20
+ * Conflict behavior — deliberately restricted to two values:
21
+ * - `fail` (default) — refuse if an item with that name exists
22
+ * - `rename` — let Graph auto-suffix (`Foo` → `Foo 1`)
23
+ *
24
+ * `replace` is NOT exposed. Graph would accept it, but replacing an
25
+ * existing folder is a rare, near-destructive intent (the existing
26
+ * folder — potentially with content — is displaced) that would push
27
+ * this tool from `write_idempotent` toward `write_irreversible`
28
+ * semantics and force a two-phase confirmation gate. Excluded by
29
+ * design; if a caller truly needs replacement they compose it from
30
+ * `delete_file` (already two-phase-gated) + `create_folder`.
31
+ *
32
+ * Category: `write_idempotent` — a repeated call with
33
+ * `conflict_behavior: fail` returns an error rather than creating a
34
+ * duplicate; the created folder is reversible via `delete_file`. No
35
+ * two-phase confirmation needed (creation, not destruction).
36
+ *
37
+ * Required Graph scope: `Files.ReadWrite` (delegated) for OneDrive;
38
+ * `Sites.ReadWrite.All` (delegated) for SharePoint document libraries.
39
+ * Both are already requested by src/auth/msal.ts as of v0.4.0.
40
+ *
41
+ * Path/name notes:
42
+ * - We only address the parent by ID (`parent_item_id`), consistent
43
+ * with the rest of the file-tool surface. Path-string addressing
44
+ * is intentionally out of scope.
45
+ * - Names with leading underscore (`_SDI-ufficiali`) or spaces
46
+ * (`New Folder`) are legal in OneDrive/SharePoint doc libraries;
47
+ * we pass through unmodified. Reserved characters (`\ / : * ? " <
48
+ * > |`) and reserved DOS-style names (CON, PRN, etc.) are rejected
49
+ * by Graph with a 400 that surfaces back to the agent as a clear
50
+ * error — no client-side sanitization that would silently mutate
51
+ * the requested name.
52
+ */
53
+ import type { Tool } from "../types/tool.js";
54
+ interface CreatedFolderSummary {
55
+ id: string;
56
+ name: string;
57
+ webUrl: string;
58
+ parent_id: string | null;
59
+ child_count: number;
60
+ }
61
+ export declare function summarizeCreatedFolder(item: Record<string, unknown>): CreatedFolderSummary;
62
+ export declare const createFolderTool: Tool;
63
+ export {};
64
+ //# sourceMappingURL=create_folder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create_folder.d.ts","sourceRoot":"","sources":["../../src/tools/create_folder.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmDG;AASH,OAAO,KAAK,EAAE,IAAI,EAA6C,MAAM,kBAAkB,CAAC;AAsCxF,UAAU,oBAAoB;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,oBAAoB,CAU1F;AAmDD,eAAO,MAAM,gBAAgB,EAAE,IAA4D,CAAC"}
@@ -0,0 +1,123 @@
1
+ /**
2
+ * Tool: m365-graph:create_folder
3
+ *
4
+ * Create a folder in a drive (OneDrive primary by default; SharePoint
5
+ * document library via `drive_id`). Wraps Graph's synchronous
6
+ * children-POST:
7
+ *
8
+ * POST /me/drive/root/children (root of primary OneDrive)
9
+ * POST /me/drive/items/{parent-id}/children (nested)
10
+ * POST /drives/{drive-id}/root/children (non-default drive)
11
+ * POST /drives/{drive-id}/items/{parent-id}/children (nested)
12
+ *
13
+ * Body:
14
+ * {
15
+ * "name": "<name>",
16
+ * "folder": {},
17
+ * "@microsoft.graph.conflictBehavior": "fail" | "replace" | "rename"
18
+ * }
19
+ *
20
+ * Conflict behavior — deliberately restricted to two values:
21
+ * - `fail` (default) — refuse if an item with that name exists
22
+ * - `rename` — let Graph auto-suffix (`Foo` → `Foo 1`)
23
+ *
24
+ * `replace` is NOT exposed. Graph would accept it, but replacing an
25
+ * existing folder is a rare, near-destructive intent (the existing
26
+ * folder — potentially with content — is displaced) that would push
27
+ * this tool from `write_idempotent` toward `write_irreversible`
28
+ * semantics and force a two-phase confirmation gate. Excluded by
29
+ * design; if a caller truly needs replacement they compose it from
30
+ * `delete_file` (already two-phase-gated) + `create_folder`.
31
+ *
32
+ * Category: `write_idempotent` — a repeated call with
33
+ * `conflict_behavior: fail` returns an error rather than creating a
34
+ * duplicate; the created folder is reversible via `delete_file`. No
35
+ * two-phase confirmation needed (creation, not destruction).
36
+ *
37
+ * Required Graph scope: `Files.ReadWrite` (delegated) for OneDrive;
38
+ * `Sites.ReadWrite.All` (delegated) for SharePoint document libraries.
39
+ * Both are already requested by src/auth/msal.ts as of v0.4.0.
40
+ *
41
+ * Path/name notes:
42
+ * - We only address the parent by ID (`parent_item_id`), consistent
43
+ * with the rest of the file-tool surface. Path-string addressing
44
+ * is intentionally out of scope.
45
+ * - Names with leading underscore (`_SDI-ufficiali`) or spaces
46
+ * (`New Folder`) are legal in OneDrive/SharePoint doc libraries;
47
+ * we pass through unmodified. Reserved characters (`\ / : * ? " <
48
+ * > |`) and reserved DOS-style names (CON, PRN, etc.) are rejected
49
+ * by Graph with a 400 that surfaces back to the agent as a clear
50
+ * error — no client-side sanitization that would silently mutate
51
+ * the requested name.
52
+ */
53
+ import { validateOptionalEnum, validateOptionalString, validateRequiredString, } from "../types/validators.js";
54
+ const CONFLICT_BEHAVIORS = ["fail", "rename"];
55
+ const definition = {
56
+ name: "m365-graph:create_folder",
57
+ description: "Create a folder in a drive (OneDrive primary by default; SharePoint document library via drive_id). Synchronous POST to /children. Default conflict behavior is 'fail' — set to 'rename' to auto-suffix on collision. 'replace' is intentionally not supported (replacing an existing folder is near-destructive; compose delete_file + create_folder if you truly need replacement). Returns the created folder's item ID so it can be passed as parent_item_id to a subsequent upload_file / create_folder call.",
58
+ inputSchema: {
59
+ type: "object",
60
+ properties: {
61
+ name: {
62
+ type: "string",
63
+ description: "Folder name to create. Passed through unmodified — Graph rejects reserved characters (\\ / : * ? \" < > |) with a 400 the agent can act on.",
64
+ },
65
+ parent_item_id: {
66
+ type: "string",
67
+ description: "Optional parent folder ID to create INTO. Defaults to the drive root. Get from list_items.",
68
+ },
69
+ drive_id: {
70
+ type: "string",
71
+ description: "Optional drive ID. Defaults to the user's primary OneDrive. Use for SharePoint document libraries.",
72
+ },
73
+ conflict_behavior: {
74
+ type: "string",
75
+ enum: ["fail", "rename"],
76
+ description: "What to do if an item with this name already exists in the parent. 'fail' (default) refuses; 'rename' lets Graph auto-suffix (Foo → Foo 1). 'replace' is intentionally not exposed — see tool description.",
77
+ },
78
+ },
79
+ required: ["name"],
80
+ },
81
+ };
82
+ export function summarizeCreatedFolder(item) {
83
+ const parent = item.parentReference;
84
+ const folder = item.folder;
85
+ return {
86
+ id: String(item.id ?? ""),
87
+ name: String(item.name ?? ""),
88
+ webUrl: String(item.webUrl ?? ""),
89
+ parent_id: parent?.id ?? null,
90
+ child_count: Number(folder?.childCount ?? 0),
91
+ };
92
+ }
93
+ const handler = async (graph, args) => {
94
+ const name = validateRequiredString(args.name, "name");
95
+ const parentItemId = validateOptionalString(args.parent_item_id, "parent_item_id");
96
+ const driveId = validateOptionalString(args.drive_id, "drive_id");
97
+ const conflictBehavior = validateOptionalEnum(args.conflict_behavior, "conflict_behavior", CONFLICT_BEHAVIORS, "fail");
98
+ const drivePath = driveId ? `/drives/${encodeURIComponent(driveId)}` : "/me/drive";
99
+ const parentPath = parentItemId
100
+ ? `${drivePath}/items/${encodeURIComponent(parentItemId)}/children`
101
+ : `${drivePath}/root/children`;
102
+ const body = {
103
+ name,
104
+ folder: {},
105
+ "@microsoft.graph.conflictBehavior": conflictBehavior,
106
+ };
107
+ console.error(`[m365-graph-mcp-server] create_folder: ${drivePath}/${parentItemId ?? "<root>"}/${name} (conflict=${conflictBehavior})`);
108
+ const created = (await graph.api(parentPath).post(body));
109
+ return {
110
+ content: [
111
+ {
112
+ type: "text",
113
+ text: JSON.stringify({
114
+ drive_id: driveId ?? null,
115
+ parent_item_id: parentItemId ?? null,
116
+ created: summarizeCreatedFolder(created),
117
+ }, null, 2),
118
+ },
119
+ ],
120
+ };
121
+ };
122
+ export const createFolderTool = { category: "write_idempotent", definition, handler };
123
+ //# sourceMappingURL=create_folder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create_folder.js","sourceRoot":"","sources":["../../src/tools/create_folder.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AA0B7C,eAAO,MAAM,SAAS,EAAE,aAAa,CAAC,IAAI,CAyBzC,CAAC;AAEF,wBAAgB,eAAe,CAAC,KAAK,EAAE,aAAa,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,CAMxF"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AA2B7C,eAAO,MAAM,SAAS,EAAE,aAAa,CAAC,IAAI,CA0BzC,CAAC;AAEF,wBAAgB,eAAe,CAAC,KAAK,EAAE,aAAa,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,CAMxF"}
@@ -14,6 +14,7 @@ import { listItemsTool } from "./list_items.js";
14
14
  import { searchFilesTool } from "./search_files.js";
15
15
  // Files — write
16
16
  import { copyFileTool } from "./copy_file.js";
17
+ import { createFolderTool } from "./create_folder.js";
17
18
  import { deleteFileTool } from "./delete_file.js";
18
19
  import { moveFileTool } from "./move_file.js";
19
20
  import { uploadFileTool } from "./upload_file.js";
@@ -39,6 +40,7 @@ export const ALL_TOOLS = [
39
40
  downloadFileTool,
40
41
  // Files — write
41
42
  uploadFileTool,
43
+ createFolderTool,
42
44
  copyFileTool,
43
45
  moveFileTool,
44
46
  deleteFileTool,
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,eAAe;AACf,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,gBAAgB;AAChB,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,mBAAmB;AACnB,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,uBAAuB,EAAE,MAAM,4BAA4B,CAAC;AACrE,gCAAgC;AAChC,OAAO,EAAE,0BAA0B,EAAE,MAAM,+BAA+B,CAAC;AAC3E,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,oBAAoB;AACpB,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEpD,MAAM,CAAC,MAAM,SAAS,GAAwB;IAC5C,eAAe;IACf,cAAc;IACd,aAAa;IACb,eAAe;IACf,gBAAgB;IAChB,gBAAgB;IAChB,cAAc;IACd,YAAY;IACZ,YAAY;IACZ,cAAc;IACd,mBAAmB;IACnB,iBAAiB;IACjB,cAAc;IACd,gBAAgB;IAChB,uBAAuB;IACvB,YAAY;IACZ,gCAAgC;IAChC,0BAA0B;IAC1B,iBAAiB;IACjB,oBAAoB;IACpB,eAAe;IACf,eAAe;IACf,eAAe;IACf,gBAAgB;CACjB,CAAC;AAEF,MAAM,UAAU,eAAe,CAAC,KAA0B;IACxD,MAAM,CAAC,GAAG,IAAI,GAAG,EAA2B,CAAC;IAC7C,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;QACtB,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC;IACtC,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,eAAe;AACf,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,gBAAgB;AAChB,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,mBAAmB;AACnB,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,uBAAuB,EAAE,MAAM,4BAA4B,CAAC;AACrE,gCAAgC;AAChC,OAAO,EAAE,0BAA0B,EAAE,MAAM,+BAA+B,CAAC;AAC3E,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,oBAAoB;AACpB,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEpD,MAAM,CAAC,MAAM,SAAS,GAAwB;IAC5C,eAAe;IACf,cAAc;IACd,aAAa;IACb,eAAe;IACf,gBAAgB;IAChB,gBAAgB;IAChB,cAAc;IACd,gBAAgB;IAChB,YAAY;IACZ,YAAY;IACZ,cAAc;IACd,mBAAmB;IACnB,iBAAiB;IACjB,cAAc;IACd,gBAAgB;IAChB,uBAAuB;IACvB,YAAY;IACZ,gCAAgC;IAChC,0BAA0B;IAC1B,iBAAiB;IACjB,oBAAoB;IACpB,eAAe;IACf,eAAe;IACf,eAAe;IACf,gBAAgB;CACjB,CAAC;AAEF,MAAM,UAAU,eAAe,CAAC,KAA0B;IACxD,MAAM,CAAC,GAAG,IAAI,GAAG,EAA2B,CAAC;IAC7C,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;QACtB,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC;IACtC,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@juvantlabs/m365-graph-mcp-server",
3
- "version": "0.4.0",
3
+ "version": "0.4.3",
4
4
  "description": "Microsoft Graph MCP server — OneDrive, SharePoint, and Calendar read+write for Juvant OS agents.",
5
5
  "license": "MIT",
6
6
  "author": "Juvant Srls",
@@ -35,25 +35,26 @@
35
35
  "audit": "npm audit --audit-level=moderate"
36
36
  },
37
37
  "dependencies": {
38
- "@azure/msal-node": "^5.0.0",
38
+ "@azure/msal-node": "^7.1.2",
39
39
  "@microsoft/microsoft-graph-client": "^3.0.7",
40
- "@modelcontextprotocol/sdk": "^1.25.2",
40
+ "@modelcontextprotocol/sdk": "^1.32.2",
41
41
  "@napi-rs/keyring": "^1.3.0",
42
42
  "isomorphic-fetch": "^3.0.0"
43
43
  },
44
44
  "overrides": {
45
- "ip-address": ">=10.2.0"
45
+ "ip-address": ">=10.2.0",
46
+ "minimatch": "^11.0.1"
46
47
  },
47
48
  "devDependencies": {
48
49
  "@types/isomorphic-fetch": "^0.0.39",
49
50
  "@types/node": "^20.0.0",
50
- "@typescript-eslint/eslint-plugin": "^8.0.0",
51
- "@typescript-eslint/parser": "^8.0.0",
52
- "@vitest/coverage-v8": "^3.0.0",
53
- "eslint": "^9.0.0",
54
- "tsx": "^4.0.0",
51
+ "@typescript-eslint/eslint-plugin": "^8.72.1",
52
+ "@typescript-eslint/parser": "^8.72.1",
53
+ "@vitest/coverage-v8": "^4.1.12",
54
+ "eslint": "^10.14.0",
55
+ "tsx": "^4.23.15",
55
56
  "typescript": "^5.4.0",
56
- "vitest": "^3.0.0"
57
+ "vitest": "^4.1.12"
57
58
  },
58
59
  "publishConfig": {
59
60
  "access": "public"