ms365-mcp-server 1.1.14 ā 1.1.16
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 +87 -9
- package/dist/utils/ms365-operations.js +917 -171
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -10,7 +10,7 @@ import path from 'path';
|
|
|
10
10
|
import { fileURLToPath } from 'url';
|
|
11
11
|
import fs from 'fs/promises';
|
|
12
12
|
import crypto from 'crypto';
|
|
13
|
-
import { CallToolRequestSchema, ListResourcesRequestSchema, ListToolsRequestSchema, ListPromptsRequestSchema, ReadResourceRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
|
|
13
|
+
import { CallToolRequestSchema, ListResourcesRequestSchema, ListToolsRequestSchema, ListPromptsRequestSchema, ReadResourceRequestSchema, ListResourceTemplatesRequestSchema, GetPromptRequestSchema } from '@modelcontextprotocol/sdk/types.js';
|
|
14
14
|
import { logger } from './utils/api.js';
|
|
15
15
|
import { MS365Operations } from './utils/ms365-operations.js';
|
|
16
16
|
import { multiUserMS365Auth } from './utils/multi-user-auth.js';
|
|
@@ -67,23 +67,28 @@ function parseArgs() {
|
|
|
67
67
|
}
|
|
68
68
|
const server = new Server({
|
|
69
69
|
name: "ms365-mcp-server",
|
|
70
|
-
version: "1.1.
|
|
70
|
+
version: "1.1.16"
|
|
71
71
|
}, {
|
|
72
72
|
capabilities: {
|
|
73
73
|
resources: {
|
|
74
74
|
read: true,
|
|
75
|
-
list: true
|
|
75
|
+
list: true,
|
|
76
|
+
templates: true
|
|
76
77
|
},
|
|
77
78
|
tools: {
|
|
78
79
|
list: true,
|
|
79
80
|
call: true
|
|
80
81
|
},
|
|
81
82
|
prompts: {
|
|
83
|
+
list: true,
|
|
84
|
+
get: true
|
|
85
|
+
},
|
|
86
|
+
resourceTemplates: {
|
|
82
87
|
list: true
|
|
83
88
|
}
|
|
84
89
|
}
|
|
85
90
|
});
|
|
86
|
-
logger.log('Server started with version 1.1.
|
|
91
|
+
logger.log('Server started with version 1.1.16');
|
|
87
92
|
// Set up the resource listing request handler
|
|
88
93
|
server.setRequestHandler(ListResourcesRequestSchema, async () => {
|
|
89
94
|
logger.log('Received list resources request');
|
|
@@ -103,6 +108,20 @@ server.setRequestHandler(ListPromptsRequestSchema, async () => {
|
|
|
103
108
|
logger.log('Received list prompts request');
|
|
104
109
|
return { prompts: [] };
|
|
105
110
|
});
|
|
111
|
+
/**
|
|
112
|
+
* Handler for getting a specific prompt.
|
|
113
|
+
*/
|
|
114
|
+
server.setRequestHandler(GetPromptRequestSchema, async (request) => {
|
|
115
|
+
logger.log('Received get prompt request: ' + JSON.stringify(request));
|
|
116
|
+
throw new Error("Prompt getting not implemented");
|
|
117
|
+
});
|
|
118
|
+
/**
|
|
119
|
+
* Handler for listing available resource templates.
|
|
120
|
+
*/
|
|
121
|
+
server.setRequestHandler(ListResourceTemplatesRequestSchema, async () => {
|
|
122
|
+
logger.log('Received list resource templates request');
|
|
123
|
+
return { resourceTemplates: [] };
|
|
124
|
+
});
|
|
106
125
|
/**
|
|
107
126
|
* List available tools for interacting with Microsoft 365.
|
|
108
127
|
*/
|
|
@@ -201,8 +220,8 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
201
220
|
},
|
|
202
221
|
action: {
|
|
203
222
|
type: "string",
|
|
204
|
-
enum: ["read", "search", "list", "mark", "move", "delete", "search_to_me", "draft", "update_draft", "send_draft", "list_drafts", "reply_draft", "forward_draft"],
|
|
205
|
-
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)"
|
|
223
|
+
enum: ["read", "search", "search_batched", "list", "mark", "move", "delete", "search_to_me", "draft", "update_draft", "send_draft", "list_drafts", "reply_draft", "forward_draft"],
|
|
224
|
+
description: "Action to perform: read (get email by ID), search (find emails), search_batched (find emails in batches of 50, up to 5 batches for better performance), 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)"
|
|
206
225
|
},
|
|
207
226
|
messageId: {
|
|
208
227
|
type: "string",
|
|
@@ -273,11 +292,24 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
273
292
|
},
|
|
274
293
|
maxResults: {
|
|
275
294
|
type: "number",
|
|
276
|
-
description: "Maximum number of results to return (
|
|
277
|
-
minimum:
|
|
278
|
-
maximum: 200,
|
|
295
|
+
description: "Maximum number of results to return. Set to 0 or omit to get ALL matching results (safety limited to 1000). For large result sets, use specific maxResults values to avoid timeouts. Default: 50",
|
|
296
|
+
minimum: 0,
|
|
279
297
|
default: 50
|
|
280
298
|
},
|
|
299
|
+
batchSize: {
|
|
300
|
+
type: "number",
|
|
301
|
+
description: "Number of results per batch for search_batched action (default: 50)",
|
|
302
|
+
minimum: 10,
|
|
303
|
+
maximum: 100,
|
|
304
|
+
default: 50
|
|
305
|
+
},
|
|
306
|
+
maxBatches: {
|
|
307
|
+
type: "number",
|
|
308
|
+
description: "Maximum number of batches for search_batched action (default: 5)",
|
|
309
|
+
minimum: 1,
|
|
310
|
+
maximum: 10,
|
|
311
|
+
default: 5
|
|
312
|
+
},
|
|
281
313
|
// Draft email parameters
|
|
282
314
|
draftTo: {
|
|
283
315
|
oneOf: [
|
|
@@ -726,6 +758,52 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
726
758
|
}
|
|
727
759
|
]
|
|
728
760
|
};
|
|
761
|
+
case "search_batched":
|
|
762
|
+
const batchSize = args?.batchSize || 50;
|
|
763
|
+
const maxBatches = args?.maxBatches || 5;
|
|
764
|
+
logger.log(`DEBUG: Starting batched search with batchSize: ${batchSize}, maxBatches: ${maxBatches}`);
|
|
765
|
+
const batchedSearchResults = await ms365Ops.searchEmailsBatched(args, batchSize, maxBatches);
|
|
766
|
+
logger.log(`DEBUG: Batched search results count: ${batchedSearchResults.messages.length} from ${batchedSearchResults.totalBatches} batches`);
|
|
767
|
+
// Enhanced feedback for batched search results
|
|
768
|
+
let batchedResponseText = `š Batched Email Search Results (${batchedSearchResults.messages.length} found from ${batchedSearchResults.totalBatches} batches)`;
|
|
769
|
+
if (batchedSearchResults.messages.length === 0) {
|
|
770
|
+
batchedResponseText = `š No emails found matching your criteria.\n\nš” Search Tips:\n`;
|
|
771
|
+
if (args?.from) {
|
|
772
|
+
batchedResponseText += `⢠Try partial names: "${args.from.split(' ')[0]}" or "${args.from.split(' ').pop()}"\n`;
|
|
773
|
+
batchedResponseText += `⢠Check spelling of sender name\n`;
|
|
774
|
+
}
|
|
775
|
+
if (args?.subject) {
|
|
776
|
+
batchedResponseText += `⢠Try broader subject terms\n`;
|
|
777
|
+
}
|
|
778
|
+
if (args?.after || args?.before) {
|
|
779
|
+
batchedResponseText += `⢠Try expanding date range\n`;
|
|
780
|
+
}
|
|
781
|
+
batchedResponseText += `⢠Remove some search criteria to get broader results`;
|
|
782
|
+
}
|
|
783
|
+
else {
|
|
784
|
+
batchedResponseText += `\n\n${batchedSearchResults.messages.map((email, index) => {
|
|
785
|
+
// Handle missing IDs more gracefully
|
|
786
|
+
const emailId = email.id || 'ID_MISSING';
|
|
787
|
+
const fromDisplay = email.from?.name ? `${email.from.name} <${email.from.address}>` : email.from?.address || 'Unknown sender';
|
|
788
|
+
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`;
|
|
789
|
+
}).join('\n')}`;
|
|
790
|
+
if (batchedSearchResults.hasMore) {
|
|
791
|
+
batchedResponseText += `\nš” There are more results available. Increase maxBatches parameter to get more emails.`;
|
|
792
|
+
}
|
|
793
|
+
batchedResponseText += `\n\nš Search Summary:\n`;
|
|
794
|
+
batchedResponseText += `⢠Total results: ${batchedSearchResults.messages.length}\n`;
|
|
795
|
+
batchedResponseText += `⢠Batches processed: ${batchedSearchResults.totalBatches}/${maxBatches}\n`;
|
|
796
|
+
batchedResponseText += `⢠Batch size: ${batchSize}\n`;
|
|
797
|
+
batchedResponseText += `⢠More results available: ${batchedSearchResults.hasMore ? 'Yes' : 'No'}`;
|
|
798
|
+
}
|
|
799
|
+
return {
|
|
800
|
+
content: [
|
|
801
|
+
{
|
|
802
|
+
type: "text",
|
|
803
|
+
text: batchedResponseText
|
|
804
|
+
}
|
|
805
|
+
]
|
|
806
|
+
};
|
|
729
807
|
case "search_to_me":
|
|
730
808
|
const searchToMeResults = await ms365Ops.searchEmailsToMe(args);
|
|
731
809
|
// Process attachments for each email
|