ms365-mcp-server 1.1.6 → 1.1.8
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 +49 -3
- package/bin/cli.js +14 -0
- package/dist/index.js +33 -19
- package/dist/utils/ms365-operations.js +5 -4
- package/package.json +3 -1
package/README.md
CHANGED
|
@@ -38,6 +38,9 @@ ms365-mcp-server --login
|
|
|
38
38
|
|
|
39
39
|
# Start the server
|
|
40
40
|
ms365-mcp-server
|
|
41
|
+
|
|
42
|
+
# Start with custom server URL
|
|
43
|
+
ms365-mcp-server --server-url https://your-domain.com
|
|
41
44
|
```
|
|
42
45
|
|
|
43
46
|
**Option B: Run with npx (no installation needed)**
|
|
@@ -47,6 +50,9 @@ npx ms365-mcp-server --login
|
|
|
47
50
|
|
|
48
51
|
# Start the server
|
|
49
52
|
npx ms365-mcp-server
|
|
53
|
+
|
|
54
|
+
# Start with custom server URL
|
|
55
|
+
npx ms365-mcp-server --server-url https://your-domain.com
|
|
50
56
|
```
|
|
51
57
|
|
|
52
58
|
### 2. SIYA Desktop Integration
|
|
@@ -57,7 +63,7 @@ npx ms365-mcp-server
|
|
|
57
63
|
"mcpServers": {
|
|
58
64
|
"ms365": {
|
|
59
65
|
"command": "ms365-mcp-server",
|
|
60
|
-
"args": []
|
|
66
|
+
"args": ["--server-url", "https://your-domain.com"]
|
|
61
67
|
}
|
|
62
68
|
}
|
|
63
69
|
}
|
|
@@ -69,7 +75,7 @@ npx ms365-mcp-server
|
|
|
69
75
|
"mcpServers": {
|
|
70
76
|
"ms365": {
|
|
71
77
|
"command": "npx",
|
|
72
|
-
"args": ["ms365-mcp-server"]
|
|
78
|
+
"args": ["ms365-mcp-server", "--server-url", "https://your-domain.com"]
|
|
73
79
|
}
|
|
74
80
|
}
|
|
75
81
|
}
|
|
@@ -84,6 +90,16 @@ Chat with SIYA and ask it to help with your emails! The tools are designed for n
|
|
|
84
90
|
```bash
|
|
85
91
|
# One-command authentication
|
|
86
92
|
ms365-mcp-server --login
|
|
93
|
+
|
|
94
|
+
# Authentication with custom server URL
|
|
95
|
+
ms365-mcp-server --login --server-url https://your-domain.com
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### Environment Variables
|
|
99
|
+
```bash
|
|
100
|
+
# Set server URL via environment variable
|
|
101
|
+
export SERVER_URL=https://your-domain.com
|
|
102
|
+
ms365-mcp-server
|
|
87
103
|
```
|
|
88
104
|
|
|
89
105
|
### MCP Tool Authentication
|
|
@@ -381,4 +397,34 @@ Contributions welcome! Please submit issues and pull requests.
|
|
|
381
397
|
|
|
382
398
|
**Built with 🔒 Security and ❤️ for the AI community**
|
|
383
399
|
|
|
384
|
-
*Production-ready Microsoft 365 integration for SIYA Desktop and MCP applications*
|
|
400
|
+
*Production-ready Microsoft 365 integration for SIYA Desktop and MCP applications*
|
|
401
|
+
|
|
402
|
+
## 🔧 Configuration Options
|
|
403
|
+
|
|
404
|
+
### Server Configuration
|
|
405
|
+
- `--server-url URL`: Set custom server URL for attachments and authentication (default: http://localhost:55000)
|
|
406
|
+
- `SERVER_URL`: Environment variable to set server URL
|
|
407
|
+
|
|
408
|
+
### Authentication Options
|
|
409
|
+
- `--setup-auth`: Set up MS365 API credentials
|
|
410
|
+
- `--reset-auth`: Clear stored authentication tokens
|
|
411
|
+
- `--multi-user`: Enable multi-user authentication mode
|
|
412
|
+
- `--login`: Login to MS365
|
|
413
|
+
- `--logout`: Logout from MS365
|
|
414
|
+
- `--verify-login`: Verify login status
|
|
415
|
+
|
|
416
|
+
### General Options
|
|
417
|
+
- `--debug`: Enable debug output
|
|
418
|
+
- `--non-interactive`, `-n`: Run in non-interactive mode (no prompt)
|
|
419
|
+
- `--help`, `-h`: Show help message
|
|
420
|
+
|
|
421
|
+
## 📝 Notes
|
|
422
|
+
|
|
423
|
+
- The server URL is used for:
|
|
424
|
+
1. Serving email attachments
|
|
425
|
+
2. Generating attachment URLs
|
|
426
|
+
3. OAuth redirect URIs
|
|
427
|
+
4. Authentication callbacks
|
|
428
|
+
- Attachments are served for 24 hours before automatic cleanup
|
|
429
|
+
- Default server port is 55000
|
|
430
|
+
- For production use, set a custom server URL with HTTPS
|
package/bin/cli.js
CHANGED
|
@@ -63,6 +63,7 @@ let multiUser = false;
|
|
|
63
63
|
let login = false;
|
|
64
64
|
let logout = false;
|
|
65
65
|
let verifyLogin = false;
|
|
66
|
+
let serverUrl = process.env.SERVER_URL || 'http://localhost:55000';
|
|
66
67
|
|
|
67
68
|
// Detect if we're running under an MCP context (Claude/SIYA/ChatGPT/etc.)
|
|
68
69
|
const isMcpContext =
|
|
@@ -104,6 +105,14 @@ for (let i = 0; i < args.length; i++) {
|
|
|
104
105
|
} else if (arg === '--verify-login') {
|
|
105
106
|
verifyLogin = true;
|
|
106
107
|
writeDebug('Verify login mode enabled');
|
|
108
|
+
} else if (arg === '--server-url') {
|
|
109
|
+
if (i + 1 < args.length) {
|
|
110
|
+
serverUrl = args[++i];
|
|
111
|
+
writeDebug(`Server URL set to: ${serverUrl}`);
|
|
112
|
+
} else {
|
|
113
|
+
console.error('Error: --server-url requires a value');
|
|
114
|
+
process.exit(1);
|
|
115
|
+
}
|
|
107
116
|
} else if (arg === '--help' || arg === '-h') {
|
|
108
117
|
console.log(`
|
|
109
118
|
MS365 MCP Server - Microsoft 365 Integration for Claude/SIYA Desktop
|
|
@@ -117,6 +126,7 @@ Options:
|
|
|
117
126
|
--login Login to MS365
|
|
118
127
|
--logout Logout from MS365
|
|
119
128
|
--verify-login Verify login to MS365
|
|
129
|
+
--server-url URL Set the server URL (default: http://localhost:55000)
|
|
120
130
|
--debug Enable debug output
|
|
121
131
|
--non-interactive, -n Run in non-interactive mode (no prompt)
|
|
122
132
|
--help, -h Show this help message
|
|
@@ -134,6 +144,7 @@ Authentication Setup:
|
|
|
134
144
|
- MS365_CLIENT_SECRET: Your Azure app client secret
|
|
135
145
|
- MS365_TENANT_ID: Your Azure tenant ID (or "common")
|
|
136
146
|
- MS365_REDIRECT_URI: OAuth redirect URI (optional)
|
|
147
|
+
- SERVER_URL: Server URL for attachments (optional)
|
|
137
148
|
|
|
138
149
|
2. Credentials File:
|
|
139
150
|
- Run --setup-auth for interactive setup
|
|
@@ -158,6 +169,7 @@ Examples:
|
|
|
158
169
|
npx ms365-mcp-server # Start the server
|
|
159
170
|
npx ms365-mcp-server --multi-user # Start in multi-user mode
|
|
160
171
|
npx ms365-mcp-server --reset-auth # Clear auth tokens
|
|
172
|
+
npx ms365-mcp-server --server-url https://your-domain.com # Set custom server URL
|
|
161
173
|
`);
|
|
162
174
|
process.exit(0);
|
|
163
175
|
}
|
|
@@ -203,6 +215,7 @@ function startServerWithPath(serverPath) {
|
|
|
203
215
|
if (verifyLogin) serverArgs.push('--verify-login');
|
|
204
216
|
if (debug) serverArgs.push('--debug');
|
|
205
217
|
if (nonInteractive) serverArgs.push('--non-interactive');
|
|
218
|
+
if (serverUrl) serverArgs.push('--server-url', serverUrl);
|
|
206
219
|
|
|
207
220
|
writeDebug(`Server arguments: ${serverArgs.join(' ')}`);
|
|
208
221
|
|
|
@@ -213,6 +226,7 @@ function startServerWithPath(serverPath) {
|
|
|
213
226
|
...process.env,
|
|
214
227
|
// Ensure environment variables are passed through
|
|
215
228
|
NODE_PATH: process.env.NODE_PATH || '',
|
|
229
|
+
SERVER_URL: serverUrl
|
|
216
230
|
}
|
|
217
231
|
});
|
|
218
232
|
|
package/dist/index.js
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
6
6
|
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
7
7
|
import express from 'express';
|
|
8
|
+
import cors from 'cors';
|
|
8
9
|
import path from 'path';
|
|
9
10
|
import { fileURLToPath } from 'url';
|
|
10
11
|
import fs from 'fs/promises';
|
|
@@ -16,7 +17,17 @@ import { multiUserMS365Auth } from './utils/multi-user-auth.js';
|
|
|
16
17
|
import { enhancedMS365Auth } from './utils/ms365-auth-enhanced.js';
|
|
17
18
|
// Create singleton MS365Operations instance
|
|
18
19
|
const ms365Ops = new MS365Operations();
|
|
19
|
-
let ms365Config
|
|
20
|
+
let ms365Config = {
|
|
21
|
+
setupAuth: false,
|
|
22
|
+
resetAuth: false,
|
|
23
|
+
debug: false,
|
|
24
|
+
nonInteractive: false,
|
|
25
|
+
multiUser: false,
|
|
26
|
+
login: false,
|
|
27
|
+
logout: false,
|
|
28
|
+
verifyLogin: false,
|
|
29
|
+
serverUrl: process.env.SERVER_URL || 'http://localhost:55000'
|
|
30
|
+
};
|
|
20
31
|
function parseArgs() {
|
|
21
32
|
const args = process.argv.slice(2);
|
|
22
33
|
const config = {
|
|
@@ -27,40 +38,36 @@ function parseArgs() {
|
|
|
27
38
|
multiUser: false,
|
|
28
39
|
login: false,
|
|
29
40
|
logout: false,
|
|
30
|
-
verifyLogin: false
|
|
41
|
+
verifyLogin: false,
|
|
42
|
+
serverUrl: process.env.SERVER_URL || 'http://localhost:55000'
|
|
31
43
|
};
|
|
32
44
|
for (let i = 0; i < args.length; i++) {
|
|
33
45
|
const arg = args[i];
|
|
34
|
-
if (arg === '--setup-auth')
|
|
46
|
+
if (arg === '--setup-auth')
|
|
35
47
|
config.setupAuth = true;
|
|
36
|
-
|
|
37
|
-
else if (arg === '--reset-auth') {
|
|
48
|
+
else if (arg === '--reset-auth')
|
|
38
49
|
config.resetAuth = true;
|
|
39
|
-
|
|
40
|
-
else if (arg === '--debug' || arg === '-d') {
|
|
50
|
+
else if (arg === '--debug')
|
|
41
51
|
config.debug = true;
|
|
42
|
-
|
|
43
|
-
else if (arg === '--non-interactive' || arg === '-n') {
|
|
52
|
+
else if (arg === '--non-interactive' || arg === '-n')
|
|
44
53
|
config.nonInteractive = true;
|
|
45
|
-
|
|
46
|
-
else if (arg === '--multi-user') {
|
|
54
|
+
else if (arg === '--multi-user')
|
|
47
55
|
config.multiUser = true;
|
|
48
|
-
|
|
49
|
-
else if (arg === '--login') {
|
|
56
|
+
else if (arg === '--login')
|
|
50
57
|
config.login = true;
|
|
51
|
-
|
|
52
|
-
else if (arg === '--logout') {
|
|
58
|
+
else if (arg === '--logout')
|
|
53
59
|
config.logout = true;
|
|
54
|
-
|
|
55
|
-
else if (arg === '--verify-login') {
|
|
60
|
+
else if (arg === '--verify-login')
|
|
56
61
|
config.verifyLogin = true;
|
|
62
|
+
else if (arg === '--server-url' && i + 1 < args.length) {
|
|
63
|
+
config.serverUrl = args[++i];
|
|
57
64
|
}
|
|
58
65
|
}
|
|
59
66
|
return config;
|
|
60
67
|
}
|
|
61
68
|
const server = new Server({
|
|
62
69
|
name: "ms365-mcp-server",
|
|
63
|
-
version: "1.1.
|
|
70
|
+
version: "1.1.8"
|
|
64
71
|
}, {
|
|
65
72
|
capabilities: {
|
|
66
73
|
resources: {
|
|
@@ -1052,10 +1059,17 @@ function getListOfArtifacts(functionName, attachments) {
|
|
|
1052
1059
|
// Set up Express server for file serving
|
|
1053
1060
|
const app = express();
|
|
1054
1061
|
const PORT = process.env.PORT || 55000;
|
|
1055
|
-
const SERVER_URL =
|
|
1062
|
+
const SERVER_URL = ms365Config.serverUrl || `http://localhost:${PORT}`;
|
|
1063
|
+
// Enable CORS for all routes
|
|
1064
|
+
app.use(cors());
|
|
1056
1065
|
// Get the directory name in ESM
|
|
1057
1066
|
const __filename = fileURLToPath(import.meta.url);
|
|
1058
1067
|
const __dirname = path.dirname(__filename);
|
|
1068
|
+
// Create public/attachments directory if it doesn't exist
|
|
1069
|
+
const attachmentsDir = path.join(__dirname, '../public/attachments');
|
|
1070
|
+
fs.mkdir(attachmentsDir, { recursive: true })
|
|
1071
|
+
.then(() => logger.log('Attachments directory ready'))
|
|
1072
|
+
.catch(err => logger.error('Error creating attachments directory:', err));
|
|
1059
1073
|
// Serve static files from public directory
|
|
1060
1074
|
app.use('/attachments', express.static(path.join(__dirname, '../public/attachments')));
|
|
1061
1075
|
// Start Express server
|
|
@@ -860,9 +860,6 @@ export class MS365Operations {
|
|
|
860
860
|
if (additionalCriteria.before) {
|
|
861
861
|
apiCall.filter(`receivedDateTime le ${new Date(additionalCriteria.before).toISOString()}`);
|
|
862
862
|
}
|
|
863
|
-
if (additionalCriteria.hasAttachment !== undefined) {
|
|
864
|
-
apiCall.filter(`hasAttachments eq ${additionalCriteria.hasAttachment}`);
|
|
865
|
-
}
|
|
866
863
|
if (additionalCriteria.isUnread !== undefined) {
|
|
867
864
|
apiCall.filter(`isRead eq ${!additionalCriteria.isUnread}`);
|
|
868
865
|
}
|
|
@@ -900,11 +897,15 @@ export class MS365Operations {
|
|
|
900
897
|
attachments: []
|
|
901
898
|
})) || [];
|
|
902
899
|
// Filter messages to only include those where the user is in TO or CC
|
|
903
|
-
|
|
900
|
+
let filteredMessages = messages.filter(message => {
|
|
904
901
|
const isInTo = message.toRecipients.some(recipient => recipient.address.toLowerCase() === userEmail.toLowerCase());
|
|
905
902
|
const isInCc = message.ccRecipients.some(recipient => recipient.address.toLowerCase() === userEmail.toLowerCase());
|
|
906
903
|
return isInTo || isInCc;
|
|
907
904
|
});
|
|
905
|
+
// Apply hasAttachment filter manually if specified
|
|
906
|
+
if (additionalCriteria.hasAttachment !== undefined) {
|
|
907
|
+
filteredMessages = filteredMessages.filter(message => message.hasAttachments === additionalCriteria.hasAttachment);
|
|
908
|
+
}
|
|
908
909
|
// Sort messages by receivedDateTime in descending order
|
|
909
910
|
filteredMessages.sort((a, b) => new Date(b.receivedDateTime).getTime() - new Date(a.receivedDateTime).getTime());
|
|
910
911
|
// For emails with attachments, get attachment counts
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ms365-mcp-server",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.8",
|
|
4
4
|
"description": "Microsoft 365 MCP Server for managing Microsoft 365 email through natural language interactions with full OAuth2 authentication support",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -33,6 +33,8 @@
|
|
|
33
33
|
"@azure/msal-node": "^2.6.6",
|
|
34
34
|
"@microsoft/microsoft-graph-client": "^3.0.7",
|
|
35
35
|
"@modelcontextprotocol/sdk": "^1.10.1",
|
|
36
|
+
"@types/cors": "^2.8.19",
|
|
37
|
+
"cors": "^2.8.5",
|
|
36
38
|
"express": "^5.1.0",
|
|
37
39
|
"isomorphic-fetch": "^3.0.0",
|
|
38
40
|
"keytar": "^7.9.0",
|