@juvantlabs/m365-graph-mcp-server 0.4.1 → 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 +2 -2
- package/CHANGELOG.md +103 -2
- package/dist/auth/msal.d.ts +28 -2
- package/dist/auth/msal.d.ts.map +1 -1
- package/dist/auth/msal.js +35 -1
- package/dist/auth/msal.js.map +1 -1
- package/dist/auth/setup.d.ts.map +1 -1
- package/dist/auth/setup.js +3 -11
- package/dist/auth/setup.js.map +1 -1
- package/package.json +11 -10
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.
|
|
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` | `^
|
|
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,104 @@ project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
|
11
11
|
|
|
12
12
|
## [Unreleased]
|
|
13
13
|
|
|
14
|
-
## [0.4.
|
|
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
|
|
15
112
|
|
|
16
113
|
> Release-hygiene note: `[0.4.0]` was tag-published on 2026-06-26 from
|
|
17
114
|
> commit `5235c78`. Three subsequent PRs (#9, #11, #12) merged to `main`
|
|
@@ -479,7 +576,11 @@ the Juvant OS instance level — see juvant-os-pm FEAT-018 / 019 /
|
|
|
479
576
|
|
|
480
577
|
---
|
|
481
578
|
|
|
482
|
-
[Unreleased]: https://github.com/juvantlabs/m365-graph-mcp-server/compare/v0.3
|
|
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
|
|
483
584
|
[0.3.0]: https://github.com/juvantlabs/m365-graph-mcp-server/compare/v0.2.1...v0.3.0
|
|
484
585
|
[0.2.1]: https://github.com/juvantlabs/m365-graph-mcp-server/compare/v0.2.0...v0.2.1
|
|
485
586
|
[0.2.0]: https://github.com/juvantlabs/m365-graph-mcp-server/compare/v0.1.4...v0.2.0
|
package/dist/auth/msal.d.ts
CHANGED
|
@@ -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
|
-
|
|
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
|
package/dist/auth/msal.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"msal.d.ts","sourceRoot":"","sources":["../../src/auth/msal.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EACL,6BAA6B,
|
|
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
|
}
|
package/dist/auth/msal.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"msal.js","sourceRoot":"","sources":["../../src/auth/msal.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EACL,6BAA6B,
|
|
1
|
+
{"version":3,"file":"msal.js","sourceRoot":"","sources":["../../src/auth/msal.ts"],"names":[],"mappings":"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"}
|
package/dist/auth/setup.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../src/auth/setup.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;
|
|
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"}
|
package/dist/auth/setup.js
CHANGED
|
@@ -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 {
|
|
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
|
}
|
package/dist/auth/setup.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"setup.js","sourceRoot":"","sources":["../../src/auth/setup.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAC1C,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAE/B,OAAO,
|
|
1
|
+
{"version":3,"file":"setup.js","sourceRoot":"","sources":["../../src/auth/setup.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.
|
|
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": "^
|
|
38
|
+
"@azure/msal-node": "^7.1.2",
|
|
39
39
|
"@microsoft/microsoft-graph-client": "^3.0.7",
|
|
40
|
-
"@modelcontextprotocol/sdk": "^1.
|
|
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.
|
|
51
|
-
"@typescript-eslint/parser": "^8.
|
|
52
|
-
"@vitest/coverage-v8": "^
|
|
53
|
-
"eslint": "^
|
|
54
|
-
"tsx": "^4.
|
|
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": "^
|
|
57
|
+
"vitest": "^4.1.12"
|
|
57
58
|
},
|
|
58
59
|
"publishConfig": {
|
|
59
60
|
"access": "public"
|