outlook-mcp/calendar/list.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

94 lines
2.9 KiB
JavaScript

/**
* List events functionality
*/
const config = require('../config');
const { callGraphAPI } = require('../utils/graph-api');
const { ensureAuthenticated } = require('../auth');
/**
* List events handler
* @param {object} args - Tool arguments
* @returns {object} - MCP response
*/
async function handleListEvents(args) {
const count = Math.min(parseInt(args.count, 10) || 10, config.MAX_RESULT_COUNT);
// Resolve date range — accept plain YYYY-MM-DD or full ISO datetime
const toISO = (dateStr, endOfDay = false) => {
if (!dateStr) return null;
// If just a date (no T), append time component
if (/^\d{4}-\d{2}-\d{2}$/.test(dateStr)) {
return endOfDay ? `${dateStr}T23:59:59Z` : `${dateStr}T00:00:00Z`;
}
return new Date(dateStr).toISOString();
};
const startISO = toISO(args.startDate) || new Date().toISOString();
const endISO = toISO(args.endDate, true);
try {
// Get access token
const accessToken = await ensureAuthenticated();
// Build API endpoint
let endpoint = 'me/events';
// Build date filter
const filterParts = [`start/dateTime ge '${startISO}'`];
if (endISO) filterParts.push(`end/dateTime le '${endISO}'`);
// Add query parameters
const queryParams = {
$top: count,
$orderby: 'start/dateTime',
$filter: filterParts.join(' and '),
$select: config.CALENDAR_SELECT_FIELDS
};
// Make API call
const response = await callGraphAPI(accessToken, 'GET', endpoint, null, queryParams);
if (!response.value || response.value.length === 0) {
return {
content: [{
type: "text",
text: "No calendar events found."
}]
};
}
// Format results
const eventList = response.value.map((event, index) => {
const startDate = new Date(event.start.dateTime).toLocaleString(event.start.timeZone);
const endDate = new Date(event.end.dateTime).toLocaleString(event.end.timeZone);
const location = event.location.displayName || 'No location';
return `${index + 1}. ${event.subject} - Location: ${location}\nStart: ${startDate}\nEnd: ${endDate}\nSubject: ${event.subject}\nSummary: ${event.bodyPreview}\nID: ${event.id}\n`;
}).join("\n");
return {
content: [{
type: "text",
text: `Found ${response.value.length} events:\n\n${eventList}`
}]
};
} catch (error) {
if (error.message === 'Authentication required') {
return {
content: [{
type: "text",
text: "Authentication required. Please use the 'authenticate' tool first."
}]
};
}
return {
content: [{
type: "text",
text: `Error listing events: ${error.message}`
}]
};
}
}
module.exports = handleListEvents;