ms365-mcp-server 1.1.0 ā 1.1.1
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 +15 -1
- package/dist/index.js +83 -3
- package/dist/utils/ms365-operations.js +68 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -16,7 +16,7 @@ A powerful **Model Context Protocol (MCP) server** that enables seamless Microso
|
|
|
16
16
|
|
|
17
17
|
### **š§ Email Management**
|
|
18
18
|
- **`send_email`** - Send emails with attachments and rich formatting
|
|
19
|
-
- **`manage_email`** - **UNIFIED**: Read, search, list, mark, move, or
|
|
19
|
+
- **`manage_email`** - **UNIFIED**: Read, search, list, mark, move, delete, or draft emails
|
|
20
20
|
- **`get_attachment`** - Download email attachments with metadata
|
|
21
21
|
- **`list_folders`** - Browse mailbox folders with item counts
|
|
22
22
|
|
|
@@ -200,6 +200,20 @@ ms365-mcp-server --login
|
|
|
200
200
|
"messageId": "email_id"
|
|
201
201
|
}
|
|
202
202
|
}
|
|
203
|
+
|
|
204
|
+
// Create draft email
|
|
205
|
+
{
|
|
206
|
+
"tool": "manage_email",
|
|
207
|
+
"arguments": {
|
|
208
|
+
"action": "draft",
|
|
209
|
+
"draftTo": ["colleague@company.com"],
|
|
210
|
+
"draftSubject": "Draft: Project Update",
|
|
211
|
+
"draftBody": "<h2>Status Report</h2><p>Project is on track!</p>",
|
|
212
|
+
"draftBodyType": "html",
|
|
213
|
+
"draftCc": ["manager@company.com"],
|
|
214
|
+
"draftImportance": "normal"
|
|
215
|
+
}
|
|
216
|
+
}
|
|
203
217
|
```
|
|
204
218
|
|
|
205
219
|
### Contact & Authentication
|
package/dist/index.js
CHANGED
|
@@ -55,7 +55,7 @@ function parseArgs() {
|
|
|
55
55
|
}
|
|
56
56
|
const server = new Server({
|
|
57
57
|
name: "ms365-mcp-server",
|
|
58
|
-
version: "1.1.
|
|
58
|
+
version: "1.1.1"
|
|
59
59
|
}, {
|
|
60
60
|
capabilities: {
|
|
61
61
|
resources: {
|
|
@@ -183,8 +183,8 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
183
183
|
},
|
|
184
184
|
action: {
|
|
185
185
|
type: "string",
|
|
186
|
-
enum: ["read", "search", "list", "mark", "move", "delete", "search_to_me"],
|
|
187
|
-
description: "Action to perform: read (get email by ID), search (find emails), list (folder contents), mark (read/unread), move (to folder), delete (permanently), search_to_me (emails addressed to you)"
|
|
186
|
+
enum: ["read", "search", "list", "mark", "move", "delete", "search_to_me", "draft"],
|
|
187
|
+
description: "Action to perform: read (get email by ID), search (find emails), list (folder contents), mark (read/unread), move (to folder), delete (permanently), search_to_me (emails addressed to you), draft (create/save draft)"
|
|
188
188
|
},
|
|
189
189
|
messageId: {
|
|
190
190
|
type: "string",
|
|
@@ -259,6 +259,64 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
259
259
|
minimum: 1,
|
|
260
260
|
maximum: 200,
|
|
261
261
|
default: 50
|
|
262
|
+
},
|
|
263
|
+
// Draft email parameters
|
|
264
|
+
draftTo: {
|
|
265
|
+
type: "array",
|
|
266
|
+
items: { type: "string" },
|
|
267
|
+
description: "List of recipient email addresses (required for draft action)"
|
|
268
|
+
},
|
|
269
|
+
draftCc: {
|
|
270
|
+
type: "array",
|
|
271
|
+
items: { type: "string" },
|
|
272
|
+
description: "List of CC recipient email addresses (optional for draft action)"
|
|
273
|
+
},
|
|
274
|
+
draftBcc: {
|
|
275
|
+
type: "array",
|
|
276
|
+
items: { type: "string" },
|
|
277
|
+
description: "List of BCC recipient email addresses (optional for draft action)"
|
|
278
|
+
},
|
|
279
|
+
draftSubject: {
|
|
280
|
+
type: "string",
|
|
281
|
+
description: "Email subject line (required for draft action)"
|
|
282
|
+
},
|
|
283
|
+
draftBody: {
|
|
284
|
+
type: "string",
|
|
285
|
+
description: "Email content (required for draft action)"
|
|
286
|
+
},
|
|
287
|
+
draftBodyType: {
|
|
288
|
+
type: "string",
|
|
289
|
+
enum: ["text", "html"],
|
|
290
|
+
description: "Content type of the email body for draft (default: text)",
|
|
291
|
+
default: "text"
|
|
292
|
+
},
|
|
293
|
+
draftImportance: {
|
|
294
|
+
type: "string",
|
|
295
|
+
enum: ["low", "normal", "high"],
|
|
296
|
+
description: "Email importance level for draft (default: normal)",
|
|
297
|
+
default: "normal"
|
|
298
|
+
},
|
|
299
|
+
draftAttachments: {
|
|
300
|
+
type: "array",
|
|
301
|
+
items: {
|
|
302
|
+
type: "object",
|
|
303
|
+
properties: {
|
|
304
|
+
name: {
|
|
305
|
+
type: "string",
|
|
306
|
+
description: "Name of the attachment file"
|
|
307
|
+
},
|
|
308
|
+
contentBytes: {
|
|
309
|
+
type: "string",
|
|
310
|
+
description: "Base64 encoded content of the attachment"
|
|
311
|
+
},
|
|
312
|
+
contentType: {
|
|
313
|
+
type: "string",
|
|
314
|
+
description: "MIME type of the attachment (optional, auto-detected if not provided)"
|
|
315
|
+
}
|
|
316
|
+
},
|
|
317
|
+
required: ["name", "contentBytes"]
|
|
318
|
+
},
|
|
319
|
+
description: "List of email attachments for draft (optional)"
|
|
262
320
|
}
|
|
263
321
|
},
|
|
264
322
|
required: ["action"],
|
|
@@ -653,6 +711,28 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
653
711
|
}
|
|
654
712
|
]
|
|
655
713
|
};
|
|
714
|
+
case "draft":
|
|
715
|
+
if (!args?.draftTo || !args?.draftSubject || !args?.draftBody) {
|
|
716
|
+
throw new Error("draftTo, draftSubject, and draftBody are required for draft action");
|
|
717
|
+
}
|
|
718
|
+
const draftResult = await ms365Ops.saveDraftEmail({
|
|
719
|
+
to: args.draftTo,
|
|
720
|
+
cc: args.draftCc,
|
|
721
|
+
bcc: args.draftBcc,
|
|
722
|
+
subject: args.draftSubject,
|
|
723
|
+
body: args.draftBody,
|
|
724
|
+
bodyType: args.draftBodyType || 'text',
|
|
725
|
+
importance: args.draftImportance || 'normal',
|
|
726
|
+
attachments: args.draftAttachments
|
|
727
|
+
});
|
|
728
|
+
return {
|
|
729
|
+
content: [
|
|
730
|
+
{
|
|
731
|
+
type: "text",
|
|
732
|
+
text: `ā
Draft email saved successfully!\nš§ Subject: ${args.draftSubject}\nš„ To: ${Array.isArray(args.draftTo) ? args.draftTo.join(', ') : args.draftTo}\nš Draft ID: ${draftResult.id}`
|
|
733
|
+
}
|
|
734
|
+
]
|
|
735
|
+
};
|
|
656
736
|
default:
|
|
657
737
|
throw new Error(`Unknown email action: ${emailAction}`);
|
|
658
738
|
}
|
|
@@ -244,6 +244,74 @@ export class MS365Operations {
|
|
|
244
244
|
throw error;
|
|
245
245
|
}
|
|
246
246
|
}
|
|
247
|
+
/**
|
|
248
|
+
* Save a draft email
|
|
249
|
+
*/
|
|
250
|
+
async saveDraftEmail(message) {
|
|
251
|
+
try {
|
|
252
|
+
const graphClient = await this.getGraphClient();
|
|
253
|
+
// Prepare recipients
|
|
254
|
+
const toRecipients = message.to.map(email => ({
|
|
255
|
+
emailAddress: {
|
|
256
|
+
address: email,
|
|
257
|
+
name: email.split('@')[0]
|
|
258
|
+
}
|
|
259
|
+
}));
|
|
260
|
+
const ccRecipients = message.cc?.map(email => ({
|
|
261
|
+
emailAddress: {
|
|
262
|
+
address: email,
|
|
263
|
+
name: email.split('@')[0]
|
|
264
|
+
}
|
|
265
|
+
})) || [];
|
|
266
|
+
const bccRecipients = message.bcc?.map(email => ({
|
|
267
|
+
emailAddress: {
|
|
268
|
+
address: email,
|
|
269
|
+
name: email.split('@')[0]
|
|
270
|
+
}
|
|
271
|
+
})) || [];
|
|
272
|
+
// Prepare attachments
|
|
273
|
+
const attachments = message.attachments?.map(att => ({
|
|
274
|
+
'@odata.type': '#microsoft.graph.fileAttachment',
|
|
275
|
+
name: att.name,
|
|
276
|
+
contentBytes: att.contentBytes,
|
|
277
|
+
contentType: att.contentType || 'application/octet-stream'
|
|
278
|
+
})) || [];
|
|
279
|
+
// Prepare draft email body
|
|
280
|
+
const draftBody = {
|
|
281
|
+
subject: message.subject,
|
|
282
|
+
body: {
|
|
283
|
+
contentType: message.bodyType === 'html' ? 'html' : 'text',
|
|
284
|
+
content: message.body || ''
|
|
285
|
+
},
|
|
286
|
+
toRecipients,
|
|
287
|
+
ccRecipients,
|
|
288
|
+
bccRecipients,
|
|
289
|
+
importance: message.importance || 'normal',
|
|
290
|
+
attachments: attachments.length > 0 ? attachments : undefined
|
|
291
|
+
};
|
|
292
|
+
if (message.replyTo) {
|
|
293
|
+
draftBody.replyTo = [{
|
|
294
|
+
emailAddress: {
|
|
295
|
+
address: message.replyTo,
|
|
296
|
+
name: message.replyTo.split('@')[0]
|
|
297
|
+
}
|
|
298
|
+
}];
|
|
299
|
+
}
|
|
300
|
+
// Save draft email
|
|
301
|
+
const result = await graphClient
|
|
302
|
+
.api('/me/messages')
|
|
303
|
+
.post(draftBody);
|
|
304
|
+
logger.log('Draft email saved successfully');
|
|
305
|
+
return {
|
|
306
|
+
id: result.id,
|
|
307
|
+
status: 'draft'
|
|
308
|
+
};
|
|
309
|
+
}
|
|
310
|
+
catch (error) {
|
|
311
|
+
logger.error('Error saving draft email:', error);
|
|
312
|
+
throw error;
|
|
313
|
+
}
|
|
314
|
+
}
|
|
247
315
|
/**
|
|
248
316
|
* Get email by ID
|
|
249
317
|
*/
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ms365-mcp-server",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.1",
|
|
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",
|
|
@@ -55,4 +55,4 @@
|
|
|
55
55
|
"engines": {
|
|
56
56
|
"node": ">=18.0.0"
|
|
57
57
|
}
|
|
58
|
-
}
|
|
58
|
+
}
|