@juvantlabs/m365-graph-mcp-server 0.4.1 → 0.5.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.
package/ARCHITECTURE.md CHANGED
@@ -208,7 +208,7 @@ Each row is also reflected in [`README.md`](README.md) § Tools.
208
208
  | `m365-graph:list_drives` | `GET /me/drive`, `GET /me/drives` | _(none)_ | `{ primary, accessible: [] }` | `Files.Read` | First-ship; validates the auth + Graph plumbing end-to-end. |
209
209
  | `m365-graph:list_items` | `GET /me/drive/root/children` or `GET /drives/{id}/items/{item}/children` | `drive_id?`, `item_id?`, `limit?` (1–100, default 50) | `{ count, items: [] }` | `Files.Read` | Item type derived from presence of `folder` facet. `child_count` populated only for folders. |
210
210
  | `m365-graph:search_files` | `GET /drives/{id}/root/search(q='…')` (defaults to `/me/drive`) | `query`, `drive_id?`, `limit?` (1–50, default 20) | `{ count, results: [] }` with virtual `path` joining `parentReference.path` + `name` | `Files.Read` | OData function call; query single quotes are escaped (`'` → `''`). |
211
- | `m365-graph:download_file` | `GET /me/drive/items/{id}` for metadata, then `GET @microsoft.graph.downloadUrl` (Graph CDN) for the bytes | `item_id`, `drive_id?` | `{ local_path, size_bytes, name, content_type }` | `Files.Read` | **Sandboxed**: writes only under `<sandbox>/<tenant>/<sha256(item_id)[:16]>-<sanitized name>`. Streamed via fetch + Node `pipeline`; no whole-file buffering. 200 MB cap, refused pre-fetch via metadata size. Folders rejected. |
211
+ | `m365-graph:download_file` | `GET /me/drive/items/{id}` for metadata, then `GET @microsoft.graph.downloadUrl` (Graph CDN) for the bytes. With `format`: `GET {drive}/items/{id}/content?format=pdf` → 302 → `GET <Location>` | `item_id`, `drive_id?`, `format?` (`pdf`) | `{ local_path, size_bytes, name, content_type, format }` (`format` is `"pdf"` when converted, `null` for a plain download; + `source_size_bytes`, `source_content_type` when converting) | `Files.Read` | **Sandboxed**: writes only under `<sandbox>/<tenant>/<sha256(item_id)[:16]>-<sanitized name>`. Streamed via fetch + Node `pipeline`; no whole-file buffering. 200 MB cap, refused pre-fetch via metadata size. Folders rejected. **Server-side conversion** (see § Download sandboxing): strict `format` enum, pre-flight source-type allowlist, redirect followed by the tool without the bearer token, 200 MB cap re-enforced on the converted stream. |
212
212
  | `m365-graph:list_calendars` | `GET /me/calendars` | `limit?` (1–100, default 50) | `{ count, calendars: [] }` | `Calendars.Read` | Owner extracted from `owner.{name,address}`; falls back to null. |
213
213
  | `m365-graph:list_events` | `GET /me/calendarView` (or `/me/calendars/{id}/calendarView`) with `startDateTime` + `endDateTime` query params | `start`, `end` (ISO 8601), `calendar_id?`, `limit?` (1–200, default 100) | `{ window, count, events: [] }` | `Calendars.Read` | **Recurrences expanded** (calendarView vs /events). Ordered by `start/dateTime` ascending. ISO 8601 input lightly validated client-side (regex), Graph does the strict parse. |
214
214
  | `m365-graph:search_events` | `GET /me/events?$filter=contains(subject, '…')` | `query`, `limit?` (1–50, default 20) | `{ count, results: [] }` | `Calendars.Read` | Subject-only substring match. `$search` is not supported on the Events resource by Graph; body search would require POST `/search/query` (separate API, deferred). Single-quote escaping (`'` → `''`) on the query. **Series masters**, not expanded occurrences. |
@@ -270,6 +270,51 @@ sandbox root before writing.
270
270
  Mode: dirs `0o700`, files `0o600` so other users on a shared host
271
271
  can't read downloaded content.
272
272
 
273
+ The same item always maps to the same local path; a repeat download
274
+ overwrites the previous copy.
275
+
276
+ #### Server-side format conversion
277
+
278
+ `download_file` accepts an optional `format` (strict enum; today only
279
+ `pdf`). Conversion happens entirely in Microsoft Graph — the server runs
280
+ no converter and never executes anything on the file:
281
+
282
+ 1. **Validation.** `format` must be exactly one of the enum values; the
283
+ query string is built from the server-side constant, never from the
284
+ raw caller string. The source name's extension is checked against the
285
+ types Graph documents as PDF-convertible (`doc`, `docx`, `dot`,
286
+ `dotx`, `dotm`, `dsn`, `dwg`, `eml`, `epub`, `fluidframework`, `htm`,
287
+ `html`, `loop`, `markdown`, `md`, `msg`, `odp`, `ods`, `odt`, `pps`,
288
+ `ppsx`, `ppt`, `pptx`, `rtf`, `tif`, `tiff`, `xls`, `xlsm`, `xlsx`).
289
+ Anything else — including a file that is already a PDF — fails
290
+ before the conversion request with an error naming the supported
291
+ types.
292
+ 2. **Request.** `GET {drive}/items/{id}/content?format=pdf` with the
293
+ SDK's automatic redirect-following disabled.
294
+ 3. **Redirect.** Graph answers `302` with a pre-authenticated `Location`.
295
+ The tool requires an absolute `https` URL and fetches it **without**
296
+ the bearer token — the same trust model as
297
+ `@microsoft.graph.downloadUrl`. A direct `200` with the body is also
298
+ accepted. Graph `406`/`415`/`notSupported` responses, including a
299
+ `400` with the `notSupported` code, are reported as a conversion
300
+ failure naming the source extension (the file may be encrypted,
301
+ corrupt, or not convertible). Any other `400` also names the extension
302
+ but does not claim the source type is the cause, because the status
303
+ alone cannot establish that. Other statuses surface with their Graph
304
+ error code. A refused conversion never falls back to the original
305
+ bytes.
306
+ 4. **Write.** The 200 MB source cap applies pre-flight as usual; since
307
+ the converted size is unknown in advance, the cap is re-enforced on
308
+ the stream (`Content-Length` when present, plus a byte counter). A
309
+ capped or failed transfer leaves no partial file.
310
+ 5. **Naming.** `<sha256(item_id)[:16]>-<stem>.pdf` — the original
311
+ extension is replaced, so the converted copy never collides with a
312
+ plain download of the same item, and the stem is trimmed so the
313
+ 200-character filename cap cannot cut the `.pdf` extension.
314
+
315
+ No additional Graph scope is required: conversion is a read on the same
316
+ item (`Files.Read` / `Sites.Read.All` or broader for SharePoint drives).
317
+
273
318
  ## Input validation
274
319
 
275
320
  Every tool validates its inputs via helpers in
@@ -290,9 +335,9 @@ security smell (handbook anti-pattern S1).
290
335
 
291
336
  | Dependency | Version | Why |
292
337
  |---|---|---|
293
- | `@modelcontextprotocol/sdk` | `^1.25.2` | MCP framing; ≥1.25.2 required (ReDoS + DNS rebinding fixes — audit C7) |
338
+ | `@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
339
  | `@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. |
