ms365-mcp-server 1.1.5 → 1.1.7
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 +25 -19
- package/dist/utils/ms365-operations.js +35 -5
- package/package.json +1 -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
|
@@ -16,7 +16,17 @@ import { multiUserMS365Auth } from './utils/multi-user-auth.js';
|
|
|
16
16
|
import { enhancedMS365Auth } from './utils/ms365-auth-enhanced.js';
|
|
17
17
|
// Create singleton MS365Operations instance
|
|
18
18
|
const ms365Ops = new MS365Operations();
|
|
19
|
-
let ms365Config
|
|
19
|
+
let ms365Config = {
|
|
20
|
+
setupAuth: false,
|
|
21
|
+
resetAuth: false,
|
|
22
|
+
debug: false,
|
|
23
|
+
nonInteractive: false,
|
|
24
|
+
multiUser: false,
|
|
25
|
+
login: false,
|
|
26
|
+
logout: false,
|
|
27
|
+
verifyLogin: false,
|
|
28
|
+
serverUrl: process.env.SERVER_URL || 'http://localhost:55000'
|
|
29
|
+
};
|
|
20
30
|
function parseArgs() {
|
|
21
31
|
const args = process.argv.slice(2);
|
|
22
32
|
const config = {
|
|
@@ -27,40 +37,36 @@ function parseArgs() {
|
|
|
27
37
|
multiUser: false,
|
|
28
38
|
login: false,
|
|
29
39
|
logout: false,
|
|
30
|
-
verifyLogin: false
|
|
40
|
+
verifyLogin: false,
|
|
41
|
+
serverUrl: process.env.SERVER_URL || 'http://localhost:55000'
|
|
31
42
|
};
|
|
32
43
|
for (let i = 0; i < args.length; i++) {
|
|
33
44
|
const arg = args[i];
|
|
34
|
-
if (arg === '--setup-auth')
|
|
45
|
+
if (arg === '--setup-auth')
|
|
35
46
|
config.setupAuth = true;
|
|
36
|
-
|
|
37
|
-
else if (arg === '--reset-auth') {
|
|
47
|
+
else if (arg === '--reset-auth')
|
|
38
48
|
config.resetAuth = true;
|
|
39
|
-
|
|
40
|
-
else if (arg === '--debug' || arg === '-d') {
|
|
49
|
+
else if (arg === '--debug')
|
|
41
50
|
config.debug = true;
|
|
42
|
-
|
|
43
|
-
else if (arg === '--non-interactive' || arg === '-n') {
|
|
51
|
+
else if (arg === '--non-interactive' || arg === '-n')
|
|
44
52
|
config.nonInteractive = true;
|
|
45
|
-
|
|
46
|
-
else if (arg === '--multi-user') {
|
|
53
|
+
else if (arg === '--multi-user')
|
|
47
54
|
config.multiUser = true;
|
|
48
|
-
|
|
49
|
-
else if (arg === '--login') {
|
|
55
|
+
else if (arg === '--login')
|
|
50
56
|
config.login = true;
|
|
51
|
-
|
|
52
|
-
else if (arg === '--logout') {
|
|
57
|
+
else if (arg === '--logout')
|
|
53
58
|
config.logout = true;
|
|
54
|
-
|
|
55
|
-
else if (arg === '--verify-login') {
|
|
59
|
+
else if (arg === '--verify-login')
|
|
56
60
|
config.verifyLogin = true;
|
|
61
|
+
else if (arg === '--server-url' && i + 1 < args.length) {
|
|
62
|
+
config.serverUrl = args[++i];
|
|
57
63
|
}
|
|
58
64
|
}
|
|
59
65
|
return config;
|
|
60
66
|
}
|
|
61
67
|
const server = new Server({
|
|
62
68
|
name: "ms365-mcp-server",
|
|
63
|
-
version: "1.1.
|
|
69
|
+
version: "1.1.7"
|
|
64
70
|
}, {
|
|
65
71
|
capabilities: {
|
|
66
72
|
resources: {
|
|
@@ -1052,7 +1058,7 @@ function getListOfArtifacts(functionName, attachments) {
|
|
|
1052
1058
|
// Set up Express server for file serving
|
|
1053
1059
|
const app = express();
|
|
1054
1060
|
const PORT = process.env.PORT || 55000;
|
|
1055
|
-
const SERVER_URL =
|
|
1061
|
+
const SERVER_URL = ms365Config.serverUrl || `http://localhost:${PORT}`;
|
|
1056
1062
|
// Get the directory name in ESM
|
|
1057
1063
|
const __filename = fileURLToPath(import.meta.url);
|
|
1058
1064
|
const __dirname = path.dirname(__filename);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { logger } from './api.js';
|
|
2
|
+
import mimeTypes from 'mime-types';
|
|
2
3
|
/**
|
|
3
4
|
* Microsoft 365 operations manager class
|
|
4
5
|
*/
|
|
@@ -686,19 +687,48 @@ export class MS365Operations {
|
|
|
686
687
|
async getAttachment(messageId, attachmentId) {
|
|
687
688
|
try {
|
|
688
689
|
const graphClient = await this.getGraphClient();
|
|
690
|
+
logger.log(`Fetching attachment ${attachmentId} from message ${messageId}...`);
|
|
691
|
+
// First get attachment metadata
|
|
689
692
|
const attachment = await graphClient
|
|
690
693
|
.api(`/me/messages/${messageId}/attachments/${attachmentId}`)
|
|
691
694
|
.get();
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
695
|
+
logger.log(`Retrieved attachment metadata: ${attachment.name} (${attachment.contentType}, ${attachment.size} bytes)`);
|
|
696
|
+
// Determine content type if not provided
|
|
697
|
+
let contentType = attachment.contentType;
|
|
698
|
+
if (!contentType && attachment.name) {
|
|
699
|
+
contentType = mimeTypes.lookup(attachment.name) || 'application/octet-stream';
|
|
700
|
+
logger.log(`Inferred content type for ${attachment.name}: ${contentType}`);
|
|
701
|
+
}
|
|
702
|
+
// Validate content bytes
|
|
703
|
+
if (!attachment.contentBytes) {
|
|
704
|
+
logger.error('No content bytes found in attachment');
|
|
705
|
+
throw new Error('Attachment content is empty');
|
|
706
|
+
}
|
|
707
|
+
// Return the attachment data
|
|
708
|
+
const result = {
|
|
709
|
+
name: attachment.name || 'unnamed_attachment',
|
|
710
|
+
contentType: contentType || 'application/octet-stream',
|
|
711
|
+
contentBytes: attachment.contentBytes,
|
|
696
712
|
size: attachment.size || 0
|
|
697
713
|
};
|
|
714
|
+
logger.log(`Successfully processed attachment: ${result.name} (${result.contentType}, ${result.size} bytes)`);
|
|
715
|
+
return result;
|
|
698
716
|
}
|
|
699
717
|
catch (error) {
|
|
700
718
|
logger.error('Error getting attachment:', error);
|
|
701
|
-
|
|
719
|
+
// Provide more specific error messages
|
|
720
|
+
if (error.status === 404) {
|
|
721
|
+
throw new Error(`Attachment not found: ${error.message}`);
|
|
722
|
+
}
|
|
723
|
+
else if (error.status === 401) {
|
|
724
|
+
throw new Error('Authentication failed. Please re-authenticate.');
|
|
725
|
+
}
|
|
726
|
+
else if (error.status === 403) {
|
|
727
|
+
throw new Error('Permission denied to access this attachment.');
|
|
728
|
+
}
|
|
729
|
+
else {
|
|
730
|
+
throw new Error(`Failed to get attachment: ${error.message}`);
|
|
731
|
+
}
|
|
702
732
|
}
|
|
703
733
|
}
|
|
704
734
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ms365-mcp-server",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.7",
|
|
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",
|