ms365-mcp-server 1.0.0 ā 1.0.2
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 +95 -362
- package/dist/index.js +144 -209
- package/dist/utils/ms365-auth-enhanced.js +202 -87
- package/dist/utils/ms365-operations.js +58 -4
- package/package.json +1 -1
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.0.
|
|
58
|
+
version: "1.0.2"
|
|
59
59
|
}, {
|
|
60
60
|
capabilities: {
|
|
61
61
|
resources: {
|
|
@@ -261,6 +261,64 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
261
261
|
additionalProperties: false
|
|
262
262
|
}
|
|
263
263
|
},
|
|
264
|
+
{
|
|
265
|
+
name: "search_emails_to_me",
|
|
266
|
+
description: "Search for emails addressed to YOU in both TO and CC fields. This automatically finds all emails where you are a recipient (direct TO or CC'd), without needing to specify your email address.",
|
|
267
|
+
inputSchema: {
|
|
268
|
+
type: "object",
|
|
269
|
+
properties: {
|
|
270
|
+
userId: {
|
|
271
|
+
type: "string",
|
|
272
|
+
description: "User ID for multi-user authentication (required if using multi-user mode)"
|
|
273
|
+
},
|
|
274
|
+
query: {
|
|
275
|
+
type: "string",
|
|
276
|
+
description: "General search query using natural language or specific terms"
|
|
277
|
+
},
|
|
278
|
+
from: {
|
|
279
|
+
type: "string",
|
|
280
|
+
description: "Search for emails from specific sender"
|
|
281
|
+
},
|
|
282
|
+
subject: {
|
|
283
|
+
type: "string",
|
|
284
|
+
description: "Search for emails with specific subject"
|
|
285
|
+
},
|
|
286
|
+
after: {
|
|
287
|
+
type: "string",
|
|
288
|
+
description: "Search for emails after date (format: YYYY-MM-DD)"
|
|
289
|
+
},
|
|
290
|
+
before: {
|
|
291
|
+
type: "string",
|
|
292
|
+
description: "Search for emails before date (format: YYYY-MM-DD)"
|
|
293
|
+
},
|
|
294
|
+
hasAttachment: {
|
|
295
|
+
type: "boolean",
|
|
296
|
+
description: "Filter emails that have attachments"
|
|
297
|
+
},
|
|
298
|
+
folder: {
|
|
299
|
+
type: "string",
|
|
300
|
+
description: "Search within specific folder (default: inbox)"
|
|
301
|
+
},
|
|
302
|
+
isUnread: {
|
|
303
|
+
type: "boolean",
|
|
304
|
+
description: "Filter for unread emails only"
|
|
305
|
+
},
|
|
306
|
+
importance: {
|
|
307
|
+
type: "string",
|
|
308
|
+
enum: ["low", "normal", "high"],
|
|
309
|
+
description: "Filter by email importance level"
|
|
310
|
+
},
|
|
311
|
+
maxResults: {
|
|
312
|
+
type: "number",
|
|
313
|
+
description: "Maximum number of results to return (default: 50, max: 200)",
|
|
314
|
+
minimum: 1,
|
|
315
|
+
maximum: 200,
|
|
316
|
+
default: 50
|
|
317
|
+
}
|
|
318
|
+
},
|
|
319
|
+
additionalProperties: false
|
|
320
|
+
}
|
|
321
|
+
},
|
|
264
322
|
{
|
|
265
323
|
name: "list_emails",
|
|
266
324
|
description: "List emails in inbox, sent, or custom folder. Returns basic email information including subjects, senders, and snippets with support for folder navigation.",
|
|
@@ -453,21 +511,6 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
453
511
|
additionalProperties: false
|
|
454
512
|
}
|
|
455
513
|
},
|
|
456
|
-
{
|
|
457
|
-
name: "get_my_session_info",
|
|
458
|
-
description: "Get information about your own authentication session (user-specific, secure).",
|
|
459
|
-
inputSchema: {
|
|
460
|
-
type: "object",
|
|
461
|
-
properties: {
|
|
462
|
-
userId: {
|
|
463
|
-
type: "string",
|
|
464
|
-
description: "Your User ID to get information for"
|
|
465
|
-
}
|
|
466
|
-
},
|
|
467
|
-
required: ["userId"],
|
|
468
|
-
additionalProperties: false
|
|
469
|
-
}
|
|
470
|
-
},
|
|
471
514
|
{
|
|
472
515
|
name: "remove_my_session",
|
|
473
516
|
description: "Remove your own authentication session (user-specific, secure).",
|
|
@@ -487,47 +530,38 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
487
530
|
// Add one-time authentication tool for single-user mode
|
|
488
531
|
const oneTimeAuthTools = [
|
|
489
532
|
{
|
|
490
|
-
name: "
|
|
491
|
-
description: "
|
|
533
|
+
name: "get_auth_link",
|
|
534
|
+
description: "Get a clickable Microsoft 365 authentication link without auto-opening browser. Perfect for manual authentication control.",
|
|
492
535
|
inputSchema: {
|
|
493
536
|
type: "object",
|
|
494
537
|
properties: {
|
|
495
538
|
force: {
|
|
496
539
|
type: "boolean",
|
|
497
|
-
description: "Force
|
|
540
|
+
description: "Force new authentication link even if already authenticated (default: false)",
|
|
498
541
|
default: false
|
|
499
542
|
}
|
|
500
543
|
},
|
|
501
544
|
additionalProperties: false
|
|
502
545
|
}
|
|
503
|
-
}
|
|
546
|
+
}
|
|
547
|
+
];
|
|
548
|
+
// Enhanced authentication tools with device code flow
|
|
549
|
+
const enhancedAuthTools = [
|
|
504
550
|
{
|
|
505
|
-
name: "
|
|
506
|
-
description: "
|
|
551
|
+
name: "authenticate_with_device_code",
|
|
552
|
+
description: "Complete device code authentication in MCP. First call shows device code, second call (after browser auth) completes the process. RECOMMENDED method.",
|
|
507
553
|
inputSchema: {
|
|
508
554
|
type: "object",
|
|
509
555
|
properties: {
|
|
510
556
|
force: {
|
|
511
557
|
type: "boolean",
|
|
512
|
-
description: "Force new authentication
|
|
558
|
+
description: "Force new authentication even if already authenticated (default: false)",
|
|
513
559
|
default: false
|
|
514
560
|
}
|
|
515
561
|
},
|
|
516
562
|
additionalProperties: false
|
|
517
563
|
}
|
|
518
564
|
},
|
|
519
|
-
{
|
|
520
|
-
name: "check_quick_auth_status",
|
|
521
|
-
description: "Check if quick authentication has completed successfully. Use this after using quick_authenticate to see if you're now authenticated.",
|
|
522
|
-
inputSchema: {
|
|
523
|
-
type: "object",
|
|
524
|
-
properties: {},
|
|
525
|
-
additionalProperties: false
|
|
526
|
-
}
|
|
527
|
-
}
|
|
528
|
-
];
|
|
529
|
-
// Enhanced authentication tools with device code flow
|
|
530
|
-
const enhancedAuthTools = [
|
|
531
565
|
{
|
|
532
566
|
name: "device_code_login",
|
|
533
567
|
description: "Start device code authentication flow and get the URL/code to enter. Shows authentication details immediately in the UI.",
|
|
@@ -543,15 +577,6 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
543
577
|
additionalProperties: false
|
|
544
578
|
}
|
|
545
579
|
},
|
|
546
|
-
{
|
|
547
|
-
name: "complete_device_code_auth",
|
|
548
|
-
description: "Check if device code authentication has completed after visiting the URL and entering the code. This is a quick status check - authentication happens automatically in the background.",
|
|
549
|
-
inputSchema: {
|
|
550
|
-
type: "object",
|
|
551
|
-
properties: {},
|
|
552
|
-
additionalProperties: false
|
|
553
|
-
}
|
|
554
|
-
},
|
|
555
580
|
{
|
|
556
581
|
name: "check_pending_auth",
|
|
557
582
|
description: "Check if there's a pending device code authentication and get the URL/code again if needed.",
|
|
@@ -579,24 +604,6 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
579
604
|
additionalProperties: false
|
|
580
605
|
}
|
|
581
606
|
},
|
|
582
|
-
{
|
|
583
|
-
name: "list_authenticated_accounts",
|
|
584
|
-
description: "List all authenticated Microsoft 365 accounts stored securely. Shows which accounts are available for use.",
|
|
585
|
-
inputSchema: {
|
|
586
|
-
type: "object",
|
|
587
|
-
properties: {},
|
|
588
|
-
additionalProperties: false
|
|
589
|
-
}
|
|
590
|
-
},
|
|
591
|
-
{
|
|
592
|
-
name: "get_storage_info",
|
|
593
|
-
description: "Get information about how credentials are stored (OS Keychain vs encrypted file). Useful for security auditing.",
|
|
594
|
-
inputSchema: {
|
|
595
|
-
type: "object",
|
|
596
|
-
properties: {},
|
|
597
|
-
additionalProperties: false
|
|
598
|
-
}
|
|
599
|
-
},
|
|
600
607
|
{
|
|
601
608
|
name: "logout",
|
|
602
609
|
description: "Log out and clear stored authentication tokens for the current user. This will require re-authentication.",
|
|
@@ -633,26 +640,54 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
633
640
|
try {
|
|
634
641
|
switch (name) {
|
|
635
642
|
// ============ ENHANCED AUTHENTICATION TOOLS ============
|
|
636
|
-
case "
|
|
637
|
-
|
|
638
|
-
//
|
|
639
|
-
|
|
640
|
-
|
|
643
|
+
case "authenticate_with_device_code":
|
|
644
|
+
try {
|
|
645
|
+
// Check if already authenticated
|
|
646
|
+
if (await enhancedMS365Auth.isAuthenticated() && !args?.force) {
|
|
647
|
+
return {
|
|
648
|
+
content: [
|
|
649
|
+
{
|
|
650
|
+
type: "text",
|
|
651
|
+
text: `ā
Already authenticated with Microsoft 365! Use force: true to re-authenticate.`
|
|
652
|
+
}
|
|
653
|
+
]
|
|
654
|
+
};
|
|
655
|
+
}
|
|
656
|
+
// First, try to complete any existing pending authentication
|
|
657
|
+
const existingResult = await enhancedMS365Auth.completeDeviceCodeAuth();
|
|
658
|
+
if (existingResult) {
|
|
659
|
+
const currentUser = await enhancedMS365Auth.getCurrentUser();
|
|
660
|
+
return {
|
|
661
|
+
content: [
|
|
662
|
+
{
|
|
663
|
+
type: "text",
|
|
664
|
+
text: `ā
Device code authentication completed successfully!\n\nš¤ User: ${currentUser || 'authenticated-user'}\nš Status: Valid\n\nš You can now use all Microsoft 365 email features!`
|
|
665
|
+
}
|
|
666
|
+
]
|
|
667
|
+
};
|
|
668
|
+
}
|
|
669
|
+
// Check if there's already a pending device code
|
|
670
|
+
let deviceCodeInfo = await enhancedMS365Auth.getPendingDeviceCodeInfo();
|
|
671
|
+
if (!deviceCodeInfo || args?.force) {
|
|
672
|
+
// No pending code or force new one, start fresh
|
|
673
|
+
deviceCodeInfo = await enhancedMS365Auth.startDeviceCodeAuth();
|
|
674
|
+
}
|
|
675
|
+
// Return device code information immediately (MCP pattern)
|
|
641
676
|
return {
|
|
642
677
|
content: [
|
|
643
678
|
{
|
|
644
679
|
type: "text",
|
|
645
|
-
text: `š Microsoft 365 Authentication
|
|
680
|
+
text: `š Microsoft 365 Device Code Authentication\n\nš± Visit: ${deviceCodeInfo.verificationUri}\nš Enter this code: ${deviceCodeInfo.userCode}\n\nā³ After completing authentication in your browser, call this tool again to finish the process.\n\nš” This code will expire in 15 minutes.`
|
|
646
681
|
}
|
|
647
682
|
]
|
|
648
683
|
};
|
|
649
684
|
}
|
|
650
|
-
|
|
685
|
+
catch (error) {
|
|
651
686
|
return {
|
|
652
687
|
content: [
|
|
653
688
|
{
|
|
654
689
|
type: "text",
|
|
655
|
-
text:
|
|
690
|
+
text: `ā Authentication failed: ${error.message}\n\nš” Try again or use CLI: node dist/index.js --login`
|
|
656
691
|
}
|
|
657
692
|
]
|
|
658
693
|
};
|
|
@@ -679,40 +714,6 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
679
714
|
]
|
|
680
715
|
};
|
|
681
716
|
}
|
|
682
|
-
case "check_quick_auth_status":
|
|
683
|
-
const isCurrentlyAuthenticated = await enhancedMS365Auth.isAuthenticated();
|
|
684
|
-
const hasPending = enhancedMS365Auth.hasPendingAuth();
|
|
685
|
-
if (isCurrentlyAuthenticated) {
|
|
686
|
-
return {
|
|
687
|
-
content: [
|
|
688
|
-
{
|
|
689
|
-
type: "text",
|
|
690
|
-
text: "ā
Quick authentication completed successfully! You can now use all Microsoft 365 email features."
|
|
691
|
-
}
|
|
692
|
-
]
|
|
693
|
-
};
|
|
694
|
-
}
|
|
695
|
-
else if (hasPending) {
|
|
696
|
-
const pendingInfo = enhancedMS365Auth.getPendingDeviceCodeInfo();
|
|
697
|
-
return {
|
|
698
|
-
content: [
|
|
699
|
-
{
|
|
700
|
-
type: "text",
|
|
701
|
-
text: `ā³ Authentication still pending.\n\nš± Please visit: ${pendingInfo?.verificationUri}\nš Enter code: ${pendingInfo?.userCode}\n\nš” Check again after entering the code in your browser. Authentication completes automatically - no need to wait or use additional tools.`
|
|
702
|
-
}
|
|
703
|
-
]
|
|
704
|
-
};
|
|
705
|
-
}
|
|
706
|
-
else {
|
|
707
|
-
return {
|
|
708
|
-
content: [
|
|
709
|
-
{
|
|
710
|
-
type: "text",
|
|
711
|
-
text: "ā No authentication found. Please use quick_authenticate to start the authentication process."
|
|
712
|
-
}
|
|
713
|
-
]
|
|
714
|
-
};
|
|
715
|
-
}
|
|
716
717
|
case "device_code_login":
|
|
717
718
|
if (!await enhancedMS365Auth.isAuthenticated() || args?.force) {
|
|
718
719
|
const deviceCodeInfo = await enhancedMS365Auth.startDeviceCodeAuth();
|
|
@@ -720,7 +721,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
720
721
|
content: [
|
|
721
722
|
{
|
|
722
723
|
type: "text",
|
|
723
|
-
text: `š Microsoft 365 Device Code Authentication Started!\n\nš± Visit: ${deviceCodeInfo.verificationUri}\nš Enter this code: ${deviceCodeInfo.userCode}\n\nā³ After entering the code, use the "
|
|
724
|
+
text: `š Microsoft 365 Device Code Authentication Started!\n\nš± Visit: ${deviceCodeInfo.verificationUri}\nš Enter this code: ${deviceCodeInfo.userCode}\n\nā³ After entering the code, use the "authenticate_with_device_code" tool to complete authentication.\n\nš” This code will expire in 15 minutes.`
|
|
724
725
|
}
|
|
725
726
|
]
|
|
726
727
|
};
|
|
@@ -735,53 +736,18 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
735
736
|
]
|
|
736
737
|
};
|
|
737
738
|
}
|
|
738
|
-
case "
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
content: [
|
|
742
|
-
{
|
|
743
|
-
type: "text",
|
|
744
|
-
text: "ā No pending device code authentication found. Use 'device_code_login' first to start the authentication process."
|
|
745
|
-
}
|
|
746
|
-
]
|
|
747
|
-
};
|
|
748
|
-
}
|
|
749
|
-
// Check if authentication has already completed (non-blocking)
|
|
750
|
-
const isNowAuthenticated = await enhancedMS365Auth.isAuthenticated();
|
|
751
|
-
if (isNowAuthenticated) {
|
|
739
|
+
case "check_pending_auth":
|
|
740
|
+
const pendingDeviceCodeState = await enhancedMS365Auth.getPendingDeviceCodeInfo();
|
|
741
|
+
if (pendingDeviceCodeState) {
|
|
752
742
|
return {
|
|
753
743
|
content: [
|
|
754
744
|
{
|
|
755
745
|
type: "text",
|
|
756
|
-
text:
|
|
746
|
+
text: `ā³ Pending Device Code Authentication\n\nš± Visit: ${pendingDeviceCodeState.verificationUri}\nš Enter this code: ${pendingDeviceCodeState.userCode}\n\nš” Use 'authenticate_with_device_code' to finish authentication after entering the code.`
|
|
757
747
|
}
|
|
758
748
|
]
|
|
759
749
|
};
|
|
760
750
|
}
|
|
761
|
-
// If still pending, return status with instructions
|
|
762
|
-
const pendingInfo = enhancedMS365Auth.getPendingDeviceCodeInfo();
|
|
763
|
-
return {
|
|
764
|
-
content: [
|
|
765
|
-
{
|
|
766
|
-
type: "text",
|
|
767
|
-
text: `ā³ Device code authentication still in progress.\n\nš± Please visit: ${pendingInfo?.verificationUri}\nš Enter code: ${pendingInfo?.userCode}\n\nš” Try this tool again after completing the authentication in your browser.\n\nNote: Authentication completes automatically once you enter the code - no need to wait.`
|
|
768
|
-
}
|
|
769
|
-
]
|
|
770
|
-
};
|
|
771
|
-
case "check_pending_auth":
|
|
772
|
-
if (enhancedMS365Auth.hasPendingAuth()) {
|
|
773
|
-
const pendingInfo = enhancedMS365Auth.getPendingDeviceCodeInfo();
|
|
774
|
-
if (pendingInfo) {
|
|
775
|
-
return {
|
|
776
|
-
content: [
|
|
777
|
-
{
|
|
778
|
-
type: "text",
|
|
779
|
-
text: `ā³ Pending Device Code Authentication\n\nš± Visit: ${pendingInfo.verificationUri}\nš Enter this code: ${pendingInfo.userCode}\n\nš” Use 'complete_device_code_auth' to finish authentication after entering the code.`
|
|
780
|
-
}
|
|
781
|
-
]
|
|
782
|
-
};
|
|
783
|
-
}
|
|
784
|
-
}
|
|
785
751
|
return {
|
|
786
752
|
content: [
|
|
787
753
|
{
|
|
@@ -802,64 +768,30 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
802
768
|
};
|
|
803
769
|
case "verify_authentication":
|
|
804
770
|
const isAuthenticated = await enhancedMS365Auth.isAuthenticated();
|
|
805
|
-
const
|
|
771
|
+
const currentUser = await enhancedMS365Auth.getCurrentUser();
|
|
806
772
|
const storageInfo = enhancedMS365Auth.getStorageInfo();
|
|
807
773
|
return {
|
|
808
774
|
content: [
|
|
809
775
|
{
|
|
810
776
|
type: "text",
|
|
811
|
-
text: `š Microsoft 365 Authentication Status\n\nš Authentication: ${isAuthenticated ? 'ā
Valid' : 'ā Not authenticated'}\n
|
|
777
|
+
text: `š Microsoft 365 Authentication Status\n\nš Authentication: ${isAuthenticated ? 'ā
Valid' : 'ā Not authenticated'}\nš¤ Current User: ${currentUser || 'None'}\nš¾ Storage method: ${storageInfo.method}\nš Storage location: ${storageInfo.location}`
|
|
812
778
|
}
|
|
813
779
|
]
|
|
814
780
|
};
|
|
815
|
-
case "
|
|
816
|
-
const
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
{
|
|
820
|
-
type: "text",
|
|
821
|
-
text: `š„ Authenticated Microsoft 365 Accounts:\n\n${authenticatedAccounts.length > 0 ? authenticatedAccounts.map(account => `⢠${account}`).join('\n') : 'No authenticated accounts found'}`
|
|
822
|
-
}
|
|
823
|
-
]
|
|
824
|
-
};
|
|
825
|
-
case "get_storage_info":
|
|
826
|
-
const storage = enhancedMS365Auth.getStorageInfo();
|
|
781
|
+
case "logout":
|
|
782
|
+
const accountKey = args?.accountKey;
|
|
783
|
+
const wasAuthenticated = await enhancedMS365Auth.isAuthenticated();
|
|
784
|
+
await enhancedMS365Auth.resetAuth();
|
|
827
785
|
return {
|
|
828
786
|
content: [
|
|
829
787
|
{
|
|
830
788
|
type: "text",
|
|
831
|
-
text:
|
|
789
|
+
text: wasAuthenticated ?
|
|
790
|
+
`ā
Successfully logged out from Microsoft 365.` :
|
|
791
|
+
`ā¹ļø No active authentication found.`
|
|
832
792
|
}
|
|
833
793
|
]
|
|
834
794
|
};
|
|
835
|
-
case "logout":
|
|
836
|
-
const accountKey = args?.accountKey;
|
|
837
|
-
// Get list of authenticated accounts before logout for better feedback
|
|
838
|
-
const authenticatedAccountsBefore = await enhancedMS365Auth.listAuthenticatedAccounts();
|
|
839
|
-
await enhancedMS365Auth.resetAuth(accountKey);
|
|
840
|
-
// Check what was actually logged out
|
|
841
|
-
const authenticatedAccountsAfter = await enhancedMS365Auth.listAuthenticatedAccounts();
|
|
842
|
-
const loggedOutAccounts = authenticatedAccountsBefore.filter(account => !authenticatedAccountsAfter.includes(account));
|
|
843
|
-
if (accountKey) {
|
|
844
|
-
return {
|
|
845
|
-
content: [
|
|
846
|
-
{
|
|
847
|
-
type: "text",
|
|
848
|
-
text: `ā
Successfully logged out from Microsoft 365. Account: ${accountKey}`
|
|
849
|
-
}
|
|
850
|
-
]
|
|
851
|
-
};
|
|
852
|
-
}
|
|
853
|
-
else {
|
|
854
|
-
return {
|
|
855
|
-
content: [
|
|
856
|
-
{
|
|
857
|
-
type: "text",
|
|
858
|
-
text: `ā
Successfully logged out from Microsoft 365.\n${loggedOutAccounts.length > 0 ? `Logged out accounts: ${loggedOutAccounts.join(', ')}` : 'No accounts found to logout'}`
|
|
859
|
-
}
|
|
860
|
-
]
|
|
861
|
-
};
|
|
862
|
-
}
|
|
863
795
|
// ============ MULTI-USER AUTHENTICATION TOOLS ============
|
|
864
796
|
case "authenticate_user":
|
|
865
797
|
if (!ms365Config.multiUser) {
|
|
@@ -874,25 +806,6 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
874
806
|
}
|
|
875
807
|
]
|
|
876
808
|
};
|
|
877
|
-
case "get_my_session_info":
|
|
878
|
-
if (!ms365Config.multiUser) {
|
|
879
|
-
throw new Error("Multi-user mode not enabled. Start server with --multi-user flag.");
|
|
880
|
-
}
|
|
881
|
-
if (!args?.userId) {
|
|
882
|
-
throw new Error("User ID is required");
|
|
883
|
-
}
|
|
884
|
-
const session = multiUserMS365Auth.getUserSession(args.userId);
|
|
885
|
-
if (!session) {
|
|
886
|
-
throw new Error(`User session not found: ${args.userId}`);
|
|
887
|
-
}
|
|
888
|
-
return {
|
|
889
|
-
content: [
|
|
890
|
-
{
|
|
891
|
-
type: "text",
|
|
892
|
-
text: `š¤ Session Information\n\nš User ID: ${session.userId}\nš§ Email: ${session.userEmail || 'Unknown'}\nš Authenticated: ${session.authenticated ? 'Yes' : 'No'}\nā° Expires: ${new Date(session.expiresOn).toLocaleString()}`
|
|
893
|
-
}
|
|
894
|
-
]
|
|
895
|
-
};
|
|
896
809
|
case "remove_my_session":
|
|
897
810
|
if (!ms365Config.multiUser) {
|
|
898
811
|
throw new Error("Multi-user mode not enabled. Start server with --multi-user flag.");
|
|
@@ -976,6 +889,28 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
976
889
|
}
|
|
977
890
|
]
|
|
978
891
|
};
|
|
892
|
+
case "search_emails_to_me":
|
|
893
|
+
if (ms365Config.multiUser) {
|
|
894
|
+
const userId = args?.userId;
|
|
895
|
+
if (!userId) {
|
|
896
|
+
throw new Error("User ID is required in multi-user mode");
|
|
897
|
+
}
|
|
898
|
+
const graphClient = await multiUserMS365Auth.getGraphClientForUser(userId);
|
|
899
|
+
ms365Ops.setGraphClient(graphClient);
|
|
900
|
+
}
|
|
901
|
+
else {
|
|
902
|
+
const graphClient = await enhancedMS365Auth.getGraphClient();
|
|
903
|
+
ms365Ops.setGraphClient(graphClient);
|
|
904
|
+
}
|
|
905
|
+
const searchToMeResults = await ms365Ops.searchEmailsToMe(args);
|
|
906
|
+
return {
|
|
907
|
+
content: [
|
|
908
|
+
{
|
|
909
|
+
type: "text",
|
|
910
|
+
text: `š Emails Addressed to You (TO & CC) - ${searchToMeResults.messages.length} found\n\n${searchToMeResults.messages.map((email, index) => `${index + 1}. š§ ${email.subject}\n š¤ From: ${email.from.name} <${email.from.address}>\n š
${new Date(email.receivedDateTime).toLocaleDateString()}\n š ID: ${email.id}\n`).join('\n')}`
|
|
911
|
+
}
|
|
912
|
+
]
|
|
913
|
+
};
|
|
979
914
|
case "list_emails":
|
|
980
915
|
if (ms365Config.multiUser) {
|
|
981
916
|
const userId = args?.userId;
|
|
@@ -1218,13 +1153,13 @@ async function main() {
|
|
|
1218
1153
|
if (ms365Config.verifyLogin) {
|
|
1219
1154
|
try {
|
|
1220
1155
|
const isAuthenticated = await enhancedMS365Auth.isAuthenticated();
|
|
1221
|
-
const
|
|
1156
|
+
const currentUser = await enhancedMS365Auth.getCurrentUser();
|
|
1222
1157
|
const storageInfo = enhancedMS365Auth.getStorageInfo();
|
|
1223
1158
|
console.log('\nš MS365 Authentication Status\n');
|
|
1224
1159
|
console.log(`Authentication: ${isAuthenticated ? 'ā
Valid' : 'ā Not authenticated'}`);
|
|
1160
|
+
console.log(`Current User: ${currentUser || 'None'}`);
|
|
1225
1161
|
console.log(`Storage method: ${storageInfo.method}`);
|
|
1226
|
-
console.log(`Storage location: ${storageInfo.location}`);
|
|
1227
|
-
console.log(`Authenticated accounts: ${accounts.length > 0 ? accounts.join(', ') : 'None'}\n`);
|
|
1162
|
+
console.log(`Storage location: ${storageInfo.location}\n`);
|
|
1228
1163
|
process.exit(isAuthenticated ? 0 : 1);
|
|
1229
1164
|
}
|
|
1230
1165
|
catch (error) {
|