fix(outlook-mcp): calendar list uses configured timezone and merge duplicate select fields

This commit is contained in:
Seton Carmichael 2026-06-21 20:53:30 -04:00
parent 68a64461eb
commit 11241a4f3e
3 changed files with 30 additions and 7 deletions

View file

@ -61,8 +61,17 @@ async function handleListEvents(args) {
// Format results // Format results
const eventList = response.value.map((event, index) => { const eventList = response.value.map((event, index) => {
const startDate = formatDateTime(event.start.dateTime, event.start.timeZone); // Graph stores timed events in UTC and returns dateTime without a 'Z' suffix.
const endDate = formatDateTime(event.end.dateTime, event.end.timeZone); // Normalize to UTC so the display matches the stored instant regardless of
// the container's default timezone.
const startDate = formatDateTime(
normalizeGraphDateTime(event.start.dateTime, event.start.timeZone),
config.DEFAULT_TIMEZONE
);
const endDate = formatDateTime(
normalizeGraphDateTime(event.end.dateTime, event.end.timeZone),
config.DEFAULT_TIMEZONE
);
const location = event.location.displayName || 'No location'; 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`; return `${index + 1}. ${event.subject} - Location: ${location}\nStart: ${startDate}\nEnd: ${endDate}\nSubject: ${event.subject}\nSummary: ${event.bodyPreview}\nID: ${event.id}\n`;
@ -93,4 +102,21 @@ async function handleListEvents(args) {
} }
} }
/**
* Ensure a Graph dateTime string is parsed as the intended instant.
* Graph returns timed events in UTC with no Z suffix; append Z so Node parses
* it as UTC rather than as the container's local timezone.
* @param {string} dateTime - Graph dateTime value
* @param {string} timeZone - Graph timeZone value
* @returns {string} - Date string safe for new Date()/toLocaleString
*/
function normalizeGraphDateTime(dateTime, timeZone) {
if (!dateTime) return dateTime;
const hasOffset = /Z|[+-]\d{2}:\d{2}$|[+-]\d{4}$/.test(dateTime);
if (!hasOffset && timeZone === 'UTC') {
return `${dateTime}Z`;
}
return dateTime;
}
module.exports = handleListEvents; module.exports = handleListEvents;

View file

@ -34,15 +34,12 @@ module.exports = {
GRAPH_API_ENDPOINT: 'https://graph.microsoft.com/v1.0/', GRAPH_API_ENDPOINT: 'https://graph.microsoft.com/v1.0/',
// Calendar constants // Calendar constants
CALENDAR_SELECT_FIELDS: 'id,subject,start,end,location,bodyPreview,isAllDay,recurrence,attendees', CALENDAR_SELECT_FIELDS: 'id,subject,bodyPreview,start,end,location,organizer,attendees,isAllDay,isCancelled,recurrence',
// Email constants // Email constants
EMAIL_SELECT_FIELDS: 'id,subject,from,toRecipients,ccRecipients,receivedDateTime,bodyPreview,hasAttachments,importance,isRead,conversationId', EMAIL_SELECT_FIELDS: 'id,subject,from,toRecipients,ccRecipients,receivedDateTime,bodyPreview,hasAttachments,importance,isRead,conversationId',
EMAIL_DETAIL_FIELDS: 'id,subject,from,toRecipients,ccRecipients,bccRecipients,receivedDateTime,bodyPreview,body,hasAttachments,importance,isRead,internetMessageHeaders', EMAIL_DETAIL_FIELDS: 'id,subject,from,toRecipients,ccRecipients,bccRecipients,receivedDateTime,bodyPreview,body,hasAttachments,importance,isRead,internetMessageHeaders',
// Calendar constants
CALENDAR_SELECT_FIELDS: 'id,subject,bodyPreview,start,end,location,organizer,attendees,isAllDay,isCancelled',
// Default timezone for calendar event creation and display (IANA tz name, e.g. 'America/New_York'). // Default timezone for calendar event creation and display (IANA tz name, e.g. 'America/New_York').
// Override via MS_TIMEZONE env var. Graph API accepts IANA timezone identifiers. // Override via MS_TIMEZONE env var. Graph API accepts IANA timezone identifiers.
DEFAULT_TIMEZONE: process.env.MS_TIMEZONE || 'America/New_York', DEFAULT_TIMEZONE: process.env.MS_TIMEZONE || 'America/New_York',

View file

@ -2,7 +2,7 @@
* Timezone-aware date formatting utilities for Outlook MCP Server. * Timezone-aware date formatting utilities for Outlook MCP Server.
* *
* All user-visible timestamps are formatted in the configured timezone * All user-visible timestamps are formatted in the configured timezone
* (MS_TIMEZONE env var, default Eastern Standard Time) so that dates * (MS_TIMEZONE env var, default America/New_York) so that dates
* rendered inside the UTC container still match the user's local time. * rendered inside the UTC container still match the user's local time.
*/ */
const config = require('../config'); const config = require('../config');