@softeria/ms-365-mcp-server 0.11.1 → 0.11.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/dist/auth-tools.js +104 -0
- package/dist/auth.js +155 -9
- package/dist/cli.js +3 -0
- package/dist/graph-client.js +48 -14
- package/dist/index.js +34 -0
- package/package.json +1 -1
- package/dist/endpoints.json +0 -490
package/dist/auth-tools.js
CHANGED
|
@@ -77,4 +77,108 @@ export function registerAuthTools(server, authManager) {
|
|
|
77
77
|
],
|
|
78
78
|
};
|
|
79
79
|
});
|
|
80
|
+
server.tool('list-accounts', {}, async () => {
|
|
81
|
+
try {
|
|
82
|
+
const accounts = await authManager.listAccounts();
|
|
83
|
+
const selectedAccountId = authManager.getSelectedAccountId();
|
|
84
|
+
const result = accounts.map(account => ({
|
|
85
|
+
id: account.homeAccountId,
|
|
86
|
+
username: account.username,
|
|
87
|
+
name: account.name,
|
|
88
|
+
selected: account.homeAccountId === selectedAccountId
|
|
89
|
+
}));
|
|
90
|
+
return {
|
|
91
|
+
content: [
|
|
92
|
+
{
|
|
93
|
+
type: 'text',
|
|
94
|
+
text: JSON.stringify({ accounts: result }),
|
|
95
|
+
},
|
|
96
|
+
],
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
catch (error) {
|
|
100
|
+
return {
|
|
101
|
+
content: [
|
|
102
|
+
{
|
|
103
|
+
type: 'text',
|
|
104
|
+
text: JSON.stringify({ error: `Failed to list accounts: ${error.message}` }),
|
|
105
|
+
},
|
|
106
|
+
],
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
server.tool('select-account', {
|
|
111
|
+
accountId: z.string().describe('The account ID to select'),
|
|
112
|
+
}, async ({ accountId }) => {
|
|
113
|
+
try {
|
|
114
|
+
const success = await authManager.selectAccount(accountId);
|
|
115
|
+
if (success) {
|
|
116
|
+
return {
|
|
117
|
+
content: [
|
|
118
|
+
{
|
|
119
|
+
type: 'text',
|
|
120
|
+
text: JSON.stringify({ message: `Selected account: ${accountId}` }),
|
|
121
|
+
},
|
|
122
|
+
],
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
return {
|
|
127
|
+
content: [
|
|
128
|
+
{
|
|
129
|
+
type: 'text',
|
|
130
|
+
text: JSON.stringify({ error: `Account not found: ${accountId}` }),
|
|
131
|
+
},
|
|
132
|
+
],
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
catch (error) {
|
|
137
|
+
return {
|
|
138
|
+
content: [
|
|
139
|
+
{
|
|
140
|
+
type: 'text',
|
|
141
|
+
text: JSON.stringify({ error: `Failed to select account: ${error.message}` }),
|
|
142
|
+
},
|
|
143
|
+
],
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
});
|
|
147
|
+
server.tool('remove-account', {
|
|
148
|
+
accountId: z.string().describe('The account ID to remove'),
|
|
149
|
+
}, async ({ accountId }) => {
|
|
150
|
+
try {
|
|
151
|
+
const success = await authManager.removeAccount(accountId);
|
|
152
|
+
if (success) {
|
|
153
|
+
return {
|
|
154
|
+
content: [
|
|
155
|
+
{
|
|
156
|
+
type: 'text',
|
|
157
|
+
text: JSON.stringify({ message: `Removed account: ${accountId}` }),
|
|
158
|
+
},
|
|
159
|
+
],
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
else {
|
|
163
|
+
return {
|
|
164
|
+
content: [
|
|
165
|
+
{
|
|
166
|
+
type: 'text',
|
|
167
|
+
text: JSON.stringify({ error: `Account not found: ${accountId}` }),
|
|
168
|
+
},
|
|
169
|
+
],
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
catch (error) {
|
|
174
|
+
return {
|
|
175
|
+
content: [
|
|
176
|
+
{
|
|
177
|
+
type: 'text',
|
|
178
|
+
text: JSON.stringify({ error: `Failed to remove account: ${error.message}` }),
|
|
179
|
+
},
|
|
180
|
+
],
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
});
|
|
80
184
|
}
|
package/dist/auth.js
CHANGED
|
@@ -4,13 +4,18 @@ import { fileURLToPath } from 'url';
|
|
|
4
4
|
import path from 'path';
|
|
5
5
|
import fs from 'fs';
|
|
6
6
|
import logger from './logger.js';
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
8
|
+
const __dirname = path.dirname(__filename);
|
|
9
|
+
const endpointsPath = path.join(__dirname, 'endpoints.json');
|
|
10
|
+
const endpoints = {
|
|
11
|
+
default: JSON.parse(fs.readFileSync(endpointsPath, 'utf8')),
|
|
12
|
+
};
|
|
10
13
|
const SERVICE_NAME = 'ms-365-mcp-server';
|
|
11
14
|
const TOKEN_CACHE_ACCOUNT = 'msal-token-cache';
|
|
15
|
+
const SELECTED_ACCOUNT_KEY = 'selected-account';
|
|
12
16
|
const FALLBACK_DIR = path.dirname(fileURLToPath(import.meta.url));
|
|
13
17
|
const FALLBACK_PATH = path.join(FALLBACK_DIR, '..', '.token-cache.json');
|
|
18
|
+
const SELECTED_ACCOUNT_PATH = path.join(FALLBACK_DIR, '..', '.selected-account.json');
|
|
14
19
|
const DEFAULT_CONFIG = {
|
|
15
20
|
auth: {
|
|
16
21
|
clientId: process.env.MS365_MCP_CLIENT_ID || '084a3e9f-a9f4-43f7-89f9-d229cf97853e',
|
|
@@ -53,6 +58,7 @@ class AuthManager {
|
|
|
53
58
|
this.msalApp = new PublicClientApplication(this.config);
|
|
54
59
|
this.accessToken = null;
|
|
55
60
|
this.tokenExpiry = null;
|
|
61
|
+
this.selectedAccountId = null;
|
|
56
62
|
const oauthTokenFromEnv = process.env.MS365_MCP_OAUTH_TOKEN;
|
|
57
63
|
this.oauthToken = oauthTokenFromEnv ?? null;
|
|
58
64
|
this.isOAuthMode = oauthTokenFromEnv != null;
|
|
@@ -75,11 +81,38 @@ class AuthManager {
|
|
|
75
81
|
if (cacheData) {
|
|
76
82
|
this.msalApp.getTokenCache().deserialize(cacheData);
|
|
77
83
|
}
|
|
84
|
+
// Load selected account
|
|
85
|
+
await this.loadSelectedAccount();
|
|
78
86
|
}
|
|
79
87
|
catch (error) {
|
|
80
88
|
logger.error(`Error loading token cache: ${error.message}`);
|
|
81
89
|
}
|
|
82
90
|
}
|
|
91
|
+
async loadSelectedAccount() {
|
|
92
|
+
try {
|
|
93
|
+
let selectedAccountData;
|
|
94
|
+
try {
|
|
95
|
+
const cachedData = await keytar.getPassword(SERVICE_NAME, SELECTED_ACCOUNT_KEY);
|
|
96
|
+
if (cachedData) {
|
|
97
|
+
selectedAccountData = cachedData;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
catch (keytarError) {
|
|
101
|
+
logger.warn(`Keychain access failed for selected account, falling back to file storage: ${keytarError.message}`);
|
|
102
|
+
}
|
|
103
|
+
if (!selectedAccountData && fs.existsSync(SELECTED_ACCOUNT_PATH)) {
|
|
104
|
+
selectedAccountData = fs.readFileSync(SELECTED_ACCOUNT_PATH, 'utf8');
|
|
105
|
+
}
|
|
106
|
+
if (selectedAccountData) {
|
|
107
|
+
const parsed = JSON.parse(selectedAccountData);
|
|
108
|
+
this.selectedAccountId = parsed.accountId;
|
|
109
|
+
logger.info(`Loaded selected account: ${this.selectedAccountId}`);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
catch (error) {
|
|
113
|
+
logger.error(`Error loading selected account: ${error.message}`);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
83
116
|
async saveTokenCache() {
|
|
84
117
|
try {
|
|
85
118
|
const cacheData = this.msalApp.getTokenCache().serialize();
|
|
@@ -95,6 +128,21 @@ class AuthManager {
|
|
|
95
128
|
logger.error(`Error saving token cache: ${error.message}`);
|
|
96
129
|
}
|
|
97
130
|
}
|
|
131
|
+
async saveSelectedAccount() {
|
|
132
|
+
try {
|
|
133
|
+
const selectedAccountData = JSON.stringify({ accountId: this.selectedAccountId });
|
|
134
|
+
try {
|
|
135
|
+
await keytar.setPassword(SERVICE_NAME, SELECTED_ACCOUNT_KEY, selectedAccountData);
|
|
136
|
+
}
|
|
137
|
+
catch (keytarError) {
|
|
138
|
+
logger.warn(`Keychain save failed for selected account, falling back to file storage: ${keytarError.message}`);
|
|
139
|
+
fs.writeFileSync(SELECTED_ACCOUNT_PATH, selectedAccountData);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
catch (error) {
|
|
143
|
+
logger.error(`Error saving selected account: ${error.message}`);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
98
146
|
async setOAuthToken(token) {
|
|
99
147
|
this.oauthToken = token;
|
|
100
148
|
this.isOAuthMode = true;
|
|
@@ -106,10 +154,10 @@ class AuthManager {
|
|
|
106
154
|
if (this.accessToken && this.tokenExpiry && this.tokenExpiry > Date.now() && !forceRefresh) {
|
|
107
155
|
return this.accessToken;
|
|
108
156
|
}
|
|
109
|
-
const
|
|
110
|
-
if (
|
|
157
|
+
const currentAccount = await this.getCurrentAccount();
|
|
158
|
+
if (currentAccount) {
|
|
111
159
|
const silentRequest = {
|
|
112
|
-
account:
|
|
160
|
+
account: currentAccount,
|
|
113
161
|
scopes: this.scopes,
|
|
114
162
|
};
|
|
115
163
|
try {
|
|
@@ -125,6 +173,22 @@ class AuthManager {
|
|
|
125
173
|
}
|
|
126
174
|
throw new Error('No valid token found');
|
|
127
175
|
}
|
|
176
|
+
async getCurrentAccount() {
|
|
177
|
+
const accounts = await this.msalApp.getTokenCache().getAllAccounts();
|
|
178
|
+
if (accounts.length === 0) {
|
|
179
|
+
return null;
|
|
180
|
+
}
|
|
181
|
+
// If a specific account is selected, find it
|
|
182
|
+
if (this.selectedAccountId) {
|
|
183
|
+
const selectedAccount = accounts.find((account) => account.homeAccountId === this.selectedAccountId);
|
|
184
|
+
if (selectedAccount) {
|
|
185
|
+
return selectedAccount;
|
|
186
|
+
}
|
|
187
|
+
logger.warn(`Selected account ${this.selectedAccountId} not found, falling back to first account`);
|
|
188
|
+
}
|
|
189
|
+
// Fall back to first account (backward compatibility)
|
|
190
|
+
return accounts[0];
|
|
191
|
+
}
|
|
128
192
|
async acquireTokenByDeviceCode(hack) {
|
|
129
193
|
const deviceCodeRequest = {
|
|
130
194
|
scopes: this.scopes,
|
|
@@ -147,6 +211,12 @@ class AuthManager {
|
|
|
147
211
|
logger.info('Device code login successful');
|
|
148
212
|
this.accessToken = response?.accessToken || null;
|
|
149
213
|
this.tokenExpiry = response?.expiresOn ? new Date(response.expiresOn).getTime() : null;
|
|
214
|
+
// Set the newly authenticated account as selected if no account is currently selected
|
|
215
|
+
if (!this.selectedAccountId && response?.account) {
|
|
216
|
+
this.selectedAccountId = response.account.homeAccountId;
|
|
217
|
+
await this.saveSelectedAccount();
|
|
218
|
+
logger.info(`Auto-selected new account: ${response.account.username}`);
|
|
219
|
+
}
|
|
150
220
|
await this.saveTokenCache();
|
|
151
221
|
return this.accessToken;
|
|
152
222
|
}
|
|
@@ -218,8 +288,10 @@ class AuthManager {
|
|
|
218
288
|
}
|
|
219
289
|
this.accessToken = null;
|
|
220
290
|
this.tokenExpiry = null;
|
|
291
|
+
this.selectedAccountId = null;
|
|
221
292
|
try {
|
|
222
293
|
await keytar.deletePassword(SERVICE_NAME, TOKEN_CACHE_ACCOUNT);
|
|
294
|
+
await keytar.deletePassword(SERVICE_NAME, SELECTED_ACCOUNT_KEY);
|
|
223
295
|
}
|
|
224
296
|
catch (keytarError) {
|
|
225
297
|
logger.warn(`Keychain deletion failed: ${keytarError.message}`);
|
|
@@ -227,6 +299,9 @@ class AuthManager {
|
|
|
227
299
|
if (fs.existsSync(FALLBACK_PATH)) {
|
|
228
300
|
fs.unlinkSync(FALLBACK_PATH);
|
|
229
301
|
}
|
|
302
|
+
if (fs.existsSync(SELECTED_ACCOUNT_PATH)) {
|
|
303
|
+
fs.unlinkSync(SELECTED_ACCOUNT_PATH);
|
|
304
|
+
}
|
|
230
305
|
return true;
|
|
231
306
|
}
|
|
232
307
|
catch (error) {
|
|
@@ -236,8 +311,8 @@ class AuthManager {
|
|
|
236
311
|
}
|
|
237
312
|
async hasWorkAccountPermissions() {
|
|
238
313
|
try {
|
|
239
|
-
const
|
|
240
|
-
if (
|
|
314
|
+
const currentAccount = await this.getCurrentAccount();
|
|
315
|
+
if (!currentAccount) {
|
|
241
316
|
return false;
|
|
242
317
|
}
|
|
243
318
|
const workScopes = endpoints.default
|
|
@@ -246,7 +321,7 @@ class AuthManager {
|
|
|
246
321
|
try {
|
|
247
322
|
await this.msalApp.acquireTokenSilent({
|
|
248
323
|
scopes: workScopes.slice(0, 1),
|
|
249
|
-
account:
|
|
324
|
+
account: currentAccount,
|
|
250
325
|
});
|
|
251
326
|
return true;
|
|
252
327
|
}
|
|
@@ -287,6 +362,12 @@ class AuthManager {
|
|
|
287
362
|
this.accessToken = response?.accessToken || null;
|
|
288
363
|
this.tokenExpiry = response?.expiresOn ? new Date(response.expiresOn).getTime() : null;
|
|
289
364
|
this.scopes = allScopes;
|
|
365
|
+
// Update selected account if this is a new account
|
|
366
|
+
if (response?.account) {
|
|
367
|
+
this.selectedAccountId = response.account.homeAccountId;
|
|
368
|
+
await this.saveSelectedAccount();
|
|
369
|
+
logger.info(`Updated selected account after scope expansion: ${response.account.username}`);
|
|
370
|
+
}
|
|
290
371
|
await this.saveTokenCache();
|
|
291
372
|
return true;
|
|
292
373
|
}
|
|
@@ -295,6 +376,71 @@ class AuthManager {
|
|
|
295
376
|
return false;
|
|
296
377
|
}
|
|
297
378
|
}
|
|
379
|
+
// Multi-account support methods
|
|
380
|
+
async listAccounts() {
|
|
381
|
+
return await this.msalApp.getTokenCache().getAllAccounts();
|
|
382
|
+
}
|
|
383
|
+
async selectAccount(accountId) {
|
|
384
|
+
const accounts = await this.listAccounts();
|
|
385
|
+
const account = accounts.find((acc) => acc.homeAccountId === accountId);
|
|
386
|
+
if (!account) {
|
|
387
|
+
logger.error(`Account with ID ${accountId} not found`);
|
|
388
|
+
return false;
|
|
389
|
+
}
|
|
390
|
+
this.selectedAccountId = accountId;
|
|
391
|
+
await this.saveSelectedAccount();
|
|
392
|
+
// Clear cached tokens to force refresh with new account
|
|
393
|
+
this.accessToken = null;
|
|
394
|
+
this.tokenExpiry = null;
|
|
395
|
+
logger.info(`Selected account: ${account.username} (${accountId})`);
|
|
396
|
+
return true;
|
|
397
|
+
}
|
|
398
|
+
async getTokenForAccount(accountId) {
|
|
399
|
+
const accounts = await this.listAccounts();
|
|
400
|
+
const account = accounts.find((acc) => acc.homeAccountId === accountId);
|
|
401
|
+
if (!account) {
|
|
402
|
+
throw new Error(`Account with ID ${accountId} not found`);
|
|
403
|
+
}
|
|
404
|
+
const silentRequest = {
|
|
405
|
+
account: account,
|
|
406
|
+
scopes: this.scopes,
|
|
407
|
+
};
|
|
408
|
+
try {
|
|
409
|
+
const response = await this.msalApp.acquireTokenSilent(silentRequest);
|
|
410
|
+
return response.accessToken;
|
|
411
|
+
}
|
|
412
|
+
catch (error) {
|
|
413
|
+
logger.error(`Failed to get token for account ${accountId}: ${error.message}`);
|
|
414
|
+
throw error;
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
async removeAccount(accountId) {
|
|
418
|
+
const accounts = await this.listAccounts();
|
|
419
|
+
const account = accounts.find((acc) => acc.homeAccountId === accountId);
|
|
420
|
+
if (!account) {
|
|
421
|
+
logger.error(`Account with ID ${accountId} not found`);
|
|
422
|
+
return false;
|
|
423
|
+
}
|
|
424
|
+
try {
|
|
425
|
+
await this.msalApp.getTokenCache().removeAccount(account);
|
|
426
|
+
// If this was the selected account, clear the selection
|
|
427
|
+
if (this.selectedAccountId === accountId) {
|
|
428
|
+
this.selectedAccountId = null;
|
|
429
|
+
await this.saveSelectedAccount();
|
|
430
|
+
this.accessToken = null;
|
|
431
|
+
this.tokenExpiry = null;
|
|
432
|
+
}
|
|
433
|
+
logger.info(`Removed account: ${account.username} (${accountId})`);
|
|
434
|
+
return true;
|
|
435
|
+
}
|
|
436
|
+
catch (error) {
|
|
437
|
+
logger.error(`Failed to remove account ${accountId}: ${error.message}`);
|
|
438
|
+
return false;
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
getSelectedAccountId() {
|
|
442
|
+
return this.selectedAccountId;
|
|
443
|
+
}
|
|
298
444
|
requiresWorkAccountScope(toolName) {
|
|
299
445
|
const endpoint = endpoints.default.find((e) => e.toolName === toolName);
|
|
300
446
|
return endpoint?.requiresWorkAccount === true;
|
package/dist/cli.js
CHANGED
|
@@ -15,6 +15,9 @@ program
|
|
|
15
15
|
.option('--login', 'Login using device code flow')
|
|
16
16
|
.option('--logout', 'Log out and clear saved credentials')
|
|
17
17
|
.option('--verify-login', 'Verify login without starting the server')
|
|
18
|
+
.option('--list-accounts', 'List all cached accounts')
|
|
19
|
+
.option('--select-account <accountId>', 'Select a specific account by ID')
|
|
20
|
+
.option('--remove-account <accountId>', 'Remove a specific account by ID')
|
|
18
21
|
.option('--read-only', 'Start server in read-only mode, disabling write operations')
|
|
19
22
|
.option('--http [port]', 'Use Streamable HTTP transport instead of stdio (optionally specify port, default: 3000)')
|
|
20
23
|
.option('--enable-auth-tools', 'Enable login/logout tools when using HTTP mode (disabled by default in HTTP mode)')
|
package/dist/graph-client.js
CHANGED
|
@@ -11,14 +11,39 @@ class GraphClient {
|
|
|
11
11
|
this.accessToken = accessToken;
|
|
12
12
|
this.refreshToken = refreshToken || null;
|
|
13
13
|
}
|
|
14
|
+
async getCurrentAccountId() {
|
|
15
|
+
const currentAccount = await this.authManager.getCurrentAccount();
|
|
16
|
+
return currentAccount?.homeAccountId || null;
|
|
17
|
+
}
|
|
18
|
+
getAccountSessions(accountId) {
|
|
19
|
+
if (!this.sessions.has(accountId)) {
|
|
20
|
+
this.sessions.set(accountId, new Map());
|
|
21
|
+
}
|
|
22
|
+
return this.sessions.get(accountId);
|
|
23
|
+
}
|
|
24
|
+
async getSessionForFile(filePath) {
|
|
25
|
+
const accountId = await this.getCurrentAccountId();
|
|
26
|
+
if (!accountId)
|
|
27
|
+
return null;
|
|
28
|
+
const accountSessions = this.getAccountSessions(accountId);
|
|
29
|
+
return accountSessions.get(filePath) || null;
|
|
30
|
+
}
|
|
31
|
+
async setSessionForFile(filePath, sessionId) {
|
|
32
|
+
const accountId = await this.getCurrentAccountId();
|
|
33
|
+
if (!accountId)
|
|
34
|
+
return;
|
|
35
|
+
const accountSessions = this.getAccountSessions(accountId);
|
|
36
|
+
accountSessions.set(filePath, sessionId);
|
|
37
|
+
}
|
|
14
38
|
async createSession(filePath) {
|
|
15
39
|
try {
|
|
16
40
|
if (!filePath) {
|
|
17
41
|
logger.error('No file path provided for Excel session');
|
|
18
42
|
return null;
|
|
19
43
|
}
|
|
20
|
-
|
|
21
|
-
|
|
44
|
+
const existingSession = await this.getSessionForFile(filePath);
|
|
45
|
+
if (existingSession) {
|
|
46
|
+
return existingSession;
|
|
22
47
|
}
|
|
23
48
|
logger.info(`Creating new Excel session for file: ${filePath}`);
|
|
24
49
|
const accessToken = await this.authManager.getToken();
|
|
@@ -37,7 +62,7 @@ class GraphClient {
|
|
|
37
62
|
}
|
|
38
63
|
const result = await response.json();
|
|
39
64
|
logger.info(`Session created successfully for file: ${filePath}`);
|
|
40
|
-
this.
|
|
65
|
+
await this.setSessionForFile(filePath, result.id);
|
|
41
66
|
return result.id;
|
|
42
67
|
}
|
|
43
68
|
catch (error) {
|
|
@@ -116,7 +141,7 @@ class GraphClient {
|
|
|
116
141
|
!endpoint.startsWith('/teams') &&
|
|
117
142
|
!endpoint.startsWith('/chats') &&
|
|
118
143
|
!endpoint.startsWith('/planner')) {
|
|
119
|
-
sessionId = this.
|
|
144
|
+
sessionId = await this.getSessionForFile(options.excelFile);
|
|
120
145
|
if (!sessionId) {
|
|
121
146
|
sessionId = await this.createSessionWithToken(options.excelFile, accessToken);
|
|
122
147
|
}
|
|
@@ -166,8 +191,9 @@ class GraphClient {
|
|
|
166
191
|
logger.error('No file path provided for Excel session');
|
|
167
192
|
return null;
|
|
168
193
|
}
|
|
169
|
-
|
|
170
|
-
|
|
194
|
+
const existingSession = await this.getSessionForFile(filePath);
|
|
195
|
+
if (existingSession) {
|
|
196
|
+
return existingSession;
|
|
171
197
|
}
|
|
172
198
|
logger.info(`Creating new Excel session for file: ${filePath}`);
|
|
173
199
|
const response = await fetch(`https://graph.microsoft.com/v1.0/me/drive/root:${filePath}:/workbook/createSession`, {
|
|
@@ -185,7 +211,7 @@ class GraphClient {
|
|
|
185
211
|
}
|
|
186
212
|
const result = await response.json();
|
|
187
213
|
logger.info(`Session created successfully for file: ${filePath}`);
|
|
188
|
-
this.
|
|
214
|
+
await this.setSessionForFile(filePath, result.id);
|
|
189
215
|
return result.id;
|
|
190
216
|
}
|
|
191
217
|
catch (error) {
|
|
@@ -236,7 +262,7 @@ class GraphClient {
|
|
|
236
262
|
!endpoint.startsWith('/chats') &&
|
|
237
263
|
!endpoint.startsWith('/planner') &&
|
|
238
264
|
!endpoint.startsWith('/sites')) {
|
|
239
|
-
sessionId = this.
|
|
265
|
+
sessionId = await this.getSessionForFile(options.excelFile);
|
|
240
266
|
if (!sessionId) {
|
|
241
267
|
sessionId = await this.createSession(options.excelFile);
|
|
242
268
|
}
|
|
@@ -407,7 +433,8 @@ class GraphClient {
|
|
|
407
433
|
}
|
|
408
434
|
}
|
|
409
435
|
async closeSession(filePath) {
|
|
410
|
-
|
|
436
|
+
const sessionId = await this.getSessionForFile(filePath);
|
|
437
|
+
if (!filePath || !sessionId) {
|
|
411
438
|
return {
|
|
412
439
|
content: [
|
|
413
440
|
{
|
|
@@ -417,7 +444,6 @@ class GraphClient {
|
|
|
417
444
|
],
|
|
418
445
|
};
|
|
419
446
|
}
|
|
420
|
-
const sessionId = this.sessions.get(filePath);
|
|
421
447
|
try {
|
|
422
448
|
const accessToken = await this.authManager.getToken();
|
|
423
449
|
const response = await fetch(`https://graph.microsoft.com/v1.0/me/drive/root:${filePath}:/workbook/closeSession`, {
|
|
@@ -429,7 +455,11 @@ class GraphClient {
|
|
|
429
455
|
},
|
|
430
456
|
});
|
|
431
457
|
if (response.ok) {
|
|
432
|
-
this.
|
|
458
|
+
const accountId = await this.getCurrentAccountId();
|
|
459
|
+
if (accountId) {
|
|
460
|
+
const accountSessions = this.getAccountSessions(accountId);
|
|
461
|
+
accountSessions.delete(filePath);
|
|
462
|
+
}
|
|
433
463
|
return {
|
|
434
464
|
content: [
|
|
435
465
|
{
|
|
@@ -458,9 +488,13 @@ class GraphClient {
|
|
|
458
488
|
}
|
|
459
489
|
async closeAllSessions() {
|
|
460
490
|
const results = [];
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
491
|
+
const accountId = await this.getCurrentAccountId();
|
|
492
|
+
if (accountId) {
|
|
493
|
+
const accountSessions = this.getAccountSessions(accountId);
|
|
494
|
+
for (const [filePath] of accountSessions) {
|
|
495
|
+
const result = await this.closeSession(filePath);
|
|
496
|
+
results.push(result);
|
|
497
|
+
}
|
|
464
498
|
}
|
|
465
499
|
return {
|
|
466
500
|
content: [
|
package/dist/index.js
CHANGED
|
@@ -40,6 +40,40 @@ async function main() {
|
|
|
40
40
|
console.log(JSON.stringify({ message: 'Logged out successfully' }));
|
|
41
41
|
process.exit(0);
|
|
42
42
|
}
|
|
43
|
+
if (args.listAccounts) {
|
|
44
|
+
const accounts = await authManager.listAccounts();
|
|
45
|
+
const selectedAccountId = authManager.getSelectedAccountId();
|
|
46
|
+
const result = accounts.map(account => ({
|
|
47
|
+
id: account.homeAccountId,
|
|
48
|
+
username: account.username,
|
|
49
|
+
name: account.name,
|
|
50
|
+
selected: account.homeAccountId === selectedAccountId
|
|
51
|
+
}));
|
|
52
|
+
console.log(JSON.stringify({ accounts: result }));
|
|
53
|
+
process.exit(0);
|
|
54
|
+
}
|
|
55
|
+
if (args.selectAccount) {
|
|
56
|
+
const success = await authManager.selectAccount(args.selectAccount);
|
|
57
|
+
if (success) {
|
|
58
|
+
console.log(JSON.stringify({ message: `Selected account: ${args.selectAccount}` }));
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
console.log(JSON.stringify({ error: `Account not found: ${args.selectAccount}` }));
|
|
62
|
+
process.exit(1);
|
|
63
|
+
}
|
|
64
|
+
process.exit(0);
|
|
65
|
+
}
|
|
66
|
+
if (args.removeAccount) {
|
|
67
|
+
const success = await authManager.removeAccount(args.removeAccount);
|
|
68
|
+
if (success) {
|
|
69
|
+
console.log(JSON.stringify({ message: `Removed account: ${args.removeAccount}` }));
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
console.log(JSON.stringify({ error: `Account not found: ${args.removeAccount}` }));
|
|
73
|
+
process.exit(1);
|
|
74
|
+
}
|
|
75
|
+
process.exit(0);
|
|
76
|
+
}
|
|
43
77
|
const server = new MicrosoftGraphServer(authManager, args);
|
|
44
78
|
await server.initialize(version);
|
|
45
79
|
await server.start();
|
package/package.json
CHANGED
package/dist/endpoints.json
DELETED
|
@@ -1,490 +0,0 @@
|
|
|
1
|
-
[
|
|
2
|
-
{
|
|
3
|
-
"pathPattern": "/me/messages",
|
|
4
|
-
"method": "get",
|
|
5
|
-
"toolName": "list-mail-messages",
|
|
6
|
-
"scopes": ["Mail.Read"]
|
|
7
|
-
},
|
|
8
|
-
{
|
|
9
|
-
"pathPattern": "/me/mailFolders",
|
|
10
|
-
"method": "get",
|
|
11
|
-
"toolName": "list-mail-folders",
|
|
12
|
-
"scopes": ["Mail.Read"]
|
|
13
|
-
},
|
|
14
|
-
{
|
|
15
|
-
"pathPattern": "/me/mailFolders/{mailFolder-id}/messages",
|
|
16
|
-
"method": "get",
|
|
17
|
-
"toolName": "list-mail-folder-messages",
|
|
18
|
-
"scopes": ["Mail.Read"]
|
|
19
|
-
},
|
|
20
|
-
{
|
|
21
|
-
"pathPattern": "/me/messages/{message-id}",
|
|
22
|
-
"method": "get",
|
|
23
|
-
"toolName": "get-mail-message",
|
|
24
|
-
"scopes": ["Mail.Read"]
|
|
25
|
-
},
|
|
26
|
-
{
|
|
27
|
-
"pathPattern": "/me/sendMail",
|
|
28
|
-
"method": "post",
|
|
29
|
-
"toolName": "send-mail",
|
|
30
|
-
"scopes": ["Mail.Send"]
|
|
31
|
-
},
|
|
32
|
-
{
|
|
33
|
-
"pathPattern": "/me/messages",
|
|
34
|
-
"method": "post",
|
|
35
|
-
"toolName": "create-draft-email",
|
|
36
|
-
"scopes": ["Mail.ReadWrite"]
|
|
37
|
-
},
|
|
38
|
-
{
|
|
39
|
-
"pathPattern": "/me/messages/{message-id}",
|
|
40
|
-
"method": "delete",
|
|
41
|
-
"toolName": "delete-mail-message",
|
|
42
|
-
"scopes": ["Mail.ReadWrite"]
|
|
43
|
-
},
|
|
44
|
-
{
|
|
45
|
-
"pathPattern": "/me/messages/{message-id}/move",
|
|
46
|
-
"method": "post",
|
|
47
|
-
"toolName": "move-mail-message",
|
|
48
|
-
"scopes": ["Mail.ReadWrite"]
|
|
49
|
-
},
|
|
50
|
-
{
|
|
51
|
-
"pathPattern": "/me/events",
|
|
52
|
-
"method": "get",
|
|
53
|
-
"toolName": "list-calendar-events",
|
|
54
|
-
"scopes": ["Calendars.Read"]
|
|
55
|
-
},
|
|
56
|
-
{
|
|
57
|
-
"pathPattern": "/me/events/{event-id}",
|
|
58
|
-
"method": "get",
|
|
59
|
-
"toolName": "get-calendar-event",
|
|
60
|
-
"scopes": ["Calendars.Read"]
|
|
61
|
-
},
|
|
62
|
-
{
|
|
63
|
-
"pathPattern": "/me/events",
|
|
64
|
-
"method": "post",
|
|
65
|
-
"toolName": "create-calendar-event",
|
|
66
|
-
"scopes": ["Calendars.ReadWrite"]
|
|
67
|
-
},
|
|
68
|
-
{
|
|
69
|
-
"pathPattern": "/me/events/{event-id}",
|
|
70
|
-
"method": "patch",
|
|
71
|
-
"toolName": "update-calendar-event",
|
|
72
|
-
"scopes": ["Calendars.ReadWrite"]
|
|
73
|
-
},
|
|
74
|
-
{
|
|
75
|
-
"pathPattern": "/me/events/{event-id}",
|
|
76
|
-
"method": "delete",
|
|
77
|
-
"toolName": "delete-calendar-event",
|
|
78
|
-
"scopes": ["Calendars.ReadWrite"]
|
|
79
|
-
},
|
|
80
|
-
{
|
|
81
|
-
"pathPattern": "/me/calendarView",
|
|
82
|
-
"method": "get",
|
|
83
|
-
"toolName": "get-calendar-view",
|
|
84
|
-
"scopes": ["Calendars.Read"]
|
|
85
|
-
},
|
|
86
|
-
{
|
|
87
|
-
"pathPattern": "/me/calendars",
|
|
88
|
-
"method": "get",
|
|
89
|
-
"toolName": "list-calendars",
|
|
90
|
-
"scopes": ["Calendars.Read"]
|
|
91
|
-
},
|
|
92
|
-
{
|
|
93
|
-
"pathPattern": "/me/drives",
|
|
94
|
-
"method": "get",
|
|
95
|
-
"toolName": "list-drives",
|
|
96
|
-
"scopes": ["Files.Read"]
|
|
97
|
-
},
|
|
98
|
-
{
|
|
99
|
-
"pathPattern": "/drives/{drive-id}/root",
|
|
100
|
-
"method": "get",
|
|
101
|
-
"toolName": "get-drive-root-item",
|
|
102
|
-
"scopes": ["Files.Read"]
|
|
103
|
-
},
|
|
104
|
-
{
|
|
105
|
-
"pathPattern": "/drives/{drive-id}/root",
|
|
106
|
-
"method": "get",
|
|
107
|
-
"toolName": "get-root-folder",
|
|
108
|
-
"scopes": ["Files.Read"]
|
|
109
|
-
},
|
|
110
|
-
{
|
|
111
|
-
"pathPattern": "/drives/{drive-id}/items/{driveItem-id}/children",
|
|
112
|
-
"method": "get",
|
|
113
|
-
"toolName": "list-folder-files",
|
|
114
|
-
"scopes": ["Files.Read"]
|
|
115
|
-
},
|
|
116
|
-
{
|
|
117
|
-
"pathPattern": "/drives/{drive-id}/items/{driveItem-id}/children/{driveItem-id1}/content",
|
|
118
|
-
"method": "get",
|
|
119
|
-
"toolName": "download-onedrive-file-content",
|
|
120
|
-
"scopes": ["Files.Read"]
|
|
121
|
-
},
|
|
122
|
-
{
|
|
123
|
-
"pathPattern": "/drives/{drive-id}/items/{driveItem-id}",
|
|
124
|
-
"method": "delete",
|
|
125
|
-
"toolName": "delete-onedrive-file",
|
|
126
|
-
"scopes": ["Files.ReadWrite"]
|
|
127
|
-
},
|
|
128
|
-
{
|
|
129
|
-
"pathPattern": "/drives/{drive-id}/items/{driveItem-id}/content",
|
|
130
|
-
"method": "put",
|
|
131
|
-
"toolName": "upload-file-content",
|
|
132
|
-
"scopes": ["Files.ReadWrite"]
|
|
133
|
-
},
|
|
134
|
-
{
|
|
135
|
-
"pathPattern": "/drives/{drive-id}/items/{driveItem-id}/workbook/worksheets/{workbookWorksheet-id}/charts/add",
|
|
136
|
-
"method": "post",
|
|
137
|
-
"toolName": "create-excel-chart",
|
|
138
|
-
"isExcelOp": true,
|
|
139
|
-
"scopes": ["Files.ReadWrite"]
|
|
140
|
-
},
|
|
141
|
-
{
|
|
142
|
-
"pathPattern": "/drives/{drive-id}/items/{driveItem-id}/workbook/worksheets/{workbookWorksheet-id}/range()/format",
|
|
143
|
-
"method": "patch",
|
|
144
|
-
"toolName": "format-excel-range",
|
|
145
|
-
"isExcelOp": true,
|
|
146
|
-
"scopes": ["Files.ReadWrite"]
|
|
147
|
-
},
|
|
148
|
-
{
|
|
149
|
-
"pathPattern": "/drives/{drive-id}/items/{driveItem-id}/workbook/worksheets/{workbookWorksheet-id}/range()/sort",
|
|
150
|
-
"method": "patch",
|
|
151
|
-
"toolName": "sort-excel-range",
|
|
152
|
-
"isExcelOp": true,
|
|
153
|
-
"scopes": ["Files.ReadWrite"]
|
|
154
|
-
},
|
|
155
|
-
{
|
|
156
|
-
"pathPattern": "/drives/{drive-id}/items/{driveItem-id}/workbook/worksheets/{workbookWorksheet-id}/range(address='{address}')",
|
|
157
|
-
"method": "get",
|
|
158
|
-
"toolName": "get-excel-range",
|
|
159
|
-
"isExcelOp": true,
|
|
160
|
-
"scopes": ["Files.Read"]
|
|
161
|
-
},
|
|
162
|
-
{
|
|
163
|
-
"pathPattern": "/drives/{drive-id}/items/{driveItem-id}/workbook/worksheets",
|
|
164
|
-
"method": "get",
|
|
165
|
-
"toolName": "list-excel-worksheets",
|
|
166
|
-
"isExcelOp": true,
|
|
167
|
-
"scopes": ["Files.Read"]
|
|
168
|
-
},
|
|
169
|
-
{
|
|
170
|
-
"pathPattern": "/me/onenote/notebooks",
|
|
171
|
-
"method": "get",
|
|
172
|
-
"toolName": "list-onenote-notebooks",
|
|
173
|
-
"scopes": ["Notes.Read"]
|
|
174
|
-
},
|
|
175
|
-
{
|
|
176
|
-
"pathPattern": "/me/onenote/notebooks/{notebook-id}/sections",
|
|
177
|
-
"method": "get",
|
|
178
|
-
"toolName": "list-onenote-notebook-sections",
|
|
179
|
-
"scopes": ["Notes.Read"]
|
|
180
|
-
},
|
|
181
|
-
{
|
|
182
|
-
"pathPattern": "/me/onenote/sections/{onenoteSection-id}/pages",
|
|
183
|
-
"method": "get",
|
|
184
|
-
"toolName": "list-onenote-section-pages",
|
|
185
|
-
"scopes": ["Notes.Read"]
|
|
186
|
-
},
|
|
187
|
-
{
|
|
188
|
-
"pathPattern": "/me/onenote/pages/{onenotePage-id}/content",
|
|
189
|
-
"method": "get",
|
|
190
|
-
"toolName": "get-onenote-page-content",
|
|
191
|
-
"scopes": ["Notes.Read"]
|
|
192
|
-
},
|
|
193
|
-
{
|
|
194
|
-
"pathPattern": "/me/onenote/pages",
|
|
195
|
-
"method": "post",
|
|
196
|
-
"toolName": "create-onenote-page",
|
|
197
|
-
"scopes": ["Notes.Create"]
|
|
198
|
-
},
|
|
199
|
-
{
|
|
200
|
-
"pathPattern": "/me/todo/lists",
|
|
201
|
-
"method": "get",
|
|
202
|
-
"toolName": "list-todo-task-lists",
|
|
203
|
-
"scopes": ["Tasks.Read"]
|
|
204
|
-
},
|
|
205
|
-
{
|
|
206
|
-
"pathPattern": "/me/todo/lists/{todoTaskList-id}/tasks",
|
|
207
|
-
"method": "get",
|
|
208
|
-
"toolName": "list-todo-tasks",
|
|
209
|
-
"scopes": ["Tasks.Read"]
|
|
210
|
-
},
|
|
211
|
-
{
|
|
212
|
-
"pathPattern": "/me/todo/lists/{todoTaskList-id}/tasks/{todoTask-id}",
|
|
213
|
-
"method": "get",
|
|
214
|
-
"toolName": "get-todo-task",
|
|
215
|
-
"scopes": ["Tasks.Read"]
|
|
216
|
-
},
|
|
217
|
-
{
|
|
218
|
-
"pathPattern": "/me/todo/lists/{todoTaskList-id}/tasks",
|
|
219
|
-
"method": "post",
|
|
220
|
-
"toolName": "create-todo-task",
|
|
221
|
-
"scopes": ["Tasks.ReadWrite"]
|
|
222
|
-
},
|
|
223
|
-
{
|
|
224
|
-
"pathPattern": "/me/todo/lists/{todoTaskList-id}/tasks/{todoTask-id}",
|
|
225
|
-
"method": "patch",
|
|
226
|
-
"toolName": "update-todo-task",
|
|
227
|
-
"scopes": ["Tasks.ReadWrite"]
|
|
228
|
-
},
|
|
229
|
-
{
|
|
230
|
-
"pathPattern": "/me/todo/lists/{todoTaskList-id}/tasks/{todoTask-id}",
|
|
231
|
-
"method": "delete",
|
|
232
|
-
"toolName": "delete-todo-task",
|
|
233
|
-
"scopes": ["Tasks.ReadWrite"]
|
|
234
|
-
},
|
|
235
|
-
{
|
|
236
|
-
"pathPattern": "/me/planner/tasks",
|
|
237
|
-
"method": "get",
|
|
238
|
-
"toolName": "list-planner-tasks",
|
|
239
|
-
"scopes": ["Tasks.Read"]
|
|
240
|
-
},
|
|
241
|
-
{
|
|
242
|
-
"pathPattern": "/planner/plans/{plannerPlan-id}",
|
|
243
|
-
"method": "get",
|
|
244
|
-
"toolName": "get-planner-plan",
|
|
245
|
-
"scopes": ["Tasks.Read"]
|
|
246
|
-
},
|
|
247
|
-
{
|
|
248
|
-
"pathPattern": "/planner/plans/{plannerPlan-id}/tasks",
|
|
249
|
-
"method": "get",
|
|
250
|
-
"toolName": "list-plan-tasks",
|
|
251
|
-
"scopes": ["Tasks.Read"]
|
|
252
|
-
},
|
|
253
|
-
{
|
|
254
|
-
"pathPattern": "/planner/tasks/{plannerTask-id}",
|
|
255
|
-
"method": "get",
|
|
256
|
-
"toolName": "get-planner-task",
|
|
257
|
-
"scopes": ["Tasks.Read"]
|
|
258
|
-
},
|
|
259
|
-
{
|
|
260
|
-
"pathPattern": "/planner/tasks",
|
|
261
|
-
"method": "post",
|
|
262
|
-
"toolName": "create-planner-task",
|
|
263
|
-
"scopes": ["Tasks.ReadWrite"]
|
|
264
|
-
},
|
|
265
|
-
{
|
|
266
|
-
"pathPattern": "/me/contacts",
|
|
267
|
-
"method": "get",
|
|
268
|
-
"toolName": "list-outlook-contacts",
|
|
269
|
-
"scopes": ["Contacts.Read"]
|
|
270
|
-
},
|
|
271
|
-
{
|
|
272
|
-
"pathPattern": "/me/contacts/{contact-id}",
|
|
273
|
-
"method": "get",
|
|
274
|
-
"toolName": "get-outlook-contact",
|
|
275
|
-
"scopes": ["Contacts.Read"]
|
|
276
|
-
},
|
|
277
|
-
{
|
|
278
|
-
"pathPattern": "/me/contacts",
|
|
279
|
-
"method": "post",
|
|
280
|
-
"toolName": "create-outlook-contact",
|
|
281
|
-
"scopes": ["Contacts.ReadWrite"]
|
|
282
|
-
},
|
|
283
|
-
{
|
|
284
|
-
"pathPattern": "/me/contacts/{contact-id}",
|
|
285
|
-
"method": "patch",
|
|
286
|
-
"toolName": "update-outlook-contact",
|
|
287
|
-
"scopes": ["Contacts.ReadWrite"]
|
|
288
|
-
},
|
|
289
|
-
{
|
|
290
|
-
"pathPattern": "/me/contacts/{contact-id}",
|
|
291
|
-
"method": "delete",
|
|
292
|
-
"toolName": "delete-outlook-contact",
|
|
293
|
-
"scopes": ["Contacts.ReadWrite"]
|
|
294
|
-
},
|
|
295
|
-
{
|
|
296
|
-
"pathPattern": "/me",
|
|
297
|
-
"method": "get",
|
|
298
|
-
"toolName": "get-current-user",
|
|
299
|
-
"scopes": ["User.Read"]
|
|
300
|
-
},
|
|
301
|
-
{
|
|
302
|
-
"pathPattern": "/me/chats",
|
|
303
|
-
"method": "get",
|
|
304
|
-
"toolName": "list-chats",
|
|
305
|
-
"scopes": ["Chat.Read"],
|
|
306
|
-
"requiresWorkAccount": true
|
|
307
|
-
},
|
|
308
|
-
{
|
|
309
|
-
"pathPattern": "/chats/{chat-id}",
|
|
310
|
-
"method": "get",
|
|
311
|
-
"toolName": "get-chat",
|
|
312
|
-
"scopes": ["Chat.Read"],
|
|
313
|
-
"requiresWorkAccount": true
|
|
314
|
-
},
|
|
315
|
-
{
|
|
316
|
-
"pathPattern": "/chats/{chat-id}/messages",
|
|
317
|
-
"method": "get",
|
|
318
|
-
"toolName": "list-chat-messages",
|
|
319
|
-
"scopes": ["ChatMessage.Read"],
|
|
320
|
-
"requiresWorkAccount": true
|
|
321
|
-
},
|
|
322
|
-
{
|
|
323
|
-
"pathPattern": "/chats/{chat-id}/messages/{chatMessage-id}",
|
|
324
|
-
"method": "get",
|
|
325
|
-
"toolName": "get-chat-message",
|
|
326
|
-
"scopes": ["ChatMessage.Read"],
|
|
327
|
-
"requiresWorkAccount": true
|
|
328
|
-
},
|
|
329
|
-
{
|
|
330
|
-
"pathPattern": "/chats/{chat-id}/messages",
|
|
331
|
-
"method": "post",
|
|
332
|
-
"toolName": "send-chat-message",
|
|
333
|
-
"scopes": ["ChatMessage.Send"],
|
|
334
|
-
"requiresWorkAccount": true
|
|
335
|
-
},
|
|
336
|
-
{
|
|
337
|
-
"pathPattern": "/me/joinedTeams",
|
|
338
|
-
"method": "get",
|
|
339
|
-
"toolName": "list-joined-teams",
|
|
340
|
-
"scopes": ["Team.ReadBasic.All"],
|
|
341
|
-
"requiresWorkAccount": true
|
|
342
|
-
},
|
|
343
|
-
{
|
|
344
|
-
"pathPattern": "/teams/{team-id}",
|
|
345
|
-
"method": "get",
|
|
346
|
-
"toolName": "get-team",
|
|
347
|
-
"scopes": ["Team.ReadBasic.All"],
|
|
348
|
-
"requiresWorkAccount": true
|
|
349
|
-
},
|
|
350
|
-
{
|
|
351
|
-
"pathPattern": "/teams/{team-id}/channels",
|
|
352
|
-
"method": "get",
|
|
353
|
-
"toolName": "list-team-channels",
|
|
354
|
-
"scopes": ["Channel.ReadBasic.All"],
|
|
355
|
-
"requiresWorkAccount": true
|
|
356
|
-
},
|
|
357
|
-
{
|
|
358
|
-
"pathPattern": "/teams/{team-id}/channels/{channel-id}",
|
|
359
|
-
"method": "get",
|
|
360
|
-
"toolName": "get-team-channel",
|
|
361
|
-
"scopes": ["Channel.ReadBasic.All"],
|
|
362
|
-
"requiresWorkAccount": true
|
|
363
|
-
},
|
|
364
|
-
{
|
|
365
|
-
"pathPattern": "/teams/{team-id}/channels/{channel-id}/messages",
|
|
366
|
-
"method": "get",
|
|
367
|
-
"toolName": "list-channel-messages",
|
|
368
|
-
"scopes": ["ChannelMessage.Read.All"],
|
|
369
|
-
"requiresWorkAccount": true
|
|
370
|
-
},
|
|
371
|
-
{
|
|
372
|
-
"pathPattern": "/teams/{team-id}/channels/{channel-id}/messages/{chatMessage-id}",
|
|
373
|
-
"method": "get",
|
|
374
|
-
"toolName": "get-channel-message",
|
|
375
|
-
"scopes": ["ChannelMessage.Read.All"],
|
|
376
|
-
"requiresWorkAccount": true
|
|
377
|
-
},
|
|
378
|
-
{
|
|
379
|
-
"pathPattern": "/teams/{team-id}/channels/{channel-id}/messages",
|
|
380
|
-
"method": "post",
|
|
381
|
-
"toolName": "send-channel-message",
|
|
382
|
-
"scopes": ["ChannelMessage.Send"],
|
|
383
|
-
"requiresWorkAccount": true
|
|
384
|
-
},
|
|
385
|
-
{
|
|
386
|
-
"pathPattern": "/teams/{team-id}/members",
|
|
387
|
-
"method": "get",
|
|
388
|
-
"toolName": "list-team-members",
|
|
389
|
-
"scopes": ["TeamMember.Read.All"],
|
|
390
|
-
"requiresWorkAccount": true
|
|
391
|
-
},
|
|
392
|
-
{
|
|
393
|
-
"pathPattern": "/chats/{chat-id}/messages/{chatMessage-id}/replies",
|
|
394
|
-
"method": "get",
|
|
395
|
-
"toolName": "list-chat-message-replies",
|
|
396
|
-
"scopes": ["ChatMessage.Read"],
|
|
397
|
-
"requiresWorkAccount": true
|
|
398
|
-
},
|
|
399
|
-
{
|
|
400
|
-
"pathPattern": "/chats/{chat-id}/messages/{chatMessage-id}/replies",
|
|
401
|
-
"method": "post",
|
|
402
|
-
"toolName": "reply-to-chat-message",
|
|
403
|
-
"scopes": ["ChatMessage.Send"],
|
|
404
|
-
"requiresWorkAccount": true
|
|
405
|
-
},
|
|
406
|
-
{
|
|
407
|
-
"pathPattern": "/sites",
|
|
408
|
-
"method": "get",
|
|
409
|
-
"toolName": "search-sharepoint-sites",
|
|
410
|
-
"scopes": ["Sites.Read.All"],
|
|
411
|
-
"requiresWorkAccount": true
|
|
412
|
-
},
|
|
413
|
-
{
|
|
414
|
-
"pathPattern": "/sites/{site-id}",
|
|
415
|
-
"method": "get",
|
|
416
|
-
"toolName": "get-sharepoint-site",
|
|
417
|
-
"scopes": ["Sites.Read.All"],
|
|
418
|
-
"requiresWorkAccount": true
|
|
419
|
-
},
|
|
420
|
-
{
|
|
421
|
-
"pathPattern": "/sites/{site-id}/drives",
|
|
422
|
-
"method": "get",
|
|
423
|
-
"toolName": "list-sharepoint-site-drives",
|
|
424
|
-
"scopes": ["Sites.Read.All"],
|
|
425
|
-
"requiresWorkAccount": true
|
|
426
|
-
},
|
|
427
|
-
{
|
|
428
|
-
"pathPattern": "/sites/{site-id}/drives/{drive-id}",
|
|
429
|
-
"method": "get",
|
|
430
|
-
"toolName": "get-sharepoint-site-drive-by-id",
|
|
431
|
-
"scopes": ["Sites.Read.All"],
|
|
432
|
-
"requiresWorkAccount": true
|
|
433
|
-
},
|
|
434
|
-
{
|
|
435
|
-
"pathPattern": "/sites/{site-id}/items",
|
|
436
|
-
"method": "get",
|
|
437
|
-
"toolName": "list-sharepoint-site-items",
|
|
438
|
-
"scopes": ["Sites.Read.All"],
|
|
439
|
-
"requiresWorkAccount": true
|
|
440
|
-
},
|
|
441
|
-
{
|
|
442
|
-
"pathPattern": "/sites/{site-id}/items/{baseItem-id}",
|
|
443
|
-
"method": "get",
|
|
444
|
-
"toolName": "get-sharepoint-site-item",
|
|
445
|
-
"scopes": ["Sites.Read.All"],
|
|
446
|
-
"requiresWorkAccount": true
|
|
447
|
-
},
|
|
448
|
-
{
|
|
449
|
-
"pathPattern": "/sites/{site-id}/lists",
|
|
450
|
-
"method": "get",
|
|
451
|
-
"toolName": "list-sharepoint-site-lists",
|
|
452
|
-
"scopes": ["Sites.Read.All"],
|
|
453
|
-
"requiresWorkAccount": true
|
|
454
|
-
},
|
|
455
|
-
{
|
|
456
|
-
"pathPattern": "/sites/{site-id}/lists/{list-id}",
|
|
457
|
-
"method": "get",
|
|
458
|
-
"toolName": "get-sharepoint-site-list",
|
|
459
|
-
"scopes": ["Sites.Read.All"],
|
|
460
|
-
"requiresWorkAccount": true
|
|
461
|
-
},
|
|
462
|
-
{
|
|
463
|
-
"pathPattern": "/sites/{site-id}/lists/{list-id}/items",
|
|
464
|
-
"method": "get",
|
|
465
|
-
"toolName": "list-sharepoint-site-list-items",
|
|
466
|
-
"scopes": ["Sites.Read.All"],
|
|
467
|
-
"requiresWorkAccount": true
|
|
468
|
-
},
|
|
469
|
-
{
|
|
470
|
-
"pathPattern": "/sites/{site-id}/lists/{list-id}/items/{listItem-id}",
|
|
471
|
-
"method": "get",
|
|
472
|
-
"toolName": "get-sharepoint-site-list-item",
|
|
473
|
-
"scopes": ["Sites.Read.All"],
|
|
474
|
-
"requiresWorkAccount": true
|
|
475
|
-
},
|
|
476
|
-
{
|
|
477
|
-
"pathPattern": "/sites/{site-id}/getByPath(path='{path}')",
|
|
478
|
-
"method": "get",
|
|
479
|
-
"toolName": "get-sharepoint-site-by-path",
|
|
480
|
-
"scopes": ["Sites.Read.All"],
|
|
481
|
-
"requiresWorkAccount": true
|
|
482
|
-
},
|
|
483
|
-
{
|
|
484
|
-
"pathPattern": "/sites/delta()",
|
|
485
|
-
"method": "get",
|
|
486
|
-
"toolName": "get-sharepoint-sites-delta",
|
|
487
|
-
"scopes": ["Sites.Read.All"],
|
|
488
|
-
"requiresWorkAccount": true
|
|
489
|
-
}
|
|
490
|
-
]
|