@softeria/ms-365-mcp-server 0.118.0 → 0.118.2
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/README.md +1 -1
- package/dist/auth.js +20 -4
- package/dist/lib/log-redactor.js +10 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -584,7 +584,7 @@ Environment variables:
|
|
|
584
584
|
- `SILENT=true|1`: Disable console output
|
|
585
585
|
- `MS365_MCP_REDACT_PII=true|1`: Scrub JWTs, Bearer headers, OAuth token fields, and email addresses from log messages before they are written (default: disabled). Useful when logs are shipped to a central store or shared host.
|
|
586
586
|
- `MS365_MCP_CLIENT_ID`: Custom Azure app client ID (defaults to built-in app)
|
|
587
|
-
- `MS365_MCP_TENANT_ID`: Custom tenant ID (defaults to 'common' for multi-tenant)
|
|
587
|
+
- `MS365_MCP_TENANT_ID`: Custom tenant ID (defaults to 'common' for multi-tenant). **Personal Microsoft accounts should set this to `consumers`** - as of June 2026, refresh tokens issued via the default 'common' authority are rejected at the first refresh, so sessions die roughly an hour after login
|
|
588
588
|
- `MS365_MCP_OAUTH_TOKEN`: Pre-existing OAuth token for Microsoft Graph API (BYOT method)
|
|
589
589
|
- `MS365_MCP_KEYVAULT_URL`: Azure Key Vault URL for secrets management (see Azure Key Vault section)
|
|
590
590
|
- `MS365_MCP_TOKEN_CACHE_PATH`: Custom file path for MSAL token cache (see Token Storage below)
|
package/dist/auth.js
CHANGED
|
@@ -243,6 +243,13 @@ function describeAuthError(error) {
|
|
|
243
243
|
}
|
|
244
244
|
return error.message;
|
|
245
245
|
}
|
|
246
|
+
const MSA_HOME_TENANT_ID = "9188040d-6c67-4c5b-b112-36a304b66dad";
|
|
247
|
+
function consumersAuthorityHint(error, account, authority) {
|
|
248
|
+
if (error instanceof AuthError && error.errorCode === "invalid_grant" && account?.tenantId === MSA_HOME_TENANT_ID && (!authority || /\/common\/?$/i.test(authority))) {
|
|
249
|
+
return `This looks like a known issue (June 2026) where Microsoft rejects refresh tokens issued to personal accounts via the default 'common' authority. If this server is used only with personal accounts, set MS365_MCP_TENANT_ID=consumers and re-login with: --login`;
|
|
250
|
+
}
|
|
251
|
+
return null;
|
|
252
|
+
}
|
|
246
253
|
class AuthManager {
|
|
247
254
|
constructor(config, scopes = [], expectedAccount, storage) {
|
|
248
255
|
logger.info(`And scopes are ${scopes.join(", ")}`, scopes);
|
|
@@ -459,8 +466,13 @@ class AuthManager {
|
|
|
459
466
|
await this.saveTokenCache();
|
|
460
467
|
return this.accessToken;
|
|
461
468
|
} catch (error) {
|
|
462
|
-
|
|
463
|
-
|
|
469
|
+
const hint = consumersAuthorityHint(error, currentAccount, this.config.auth.authority);
|
|
470
|
+
logger.error(
|
|
471
|
+
`Silent token acquisition failed: ${describeAuthError(error)}${hint ? ` ${hint}` : ""}`
|
|
472
|
+
);
|
|
473
|
+
throw new Error(
|
|
474
|
+
hint ? `Silent token acquisition failed. ${hint}` : "Silent token acquisition failed"
|
|
475
|
+
);
|
|
464
476
|
}
|
|
465
477
|
}
|
|
466
478
|
throw new Error("No valid token found");
|
|
@@ -774,9 +786,12 @@ class AuthManager {
|
|
|
774
786
|
await this.saveTokenCache();
|
|
775
787
|
return response.accessToken;
|
|
776
788
|
} catch (error) {
|
|
777
|
-
|
|
789
|
+
const hint = consumersAuthorityHint(error, targetAccount, this.config.auth.authority);
|
|
790
|
+
logger.error(
|
|
791
|
+
`Silent token acquisition failed: ${describeAuthError(error)}${hint ? ` ${hint}` : ""}`
|
|
792
|
+
);
|
|
778
793
|
throw new Error(
|
|
779
|
-
`Failed to acquire token for account '${targetAccount.username || targetAccount.name || "unknown"}'. The token may have expired. Please re-login with: --login
|
|
794
|
+
`Failed to acquire token for account '${targetAccount.username || targetAccount.name || "unknown"}'. ` + (hint ?? "The token may have expired. Please re-login with: --login")
|
|
780
795
|
);
|
|
781
796
|
}
|
|
782
797
|
}
|
|
@@ -787,6 +802,7 @@ export {
|
|
|
787
802
|
buildScopeDiagnostics,
|
|
788
803
|
buildScopesFromEndpoints,
|
|
789
804
|
collapseScopeHierarchy,
|
|
805
|
+
consumersAuthorityHint,
|
|
790
806
|
auth_default as default,
|
|
791
807
|
describeAuthError,
|
|
792
808
|
getEndpointRequiredScopes,
|
package/dist/lib/log-redactor.js
CHANGED
|
@@ -10,9 +10,17 @@ const REDACTIONS = [
|
|
|
10
10
|
replacement: "$1[REDACTED]"
|
|
11
11
|
},
|
|
12
12
|
// OAuth token fields in query strings or JSON bodies:
|
|
13
|
-
// refresh_token=..., "access_token": "...",
|
|
13
|
+
// refresh_token=..., "access_token": "...", client_secret=...
|
|
14
|
+
// The \b keeps composite keys like `statusCode` from matching via a substring.
|
|
14
15
|
{
|
|
15
|
-
pattern: /(["']
|
|
16
|
+
pattern: /(["']?\b(?:refresh_token|access_token|id_token|client_secret|assertion)["']?\s*[=:]\s*["']?)[A-Za-z0-9._~+/-]+=*/gi,
|
|
17
|
+
replacement: "$1[REDACTED]"
|
|
18
|
+
},
|
|
19
|
+
// OAuth authorization codes, query-string form only (?code=... / &code=...).
|
|
20
|
+
// `code:` in JSON or prose is an error/status code (ECONNRESET, AADSTS...),
|
|
21
|
+
// which must stay readable for diagnostics.
|
|
22
|
+
{
|
|
23
|
+
pattern: /([?&]code=)[^&\s"']+/gi,
|
|
16
24
|
replacement: "$1[REDACTED]"
|
|
17
25
|
},
|
|
18
26
|
// Email addresses / UPNs
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@softeria/ms-365-mcp-server",
|
|
3
|
-
"version": "0.118.
|
|
3
|
+
"version": "0.118.2",
|
|
4
4
|
"description": " A Model Context Protocol (MCP) server for interacting with Microsoft 365 and Office services through the Graph API",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|