@softeria/ms-365-mcp-server 0.114.3 → 0.114.4
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/dist/auth-tools.js +3 -1
- package/dist/auth.js +5 -0
- package/dist/graph-tools.js +24 -1
- package/dist/server.js +17 -10
- package/package.json +1 -1
package/dist/auth-tools.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
+
import { getRequestTokens } from "./request-context.js";
|
|
2
3
|
function registerAuthTools(server, authManager) {
|
|
3
4
|
server.tool(
|
|
4
5
|
"login",
|
|
@@ -121,6 +122,7 @@ function registerAuthTools(server, authManager) {
|
|
|
121
122
|
const accounts = await authManager.listAccounts();
|
|
122
123
|
const selectedAccountId = authManager.getSelectedAccountId();
|
|
123
124
|
const pinnedMode = authManager.hasExpectedAccount();
|
|
125
|
+
const oauthBearerMode = authManager.isOAuthModeEnabled() || Boolean(getRequestTokens());
|
|
124
126
|
const result = accounts.map((account) => ({
|
|
125
127
|
email: account.username || "unknown",
|
|
126
128
|
name: account.name,
|
|
@@ -133,7 +135,7 @@ function registerAuthTools(server, authManager) {
|
|
|
133
135
|
text: JSON.stringify({
|
|
134
136
|
accounts: result,
|
|
135
137
|
count: result.length,
|
|
136
|
-
tip: pinnedMode ? "Expected account pinning is configured; account parameters are disabled." : "Pass the 'email' value as the 'account' parameter in any tool call to target a specific account."
|
|
138
|
+
tip: pinnedMode ? "Expected account pinning is configured; account parameters are disabled." : oauthBearerMode ? "This server is in HTTP/OAuth mode: every request uses the identity of the connecting client's bearer token. The cached accounts listed here cannot be targeted via the 'account' parameter; reconnect the MCP client as the desired account instead." : "Pass the 'email' value as the 'account' parameter in any tool call to target a specific account."
|
|
137
139
|
})
|
|
138
140
|
}
|
|
139
141
|
]
|
package/dist/auth.js
CHANGED
|
@@ -718,6 +718,11 @@ class AuthManager {
|
|
|
718
718
|
*/
|
|
719
719
|
async getTokenForAccount(identifier) {
|
|
720
720
|
if (this.isOAuthMode && this.oauthToken) {
|
|
721
|
+
if (identifier) {
|
|
722
|
+
throw new Error(
|
|
723
|
+
`Cannot switch to account '${identifier}': the server is in OAuth mode and always uses the identity of the supplied bearer token. Account switching requires stdio mode (or HTTP with --trust-proxy-auth).`
|
|
724
|
+
);
|
|
725
|
+
}
|
|
721
726
|
return this.oauthToken;
|
|
722
727
|
}
|
|
723
728
|
let targetAccount = null;
|
package/dist/graph-tools.js
CHANGED
|
@@ -46,6 +46,15 @@ function formatDisabledToolsForLog(disabledTools) {
|
|
|
46
46
|
const suffix = disabledTools.length > shown.length ? `, ... +${disabledTools.length - shown.length} more` : "";
|
|
47
47
|
return `${shown.join("; ")}${suffix}`;
|
|
48
48
|
}
|
|
49
|
+
async function checkAccountParamInBearerMode(accountParam, authManager) {
|
|
50
|
+
if (!accountParam || !authManager) return null;
|
|
51
|
+
const contextToken = getRequestTokens()?.accessToken;
|
|
52
|
+
if (!contextToken && !authManager.isOAuthModeEnabled()) return null;
|
|
53
|
+
const bearerToken = contextToken ?? await authManager.getToken().catch(() => null) ?? void 0;
|
|
54
|
+
const bearerIdentity = getUserIdentityForAudit(bearerToken);
|
|
55
|
+
if (bearerIdentity && bearerIdentity.toLowerCase() === accountParam.toLowerCase()) return null;
|
|
56
|
+
return `The 'account' parameter is not supported in HTTP/OAuth mode: every request uses the identity of the connecting client's bearer token` + (bearerIdentity ? ` ('${bearerIdentity}')` : "") + `, so account switching is not possible. To act as '${accountParam}', reconnect the MCP client authenticated as that account, or run the server in stdio mode (or HTTP with --trust-proxy-auth) where cached accounts are available.`;
|
|
57
|
+
}
|
|
49
58
|
const UTILITY_TOOLS = [
|
|
50
59
|
{
|
|
51
60
|
name: "parse-teams-url",
|
|
@@ -124,6 +133,13 @@ const UTILITY_TOOLS = [
|
|
|
124
133
|
};
|
|
125
134
|
}
|
|
126
135
|
try {
|
|
136
|
+
const accountModeError = await checkAccountParamInBearerMode(accountParam, authManager);
|
|
137
|
+
if (accountModeError) {
|
|
138
|
+
return {
|
|
139
|
+
content: [{ type: "text", text: JSON.stringify({ error: accountModeError }) }],
|
|
140
|
+
isError: true
|
|
141
|
+
};
|
|
142
|
+
}
|
|
127
143
|
let accountAccessToken;
|
|
128
144
|
if (authManager && !authManager.isOAuthModeEnabled() && !getRequestTokens()) {
|
|
129
145
|
accountAccessToken = await authManager.getTokenForAccount(accountParam);
|
|
@@ -158,9 +174,16 @@ async function executeGraphTool(tool, config, graphClient, params, authManager)
|
|
|
158
174
|
const upn = getUserIdentityForAudit(getRequestTokens()?.accessToken);
|
|
159
175
|
const httpMethod = tool.method.toUpperCase();
|
|
160
176
|
try {
|
|
177
|
+
const accountParam = params.account;
|
|
178
|
+
const accountModeError = await checkAccountParamInBearerMode(accountParam, authManager);
|
|
179
|
+
if (accountModeError) {
|
|
180
|
+
return {
|
|
181
|
+
content: [{ type: "text", text: JSON.stringify({ error: accountModeError }) }],
|
|
182
|
+
isError: true
|
|
183
|
+
};
|
|
184
|
+
}
|
|
161
185
|
let accountAccessToken;
|
|
162
186
|
if (authManager && !authManager.isOAuthModeEnabled() && !getRequestTokens()) {
|
|
163
|
-
const accountParam = params.account;
|
|
164
187
|
try {
|
|
165
188
|
accountAccessToken = await authManager.getTokenForAccount(accountParam);
|
|
166
189
|
} catch (err) {
|
package/dist/server.js
CHANGED
|
@@ -105,17 +105,24 @@ class MicrosoftGraphServer {
|
|
|
105
105
|
async initialize(version) {
|
|
106
106
|
this.secrets = await getSecrets();
|
|
107
107
|
this.version = version;
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
108
|
+
const accountRoutingAvailable = (!this.options.http || this.options.trustProxyAuth) && !this.authManager.isOAuthModeEnabled();
|
|
109
|
+
if (accountRoutingAvailable) {
|
|
110
|
+
try {
|
|
111
|
+
this.multiAccount = await this.authManager.isMultiAccount();
|
|
112
|
+
if (this.multiAccount) {
|
|
113
|
+
const accounts = await this.authManager.listAccounts();
|
|
114
|
+
this.accountNames = accounts.map((a) => a.username).filter((u) => !!u);
|
|
115
|
+
logger.info(
|
|
116
|
+
`Multi-account mode detected (${this.accountNames.length} accounts): "account" parameter will be injected into all tool schemas`
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
} catch (err) {
|
|
120
|
+
logger.warn(`Failed to detect multi-account mode: ${err.message}`);
|
|
116
121
|
}
|
|
117
|
-
}
|
|
118
|
-
logger.
|
|
122
|
+
} else {
|
|
123
|
+
logger.info(
|
|
124
|
+
'Account routing disabled: requests use the OAuth bearer identity, so the "account" parameter is not injected into tool schemas'
|
|
125
|
+
);
|
|
119
126
|
}
|
|
120
127
|
if (this.options.obo) {
|
|
121
128
|
if (!this.options.http) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@softeria/ms-365-mcp-server",
|
|
3
|
-
"version": "0.114.
|
|
3
|
+
"version": "0.114.4",
|
|
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",
|