MCP server providing Microsoft Outlook integration via Graph API: - Email: list, search, read, send, thread reconstruction - Calendar: list, create, decline, cancel, delete events - Folders: list, create, move emails - Inbox rules: list, create, reorder - MSAL device code flow auth with persistent token cache - Test mode with mock data - Comprehensive README with setup, config, and tool reference 20 MCP tools across 5 modules. Node.js >= 14. MIT license.
113 lines
3.7 KiB
JavaScript
113 lines
3.7 KiB
JavaScript
/**
|
|
* Authentication-related tools for the Outlook MCP server
|
|
*/
|
|
const config = require('../config');
|
|
const tokenManager = require('./token-manager');
|
|
|
|
async function handleAbout() {
|
|
return {
|
|
content: [{
|
|
type: "text",
|
|
text: `Outlook Assistant MCP Server v${config.SERVER_VERSION}\n\nProvides access to Microsoft Outlook email, calendar, and contacts through Microsoft Graph API.`
|
|
}]
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Initiates device code flow via MSAL. Returns the code and URL to the user
|
|
* immediately; MSAL polls internally until the user completes sign-in.
|
|
*/
|
|
async function handleAuthenticate(args) {
|
|
if (config.USE_TEST_MODE) {
|
|
tokenManager.createTestTokens();
|
|
return {
|
|
content: [{ type: "text", text: 'Successfully authenticated with Microsoft Graph API (test mode)' }]
|
|
};
|
|
}
|
|
|
|
let flowResult;
|
|
try {
|
|
flowResult = await tokenManager.initiateDeviceCodeFlow();
|
|
} catch (err) {
|
|
console.error('[authenticate] Failed to initiate device code flow:', err.message);
|
|
return {
|
|
content: [{ type: "text", text: `Failed to start authentication: ${err.message}` }]
|
|
};
|
|
}
|
|
|
|
const { deviceCodeInfo, tokenPromise } = flowResult;
|
|
const { userCode, verificationUri, expiresIn } = deviceCodeInfo;
|
|
const minutesRemaining = Math.floor(expiresIn / 60);
|
|
|
|
// MSAL polls internally — just log completion when it resolves
|
|
tokenPromise
|
|
.then(result => {
|
|
if (result) console.error('[authenticate] Sign-in completed — MSAL cached tokens.');
|
|
})
|
|
.catch(err => {
|
|
console.error(`[authenticate] Device code flow ended: ${err.message}`);
|
|
});
|
|
|
|
return {
|
|
content: [{
|
|
type: "text",
|
|
text: [
|
|
`To sign in to Microsoft, please:`,
|
|
``,
|
|
` 1. Open: ${verificationUri}`,
|
|
` 2. Enter code: ${userCode}`,
|
|
``,
|
|
`You have ${minutesRemaining} minutes to complete sign-in.`,
|
|
`After signing in, call check-auth-status to confirm.`
|
|
].join('\n')
|
|
}]
|
|
};
|
|
}
|
|
|
|
async function handleCheckAuthStatus() {
|
|
console.error(`[CHECK-AUTH-STATUS] Checking for valid token...`);
|
|
try {
|
|
const token = await tokenManager.getAccessToken();
|
|
if (!token) {
|
|
console.error('[CHECK-AUTH-STATUS] No valid token found');
|
|
return { content: [{ type: "text", text: "Not authenticated" }] };
|
|
}
|
|
console.error('[CHECK-AUTH-STATUS] Valid token acquired');
|
|
return { content: [{ type: "text", text: "Authenticated and ready" }] };
|
|
} catch (e) {
|
|
console.error('[CHECK-AUTH-STATUS] Error:', e.message);
|
|
return { content: [{ type: "text", text: "Not authenticated" }] };
|
|
}
|
|
}
|
|
|
|
const authTools = [
|
|
{
|
|
name: "about",
|
|
description: "Returns information about this Outlook Assistant server",
|
|
inputSchema: { type: "object", properties: {}, required: [] },
|
|
handler: handleAbout
|
|
},
|
|
{
|
|
name: "authenticate",
|
|
description: "Authenticate with Microsoft Graph API using device code flow. Returns a short code and URL. IMPORTANT: Show the user the code and URL — they must visit the URL on any device and enter the code to complete sign-in. After they sign in, call check-auth-status to confirm.",
|
|
inputSchema: {
|
|
type: "object",
|
|
properties: {
|
|
force: {
|
|
anyOf: [{ type: "boolean" }, { type: "string" }],
|
|
description: "Force re-authentication even if already authenticated"
|
|
}
|
|
},
|
|
required: []
|
|
},
|
|
handler: handleAuthenticate
|
|
},
|
|
{
|
|
name: "check-auth-status",
|
|
description: "Check the current authentication status with Microsoft Graph API",
|
|
inputSchema: { type: "object", properties: {}, required: [] },
|
|
handler: handleCheckAuthStatus
|
|
}
|
|
];
|
|
|
|
module.exports = { authTools, handleAbout, handleAuthenticate, handleCheckAuthStatus };
|