ms365-mcp-server 1.1.12 → 1.1.13

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.12"
70
+ version: "1.1.13"
71
71
  }, {
72
72
  capabilities: {
73
73
  resources: {
@@ -83,7 +83,7 @@ const server = new Server({
83
83
  }
84
84
  }
85
85
  });
86
- logger.log('Server started with version 1.1.12');
86
+ logger.log('Server started with version 1.1.13');
87
87
  // Set up the resource listing request handler
88
88
  server.setRequestHandler(ListResourcesRequestSchema, async () => {
89
89
  logger.log('Received list resources request');
@@ -937,7 +937,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
937
937
  if (!args?.originalMessageId) {
938
938
  throw new Error("originalMessageId is required for reply_draft action");
939
939
  }
940
- const replyDraftResult = await ms365Ops.createReplyDraft(args.originalMessageId, args.draftBody, args.replyToAll || false);
940
+ const replyDraftResult = await ms365Ops.createReplyDraft(args.originalMessageId, args.draftBody, args.replyToAll || false, args.draftBodyType || 'text');
941
941
  return {
942
942
  content: [
943
943
  {
@@ -950,7 +950,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
950
950
  if (!args?.originalMessageId) {
951
951
  throw new Error("originalMessageId is required for forward_draft action");
952
952
  }
953
- const forwardDraftResult = await ms365Ops.createForwardDraft(args.originalMessageId, args.draftBody);
953
+ const forwardDraftResult = await ms365Ops.createForwardDraft(args.originalMessageId, args.draftBody, args.draftBodyType || 'text');
954
954
  return {
955
955
  content: [
956
956
  {
@@ -522,7 +522,7 @@ export class MS365Operations {
522
522
  /**
523
523
  * Create a threaded reply draft from a specific message
524
524
  */
525
- async createReplyDraft(originalMessageId, body, replyToAll = false) {
525
+ async createReplyDraft(originalMessageId, body, replyToAll = false, bodyType = 'text') {
526
526
  try {
527
527
  const graphClient = await this.getGraphClient();
528
528
  logger.log(`Creating reply draft for message: ${originalMessageId}`);
@@ -536,7 +536,25 @@ export class MS365Operations {
536
536
  const originalBodyContent = originalMessage.body?.content || '';
537
537
  const fromDisplay = originalMessage.from?.emailAddress?.name || originalMessage.from?.emailAddress?.address || '';
538
538
  const sentDate = new Date(originalMessage.sentDateTime).toLocaleString();
539
- const completeReplyBody = `${body || ''}
539
+ // Helper function to escape HTML characters
540
+ const escapeHtml = (text) => {
541
+ return text
542
+ .replace(/&/g, '&')
543
+ .replace(/</g, '&lt;')
544
+ .replace(/>/g, '&gt;')
545
+ .replace(/"/g, '&quot;')
546
+ .replace(/'/g, '&#x27;');
547
+ };
548
+ // Helper function to convert text to HTML
549
+ const textToHtml = (text) => {
550
+ return escapeHtml(text).replace(/\n/g, '<br>');
551
+ };
552
+ // Process the user's body based on the specified type
553
+ let processedUserBody = body || '';
554
+ if (bodyType === 'text' && processedUserBody) {
555
+ processedUserBody = textToHtml(processedUserBody);
556
+ }
557
+ const completeReplyBody = `${processedUserBody}
540
558
 
541
559
  <br><br>
542
560
  <div style="border-left: 2px solid #ccc; padding-left: 10px; margin-top: 10px;">
@@ -670,20 +688,38 @@ ${originalBodyContent}
670
688
  /**
671
689
  * Create a threaded forward draft from a specific message
672
690
  */
673
- async createForwardDraft(originalMessageId, comment) {
691
+ async createForwardDraft(originalMessageId, comment, bodyType = 'text') {
674
692
  try {
675
693
  const graphClient = await this.getGraphClient();
676
694
  logger.log(`Creating forward draft for message: ${originalMessageId}`);
677
695
  // First, try using the official Microsoft Graph createForward endpoint for proper threading
678
696
  try {
679
697
  logger.log(`Using official Graph API endpoint: /me/messages/${originalMessageId}/createForward`);
698
+ // Helper function to escape HTML characters
699
+ const escapeHtml = (text) => {
700
+ return text
701
+ .replace(/&/g, '&amp;')
702
+ .replace(/</g, '&lt;')
703
+ .replace(/>/g, '&gt;')
704
+ .replace(/"/g, '&quot;')
705
+ .replace(/'/g, '&#x27;');
706
+ };
707
+ // Helper function to convert text to HTML
708
+ const textToHtml = (text) => {
709
+ return escapeHtml(text).replace(/\n/g, '<br>');
710
+ };
711
+ // Process the comment based on the specified type
712
+ let processedComment = comment || '';
713
+ if (bodyType === 'text' && processedComment) {
714
+ processedComment = textToHtml(processedComment);
715
+ }
680
716
  const forwardDraft = await graphClient
681
717
  .api(`/me/messages/${originalMessageId}/createForward`)
682
718
  .post({
683
719
  message: {
684
720
  body: {
685
721
  contentType: 'html',
686
- content: comment || ''
722
+ content: processedComment
687
723
  }
688
724
  }
689
725
  });
@@ -717,11 +753,29 @@ ${originalBodyContent}
717
753
  referencesHeader = `${existingReferences.value} ${referencesHeader}`;
718
754
  }
719
755
  }
720
- const forwardedBody = `${comment ? comment + '\n\n' : ''}---------- Forwarded message ----------\nFrom: ${originalMessage.from?.emailAddress?.name || originalMessage.from?.emailAddress?.address}\nDate: ${originalMessage.sentDateTime}\nSubject: ${originalMessage.subject}\nTo: ${originalMessage.toRecipients?.map((r) => r.emailAddress.address).join(', ')}\n\n${originalMessage.body?.content || ''}`;
756
+ // Helper function to escape HTML characters for fallback
757
+ const escapeHtml = (text) => {
758
+ return text
759
+ .replace(/&/g, '&amp;')
760
+ .replace(/</g, '&lt;')
761
+ .replace(/>/g, '&gt;')
762
+ .replace(/"/g, '&quot;')
763
+ .replace(/'/g, '&#x27;');
764
+ };
765
+ // Helper function to convert text to HTML for fallback
766
+ const textToHtml = (text) => {
767
+ return escapeHtml(text).replace(/\n/g, '<br>');
768
+ };
769
+ // Process the comment based on the specified type for fallback
770
+ let processedComment = comment || '';
771
+ if (bodyType === 'text' && processedComment) {
772
+ processedComment = textToHtml(processedComment);
773
+ }
774
+ const forwardedBody = `${processedComment ? processedComment + '<br><br>' : ''}---------- Forwarded message ----------<br>From: ${originalMessage.from?.emailAddress?.name || originalMessage.from?.emailAddress?.address}<br>Date: ${originalMessage.sentDateTime}<br>Subject: ${originalMessage.subject}<br>To: ${originalMessage.toRecipients?.map((r) => r.emailAddress.address).join(', ')}<br><br>${originalMessage.body?.content || ''}`;
721
775
  const draftBody = {
722
776
  subject: originalMessage.subject?.startsWith('Fwd:') ? originalMessage.subject : `Fwd: ${originalMessage.subject}`,
723
777
  body: {
724
- contentType: originalMessage.body?.contentType || 'html',
778
+ contentType: 'html',
725
779
  content: forwardedBody
726
780
  },
727
781
  conversationId: originalMessage.conversationId,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ms365-mcp-server",
3
- "version": "1.1.12",
3
+ "version": "1.1.13",
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",