v1.0.1: Fix accept-event registration, edit-rule-sequence import, timezone config

Bug fixes (non-breaking):
- Register accept-event tool in calendar module (was dead code)
- Add missing callGraphAPI + ensureAuthenticated imports to rules/index.js
  (edit-rule-sequence would throw ReferenceError at runtime)
- Make calendar event timezone configurable via MS_TIMEZONE env var
  (was hardcoded to UTC; default is now Eastern Standard Time)

Version bump: 1.0.0 → 1.0.1
README updated: 21 tools, MS_TIMEZONE in config table, known issues pruned
This commit is contained in:
Seton Carmichael 2026-06-21 19:43:54 -04:00
parent a7886b5b2b
commit ba45f57b39
7 changed files with 43 additions and 16 deletions

View file

@ -11,3 +11,8 @@ USE_TEST_MODE=false
# Optional: Enable verbose debug logging # Optional: Enable verbose debug logging
DEBUG_MODE=false DEBUG_MODE=false
# Optional: Default timezone for calendar event creation (IANA tz name).
# Examples: 'America/New_York', 'Europe/London', 'Australia/Sydney'
# Defaults to Eastern Standard Time if not set.
# MS_TIMEZONE=America/New_York

View file

@ -91,6 +91,7 @@ All configuration is via environment variables:
| `USE_TEST_MODE` | No | `false` | Use mock data instead of real API calls | | `USE_TEST_MODE` | No | `false` | Use mock data instead of real API calls |
| `DEBUG_MODE` | No | `false` | Verbose logging (MSAL, API calls, working directory) | | `DEBUG_MODE` | No | `false` | Verbose logging (MSAL, API calls, working directory) |
| `OUTLOOK_TOKEN_STORE_PATH` | No | `~/.outlook-mcp-tokens.json` | Token cache file path (override for multi-instance setups) | | `OUTLOOK_TOKEN_STORE_PATH` | No | `~/.outlook-mcp-tokens.json` | Token cache file path (override for multi-instance setups) |
| `MS_TIMEZONE` | No | `Eastern Standard Time` | Default timezone for calendar event creation (IANA or Windows timezone name) |
## MCP Client Configuration ## MCP Client Configuration
@ -149,7 +150,7 @@ Each instance gets its own MSAL cache — no account-selection conflicts.
## Tools Reference ## Tools Reference
The server exposes **20 tools** across five categories. The server exposes **21 tools** across five categories.
### Authentication (3 tools) ### Authentication (3 tools)
@ -174,12 +175,13 @@ The server exposes **20 tools** across five categories.
**Search strategy**: The server uses a progressive fallback approach because Graph API doesn't allow `$search` with `$orderby` or `$filter`. It tries: (1) combined KQL search with client-side boolean filtering, (2) individual term searches, (3) boolean-filter-only with `$filter` + `$orderby`, (4) fallback to recent emails. **Search strategy**: The server uses a progressive fallback approach because Graph API doesn't allow `$search` with `$orderby` or `$filter`. It tries: (1) combined KQL search with client-side boolean filtering, (2) individual term searches, (3) boolean-filter-only with `$filter` + `$orderby`, (4) fallback to recent emails.
### Calendar (5 tools) ### Calendar (6 tools)
| Tool | Key Parameters | Description | | Tool | Key Parameters | Description |
|---|---|---| |---|---|---|
| `list-events` | `count`, `startDate`, `endDate` | Lists events in a date range (defaults to upcoming from now) | | `list-events` | `count`, `startDate`, `endDate` | Lists events in a date range (defaults to upcoming from now) |
| `create-event` | `subject`, `start`, `end`, `attendees`, `body` | Creates a calendar event (times in ISO 8601, UTC timezone) | | `create-event` | `subject`, `start`, `end`, `attendees`, `body` | Creates a calendar event (times in ISO 8601, timezone configurable via `MS_TIMEZONE`) |
| `accept-event` | `eventId`, `comment` | Accepts a meeting invitation |
| `decline-event` | `eventId`, `comment` | Declines a meeting invitation | | `decline-event` | `eventId`, `comment` | Declines a meeting invitation |
| `cancel-event` | `eventId`, `comment` | Cancels an event you organized | | `cancel-event` | `eventId`, `comment` | Cancels an event you organized |
| `delete-event` | `eventId` | Deletes an event from your calendar | | `delete-event` | `eventId` | Deletes an event from your calendar |
@ -228,7 +230,7 @@ calendar/
decline.js # decline-event handler decline.js # decline-event handler
cancel.js # cancel-event handler cancel.js # cancel-event handler
delete.js # delete-event handler delete.js # delete-event handler
accept.js # ⚠️ Dead file — not registered (see Known Issues) accept.js # accept-event handler
folder/ folder/
index.js # Tool definitions for folder tools index.js # Tool definitions for folder tools
@ -291,13 +293,7 @@ Launches the [MCP Inspector](https://modelcontextprotocol.io/docs/tools/inspecto
## Known Issues ## Known Issues
1. **`calendar/accept.js` is not registered** — The `accept-event` handler exists in `calendar/accept.js` but is not imported or registered in `calendar/index.js`. The tool is unavailable to MCP clients. To fix: import and add it to `calendarTools`. 1. **`authenticate` `force` parameter is a no-op** — The `force` parameter is declared in the tool schema but never read by the handler. Calling `authenticate(force=false)` will still start a fresh device code flow. Use `check-auth-status` to check auth state without side effects.
2. **`rules/index.js` missing `callGraphAPI` import** — `handleEditRuleSequence` calls `callGraphAPI()` but the function is never imported at the top of the file. This will throw a `ReferenceError` at runtime when `edit-rule-sequence` is invoked. To fix: add `const { callGraphAPI } = require('../utils/graph-api');` to `rules/index.js`.
3. **Calendar events are created in UTC**`create-event` hardcodes `timeZone: "UTC"` for both start and end. Events created through the server will be in UTC regardless of the user's local timezone.
4. **`authenticate` `force` parameter is a no-op** — The `force` parameter is declared in the tool schema but never read by the handler. Calling `authenticate(force=false)` will still start a fresh device code flow. Use `check-auth-status` to check auth state without side effects.
## License ## License

View file

@ -3,6 +3,7 @@
*/ */
const { callGraphAPI } = require('../utils/graph-api'); const { callGraphAPI } = require('../utils/graph-api');
const { ensureAuthenticated } = require('../auth'); const { ensureAuthenticated } = require('../auth');
const config = require('../config');
/** /**
* Create event handler * Create event handler
@ -31,8 +32,8 @@ async function handleCreateEvent(args) {
// Request body // Request body
const bodyContent = { const bodyContent = {
subject, subject,
start: { dateTime: start, timeZone: "UTC" }, start: { dateTime: start, timeZone: config.DEFAULT_TIMEZONE },
end: { dateTime: end, timeZone: "UTC" }, end: { dateTime: end, timeZone: config.DEFAULT_TIMEZONE },
attendees: attendees?.map(email => ({ emailAddress: { address: email }, type: "required" })), attendees: attendees?.map(email => ({ emailAddress: { address: email }, type: "required" })),
body: { contentType: "HTML", content: body || "" } body: { contentType: "HTML", content: body || "" }
}; };

View file

@ -3,6 +3,7 @@
*/ */
const handleListEvents = require('./list'); const handleListEvents = require('./list');
const handleDeclineEvent = require('./decline'); const handleDeclineEvent = require('./decline');
const handleAcceptEvent = require('./accept');
const handleCreateEvent = require('./create'); const handleCreateEvent = require('./create');
const handleCancelEvent = require('./cancel'); const handleCancelEvent = require('./cancel');
const handleDeleteEvent = require('./delete'); const handleDeleteEvent = require('./delete');
@ -32,6 +33,25 @@ const calendarTools = [
}, },
handler: handleListEvents handler: handleListEvents
}, },
{
name: "accept-event",
description: "Accepts a calendar event",
inputSchema: {
type: "object",
properties: {
eventId: {
type: "string",
description: "The ID of the event to accept"
},
comment: {
type: "string",
description: "Optional comment for accepting the event"
}
},
required: ["eventId"]
},
handler: handleAcceptEvent
},
{ {
name: "decline-event", name: "decline-event",
description: "Declines a calendar event", description: "Declines a calendar event",
@ -124,6 +144,7 @@ const calendarTools = [
module.exports = { module.exports = {
calendarTools, calendarTools,
handleListEvents, handleListEvents,
handleAcceptEvent,
handleDeclineEvent, handleDeclineEvent,
handleCreateEvent, handleCreateEvent,
handleCancelEvent, handleCancelEvent,

View file

@ -10,7 +10,7 @@ const homeDir = process.env.HOME || process.env.USERPROFILE || os.homedir() || '
module.exports = { module.exports = {
// Server information // Server information
SERVER_NAME: "outlook-assistant-main", SERVER_NAME: "outlook-assistant-main",
SERVER_VERSION: "1.0.0", SERVER_VERSION: "1.0.1",
// Test mode setting // Test mode setting
USE_TEST_MODE: process.env.USE_TEST_MODE === 'true', USE_TEST_MODE: process.env.USE_TEST_MODE === 'true',
@ -43,7 +43,9 @@ module.exports = {
// Calendar constants // Calendar constants
CALENDAR_SELECT_FIELDS: 'id,subject,bodyPreview,start,end,location,organizer,attendees,isAllDay,isCancelled', CALENDAR_SELECT_FIELDS: 'id,subject,bodyPreview,start,end,location,organizer,attendees,isAllDay,isCancelled',
// Pagination // Default timezone for calendar event creation (IANA tz name, e.g. 'America/New_York').
// Override via MS_TIMEZONE env var. Graph API accepts IANA timezone identifiers.
DEFAULT_TIMEZONE: process.env.MS_TIMEZONE || 'Eastern Standard Time',
DEFAULT_PAGE_SIZE: 25, DEFAULT_PAGE_SIZE: 25,
MAX_RESULT_COUNT: 500 MAX_RESULT_COUNT: 500
}; };

View file

@ -1,6 +1,6 @@
{ {
"name": "outlook-mcp", "name": "outlook-mcp",
"version": "1.0.0", "version": "1.0.1",
"description": "MCP server for Claude to access Outlook data via Microsoft Graph API", "description": "MCP server for Claude to access Outlook data via Microsoft Graph API",
"main": "index.js", "main": "index.js",
"scripts": { "scripts": {

View file

@ -3,6 +3,8 @@
*/ */
const handleListRules = require('./list'); const handleListRules = require('./list');
const handleCreateRule = require('./create'); const handleCreateRule = require('./create');
const { callGraphAPI } = require('../utils/graph-api');
const { ensureAuthenticated } = require('../auth');
// Import getInboxRules for the edit sequence tool // Import getInboxRules for the edit sequence tool
const { getInboxRules } = require('./list'); const { getInboxRules } = require('./list');