340
+ | `@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
341
  | `@napi-rs/keyring` | `^1.3.0` | OS keychain for token persistence; replaces archived `keytar`. |
297
342
  | `isomorphic-fetch` | `^3.0.0` | Peer dep of the Graph SDK. |
298
343
 
package/CHANGELOG.md CHANGED
@@ -11,7 +11,157 @@ project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
11
11
 
12
12
  ## [Unreleased]
13
13
 
14
- ## [0.4.1] - unreleased — folder creation + confirmation-token expiry semantics
14
+ ## [0.5.0] - unreleased — server-side PDF conversion in `download_file`
15
+
16
+ ### Added — Files
17
+
18
+ - **`m365-graph:download_file` — optional `format` parameter
19
+ (`"pdf"`).** When set, the tool asks Microsoft Graph to convert the
20
+ file server-side via `GET {drive}/items/{id}/content?format=pdf` and
21
+ saves the resulting PDF to the sandbox instead of the original bytes.
22
+ This lets agents read Word / Excel / PowerPoint / OpenDocument / RTF /
23
+ HTML / Markdown / email / TIFF documents through a plain PDF reader
24
+ with no local converter (no subprocess, no new executable surface).
25
+ - `format` is a strict enum; the query value is a server-side
26
+ constant, never the raw caller string.
27
+ - Source type is checked pre-flight against the extensions Graph
28
+ documents as PDF-convertible. Unsupported types (and files that are
29
+ already PDFs) fail fast with an error listing the supported types.
30
+ Graph-side conversion failures (`406` / `415` / `notSupported`,
31
+ including a `400` with that code) are reported as such and name the
32
+ source extension. Any other `400` also names the extension but does
33
+ not claim the source type is the cause. Other Graph errors surface
34
+ with status and code. A refused conversion never falls back to the
35
+ original bytes.
36
+ - Graph's `302` to the converted content is handled explicitly: the
37
+ SDK's redirect-following is disabled for this call, the `Location`
38
+ must be an absolute `https` URL, and it is fetched without the
39
+ bearer token (same trust model as `@microsoft.graph.downloadUrl`).
40
+ - Same sandbox (`0700` dir / `0600` file, per-tenant root), same
41
+ naming and overwrite policy: `<sha256(item_id)[:16]>-<stem>.pdf`.
42
+ The 200 MB cap applies to the source pre-flight and is re-enforced
43
+ on the converted stream; a capped or failed transfer leaves no
44
+ partial file.
45
+ - The output always includes `format`: `"pdf"` when converted, `null`
46
+ for a plain download. Additive output fields when converting:
47
+ `source_size_bytes`, `source_content_type`; `content_type` is
48
+ `application/pdf` and `size_bytes` is the size of the PDF on disk.
49
+ - No new Graph scope.
50
+ - **Validators**: `validateOptionalStrictEnum` (optional enum with no
51
+ default) and `validateHttpsUrl` in `src/types/validators.ts`.
52
+
53
+ ### Fixed — Calendar
54
+
55
+ - **`m365-graph:list_events`: positive UTC offsets no longer fail.**
56
+ `start` / `end` such as `2026-11-04T00:00:00+01:00` were rejected by
57
+ Graph (`The value '2026-11-04T00:00:00 01:00' of parameter
58
+ 'StartDateTime' is invalid`). The Graph SDK does not URL-encode query
59
+ values, so the `+` was sent literally and decoded as a space. Values
60
+ are now percent-encoded; `window` in the result still echoes the
61
+ caller's input ([#18](https://github.com/juvantlabs/m365-graph-mcp-server/issues/18)).
62
+ - **`m365-graph:search_events`: search terms containing `+`, `&` or `#`
63
+ are now matched as written.** Same cause: `+` searched for a space,
64
+ `&` split `$filter` into a stray query parameter, and `#` cut off the
65
+ rest of the query string ([#18](https://github.com/juvantlabs/m365-graph-mcp-server/issues/18)).
66
+
67
+ ## [0.4.3] - unreleased — publish-workflow fix; first npm release of the 0.4.2 content
68
+
69
+ Ships everything listed under `[0.4.2]` below (that version was tagged
70
+ but never reached npm). No tool, schema or behaviour change.
71
+
72
+ ### Fixed — release pipeline
73
+
74
+ - **`publish.yml`: pin the npm upgrade to `npm@^11.5.1`** instead of
75
+ `npm@latest`. npm 12 dropped Node 20 (engines `^22.22.2 || ^24.15.0
76
+ || >=26`), so `npm install -g npm@latest` failed with `EBADENGINE` on
77
+ the Node 20 publish job and the `v0.4.2` run published nothing.
78
+ 11.5.1 is the npm Trusted Publishing minimum, and npm 11 supports
79
+ Node `^20.17.0` (the job runs Node 20.20.x). `ci.yml` does not upgrade
80
+ npm and is unaffected.
81
+
82
+ ## [0.4.2] - tagged, never published — dependency security remediation
83
+
84
+ > **Not on npm.** The `v0.4.2` tag exists, but its publish run failed at
85
+ > the npm-upgrade step (see `[0.4.3]`) before anything was published.
86
+ > The tag was deliberately not moved; this content first ships in
87
+ > **0.4.3**.
88
+
89
+ No tool, schema or behaviour change. Clears every `npm audit` advisory
90
+ (34 → 0: 3 critical, 13 high, 17 moderate, 1 low) so the CI and publish
91
+ audit gate (`--audit-level=moderate`, unchanged) passes again. No
92
+ advisory is ignored.
93
+
94
+ ### Security — runtime dependencies (shipped)
95
+
96
+ - **`@azure/msal-node` `^5.0.0` → `^7.1.2`** (high; affected range
97
+ 5.0.0-beta.0 – 7.0.2; resolved 5.1.5 → 7.1.2; `@azure/msal-common`
98
+ stays on the 16.x line, 16.5.2 → 16.15.0). Migration review:
99
+ - v6 / v7 breaking changes are confined to
100
+ `PublicClientApplication.acquireTokenInteractive` (`form_post`
101
+ default, then `responseMode` removed; custom `loopbackClient` /
102
+ `ILoopbackClient` removed; loopback GET callbacks rejected). This
103
+ server uses `ConfidentialClientApplication` with a manually hosted
104
+ authorization-code flow (`getAuthCodeUrl` + own localhost listener +
105
+ `acquireTokenByCode`), `acquireTokenSilent`, and a custom
106
+ `ICachePlugin` on the OS keychain — none of which changed contract.
107
+ No device-code or interactive (`acquireTokenInteractive`) path
108
+ exists here.
109
+ - `getAuthCodeUrl` on a confidential client still defaults to
110
+ `response_mode=query`, which the setup listener reads.
111
+ - Since 5.6 / 6.0.1, `acquireTokenByCode` validates the ID-token nonce
112
+ strictly. Setup sends no nonce, so Entra issues none and the
113
+ exchange passes; the two setup requests are now built by
114
+ `authCodeUrlRequest()` / `authCodeTokenRequest()` in
115
+ `src/auth/msal.ts` so they cannot drift apart.
116
+ - 7.0.2 / 7.1.0 sanitize the auth-code payload and reject
117
+ `instanceAware` for confidential clients — not used here.
118
+ - 7.0.0 coalesces concurrent identical silent-token requests
119
+ (beneficial for parallel tool calls).
120
+ - Token-cache format: a cache serialized by 5.1.5 is read by 7.1.2
121
+ and refreshes with its refresh token — existing keychain entries
122
+ keep working; no re-run of `setup` expected.
123
+ - **`@modelcontextprotocol/sdk` `^1.25.2` → `^1.32.2`** (high; also
124
+ clears transitive `hono`, `@hono/node-server`, `express-rate-limit`,
125
+ `body-parser`, `proxy-addr` (critical), `qs`, `fast-uri`, `zod`,
126
+ `ip-address`).
127
+
128
+ ### Security — development toolchain (not shipped)
129
+
130
+ - `vitest` / `@vitest/coverage-v8` `^3` → `^4.1.12` (critical via
131
+ `vitest`, `tinypool`; also `vite`, `esbuild`, `postcss`, `nanoid`,
132
+ `source-map-js`, `glob`, `test-exclude`, `js-yaml`). Vitest 5 was not
133
+ taken: it requires Node ≥ 22 and this package supports Node ≥ 20.
134
+ - `eslint` `^9` → `^10.14.0`, `@typescript-eslint/*` → `^8.72.1`,
135
+ `tsx` → `^4.23.15`.
136
+ - `overrides.minimatch: ^11.0.1` (moderate, GHSA-g3hv-75wg-m249). Every
137
+ current ESLint / typescript-eslint release still depends on
138
+ minimatch 10.x and there is no 10.x backport, so the patched major is
139
+ forced. Its consumers here only use `new Minimatch(pattern, { dot })`,
140
+ `Minimatch#match` and the named `minimatch()` — all retained in 11.x
141
+ (11.0 removed `makeRe`, `regexp`, `AST`, `debug`, none of which they
142
+ call).
143
+
144
+ ### Tests
145
+
146
+ - Vitest 4: constructor mocks (`new Entry(...)`) now use `function`
147
+ implementations (arrow functions are not constructible under v4).
148
+ - `@vitest/coverage-v8` 4 counts lines and branches more strictly; the
149
+ per-file thresholds (unchanged) are met by new tests rather than by
150
+ lowering them: plain streaming download (`download_file_stream`),
151
+ resumable large-file upload (`upload_file_large`), and search result
152
+ mapping.
153
+ - New `msal_contract.test.ts` runs the **real** msal-node offline (fake
154
+ keychain + fake token endpoint): setup URL (`response_mode=query`, no
155
+ nonce), code exchange → keychain → silent token after restart, strict
156
+ nonce rejection, and a keychain cache written by msal-node 5.1.5
157
+ (fixture + generator in `tests/fixtures/msal-legacy-cache/`) yielding
158
+ its token and refreshing with its refresh token. The fixture stores a
159
+ placeholder instead of the JWT-shaped synthetic ID token (secret
160
+ scanning treats it as a credential); the test rebuilds it at load.
161
+ - `makeMsalClient()` accepts optional offline-metadata / network-module
162
+ overrides (test seam; production passes none).
163
+
164
+ ## [0.4.1] - 2026-07-04 — folder creation + confirmation-token expiry semantics
15
165
 
16
166
  > Release-hygiene note: `[0.4.0]` was tag-published on 2026-06-26 from
17
167
  > commit `5235c78`. Three subsequent PRs (#9, #11, #12) merged to `main`
@@ -479,7 +629,12 @@ the Juvant OS instance level — see juvant-os-pm FEAT-018 / 019 /
479
629
 
480
630
  ---
481
631
 
482
- [Unreleased]: https://github.com/juvantlabs/m365-graph-mcp-server/compare/v0.3.0...HEAD
632
+ [Unreleased]: https://github.com/juvantlabs/m365-graph-mcp-server/compare/v0.5.0...HEAD
633
+ [0.5.0]: https://github.com/juvantlabs/m365-graph-mcp-server/compare/v0.4.3...v0.5.0
634
+ [0.4.3]: https://github.com/juvantlabs/m365-graph-mcp-server/compare/v0.4.2...v0.4.3
635
+ [0.4.2]: https://github.com/juvantlabs/m365-graph-mcp-server/compare/v0.4.1...v0.4.2
636
+ [0.4.1]: https://github.com/juvantlabs/m365-graph-mcp-server/compare/v0.4.0...v0.4.1
637
+ [0.4.0]: https://github.com/juvantlabs/m365-graph-mcp-server/compare/v0.3.0...v0.4.0
483
638
  [0.3.0]: https://github.com/juvantlabs/m365-graph-mcp-server/compare/v0.2.1...v0.3.0
484
639
  [0.2.1]: https://github.com/juvantlabs/m365-graph-mcp-server/compare/v0.2.0...v0.2.1
485
640
  [0.2.0]: https://github.com/juvantlabs/m365-graph-mcp-server/compare/v0.1.4...v0.2.0
package/README.md CHANGED
@@ -119,7 +119,7 @@ Step 8.5 cross-check semantics.
119
119
  | `m365-graph:list_drives` | Lists the drives the user has access to (primary OneDrive + shared document libraries). | _(none)_ | `{ primary, accessible: [] }` with id / driveType / name / webUrl / owner. | `Files.Read` |
120
120
  | `m365-graph:list_items` | Lists immediate children (files + folders) of a folder. Defaults to the drive root. | `drive_id?`, `item_id?`, `limit?` (1–100, default 50) | `{ count, items: [] }` with id / name / type / size / child_count / lastModified / webUrl. | `Files.Read` |
121
121
  | `m365-graph:search_files` | Searches files by name and content within a drive. | `query` (required), `drive_id?`, `limit?` (1–50, default 20) | `{ count, results: [] }` with id / name / path / size / is_folder / lastModified / webUrl. | `Files.Read` |
122
- | `m365-graph:download_file` | Downloads a file to a per-tenant local sandbox. Returns the local path; agent reads via a filesystem-aware tool. Streams, capped at 200 MB. | `item_id` (required), `drive_id?` | `{ local_path, size_bytes, name, content_type }` | `Files.Read` |
122
+ | `m365-graph:download_file` | Downloads a file to a per-tenant local sandbox. Returns the local path; agent reads via a filesystem-aware tool. Streams, capped at 200 MB. With `format: "pdf"`, Microsoft Graph converts the file to PDF server-side (no local converter) and the PDF is saved as `<name>.pdf` in the same sandbox; unsupported source types are rejected with an error listing the supported ones. | `item_id` (required), `drive_id?`, `format?` (`pdf`) | `{ local_path, size_bytes, name, content_type, format }`, where `format` is `"pdf"` when converted (`content_type` is then `application/pdf`) and `null` for a plain download; when converted also `source_size_bytes`, `source_content_type` | `Files.Read` |
123
123
  | `m365-graph:list_calendars` | Lists the user's calendars (primary + group / shared). | `limit?` (1–100, default 50) | `{ count, calendars: [] }` with id / name / color / owner_name / owner_email / is_default / can_edit / can_share. | `Calendars.Read` |
124
124
  | `m365-graph:list_events` | Lists events in a date window. Recurrences are expanded — each occurrence is its own event. | `start` + `end` (ISO 8601, required), `calendar_id?`, `limit?` (1–200, default 100) | `{ calendar_id, window, count, events: [] }` with id / subject / body_preview / start / end / is_all_day / is_online_meeting / location / organizer_name / organizer_email / attendees / webLink. | `Calendars.Read` |
125
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` |
@@ -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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"}
@@ -23,6 +23,8 @@
23
23
  * - 0o700 dir mode + 0o600 file mode (defense-in-depth on shared hosts).
24
24
  * - Resolved path is verified to start with the sandbox root before
25
25
  * writing — an extra check on top of the structurally-safe naming.
26
+ * - Same item → same local path; a repeat download overwrites the
27
+ * previous copy (deterministic, no accumulation).
26
28
  *
27
29
  * Size cap: 200 MB (handbook spec § Performance characteristics). Item
28
30
  * size is fetched via `/items/{id}` metadata BEFORE downloading; the
@@ -33,11 +35,74 @@
33
35
  * auth needed for the bytes themselves). Streamed via fetch + Node
34
36
  * streams pipeline (no whole-file buffering — handbook anti-pattern #11).
35
37
  *
36
- * Required Graph scope: `Files.Read` (delegated). Read-only on the
37
- * cloud side; writes only to the sandbox locally.
38
+ * Server-side format conversion (`format`, optional):
39
+ * - `format: "pdf"` asks Graph to convert the file server-side via
40
+ * `GET {drive}/items/{id}/content?format=pdf`. No local converter
41
+ * runs — the server never executes anything on the file.
42
+ * - `format` is a strict enum (`DOWNLOAD_FORMATS`); the query value
43
+ * is always the server-side constant, never the raw caller string.
44
+ * - Source type is checked pre-flight against the extensions Graph
45
+ * documents as PDF-convertible; unsupported types fail fast with a
46
+ * clear error and no network call beyond the metadata GET.
47
+ * - Graph answers with a 302 to a pre-authenticated URL for the
48
+ * converted bytes. The SDK's automatic redirect-following is
49
+ * disabled for this request: we read `Location` ourselves, require
50
+ * https, and fetch it WITHOUT the bearer token (same trust model as
51
+ * `@microsoft.graph.downloadUrl`).
52
+ * - A Graph refusal never falls back to the original bytes. 406, 415
53
+ * and a `notSupported` code name the source extension as a conversion
54
+ * failure. Any other 400 also names it, but does not claim the source
55
+ * type is the cause, because the status alone cannot establish that.
56
+ * - The converted size is not known in advance, so the 200 MB cap is
57
+ * also enforced on the stream (Content-Length when present, plus a
58
+ * byte counter). A capped or failed conversion leaves no partial
59
+ * file behind.
60
+ * - Local filename: `<sha256(item_id)[:16]>-<stem>.pdf` — same
61
+ * sandbox, same naming and overwrite policy as plain downloads.
62
+ *
63
+ * Required Graph scope: `Files.Read` (delegated; `Sites.Read(Write).All`
64
+ * for SharePoint drives). Read-only on the cloud side; writes only to
65
+ * the sandbox locally. Conversion needs no additional scope.
38
66
  */
67
+ import { Transform } from "node:stream";
39
68
  import type { Tool } from "../types/tool.js";
69
+ /** Server-side conversion targets accepted by the `format` parameter. */
70
+ export declare const DOWNLOAD_FORMATS: readonly ["pdf"];
71
+ export type DownloadFormat = (typeof DOWNLOAD_FORMATS)[number];
72
+ /**
73
+ * Source extensions Microsoft Graph documents as convertible with
74
+ * `?format=pdf` ("Download a file in another format").
75
+ */
76
+ export declare const PDF_CONVERTIBLE_EXTENSIONS: ReadonlySet<string>;
40
77
  export declare function getSandboxRoot(tenantId: string): string;
41
78
  export declare function deriveSafeLocalPath(sandboxRoot: string, itemId: string, originalName: string): string;
79
+ /**
80
+ * Lower-cased extension without the dot, or null when the name has
81
+ * none. A leading dot alone (".profile") is not an extension.
82
+ */
83
+ export declare function fileExtension(name: string): string | null;
84
+ /**
85
+ * Throw a caller-actionable error when Graph cannot convert this source
86
+ * type to the requested format. Returns the validated source extension.
87
+ */
88
+ export declare function checkConvertible(name: string, format: DownloadFormat): string;
89
+ /**
90
+ * Graph path for the converted content of an item. The `format` value
91
+ * comes from the enum constant, never from raw caller input.
92
+ */
93
+ export declare function buildConvertedContentPath(driveRoot: string, itemId: string, format: DownloadFormat): string;
94
+ /**
95
+ * Local name for a converted file: original stem + `.<format>`. The stem
96
+ * is trimmed so the sanitizer's length cap can never cut the extension.
97
+ */
98
+ export declare function convertedFilename(originalName: string, format: DownloadFormat): string;
99
+ /**
100
+ * Byte-counting pass-through that errors once `limit` is exceeded.
101
+ * `bytes()` reports how many bytes have passed through.
102
+ */
103
+ export declare function cappedCounter(limit: number): {
104
+ stream: Transform;
105
+ bytes: () => number;
106
+ };
42
107
  export declare const downloadFileTool: Tool;
43
108
  //# sourceMappingURL=download_file.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"download_file.d.ts","sourceRoot":"","sources":["../../src/tools/download_file.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AAiBH,OAAO,KAAK,EAAE,IAAI,EAA6C,MAAM,kBAAkB,CAAC;AA2BxF,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAQvD;AAED,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM,CAWrG;AAgED,eAAO,MAAM,gBAAgB,EAAE,IAAgD,CAAC"}
1
+ {"version":3,"file":"download_file.d.ts","sourceRoot":"","sources":["../../src/tools/download_file.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiEG;AAOH,OAAO,EAAY,SAAS,EAA0B,MAAM,aAAa,CAAC;AAgB1E,OAAO,KAAK,EAAE,IAAI,EAA6C,MAAM,kBAAkB,CAAC;AAUxF,yEAAyE;AACzE,eAAO,MAAM,gBAAgB,kBAAmB,CAAC;AACjD,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,gBAAgB,CAAC,CAAC,MAAM,CAAC,CAAC;AAE/D;;;GAGG;AACH,eAAO,MAAM,0BAA0B,EAAE,WAAW,CAAC,MAAM,CA8BzD,CAAC;AAuCH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAQvD;AAED,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM,CAWrG;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAIzD;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,cAAc,GAAG,MAAM,CAe7E;AAED;;;GAGG;AACH,wBAAgB,yBAAyB,CACvC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,cAAc,GACrB,MAAM,CAER;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,cAAc,GAAG,MAAM,CAMtF;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG;IAAE,MAAM,EAAE,SAAS,CAAC;IAAC,KAAK,EAAE,MAAM,MAAM,CAAA;CAAE,CAavF;AAoND,eAAO,MAAM,gBAAgB,EAAE,IAAgD,CAAC"}
@@ -23,6 +23,8 @@
23
23
  * - 0o700 dir mode + 0o600 file mode (defense-in-depth on shared hosts).
24
24
  * - Resolved path is verified to start with the sandbox root before
25
25
  * writing — an extra check on top of the structurally-safe naming.
26
+ * - Same item → same local path; a repeat download overwrites the
27
+ * previous copy (deterministic, no accumulation).
26
28
  *
27
29
  * Size cap: 200 MB (handbook spec § Performance characteristics). Item
28
30
  * size is fetched via `/items/{id}` metadata BEFORE downloading; the
@@ -33,23 +35,98 @@
33
35
  * auth needed for the bytes themselves). Streamed via fetch + Node
34
36
  * streams pipeline (no whole-file buffering — handbook anti-pattern #11).
35
37
  *
36
- * Required Graph scope: `Files.Read` (delegated). Read-only on the
37
- * cloud side; writes only to the sandbox locally.
38
+ * Server-side format conversion (`format`, optional):
39
+ * - `format: "pdf"` asks Graph to convert the file server-side via
40
+ * `GET {drive}/items/{id}/content?format=pdf`. No local converter
41
+ * runs — the server never executes anything on the file.
42
+ * - `format` is a strict enum (`DOWNLOAD_FORMATS`); the query value
43
+ * is always the server-side constant, never the raw caller string.
44
+ * - Source type is checked pre-flight against the extensions Graph
45
+ * documents as PDF-convertible; unsupported types fail fast with a
46
+ * clear error and no network call beyond the metadata GET.
47
+ * - Graph answers with a 302 to a pre-authenticated URL for the
48
+ * converted bytes. The SDK's automatic redirect-following is
49
+ * disabled for this request: we read `Location` ourselves, require
50
+ * https, and fetch it WITHOUT the bearer token (same trust model as
51
+ * `@microsoft.graph.downloadUrl`).
52
+ * - A Graph refusal never falls back to the original bytes. 406, 415
53
+ * and a `notSupported` code name the source extension as a conversion
54
+ * failure. Any other 400 also names it, but does not claim the source
55
+ * type is the cause, because the status alone cannot establish that.
56
+ * - The converted size is not known in advance, so the 200 MB cap is
57
+ * also enforced on the stream (Content-Length when present, plus a
58
+ * byte counter). A capped or failed conversion leaves no partial
59
+ * file behind.
60
+ * - Local filename: `<sha256(item_id)[:16]>-<stem>.pdf` — same
61
+ * sandbox, same naming and overwrite policy as plain downloads.
62
+ *
63
+ * Required Graph scope: `Files.Read` (delegated; `Sites.Read(Write).All`
64
+ * for SharePoint drives). Read-only on the cloud side; writes only to
65
+ * the sandbox locally. Conversion needs no additional scope.
38
66
  */
39
67
  import { createWriteStream } from "node:fs";
40
- import { mkdir } from "node:fs/promises";
68
+ import { mkdir, rm } from "node:fs/promises";
41
69
  import os from "node:os";
42
70
  import path from "node:path";
43
71
  import crypto from "node:crypto";
44
- import { Readable } from "node:stream";
72
+ import { Readable, Transform } from "node:stream";
45
73
  import { pipeline } from "node:stream/promises";
46
- import { sanitizeFilename, validateOptionalString, validateRequiredString, } from "../types/validators.js";
74
+ import { RedirectHandlerOptions, ResponseType, } from "@microsoft/microsoft-graph-client";
75
+ import { sanitizeFilename, validateHttpsUrl, validateOptionalStrictEnum, validateOptionalString, validateRequiredString, } from "../types/validators.js";
47
76
  const MAX_FILE_SIZE_BYTES = 200 * 1024 * 1024; // 200 MB per handbook spec
48
77
  const SANDBOX_DIR_MODE = 0o700;
49
78
  const SANDBOX_FILE_MODE = 0o600;
79
+ /** Mirrors sanitizeFilename's length cap so a converted name keeps its extension. */
80
+ const MAX_LOCAL_NAME_CHARS = 200;
81
+ /** Upper bound on how much of a Graph error body we read to build a message. */
82
+ const MAX_ERROR_BODY_CHARS = 4096;
83
+ /** Server-side conversion targets accepted by the `format` parameter. */
84
+ export const DOWNLOAD_FORMATS = ["pdf"];
85
+ /**
86
+ * Source extensions Microsoft Graph documents as convertible with
87
+ * `?format=pdf` ("Download a file in another format").
88
+ */
89
+ export const PDF_CONVERTIBLE_EXTENSIONS = new Set([
90
+ "doc",
91
+ "docx",
92
+ "dot",
93
+ "dotx",
94
+ "dotm",
95
+ "dsn",
96
+ "dwg",
97
+ "eml",
98
+ "epub",
99
+ "fluidframework",
100
+ "htm",
101
+ "html",
102
+ "loop",
103
+ "markdown",
104
+ "md",
105
+ "msg",
106
+ "odp",
107
+ "ods",
108
+ "odt",
109
+ "pps",
110
+ "ppsx",
111
+ "ppt",
112
+ "pptx",
113
+ "rtf",
114
+ "tif",
115
+ "tiff",
116
+ "xls",
117
+ "xlsm",
118
+ "xlsx",
119
+ ]);
120
+ const CONVERTIBLE_EXTENSIONS = {
121
+ pdf: PDF_CONVERTIBLE_EXTENSIONS,
122
+ };
123
+ const FORMAT_CONTENT_TYPES = {
124
+ pdf: "application/pdf",
125
+ };
126
+ const REDIRECT_STATUSES = new Set([301, 302, 303, 307, 308]);
50
127
  const definition = {
51
128
  name: "m365-graph:download_file",
52
- description: "Download a file from a drive to a local sandbox directory. Returns the local path, not the file content — agents read the file via a filesystem-aware tool. Size is capped at 200 MB. Read-only on the cloud side.",
129
+ description: "Download a file from a drive to a local sandbox directory. Returns the local path, not the file content — agents read the file via a filesystem-aware tool. Size is capped at 200 MB. Optional `format: \"pdf\"` has Microsoft Graph convert the file to PDF server-side (Word, Excel, PowerPoint, OpenDocument, RTF, HTML, Markdown, email, TIFF, …) and saves the PDF instead of the original. Read-only on the cloud side.",
53
130
  inputSchema: {
54
131
  type: "object",
55
132
  properties: {
@@ -61,6 +138,11 @@ const definition = {
61
138
  type: "string",
62
139
  description: "Optional drive ID. Defaults to the user's primary OneDrive.",
63
140
  },
141
+ format: {
142
+ type: "string",
143
+ enum: [...DOWNLOAD_FORMATS],
144
+ description: "Optional server-side conversion. 'pdf' converts the file to PDF in Microsoft Graph and saves it as '<name>.pdf' in the sandbox. Omit to download the original bytes. Unsupported source types (e.g. images other than TIFF, archives, existing PDFs) are rejected with an error.",
145
+ },
64
146
  },
65
147
  required: ["item_id"],
66
148
  },
@@ -85,9 +167,158 @@ export function deriveSafeLocalPath(sandboxRoot, itemId, originalName) {
85
167
  }
86
168
  return resolved;
87
169
  }
170
+ /**
171
+ * Lower-cased extension without the dot, or null when the name has
172
+ * none. A leading dot alone (".profile") is not an extension.
173
+ */
174
+ export function fileExtension(name) {
175
+ const dot = name.lastIndexOf(".");
176
+ if (dot <= 0 || dot === name.length - 1)
177
+ return null;
178
+ return name.slice(dot + 1).toLowerCase();
179
+ }
180
+ /**
181
+ * Throw a caller-actionable error when Graph cannot convert this source
182
+ * type to the requested format. Returns the validated source extension.
183
+ */
184
+ export function checkConvertible(name, format) {
185
+ const ext = fileExtension(name);
186
+ const supported = CONVERTIBLE_EXTENSIONS[format];
187
+ if (ext !== null && supported.has(ext))
188
+ return ext;
189
+ const list = [...supported].join(", ");
190
+ if (ext === format) {
191
+ throw new Error(`'${name}' is already a ${format.toUpperCase()} — call download_file without 'format' to fetch it as-is.`);
192
+ }
193
+ const what = ext === null ? "has no file extension" : `has extension '.${ext}'`;
194
+ throw new Error(`Cannot convert '${name}' to ${format.toUpperCase()}: the file ${what}, which Microsoft Graph does not convert to ${format}. Supported source types: ${list}.`);
195
+ }
196
+ /**
197
+ * Graph path for the converted content of an item. The `format` value
198
+ * comes from the enum constant, never from raw caller input.
199
+ */
200
+ export function buildConvertedContentPath(driveRoot, itemId, format) {
201
+ return `${driveRoot}/items/${encodeURIComponent(itemId)}/content?format=${encodeURIComponent(format)}`;
202
+ }
203
+ /**
204
+ * Local name for a converted file: original stem + `.<format>`. The stem
205
+ * is trimmed so the sanitizer's length cap can never cut the extension.
206
+ */
207
+ export function convertedFilename(originalName, format) {
208
+ const ext = fileExtension(originalName);
209
+ const stem = ext === null ? originalName : originalName.slice(0, -(ext.length + 1));
210
+ const suffix = `.${format}`;
211
+ const trimmed = stem.slice(0, MAX_LOCAL_NAME_CHARS - suffix.length);
212
+ return `${trimmed.length > 0 ? trimmed : "file"}${suffix}`;
213
+ }
214
+ /**
215
+ * Byte-counting pass-through that errors once `limit` is exceeded.
216
+ * `bytes()` reports how many bytes have passed through.
217
+ */
218
+ export function cappedCounter(limit) {
219
+ let seen = 0;
220
+ const stream = new Transform({
221
+ transform(chunk, _enc, cb) {
222
+ seen += chunk.length;
223
+ if (seen > limit) {
224
+ cb(new Error("Converted file exceeds the 200 MB cap. Download aborted."));
225
+ return;
226
+ }
227
+ cb(null, chunk);
228
+ },
229
+ });
230
+ return { stream, bytes: () => seen };
231
+ }
232
+ async function readErrorSummary(raw) {
233
+ let text = "";
234
+ try {
235
+ text = (await raw.text()).slice(0, MAX_ERROR_BODY_CHARS);
236
+ }
237
+ catch {
238
+ return { code: "", detail: "" };
239
+ }
240
+ try {
241
+ const parsed = JSON.parse(text);
242
+ const code = typeof parsed.error?.code === "string" ? parsed.error.code : "";
243
+ const message = typeof parsed.error?.message === "string" ? parsed.error.message : "";
244
+ return { code, detail: [code, message].filter(Boolean).join(": ") };
245
+ }
246
+ catch {
247
+ return { code: "", detail: text.trim().slice(0, 300) };
248
+ }
249
+ }
250
+ /**
251
+ * Whether a failed conversion response is Graph refusing the conversion
252
+ * itself. A 400 counts only on Graph's structured `notSupported` code:
253
+ * the status alone covers any malformed request, and free text such as
254
+ * "Unsupported query option" says nothing about the source file.
255
+ */
256
+ function isConversionRefusal(status, code, detail) {
257
+ if (status === 406 || status === 415)
258
+ return true;
259
+ if (status === 400)
260
+ return code.toLowerCase() === "notsupported";
261
+ return /notSupported|unsupported/i.test(detail);
262
+ }
263
+ /**
264
+ * Request the converted content from Graph and return a response whose
265
+ * body is the converted bytes. Handles Graph's 302-to-pre-authenticated
266
+ * URL contract explicitly; tolerates a direct 200 with the body.
267
+ */
268
+ async function fetchConverted(graph, contentPath, name, sourceExtension, format) {
269
+ const raw = (await graph
270
+ .api(contentPath)
271
+ // Do not let the SDK follow the redirect: we validate the target and
272
+ // fetch it ourselves without the bearer token.
273
+ .middlewareOptions([new RedirectHandlerOptions(0, () => false)])
274
+ .responseType(ResponseType.RAW)
275
+ .get());
276
+ if (REDIRECT_STATUSES.has(raw.status)) {
277
+ const target = validateHttpsUrl(raw.headers.get("location"), "PDF conversion: Graph redirect Location");
278
+ await raw.body?.cancel().catch(() => undefined);
279
+ const converted = await fetch(target);
280
+ if (!converted.ok) {
281
+ throw new Error(`PDF conversion download HTTP ${converted.status}: ${converted.statusText}`);
282
+ }
283
+ return converted;
284
+ }
285
+ if (raw.status === 200)
286
+ return raw;
287
+ const { code, detail } = await readErrorSummary(raw);
288
+ const suffix = detail ? ` (${detail})` : "";
289
+ if (isConversionRefusal(raw.status, code, detail)) {
290
+ throw new Error(`Microsoft Graph could not convert '${name}' to ${format.toUpperCase()}: HTTP ${raw.status}${suffix}. Source extension: '.${sourceExtension}'. The file may be encrypted, corrupt, or of a type Graph cannot convert.`);
291
+ }
292
+ if (raw.status === 400) {
293
+ throw new Error(`PDF conversion HTTP 400${suffix} for '${name}' (source extension '.${sourceExtension}'). This response does not establish that the source type is the cause.`);
294
+ }
295
+ throw new Error(`PDF conversion HTTP ${raw.status}${suffix}`);
296
+ }
297
+ async function writeCapped(response, localPath) {
298
+ const declared = Number(response.headers.get("content-length") ?? NaN);
299
+ if (Number.isFinite(declared) && declared > MAX_FILE_SIZE_BYTES) {
300
+ await response.body?.cancel().catch(() => undefined);
301
+ throw new Error(`Converted file size (${declared} bytes) exceeds the 200 MB cap. Refusing to download.`);
302
+ }
303
+ if (!response.body) {
304
+ throw new Error("Download response has no body stream.");
305
+ }
306
+ const counter = cappedCounter(MAX_FILE_SIZE_BYTES);
307
+ const out = createWriteStream(localPath, { mode: SANDBOX_FILE_MODE });
308
+ try {
309
+ await pipeline(Readable.fromWeb(response.body), counter.stream, out);
310
+ }
311
+ catch (err) {
312
+ // No partial artifact left in the sandbox.
313
+ await rm(localPath, { force: true }).catch(() => undefined);
314
+ throw err;
315
+ }
316
+ return counter.bytes();
317
+ }
88
318
  const handler = async (graph, args) => {
89
319
  const itemId = validateRequiredString(args.item_id, "item_id");
90
320
  const driveId = validateOptionalString(args.drive_id, "drive_id");
321
+ const format = validateOptionalStrictEnum(args.format, "format", DOWNLOAD_FORMATS);
91
322
  const driveRoot = driveId ? `/drives/${encodeURIComponent(driveId)}` : "/me/drive";
92
323
  const item = await graph.api(`${driveRoot}/items/${encodeURIComponent(itemId)}`).get();
93
324
  if (item.folder !== undefined) {
@@ -97,6 +328,31 @@ const handler = async (graph, args) => {
97
328
  if (size > MAX_FILE_SIZE_BYTES) {
98
329
  throw new Error(`File size (${size} bytes) exceeds the 200 MB cap. Refusing to download.`);
99
330
  }
331
+ const itemName = String(item.name ?? "");
332
+ const sourceContentType = item.file?.mimeType ?? null;
333
+ if (format !== undefined) {
334
+ const sourceExtension = checkConvertible(itemName, format);
335
+ const tenantId = process.env.M365_TENANT_ID ?? "unknown";
336
+ const sandboxRoot = getSandboxRoot(tenantId);
337
+ await mkdir(sandboxRoot, { recursive: true, mode: SANDBOX_DIR_MODE });
338
+ const localPath = deriveSafeLocalPath(sandboxRoot, itemId, convertedFilename(itemName, format));
339
+ const response = await fetchConverted(graph, buildConvertedContentPath(driveRoot, itemId, format), itemName, sourceExtension, format);
340
+ const written = await writeCapped(response, localPath);
341
+ const result = {
342
+ item_id: itemId,
343
+ drive_id: driveId ?? null,
344
+ local_path: localPath,
345
+ size_bytes: written,
346
+ name: itemName,
347
+ content_type: FORMAT_CONTENT_TYPES[format],
348
+ format,
349
+ source_size_bytes: size,
350
+ source_content_type: sourceContentType,
351
+ };
352
+ return {
353
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
354
+ };
355
+ }
100
356
  const downloadUrl = item["@microsoft.graph.downloadUrl"];
101
357
  if (!downloadUrl) {
102
358
  throw new Error("No @microsoft.graph.downloadUrl in item metadata — Graph returned an unexpected shape.");
@@ -122,8 +378,9 @@ const handler = async (graph, args) => {
122
378
  drive_id: driveId ?? null,
123
379
  local_path: localPath,
124
380
  size_bytes: size,
125
- name: String(item.name ?? ""),
126
- content_type: item.file?.mimeType ?? null,
381
+ name: itemName,
382
+ content_type: sourceContentType,
383
+ format: null,
127
384
  };
128
385
  return {
129
386
  content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
@@ -1 +1 @@
1
- {"version":3,"file":"download_file.js","sourceRoot":"","sources":["../../src/tools/download_file.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"download_file.js","sourceRoot":"","sources":["../../src/tools/download_file.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiEG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,MAAM,MAAM,aAAa,CAAC;AACjC,OAAO,EAAE,QAAQ,EAAE,SAAS,EAA0B,MAAM,aAAa,CAAC;AAC1E,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAEhD,OAAO,EACL,sBAAsB,EACtB,YAAY,GAEb,MAAM,mCAAmC,CAAC;AAE3C,OAAO,EACL,gBAAgB,EAChB,gBAAgB,EAChB,0BAA0B,EAC1B,sBAAsB,EACtB,sBAAsB,GACvB,MAAM,wBAAwB,CAAC;AAGhC,MAAM,mBAAmB,GAAG,GAAG,GAAG,IAAI,GAAG,IAAI,CAAC,CAAC,2BAA2B;AAC1E,MAAM,gBAAgB,GAAG,KAAK,CAAC;AAC/B,MAAM,iBAAiB,GAAG,KAAK,CAAC;AAChC,qFAAqF;AACrF,MAAM,oBAAoB,GAAG,GAAG,CAAC;AACjC,gFAAgF;AAChF,MAAM,oBAAoB,GAAG,IAAI,CAAC;AAElC,yEAAyE;AACzE,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,KAAK,CAAU,CAAC;AAGjD;;;GAGG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAwB,IAAI,GAAG,CAAC;IACrE,KAAK;IACL,MAAM;IACN,KAAK;IACL,MAAM;IACN,MAAM;IACN,KAAK;IACL,KAAK;IACL,KAAK;IACL,MAAM;IACN,gBAAgB;IAChB,KAAK;IACL,MAAM;IACN,MAAM;IACN,UAAU;IACV,IAAI;IACJ,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,MAAM;IACN,KAAK;IACL,MAAM;IACN,KAAK;IACL,KAAK;IACL,MAAM;IACN,KAAK;IACL,MAAM;IACN,MAAM;CACP,CAAC,CAAC;AAEH,MAAM,sBAAsB,GAAgD;IAC1E,GAAG,EAAE,0BAA0B;CAChC,CAAC;AAEF,MAAM,oBAAoB,GAAmC;IAC3D,GAAG,EAAE,iBAAiB;CACvB,CAAC;AAEF,MAAM,iBAAiB,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;AAE7D,MAAM,UAAU,GAAmB;IACjC,IAAI,EAAE,0BAA0B;IAChC,WAAW,EACT,+ZAA+Z;IACja,WAAW,EAAE;QACX,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACV,OAAO,EAAE;gBACP,IAAI,EAAE,QAAQ;gBACd,WAAW,EACT,wGAAwG;aAC3G;YACD,QAAQ,EAAE;gBACR,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,6DAA6D;aAC3E;YACD,MAAM,EAAE;gBACN,IAAI,EAAE,QAAQ;gBACd,IAAI,EAAE,CAAC,GAAG,gBAAgB,CAAC;gBAC3B,WAAW,EACT,kRAAkR;aACrR;SACF;QACD,QAAQ,EAAE,CAAC,SAAS,CAAC;KACtB;CACF,CAAC;AAEF,MAAM,UAAU,cAAc,CAAC,QAAgB;IAC7C,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC;IAC/C,IAAI,QAAQ;QAAE,OAAO,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IAEtD,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC;IACvC,IAAI,GAAG;QAAE,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,uBAAuB,EAAE,QAAQ,CAAC,CAAC;IAErE,OAAO,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,uBAAuB,EAAE,QAAQ,CAAC,CAAC;AACjF,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,WAAmB,EAAE,MAAc,EAAE,YAAoB;IAC3F,MAAM,QAAQ,GAAG,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACvF,MAAM,IAAI,GAAG,gBAAgB,CAAC,YAAY,CAAC,CAAC;IAC5C,MAAM,QAAQ,GAAG,GAAG,QAAQ,IAAI,IAAI,EAAE,CAAC;IACvC,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;IAErD,mEAAmE;IACnE,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,QAAQ,KAAK,WAAW,EAAE,CAAC;QAC7E,MAAM,IAAI,KAAK,CAAC,sCAAsC,QAAQ,EAAE,CAAC,CAAC;IACpE,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,IAAY;IACxC,MAAM,GAAG,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IAClC,IAAI,GAAG,IAAI,CAAC,IAAI,GAAG,KAAK,IAAI,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IACrD,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;AAC3C,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,IAAY,EAAE,MAAsB;IACnE,MAAM,GAAG,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC;IAChC,MAAM,SAAS,GAAG,sBAAsB,CAAC,MAAM,CAAC,CAAC;IACjD,IAAI,GAAG,KAAK,IAAI,IAAI,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC;QAAE,OAAO,GAAG,CAAC;IAEnD,MAAM,IAAI,GAAG,CAAC,GAAG,SAAS,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACvC,IAAI,GAAG,KAAK,MAAM,EAAE,CAAC;QACnB,MAAM,IAAI,KAAK,CACb,IAAI,IAAI,kBAAkB,MAAM,CAAC,WAAW,EAAE,2DAA2D,CAC1G,CAAC;IACJ,CAAC;IACD,MAAM,IAAI,GAAG,GAAG,KAAK,IAAI,CAAC,CAAC,CAAC,uBAAuB,CAAC,CAAC,CAAC,mBAAmB,GAAG,GAAG,CAAC;IAChF,MAAM,IAAI,KAAK,CACb,mBAAmB,IAAI,QAAQ,MAAM,CAAC,WAAW,EAAE,cAAc,IAAI,+CAA+C,MAAM,6BAA6B,IAAI,GAAG,CAC/J,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,yBAAyB,CACvC,SAAiB,EACjB,MAAc,EACd,MAAsB;IAEtB,OAAO,GAAG,SAAS,UAAU,kBAAkB,CAAC,MAAM,CAAC,mBAAmB,kBAAkB,CAAC,MAAM,CAAC,EAAE,CAAC;AACzG,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,YAAoB,EAAE,MAAsB;IAC5E,MAAM,GAAG,GAAG,aAAa,CAAC,YAAY,CAAC,CAAC;IACxC,MAAM,IAAI,GAAG,GAAG,KAAK,IAAI,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC;IACpF,MAAM,MAAM,GAAG,IAAI,MAAM,EAAE,CAAC;IAC5B,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,oBAAoB,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;IACpE,OAAO,GAAG,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,GAAG,MAAM,EAAE,CAAC;AAC7D,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,KAAa;IACzC,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;QAC3B,SAAS,CAAC,KAAa,EAAE,IAAoB,EAAE,EAAqB;YAClE,IAAI,IAAI,KAAK,CAAC,MAAM,CAAC;YACrB,IAAI,IAAI,GAAG,KAAK,EAAE,CAAC;gBACjB,EAAE,CAAC,IAAI,KAAK,CAAC,0DAA0D,CAAC,CAAC,CAAC;gBAC1E,OAAO;YACT,CAAC;YACD,EAAE,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QAClB,CAAC;KACF,CAAC,CAAC;IACH,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,IAAI,EAAE,CAAC;AACvC,CAAC;AAED,KAAK,UAAU,gBAAgB,CAAC,GAAa;IAC3C,IAAI,IAAI,GAAG,EAAE,CAAC;IACd,IAAI,CAAC;QACH,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,oBAAoB,CAAC,CAAC;IAC3D,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;IAClC,CAAC;IACD,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAsD,CAAC;QACrF,MAAM,IAAI,GAAG,OAAO,MAAM,CAAC,KAAK,EAAE,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;QAC7E,MAAM,OAAO,GAAG,OAAO,MAAM,CAAC,KAAK,EAAE,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;QACtF,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;IACtE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC;IACzD,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,SAAS,mBAAmB,CAAC,MAAc,EAAE,IAAY,EAAE,MAAc;IACvE,IAAI,MAAM,KAAK,GAAG,IAAI,MAAM,KAAK,GAAG;QAAE,OAAO,IAAI,CAAC;IAClD,IAAI,MAAM,KAAK,GAAG;QAAE,OAAO,IAAI,CAAC,WAAW,EAAE,KAAK,cAAc,CAAC;IACjE,OAAO,2BAA2B,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AAClD,CAAC;AAED;;;;GAIG;AACH,KAAK,UAAU,cAAc,CAC3B,KAAa,EACb,WAAmB,EACnB,IAAY,EACZ,eAAuB,EACvB,MAAsB;IAEtB,MAAM,GAAG,GAAG,CAAC,MAAM,KAAK;SACrB,GAAG,CAAC,WAAW,CAAC;QACjB,qEAAqE;QACrE,+CAA+C;SAC9C,iBAAiB,CAAC,CAAC,IAAI,sBAAsB,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;SAC/D,YAAY,CAAC,YAAY,CAAC,GAAG,CAAC;SAC9B,GAAG,EAAE,CAAa,CAAC;IAEtB,IAAI,iBAAiB,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;QACtC,MAAM,MAAM,GAAG,gBAAgB,CAC7B,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,EAC3B,yCAAyC,CAC1C,CAAC;QACF,MAAM,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;QAChD,MAAM,SAAS,GAAG,MAAM,KAAK,CAAC,MAAM,CAAC,CAAC;QACtC,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,CAAC;YAClB,MAAM,IAAI,KAAK,CACb,gCAAgC,SAAS,CAAC,MAAM,KAAK,SAAS,CAAC,UAAU,EAAE,CAC5E,CAAC;QACJ,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG;QAAE,OAAO,GAAG,CAAC;IAEnC,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,gBAAgB,CAAC,GAAG,CAAC,CAAC;IACrD,MAAM,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC,KAAK,MAAM,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;IAC5C,IAAI,mBAAmB,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,EAAE,CAAC;QAClD,MAAM,IAAI,KAAK,CACb,sCAAsC,IAAI,QAAQ,MAAM,CAAC,WAAW,EAAE,UAAU,GAAG,CAAC,MAAM,GAAG,MAAM,yBAAyB,eAAe,2EAA2E,CACvN,CAAC;IACJ,CAAC;IACD,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CACb,0BAA0B,MAAM,SAAS,IAAI,yBAAyB,eAAe,yEAAyE,CAC/J,CAAC;IACJ,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,uBAAuB,GAAG,CAAC,MAAM,GAAG,MAAM,EAAE,CAAC,CAAC;AAChE,CAAC;AAED,KAAK,UAAU,WAAW,CAAC,QAAkB,EAAE,SAAiB;IAC9D,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,IAAI,GAAG,CAAC,CAAC;IACvE,IAAI,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,QAAQ,GAAG,mBAAmB,EAAE,CAAC;QAChE,MAAM,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;QACrD,MAAM,IAAI,KAAK,CACb,wBAAwB,QAAQ,uDAAuD,CACxF,CAAC;IACJ,CAAC;IACD,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;QACnB,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;IAC3D,CAAC;IAED,MAAM,OAAO,GAAG,aAAa,CAAC,mBAAmB,CAAC,CAAC;IACnD,MAAM,GAAG,GAAG,iBAAiB,CAAC,SAAS,EAAE,EAAE,IAAI,EAAE,iBAAiB,EAAE,CAAC,CAAC;IACtE,IAAI,CAAC;QACH,MAAM,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAa,CAAC,EAAE,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAChF,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,2CAA2C;QAC3C,MAAM,EAAE,CAAC,SAAS,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;QAC5D,MAAM,GAAG,CAAC;IACZ,CAAC;IACD,OAAO,OAAO,CAAC,KAAK,EAAE,CAAC;AACzB,CAAC;AAED,MAAM,OAAO,GAAgB,KAAK,EAChC,KAAa,EACb,IAA6B,EACN,EAAE;IACzB,MAAM,MAAM,GAAG,sBAAsB,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;IAC/D,MAAM,OAAO,GAAG,sBAAsB,CAAC,IAAI,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;IAClE,MAAM,MAAM,GAAG,0BAA0B,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,EAAE,gBAAgB,CAAC,CAAC;IAEnF,MAAM,SAAS,GAAG,OAAO,CAAC,CAAC,CAAC,WAAW,kBAAkB,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC;IACnF,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,GAAG,SAAS,UAAU,kBAAkB,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC;IAEvF,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CAAC,QAAQ,MAAM,kDAAkD,CAAC,CAAC;IACpF,CAAC;IAED,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC;IACpC,IAAI,IAAI,GAAG,mBAAmB,EAAE,CAAC;QAC/B,MAAM,IAAI,KAAK,CACb,cAAc,IAAI,uDAAuD,CAC1E,CAAC;IACJ,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;IACzC,MAAM,iBAAiB,GACpB,IAAI,CAAC,IAA4C,EAAE,QAAQ,IAAI,IAAI,CAAC;IAEvE,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QACzB,MAAM,eAAe,GAAG,gBAAgB,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QAE3D,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,SAAS,CAAC;QACzD,MAAM,WAAW,GAAG,cAAc,CAAC,QAAQ,CAAC,CAAC;QAC7C,MAAM,KAAK,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,gBAAgB,EAAE,CAAC,CAAC;QACtE,MAAM,SAAS,GAAG,mBAAmB,CACnC,WAAW,EACX,MAAM,EACN,iBAAiB,CAAC,QAAQ,EAAE,MAAM,CAAC,CACpC,CAAC;QAEF,MAAM,QAAQ,GAAG,MAAM,cAAc,CACnC,KAAK,EACL,yBAAyB,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,CAAC,EACpD,QAAQ,EACR,eAAe,EACf,MAAM,CACP,CAAC;QACF,MAAM,OAAO,GAAG,MAAM,WAAW,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;QAEvD,MAAM,MAAM,GAAG;YACb,OAAO,EAAE,MAAM;YACf,QAAQ,EAAE,OAAO,IAAI,IAAI;YACzB,UAAU,EAAE,SAAS;YACrB,UAAU,EAAE,OAAO;YACnB,IAAI,EAAE,QAAQ;YACd,YAAY,EAAE,oBAAoB,CAAC,MAAM,CAAC;YAC1C,MAAM;YACN,iBAAiB,EAAE,IAAI;YACvB,mBAAmB,EAAE,iBAAiB;SACvC,CAAC;QACF,OAAO;YACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;SACnE,CAAC;IACJ,CAAC;IAED,MAAM,WAAW,GAAG,IAAI,CAAC,8BAA8B,CAAuB,CAAC;IAC/E,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CACb,wFAAwF,CACzF,CAAC;IACJ,CAAC;IAED,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,SAAS,CAAC;IACzD,MAAM,WAAW,GAAG,cAAc,CAAC,QAAQ,CAAC,CAAC;IAC7C,MAAM,KAAK,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,gBAAgB,EAAE,CAAC,CAAC;IAEtE,MAAM,SAAS,GAAG,mBAAmB,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI,IAAI,MAAM,CAAC,CAAC,CAAC;IAExF,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,WAAW,CAAC,CAAC;IAC1C,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CAAC,iBAAiB,QAAQ,CAAC,MAAM,KAAK,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAC;IAC9E,CAAC;IACD,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;QACnB,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;IAC3D,CAAC;IAED,MAAM,GAAG,GAAG,iBAAiB,CAAC,SAAS,EAAE,EAAE,IAAI,EAAE,iBAAiB,EAAE,CAAC,CAAC;IACtE,oEAAoE;IACpE,kEAAkE;IAClE,6DAA6D;IAC7D,MAAM,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAa,CAAC,EAAE,GAAG,CAAC,CAAC;IAE9D,MAAM,MAAM,GAAG;QACb,OAAO,EAAE,MAAM;QACf,QAAQ,EAAE,OAAO,IAAI,IAAI;QACzB,UAAU,EAAE,SAAS;QACrB,UAAU,EAAE,IAAI;QAChB,IAAI,EAAE,QAAQ;QACd,YAAY,EAAE,iBAAiB;QAC/B,MAAM,EAAE,IAAI;KACb,CAAC;IAEF,OAAO;QACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;KACnE,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,gBAAgB,GAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"list_events.d.ts","sourceRoot":"","sources":["../../src/tools/list_events.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AASH,OAAO,KAAK,EAAE,IAAI,EAA6C,MAAM,kBAAkB,CAAC;AAkCxF,UAAU,eAAe;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,UAAU,YAAY;IACpB,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IAC9C,GAAG,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IAC5C,UAAU,EAAE,OAAO,CAAC;IACpB,iBAAiB,EAAE,OAAO,CAAC;IAC3B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,SAAS,EAAE,eAAe,EAAE,CAAC;IAC7B,OAAO,EAAE,MAAM,CAAC;CACjB;AAaD,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,YAAY,CA2B3E;AA0CD,eAAO,MAAM,cAAc,EAAE,IAAgD,CAAC"}
1
+ {"version":3,"file":"list_events.d.ts","sourceRoot":"","sources":["../../src/tools/list_events.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AASH,OAAO,KAAK,EAAE,IAAI,EAA6C,MAAM,kBAAkB,CAAC;AAkCxF,UAAU,eAAe;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,UAAU,YAAY;IACpB,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IAC9C,GAAG,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IAC5C,UAAU,EAAE,OAAO,CAAC;IACpB,iBAAiB,EAAE,OAAO,CAAC;IAC3B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,SAAS,EAAE,eAAe,EAAE,CAAC;IAC7B,OAAO,EAAE,MAAM,CAAC;CACjB;AAaD,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,YAAY,CA2B3E;AA+CD,eAAO,MAAM,cAAc,EAAE,IAAgD,CAAC"}
@@ -98,9 +98,14 @@ const handler = async (graph, args) => {
98
98
  const apiBase = calendarId
99
99
  ? `/me/calendars/${encodeURIComponent(calendarId)}/calendarView`
100
100
  : "/me/calendarView";
101
+ // The SDK joins query values raw. Encode them here, or the '+' of a
102
+ // positive UTC offset reaches Graph as a space.
101
103
  const response = await graph
102
104
  .api(apiBase)
103
- .query({ startDateTime: start, endDateTime: end })
105
+ .query({
106
+ startDateTime: encodeURIComponent(start),
107
+ endDateTime: encodeURIComponent(end),
108
+ })
104
109
  .select("id,subject,bodyPreview,start,end,isAllDay,isOnlineMeeting,location,organizer,attendees,webLink")
105
110
  .top(limit)
106
111
  .orderby("start/dateTime")
@@ -1 +1 @@
1
- {"version":3,"file":"list_events.js","sourceRoot":"","sources":["../../src/tools/list_events.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"list_events.js","sourceRoot":"","sources":["../../src/tools/list_events.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"search_events.d.ts","sourceRoot":"","sources":["../../src/tools/search_events.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AASH,OAAO,KAAK,EAAE,IAAI,EAA6C,MAAM,kBAAkB,CAAC;AA0DxF,eAAO,MAAM,gBAAgB,EAAE,IAAgD,CAAC"}
1
+ {"version":3,"file":"search_events.d.ts","sourceRoot":"","sources":["../../src/tools/search_events.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AASH,OAAO,KAAK,EAAE,IAAI,EAA6C,MAAM,kBAAkB,CAAC;AA4DxF,eAAO,MAAM,gBAAgB,EAAE,IAAgD,CAAC"}
@@ -51,9 +51,11 @@ const handler = async (graph, args) => {
51
51
  });
52
52
  // OData literal-string escape: ' → ''
53
53
  const escapedQuery = query.replace(/'/g, "''");
54
+ // The SDK stores $filter raw. Encode the literal here, or '+', '&' and
55
+ // '#' in the search term corrupt or split the query string.
54
56
  const response = await graph
55
57
  .api("/me/events")
56
- .filter(`contains(subject, '${escapedQuery}')`)
58
+ .filter(`contains(subject, '${encodeURIComponent(escapedQuery)}')`)
57
59
  .top(limit)
58
60
  .get();
59
61
  const items = Array.isArray(response?.value) ? response.value : [];
@@ -1 +1 @@
1
- {"version":3,"file":"search_events.js","sourceRoot":"","sources":["../../src/tools/search_events.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAIH,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EACL,uBAAuB,EACvB,sBAAsB,GACvB,MAAM,wBAAwB,CAAC;AAGhC,MAAM,UAAU,GAAmB;IACjC,IAAI,EAAE,0BAA0B;IAChC,WAAW,EACT,oPAAoP;IACtP,WAAW,EAAE;QACX,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACV,KAAK,EAAE;gBACL,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,mFAAmF;aACjG;YACD,KAAK,EAAE;gBACL,IAAI,EAAE,SAAS;gBACf,OAAO,EAAE,CAAC;gBACV,OAAO,EAAE,EAAE;gBACX,WAAW,EAAE,mDAAmD;aACjE;SACF;QACD,QAAQ,EAAE,CAAC,OAAO,CAAC;KACpB;CACF,CAAC;AAEF,MAAM,OAAO,GAAgB,KAAK,EAChC,KAAa,EACb,IAA6B,EACN,EAAE;IACzB,MAAM,KAAK,GAAG,sBAAsB,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IAC1D,MAAM,KAAK,GAAG,uBAAuB,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,EAAE;QACzD,GAAG,EAAE,CAAC;QACN,GAAG,EAAE,EAAE;QACP,OAAO,EAAE,EAAE;KACZ,CAAC,CAAC;IAEH,sCAAsC;IACtC,MAAM,YAAY,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAE/C,MAAM,QAAQ,GAAG,MAAM,KAAK;SACzB,GAAG,CAAC,YAAY,CAAC;SACjB,MAAM,CAAC,sBAAsB,YAAY,IAAI,CAAC;SAC9C,GAAG,CAAC,KAAK,CAAC;SACV,GAAG,EAAE,CAAC;IAET,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;IACnE,MAAM,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAA0B,EAAE,EAAE,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC;IAE5E,MAAM,MAAM,GAAG;QACb,KAAK;QACL,KAAK,EAAE,MAAM,CAAC,MAAM;QACpB,OAAO,EAAE,MAAM;KAChB,CAAC;IAEF,OAAO;QACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;KACnE,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,gBAAgB,GAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,CAAC"}
1
+ {"version":3,"file":"search_events.js","sourceRoot":"","sources":["../../src/tools/search_events.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAIH,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EACL,uBAAuB,EACvB,sBAAsB,GACvB,MAAM,wBAAwB,CAAC;AAGhC,MAAM,UAAU,GAAmB;IACjC,IAAI,EAAE,0BAA0B;IAChC,WAAW,EACT,oPAAoP;IACtP,WAAW,EAAE;QACX,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACV,KAAK,EAAE;gBACL,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,mFAAmF;aACjG;YACD,KAAK,EAAE;gBACL,IAAI,EAAE,SAAS;gBACf,OAAO,EAAE,CAAC;gBACV,OAAO,EAAE,EAAE;gBACX,WAAW,EAAE,mDAAmD;aACjE;SACF;QACD,QAAQ,EAAE,CAAC,OAAO,CAAC;KACpB;CACF,CAAC;AAEF,MAAM,OAAO,GAAgB,KAAK,EAChC,KAAa,EACb,IAA6B,EACN,EAAE;IACzB,MAAM,KAAK,GAAG,sBAAsB,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IAC1D,MAAM,KAAK,GAAG,uBAAuB,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,EAAE;QACzD,GAAG,EAAE,CAAC;QACN,GAAG,EAAE,EAAE;QACP,OAAO,EAAE,EAAE;KACZ,CAAC,CAAC;IAEH,sCAAsC;IACtC,MAAM,YAAY,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAE/C,uEAAuE;IACvE,4DAA4D;IAC5D,MAAM,QAAQ,GAAG,MAAM,KAAK;SACzB,GAAG,CAAC,YAAY,CAAC;SACjB,MAAM,CAAC,sBAAsB,kBAAkB,CAAC,YAAY,CAAC,IAAI,CAAC;SAClE,GAAG,CAAC,KAAK,CAAC;SACV,GAAG,EAAE,CAAC;IAET,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;IACnE,MAAM,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAA0B,EAAE,EAAE,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC;IAE5E,MAAM,MAAM,GAAG;QACb,KAAK;QACL,KAAK,EAAE,MAAM,CAAC,MAAM;QACpB,OAAO,EAAE,MAAM;KAChB,CAAC;IAEF,OAAO;QACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;KACnE,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,gBAAgB,GAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,CAAC"}
@@ -19,6 +19,18 @@ export declare function validateOptionalInteger(value: unknown, fieldName: strin
19
19
  default: number;
20
20
  }): number;
21
21
  export declare function validateOptionalEnum<T extends string>(value: unknown, fieldName: string, allowed: ReadonlyArray<T>, defaultValue: T): T;
22
+ /**
23
+ * Optional strict enum with no default: absent/null → undefined;
24
+ * anything else must be one of `allowed` exactly (case-sensitive).
25
+ * Used where "unset" has its own meaning (e.g. download_file `format`
26
+ * absent = original bytes), so a default value would be wrong.
27
+ */
28
+ export declare function validateOptionalStrictEnum<T extends string>(value: unknown, fieldName: string, allowed: ReadonlyArray<T>): T | undefined;
29
+ /**
30
+ * Require an absolute https URL (e.g. a server-issued redirect target
31
+ * that will be fetched). Returns the normalized URL string.
32
+ */
33
+ export declare function validateHttpsUrl(value: unknown, label: string): string;
22
34
  /**
23
35
  * Lightweight ISO 8601 date/datetime check. Accepts:
24
36
  * - YYYY-MM-DD
@@ -1 +1 @@
1
- {"version":3,"file":"validators.d.ts","sourceRoot":"","sources":["../../src/types/validators.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAKhF;AAED,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,OAAO,EACd,SAAS,EAAE,MAAM,GAChB,MAAM,GAAG,SAAS,CAGpB;AAED,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,OAAO,EACd,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GACrD,MAAM,CAaR;AAID,wBAAgB,oBAAoB,CAAC,CAAC,SAAS,MAAM,EACnD,KAAK,EAAE,OAAO,EACd,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,aAAa,CAAC,CAAC,CAAC,EACzB,YAAY,EAAE,CAAC,GACd,CAAC,CAQH;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAQjF;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAKrD"}
1
+ {"version":3,"file":"validators.d.ts","sourceRoot":"","sources":["../../src/types/validators.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAKhF;AAED,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,OAAO,EACd,SAAS,EAAE,MAAM,GAChB,MAAM,GAAG,SAAS,CAGpB;AAED,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,OAAO,EACd,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GACrD,MAAM,CAaR;AAID,wBAAgB,oBAAoB,CAAC,CAAC,SAAS,MAAM,EACnD,KAAK,EAAE,OAAO,EACd,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,aAAa,CAAC,CAAC,CAAC,EACzB,YAAY,EAAE,CAAC,GACd,CAAC,CAQH;AAED;;;;;GAKG;AACH,wBAAgB,0BAA0B,CAAC,CAAC,SAAS,MAAM,EACzD,KAAK,EAAE,OAAO,EACd,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,aAAa,CAAC,CAAC,CAAC,GACxB,CAAC,GAAG,SAAS,CAQf;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CActE;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAQjF;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAKrD"}
@@ -42,6 +42,40 @@ export function validateOptionalEnum(value, fieldName, allowed, defaultValue) {
42
42
  }
43
43
  return value;
44
44
  }
45
+ /**
46
+ * Optional strict enum with no default: absent/null → undefined;
47
+ * anything else must be one of `allowed` exactly (case-sensitive).
48
+ * Used where "unset" has its own meaning (e.g. download_file `format`
49
+ * absent = original bytes), so a default value would be wrong.
50
+ */
51
+ export function validateOptionalStrictEnum(value, fieldName, allowed) {
52
+ if (value === undefined || value === null)
53
+ return undefined;
54
+ if (typeof value !== "string" || !allowed.includes(value)) {
55
+ throw new Error(`'${fieldName}' must be one of ${JSON.stringify(allowed)}; got ${JSON.stringify(value)}`);
56
+ }
57
+ return value;
58
+ }
59
+ /**
60
+ * Require an absolute https URL (e.g. a server-issued redirect target
61
+ * that will be fetched). Returns the normalized URL string.
62
+ */
63
+ export function validateHttpsUrl(value, label) {
64
+ if (typeof value !== "string" || value.length === 0) {
65
+ throw new Error(`${label} is missing`);
66
+ }
67
+ let url;
68
+ try {
69
+ url = new URL(value);
70
+ }
71
+ catch {
72
+ throw new Error(`${label} is not an absolute URL`);
73
+ }
74
+ if (url.protocol !== "https:") {
75
+ throw new Error(`${label} must be https; refusing non-https target (${url.protocol})`);
76
+ }
77
+ return url.toString();
78
+ }
45
79
  /**
46
80
  * Lightweight ISO 8601 date/datetime check. Accepts:
47
81
  * - YYYY-MM-DD
@@ -1 +1 @@
1
- {"version":3,"file":"validators.js","sourceRoot":"","sources":["../../src/types/validators.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,MAAM,UAAU,sBAAsB,CAAC,KAAc,EAAE,SAAiB;IACtE,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACpD,MAAM,IAAI,KAAK,CAAC,IAAI,SAAS,8BAA8B,CAAC,CAAC;IAC/D,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,sBAAsB,CACpC,KAAc,EACd,SAAiB;IAEjB,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,SAAS,CAAC;IAC5D,OAAO,sBAAsB,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;AAClD,CAAC;AAED,MAAM,UAAU,uBAAuB,CACrC,KAAc,EACd,SAAiB,EACjB,OAAsD;IAEtD,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,OAAO,CAAC,OAAO,CAAC;IAClE,IACE,OAAO,KAAK,KAAK,QAAQ;QACzB,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC;QACxB,KAAK,GAAG,OAAO,CAAC,GAAG;QACnB,KAAK,GAAG,OAAO,CAAC,GAAG,EACnB,CAAC;QACD,MAAM,IAAI,KAAK,CACb,IAAI,SAAS,gCAAgC,OAAO,CAAC,GAAG,QAAQ,OAAO,CAAC,GAAG,EAAE,CAC9E,CAAC;IACJ,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,mBAAmB,GAAG,0EAA0E,CAAC;AAEvG,MAAM,UAAU,oBAAoB,CAClC,KAAc,EACd,SAAiB,EACjB,OAAyB,EACzB,YAAe;IAEf,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,YAAY,CAAC;IAC/D,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAE,OAAiC,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QACrF,MAAM,IAAI,KAAK,CACb,IAAI,SAAS,oBAAoB,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,SAAS,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CACzF,CAAC;IACJ,CAAC;IACD,OAAO,KAAU,CAAC;AACpB,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,uBAAuB,CAAC,KAAc,EAAE,SAAiB;IACvE,MAAM,CAAC,GAAG,sBAAsB,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;IACnD,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;QACjC,MAAM,IAAI,KAAK,CACb,IAAI,SAAS,6FAA6F,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAC9H,CAAC;IACJ,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,gBAAgB,CAAC,IAAY;IAC3C,OAAO,IAAI;SACR,OAAO,CAAC,UAAU,EAAE,GAAG,CAAC;SACxB,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,kBAAkB;SACvC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;AACnB,CAAC"}
1
+ {"version":3,"file":"validators.js","sourceRoot":"","sources":["../../src/types/validators.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@juvantlabs/m365-graph-mcp-server",
3
- "version": "0.4.1",
3
+ "version": "0.5.0",
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"