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 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.6"
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 = process.env.SERVER_URL || `http://localhost:${PORT}`;
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
- const filteredMessages = messages.filter(message => {
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.6",
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",