ms365-mcp-server 1.1.10 ā 1.1.12
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/index.js +26 -5
- package/dist/utils/ms365-operations.js +1120 -146
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -67,7 +67,7 @@ function parseArgs() {
|
|
|
67
67
|
}
|
|
68
68
|
const server = new Server({
|
|
69
69
|
name: "ms365-mcp-server",
|
|
70
|
-
version: "1.1.
|
|
70
|
+
version: "1.1.12"
|
|
71
71
|
}, {
|
|
72
72
|
capabilities: {
|
|
73
73
|
resources: {
|
|
@@ -83,6 +83,7 @@ const server = new Server({
|
|
|
83
83
|
}
|
|
84
84
|
}
|
|
85
85
|
});
|
|
86
|
+
logger.log('Server started with version 1.1.12');
|
|
86
87
|
// Set up the resource listing request handler
|
|
87
88
|
server.setRequestHandler(ListResourcesRequestSchema, async () => {
|
|
88
89
|
logger.log('Received list resources request');
|
|
@@ -185,7 +186,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
185
186
|
},
|
|
186
187
|
{
|
|
187
188
|
name: "manage_email",
|
|
188
|
-
description: "UNIFIED EMAIL MANAGEMENT: Read, search, list, mark, move, or delete emails. Combines all email operations in one powerful tool. Supports intelligent partial name matching, folder management, and advanced search criteria.",
|
|
189
|
+
description: "UNIFIED EMAIL MANAGEMENT: Read, search, list, mark, move, or delete emails. Combines all email operations in one powerful tool. Supports intelligent partial name matching, folder management, and advanced search criteria. IMPORTANT: Use 'reply_draft' or 'forward_draft' actions (not 'draft') to create threaded drafts that appear in email conversations.",
|
|
189
190
|
inputSchema: {
|
|
190
191
|
type: "object",
|
|
191
192
|
properties: {
|
|
@@ -196,7 +197,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
196
197
|
action: {
|
|
197
198
|
type: "string",
|
|
198
199
|
enum: ["read", "search", "list", "mark", "move", "delete", "search_to_me", "draft", "update_draft", "send_draft", "list_drafts", "reply_draft", "forward_draft"],
|
|
199
|
-
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/
|
|
200
|
+
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 standalone draft - NOTE: Use reply_draft/forward_draft for threaded drafts), update_draft (modify existing draft), send_draft (send saved draft), list_drafts (list draft emails), reply_draft (create threaded reply draft that appears in conversation), forward_draft (create threaded forward draft that appears in conversation)"
|
|
200
201
|
},
|
|
201
202
|
messageId: {
|
|
202
203
|
type: "string",
|
|
@@ -631,6 +632,8 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
631
632
|
}
|
|
632
633
|
// ============ UNIFIED EMAIL MANAGEMENT TOOL ============
|
|
633
634
|
case "manage_email":
|
|
635
|
+
// Debug logging for parameter validation
|
|
636
|
+
logger.log('DEBUG: manage_email called with args:', JSON.stringify(args, null, 2));
|
|
634
637
|
if (ms365Config.multiUser) {
|
|
635
638
|
const userId = args?.userId;
|
|
636
639
|
if (!userId) {
|
|
@@ -644,6 +647,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
644
647
|
ms365Ops.setGraphClient(graphClient);
|
|
645
648
|
}
|
|
646
649
|
const emailAction = args?.action;
|
|
650
|
+
logger.log(`DEBUG: Email action: ${emailAction}`);
|
|
647
651
|
switch (emailAction) {
|
|
648
652
|
case "read":
|
|
649
653
|
if (!args?.messageId) {
|
|
@@ -681,6 +685,8 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
681
685
|
};
|
|
682
686
|
case "search":
|
|
683
687
|
const searchResults = await ms365Ops.searchEmails(args);
|
|
688
|
+
logger.log(`DEBUG: Search results count: ${searchResults.messages.length}`);
|
|
689
|
+
logger.log(`DEBUG: First result:`, JSON.stringify(searchResults.messages[0], null, 2));
|
|
684
690
|
// Enhanced feedback for search results
|
|
685
691
|
let responseText = `š Email Search Results (${searchResults.messages.length} found)`;
|
|
686
692
|
if (searchResults.messages.length === 0) {
|
|
@@ -698,7 +704,12 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
698
704
|
responseText += `⢠Remove some search criteria to get broader results`;
|
|
699
705
|
}
|
|
700
706
|
else {
|
|
701
|
-
responseText += `\n\n${searchResults.messages.map((email, index) =>
|
|
707
|
+
responseText += `\n\n${searchResults.messages.map((email, index) => {
|
|
708
|
+
// Handle missing IDs more gracefully
|
|
709
|
+
const emailId = email.id || 'ID_MISSING';
|
|
710
|
+
const fromDisplay = email.from?.name ? `${email.from.name} <${email.from.address}>` : email.from?.address || 'Unknown sender';
|
|
711
|
+
return `${index + 1}. š§ ${email.subject || 'No subject'}\n š¤ From: ${fromDisplay}\n š
${email.receivedDateTime ? new Date(email.receivedDateTime).toLocaleDateString() : 'Unknown date'}\n ${email.isRead ? 'š Read' : 'š© Unread'}\n š ID: ${emailId}\n`;
|
|
712
|
+
}).join('\n')}`;
|
|
702
713
|
if (searchResults.hasMore) {
|
|
703
714
|
responseText += `\nš” There are more results available. Use maxResults parameter to get more emails.`;
|
|
704
715
|
}
|
|
@@ -840,6 +851,11 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
840
851
|
if (!args?.draftTo || !args?.draftSubject || !args?.draftBody) {
|
|
841
852
|
throw new Error("draftTo, draftSubject, and draftBody are required for draft action");
|
|
842
853
|
}
|
|
854
|
+
// Check if this looks like a reply based on subject
|
|
855
|
+
const isLikelyReply = args.draftSubject?.toString().toLowerCase().startsWith('re:');
|
|
856
|
+
if (isLikelyReply) {
|
|
857
|
+
logger.log('š SUGGESTION: Consider using "reply_draft" action instead of "draft" for threaded replies that appear in conversations');
|
|
858
|
+
}
|
|
843
859
|
const draftResult = await ms365Ops.saveDraftEmail({
|
|
844
860
|
to: args.draftTo,
|
|
845
861
|
cc: args.draftCc,
|
|
@@ -851,11 +867,16 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
851
867
|
attachments: args.draftAttachments,
|
|
852
868
|
conversationId: args.conversationId
|
|
853
869
|
});
|
|
870
|
+
let draftResponseText = `ā
Draft email saved successfully!\nš§ Subject: ${args.draftSubject}\nš„ To: ${Array.isArray(args.draftTo) ? args.draftTo.join(', ') : args.draftTo}\nš Draft ID: ${draftResult.id}`;
|
|
871
|
+
// Add helpful suggestion for threaded drafts
|
|
872
|
+
if (isLikelyReply) {
|
|
873
|
+
draftResponseText += `\n\nš” TIP: This looks like a reply email. For drafts that appear in email threads, use "reply_draft" action with the original message ID instead of "draft".`;
|
|
874
|
+
}
|
|
854
875
|
return {
|
|
855
876
|
content: [
|
|
856
877
|
{
|
|
857
878
|
type: "text",
|
|
858
|
-
text:
|
|
879
|
+
text: draftResponseText
|
|
859
880
|
}
|
|
860
881
|
]
|
|
861
882
|
};
|