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 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.10"
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/save draft), update_draft (modify existing draft), send_draft (send saved draft), list_drafts (list draft emails), reply_draft (create reply draft), forward_draft (create forward draft)"
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) => `${index + 1}. šŸ“§ ${email.subject}\n šŸ‘¤ From: ${email.from.name} <${email.from.address}>\n šŸ“… ${new Date(email.receivedDateTime).toLocaleDateString()}\n ${email.isRead ? 'šŸ“– Read' : 'šŸ“© Unread'}\n šŸ†” ID: ${email.id}\n`).join('\n')}`;
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: `āœ… Draft email saved successfully!\nšŸ“§ Subject: ${args.draftSubject}\nšŸ‘„ To: ${Array.isArray(args.draftTo) ? args.draftTo.join(', ') : args.draftTo}\nšŸ†” Draft ID: ${draftResult.id}`
879
+ text: draftResponseText
859
880
  }
860
881
  ]
861
882
  };