outlook-mcp/auth/tools.js
Seton Carmichael a7886b5b2b Initial commit: Outlook MCP Server v1.0.0
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.
2026-06-21 19:39:31 -04:00

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 };