@joshluedeman/m365-mcp 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/server.ts","../src/tools/tasks/schemas.ts","../src/graph/client.ts","../src/utils/pagination.ts","../src/utils/formatting.ts","../src/utils/errors.ts","../src/tools/tasks/handlers.ts","../src/tools/tasks/index.ts","../src/tools/calendar/schemas.ts","../src/tools/calendar/handlers.ts","../src/tools/calendar/index.ts","../src/tools/mail/schemas.ts","../src/tools/mail/handlers.ts","../src/tools/mail/index.ts","../src/tools/contacts/schemas.ts","../src/tools/contacts/handlers.ts","../src/tools/contacts/index.ts","../src/version.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport { runAuthCommand } from './auth/device-code-flow.js';\nimport { createServer } from './server.js';\n\nconst command = process.argv[2];\n\nasync function main(): Promise<void> {\n if (command === 'setup') {\n const { runSetupCommand } = await import('./setup/index.js');\n await runSetupCommand();\n return;\n }\n\n if (command === 'auth') {\n await runAuthCommand();\n return;\n }\n\n // Default: start MCP server on stdio transport\n const server = createServer();\n const transport = new StdioServerTransport();\n\n // Catch unhandled transport errors — never crash the process\n process.on('uncaughtException', (err) => {\n process.stderr.write(`[m365-mcp] Uncaught exception: ${String(err)}\\n`);\n });\n\n process.on('unhandledRejection', (reason) => {\n process.stderr.write(`[m365-mcp] Unhandled rejection: ${String(reason)}\\n`);\n });\n\n await server.connect(transport);\n}\n\nmain().catch((err) => {\n process.stderr.write(`[m365-mcp] Fatal startup error: ${String(err)}\\n`);\n process.exit(1);\n});\n","import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { register as registerTasks } from './tools/tasks/index.js';\nimport { register as registerCalendar } from './tools/calendar/index.js';\nimport { register as registerMail } from './tools/mail/index.js';\nimport { register as registerContacts } from './tools/contacts/index.js';\nimport { VERSION } from './version.js';\n\n/**\n * Creates and configures the MCP server with all domain tool registrations.\n * Returns the server instance ready to be connected to a transport.\n */\nexport function createServer(): McpServer {\n const server = new McpServer({\n name: 'm365-mcp',\n version: VERSION,\n });\n\n registerTasks(server);\n registerCalendar(server);\n registerMail(server);\n registerContacts(server);\n\n return server;\n}\n","import { z } from 'zod';\n\nexport const ListTasksSchema = {\n listId: z.string().describe('The ID of the To Do task list'),\n filter: z.string().optional().describe('OData $filter expression (e.g. \"status eq \\'notStarted\\'\")'),\n top: z.number().int().min(1).max(100).optional().describe('Maximum number of tasks to return (1-100)'),\n};\n\nexport const GetTaskSchema = {\n listId: z.string().describe('The ID of the To Do task list'),\n taskId: z.string().describe('The ID of the task'),\n};\n\nexport const CreateTaskSchema = {\n listId: z.string().describe('The ID of the To Do task list'),\n title: z.string().describe('Task title'),\n body: z.string().optional().describe('Task body / notes (plain text)'),\n dueDate: z.string().optional().describe('Due date in ISO 8601 format (e.g. 2026-06-01)'),\n importance: z\n .enum(['low', 'normal', 'high'])\n .optional()\n .describe('Task importance level'),\n};\n\nexport const UpdateTaskSchema = {\n listId: z.string().describe('The ID of the To Do task list'),\n taskId: z.string().describe('The ID of the task'),\n title: z.string().optional().describe('Updated task title'),\n body: z.string().optional().describe('Updated task body / notes'),\n dueDate: z.string().optional().describe('Updated due date in ISO 8601 format'),\n importance: z.enum(['low', 'normal', 'high']).optional().describe('Updated importance level'),\n};\n\nexport const CompleteTaskSchema = {\n listId: z.string().describe('The ID of the To Do task list'),\n taskId: z.string().describe('The ID of the task to mark complete'),\n};\n\nexport const DeleteTaskSchema = {\n listId: z.string().describe('The ID of the To Do task list'),\n taskId: z.string().describe('The ID of the task to delete'),\n};\n","import { Client } from '@microsoft/microsoft-graph-client';\nimport type { AuthenticationProvider } from '@microsoft/microsoft-graph-client';\n\n/**\n * Creates an authenticated Microsoft Graph client using the provided access token.\n * The token is injected via a custom AuthenticationProvider — no MSAL coupling here.\n */\nexport function getGraphClient(accessToken: string): Client {\n const authProvider: AuthenticationProvider = {\n getAccessToken: async (): Promise<string> => accessToken,\n };\n\n return Client.initWithMiddleware({ authProvider });\n}\n","import type { Client } from '@microsoft/microsoft-graph-client';\n\ninterface PagedResponse<T> {\n value?: T[];\n '@odata.nextLink'?: string;\n}\n\n/**\n * Follows @odata.nextLink cursors to collect all pages for a Graph API list response.\n * Returns an empty array if the first response has no `value` property.\n */\nexport async function collectAllPages<T>(client: Client, url: string): Promise<T[]> {\n const results: T[] = [];\n let nextUrl: string | undefined = url;\n\n while (nextUrl !== undefined) {\n const response = await client.api(nextUrl).get() as PagedResponse<T>;\n\n if (Array.isArray(response.value)) {\n results.push(...response.value);\n }\n\n nextUrl = response['@odata.nextLink'];\n }\n\n return results;\n}\n","import type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';\n\n/**\n * Shapes arbitrary data into an MCP CallToolResult with a single text content block.\n * All Graph API responses flow through here for consistent serialization.\n */\nexport function formatResponse(data: unknown): CallToolResult {\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(data, null, 2),\n },\n ],\n };\n}\n\n/**\n * Returns a formatted error result (isError: true) for tool-level error reporting.\n * Use this when an error should be surfaced to the LLM rather than thrown as an MCP protocol error.\n */\nexport function formatError(message: string): CallToolResult {\n return {\n content: [\n {\n type: 'text',\n text: message,\n },\n ],\n isError: true,\n };\n}\n","import { McpError, ErrorCode } from '@modelcontextprotocol/sdk/types.js';\n\ninterface GraphErrorResponse {\n code?: string;\n message?: string;\n innerError?: {\n code?: string;\n message?: string;\n 'retry-after'?: string;\n };\n}\n\ninterface GraphErrorBody {\n error?: GraphErrorResponse;\n}\n\ninterface GraphApiError {\n statusCode?: number;\n body?: string | GraphErrorBody;\n message?: string;\n}\n\n/**\n * Parses a Microsoft Graph API error into a human-readable string.\n * Handles 429 throttling by surfacing retry-after information.\n */\nexport function parseGraphError(err: unknown): string {\n if (err instanceof Error) {\n // Graph client wraps errors with statusCode + body\n const graphErr = err as GraphApiError & Error;\n\n if (graphErr.statusCode === 429) {\n let retryAfter = 'unknown';\n try {\n if (typeof graphErr.body === 'string') {\n const parsed = JSON.parse(graphErr.body) as GraphErrorBody;\n retryAfter = parsed.error?.innerError?.['retry-after'] ?? 'unknown';\n } else if (typeof graphErr.body === 'object' && graphErr.body !== null) {\n retryAfter = graphErr.body.error?.innerError?.['retry-after'] ?? 'unknown';\n }\n } catch {\n // ignore parse errors\n }\n return `Graph API rate limit exceeded (429). Retry after ${retryAfter} seconds.`;\n }\n\n if (graphErr.statusCode !== undefined && graphErr.body !== undefined) {\n try {\n const body: GraphErrorBody =\n typeof graphErr.body === 'string'\n ? (JSON.parse(graphErr.body) as GraphErrorBody)\n : graphErr.body;\n\n const code = body.error?.code ?? 'UnknownError';\n const message = body.error?.message ?? graphErr.message;\n return `Graph API error [${graphErr.statusCode}] ${code}: ${message}`;\n } catch {\n return `Graph API error [${graphErr.statusCode}]: ${graphErr.message}`;\n }\n }\n\n return `Error: ${err.message}`;\n }\n\n return `Unexpected error: ${String(err)}`;\n}\n\n/**\n * Creates an MCP protocol error with a clean error message.\n */\nexport function createMcpError(message: string): McpError {\n return new McpError(ErrorCode.InternalError, message);\n}\n","import type { TodoTask, TodoTaskList } from '@microsoft/microsoft-graph-types';\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';\nimport { acquireToken } from '../../auth/device-code-flow.js';\nimport { getGraphClient } from '../../graph/client.js';\nimport { collectAllPages } from '../../utils/pagination.js';\nimport { formatResponse, formatError } from '../../utils/formatting.js';\nimport { parseGraphError } from '../../utils/errors.js';\n\nexport async function handleListTaskLists(): Promise<CallToolResult> {\n try {\n const token = await acquireToken();\n const client = getGraphClient(token);\n const lists = await collectAllPages<TodoTaskList>(client, '/me/todo/lists');\n return formatResponse(lists);\n } catch (err) {\n return formatError(parseGraphError(err));\n }\n}\n\nexport async function handleListTasks(\n listId: string,\n filter?: string,\n top?: number,\n): Promise<CallToolResult> {\n try {\n const token = await acquireToken();\n const client = getGraphClient(token);\n\n let request = client.api(`/me/todo/lists/${listId}/tasks`);\n if (filter !== undefined) {\n request = request.filter(filter);\n }\n if (top !== undefined) {\n request = request.top(top);\n }\n\n const response = await request.get() as { value?: TodoTask[]; '@odata.nextLink'?: string };\n const tasks: TodoTask[] = response.value ?? [];\n\n // Follow nextLink if top was not specified\n if (top === undefined && response['@odata.nextLink'] !== undefined) {\n const remaining = await collectAllPages<TodoTask>(\n client,\n response['@odata.nextLink'],\n );\n tasks.push(...remaining);\n }\n\n return formatResponse(tasks);\n } catch (err) {\n return formatError(parseGraphError(err));\n }\n}\n\nexport async function handleGetTask(listId: string, taskId: string): Promise<CallToolResult> {\n try {\n const token = await acquireToken();\n const client = getGraphClient(token);\n const task = await client.api(`/me/todo/lists/${listId}/tasks/${taskId}`).get() as TodoTask;\n return formatResponse(task);\n } catch (err) {\n return formatError(parseGraphError(err));\n }\n}\n\ninterface CreateTaskParams {\n listId: string;\n title: string;\n body?: string;\n dueDate?: string;\n importance?: 'low' | 'normal' | 'high';\n}\n\nexport async function handleCreateTask(params: CreateTaskParams): Promise<CallToolResult> {\n try {\n const token = await acquireToken();\n const client = getGraphClient(token);\n\n const body: Partial<TodoTask> = {\n title: params.title,\n };\n\n if (params.body !== undefined) {\n body.body = { content: params.body, contentType: 'text' };\n }\n\n if (params.dueDate !== undefined) {\n body.dueDateTime = { dateTime: `${params.dueDate}T00:00:00`, timeZone: 'UTC' };\n }\n\n if (params.importance !== undefined) {\n body.importance = params.importance;\n }\n\n const created = await client\n .api(`/me/todo/lists/${params.listId}/tasks`)\n .post(body) as TodoTask;\n\n return formatResponse(created);\n } catch (err) {\n return formatError(parseGraphError(err));\n }\n}\n\ninterface UpdateTaskParams {\n listId: string;\n taskId: string;\n title?: string;\n body?: string;\n dueDate?: string;\n importance?: 'low' | 'normal' | 'high';\n}\n\nexport async function handleUpdateTask(params: UpdateTaskParams): Promise<CallToolResult> {\n try {\n const token = await acquireToken();\n const client = getGraphClient(token);\n\n const patch: Partial<TodoTask> = {};\n\n if (params.title !== undefined) patch.title = params.title;\n if (params.body !== undefined) patch.body = { content: params.body, contentType: 'text' };\n if (params.dueDate !== undefined) {\n patch.dueDateTime = { dateTime: `${params.dueDate}T00:00:00`, timeZone: 'UTC' };\n }\n if (params.importance !== undefined) patch.importance = params.importance;\n\n const updated = await client\n .api(`/me/todo/lists/${params.listId}/tasks/${params.taskId}`)\n .patch(patch) as TodoTask;\n\n return formatResponse(updated);\n } catch (err) {\n return formatError(parseGraphError(err));\n }\n}\n\nexport async function handleCompleteTask(listId: string, taskId: string): Promise<CallToolResult> {\n try {\n const token = await acquireToken();\n const client = getGraphClient(token);\n const updated = await client\n .api(`/me/todo/lists/${listId}/tasks/${taskId}`)\n .patch({ status: 'completed' }) as TodoTask;\n return formatResponse(updated);\n } catch (err) {\n return formatError(parseGraphError(err));\n }\n}\n\nexport async function handleDeleteTask(listId: string, taskId: string): Promise<CallToolResult> {\n try {\n const token = await acquireToken();\n const client = getGraphClient(token);\n await client.api(`/me/todo/lists/${listId}/tasks/${taskId}`).delete();\n return formatResponse({ deleted: true, taskId });\n } catch (err) {\n return formatError(parseGraphError(err));\n }\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport {\n ListTasksSchema,\n GetTaskSchema,\n CreateTaskSchema,\n UpdateTaskSchema,\n CompleteTaskSchema,\n DeleteTaskSchema,\n} from './schemas.js';\nimport {\n handleListTaskLists,\n handleListTasks,\n handleGetTask,\n handleCreateTask,\n handleUpdateTask,\n handleCompleteTask,\n handleDeleteTask,\n} from './handlers.js';\n\nexport function register(server: McpServer): void {\n server.tool(\n 'list_task_lists',\n 'List all Microsoft To Do task lists for the signed-in user',\n {},\n async () => handleListTaskLists(),\n );\n\n server.tool(\n 'list_tasks',\n 'List tasks in a specific To Do task list, with optional filter and limit',\n ListTasksSchema,\n async ({ listId, filter, top }) => handleListTasks(listId, filter, top),\n );\n\n server.tool(\n 'get_task',\n 'Get a single To Do task by list ID and task ID',\n GetTaskSchema,\n async ({ listId, taskId }) => handleGetTask(listId, taskId),\n );\n\n server.tool(\n 'create_task',\n 'Create a new task in a To Do task list',\n CreateTaskSchema,\n async (params) => handleCreateTask(params),\n );\n\n server.tool(\n 'update_task',\n 'Update an existing To Do task (title, body, due date, importance)',\n UpdateTaskSchema,\n async (params) => handleUpdateTask(params),\n );\n\n server.tool(\n 'complete_task',\n 'Mark a To Do task as completed',\n CompleteTaskSchema,\n async ({ listId, taskId }) => handleCompleteTask(listId, taskId),\n );\n\n server.tool(\n 'delete_task',\n 'Delete a To Do task permanently',\n DeleteTaskSchema,\n async ({ listId, taskId }) => handleDeleteTask(listId, taskId),\n );\n}\n","import { z } from 'zod';\n\nexport const SearchEventsSchema = {\n query: z.string().optional().describe('Search query string for event subject/content'),\n startDate: z\n .string()\n .optional()\n .describe('Filter events starting on or after this date (ISO 8601, e.g. 2026-06-01)'),\n endDate: z\n .string()\n .optional()\n .describe('Filter events ending on or before this date (ISO 8601, e.g. 2026-06-30)'),\n top: z\n .number()\n .int()\n .min(1)\n .max(100)\n .optional()\n .describe('Maximum number of events to return (1-100)'),\n};\n\nexport const GetEventSchema = {\n eventId: z.string().describe('The ID of the calendar event'),\n};\n\nexport const CreateEventSchema = {\n subject: z.string().describe('Event subject / title'),\n start: z\n .string()\n .describe('Event start time in ISO 8601 format (e.g. 2026-06-01T10:00:00)'),\n end: z.string().describe('Event end time in ISO 8601 format (e.g. 2026-06-01T11:00:00)'),\n timeZone: z\n .string()\n .optional()\n .default('UTC')\n .describe('IANA time zone for start/end (default: UTC)'),\n attendees: z\n .array(z.string())\n .optional()\n .describe('List of attendee email addresses'),\n body: z.string().optional().describe('Event body / description (HTML or plain text)'),\n location: z.string().optional().describe('Event location'),\n isTeamsMeeting: z\n .boolean()\n .optional()\n .describe('If true, create a Teams online meeting link'),\n};\n\nexport const UpdateEventSchema = {\n eventId: z.string().describe('The ID of the calendar event to update'),\n subject: z.string().optional().describe('Updated event subject'),\n start: z.string().optional().describe('Updated start time in ISO 8601 format'),\n end: z.string().optional().describe('Updated end time in ISO 8601 format'),\n timeZone: z.string().optional().describe('IANA time zone for updated start/end'),\n attendees: z.array(z.string()).optional().describe('Updated list of attendee email addresses'),\n body: z.string().optional().describe('Updated event body'),\n location: z.string().optional().describe('Updated event location'),\n};\n\nexport const FindAvailabilitySchema = {\n emails: z.array(z.string()).describe('List of email addresses to check availability for'),\n startTime: z\n .string()\n .describe('Start of the availability window in ISO 8601 format'),\n endTime: z\n .string()\n .describe('End of the availability window in ISO 8601 format'),\n timeZone: z\n .string()\n .optional()\n .default('UTC')\n .describe('IANA time zone for the window (default: UTC)'),\n intervalMinutes: z\n .number()\n .int()\n .min(5)\n .max(1440)\n .optional()\n .default(30)\n .describe('Schedule slot interval in minutes (default: 30)'),\n};\n","import type { Event } from '@microsoft/microsoft-graph-types';\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';\nimport { acquireToken } from '../../auth/device-code-flow.js';\nimport { getGraphClient } from '../../graph/client.js';\nimport { formatResponse, formatError } from '../../utils/formatting.js';\nimport { parseGraphError } from '../../utils/errors.js';\n\ninterface AttendeeEmailAddress {\n address: string;\n name?: string;\n}\n\ninterface Attendee {\n emailAddress: AttendeeEmailAddress;\n type: 'required' | 'optional' | 'resource';\n}\n\nexport async function handleSearchEvents(\n query?: string,\n startDate?: string,\n endDate?: string,\n top?: number,\n): Promise<CallToolResult> {\n try {\n const token = await acquireToken();\n const client = getGraphClient(token);\n\n let request = client.api('/me/events');\n\n if (query !== undefined) {\n request = request.search(`\"${query}\"`);\n }\n\n const filters: string[] = [];\n if (startDate !== undefined) {\n filters.push(`start/dateTime ge '${startDate}T00:00:00Z'`);\n }\n if (endDate !== undefined) {\n filters.push(`end/dateTime le '${endDate}T23:59:59Z'`);\n }\n if (filters.length > 0) {\n request = request.filter(filters.join(' and '));\n }\n\n if (top !== undefined) {\n request = request.top(top);\n }\n\n request = request.select('id,subject,start,end,location,attendees,bodyPreview,isOnlineMeeting,onlineMeetingUrl');\n\n const response = await request.get() as { value?: Event[] };\n return formatResponse(response.value ?? []);\n } catch (err) {\n return formatError(parseGraphError(err));\n }\n}\n\nexport async function handleGetEvent(eventId: string): Promise<CallToolResult> {\n try {\n const token = await acquireToken();\n const client = getGraphClient(token);\n const event = await client.api(`/me/events/${eventId}`).get() as Event;\n return formatResponse(event);\n } catch (err) {\n return formatError(parseGraphError(err));\n }\n}\n\ninterface CreateEventParams {\n subject: string;\n start: string;\n end: string;\n timeZone?: string;\n attendees?: string[];\n body?: string;\n location?: string;\n isTeamsMeeting?: boolean;\n}\n\nexport async function handleCreateEvent(params: CreateEventParams): Promise<CallToolResult> {\n try {\n const token = await acquireToken();\n const client = getGraphClient(token);\n\n const tz = params.timeZone ?? 'UTC';\n\n const eventBody: Partial<Event> & { isOnlineMeeting?: boolean } = {\n subject: params.subject,\n start: { dateTime: params.start, timeZone: tz },\n end: { dateTime: params.end, timeZone: tz },\n };\n\n if (params.body !== undefined) {\n eventBody.body = { contentType: 'text', content: params.body };\n }\n\n if (params.location !== undefined) {\n eventBody.location = { displayName: params.location };\n }\n\n if (params.attendees !== undefined && params.attendees.length > 0) {\n eventBody.attendees = params.attendees.map((email): Attendee => ({\n emailAddress: { address: email },\n type: 'required',\n }));\n }\n\n if (params.isTeamsMeeting === true) {\n eventBody.isOnlineMeeting = true;\n }\n\n const created = await client.api('/me/events').post(eventBody) as Event;\n return formatResponse(created);\n } catch (err) {\n return formatError(parseGraphError(err));\n }\n}\n\ninterface UpdateEventParams {\n eventId: string;\n subject?: string;\n start?: string;\n end?: string;\n timeZone?: string;\n attendees?: string[];\n body?: string;\n location?: string;\n}\n\nexport async function handleUpdateEvent(params: UpdateEventParams): Promise<CallToolResult> {\n try {\n const token = await acquireToken();\n const client = getGraphClient(token);\n\n const patch: Partial<Event> = {};\n const tz = params.timeZone ?? 'UTC';\n\n if (params.subject !== undefined) patch.subject = params.subject;\n if (params.start !== undefined) patch.start = { dateTime: params.start, timeZone: tz };\n if (params.end !== undefined) patch.end = { dateTime: params.end, timeZone: tz };\n if (params.body !== undefined) patch.body = { contentType: 'text', content: params.body };\n if (params.location !== undefined) patch.location = { displayName: params.location };\n if (params.attendees !== undefined) {\n patch.attendees = params.attendees.map((email): Attendee => ({\n emailAddress: { address: email },\n type: 'required',\n }));\n }\n\n const updated = await client.api(`/me/events/${params.eventId}`).patch(patch) as Event;\n return formatResponse(updated);\n } catch (err) {\n return formatError(parseGraphError(err));\n }\n}\n\ninterface ScheduleInformation {\n scheduleId: string;\n availabilityView?: string;\n scheduleItems?: unknown[];\n workingHours?: unknown;\n error?: unknown;\n}\n\ninterface GetScheduleResponse {\n value?: ScheduleInformation[];\n}\n\ninterface FindAvailabilityParams {\n emails: string[];\n startTime: string;\n endTime: string;\n timeZone?: string;\n intervalMinutes?: number;\n}\n\nexport async function handleFindAvailability(params: FindAvailabilityParams): Promise<CallToolResult> {\n try {\n const token = await acquireToken();\n const client = getGraphClient(token);\n\n const tz = params.timeZone ?? 'UTC';\n const interval = params.intervalMinutes ?? 30;\n\n const requestBody = {\n schedules: params.emails,\n startTime: { dateTime: params.startTime, timeZone: tz },\n endTime: { dateTime: params.endTime, timeZone: tz },\n availabilityViewInterval: interval,\n };\n\n const response = await client\n .api('/me/calendar/getSchedule')\n .post(requestBody) as GetScheduleResponse;\n\n return formatResponse(response.value ?? []);\n } catch (err) {\n return formatError(parseGraphError(err));\n }\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport {\n SearchEventsSchema,\n GetEventSchema,\n CreateEventSchema,\n UpdateEventSchema,\n FindAvailabilitySchema,\n} from './schemas.js';\nimport {\n handleSearchEvents,\n handleGetEvent,\n handleCreateEvent,\n handleUpdateEvent,\n handleFindAvailability,\n} from './handlers.js';\n\nexport function register(server: McpServer): void {\n server.tool(\n 'search_events',\n 'Search calendar events by query, date range, or both',\n SearchEventsSchema,\n async ({ query, startDate, endDate, top }) =>\n handleSearchEvents(query, startDate, endDate, top),\n );\n\n server.tool(\n 'get_event',\n 'Get a single calendar event by ID',\n GetEventSchema,\n async ({ eventId }) => handleGetEvent(eventId),\n );\n\n server.tool(\n 'create_event',\n 'Create a new calendar event, optionally with attendees and a Teams meeting link',\n CreateEventSchema,\n async (params) => handleCreateEvent(params),\n );\n\n server.tool(\n 'update_event',\n 'Update an existing calendar event (subject, times, attendees, body, location)',\n UpdateEventSchema,\n async (params) => handleUpdateEvent(params),\n );\n\n server.tool(\n 'find_availability',\n 'Check free/busy availability for a list of people over a time window',\n FindAvailabilitySchema,\n async (params) => handleFindAvailability(params),\n );\n}\n","import { z } from 'zod';\n\nexport const SearchEmailsSchema = {\n query: z.string().optional().describe('Full-text search query across email subject and body'),\n from: z.string().optional().describe('Filter by sender email address'),\n startDate: z\n .string()\n .optional()\n .describe('Filter emails received on or after this date (ISO 8601)'),\n endDate: z\n .string()\n .optional()\n .describe('Filter emails received on or before this date (ISO 8601)'),\n folder: z\n .string()\n .optional()\n .describe('Mail folder name or well-known name (e.g. \"inbox\", \"sentitems\", \"drafts\")'),\n top: z\n .number()\n .int()\n .min(1)\n .max(100)\n .optional()\n .describe('Maximum number of emails to return (1-100)'),\n};\n\nexport const ReadEmailSchema = {\n messageId: z.string().describe('The ID of the email message'),\n};\n\nexport const SendEmailSchema = {\n to: z.array(z.string()).describe('List of recipient email addresses'),\n subject: z.string().describe('Email subject'),\n body: z.string().describe('Email body content'),\n cc: z.array(z.string()).optional().describe('CC recipient email addresses'),\n bcc: z.array(z.string()).optional().describe('BCC recipient email addresses'),\n contentType: z\n .enum(['text', 'html'])\n .optional()\n .default('text')\n .describe('Body content type (default: text)'),\n};\n\nexport const FlagEmailSchema = {\n messageId: z.string().describe('The ID of the email message'),\n flagStatus: z\n .enum(['flagged', 'complete', 'notFlagged'])\n .describe('Flag status to set on the message'),\n};\n\nexport const MoveEmailSchema = {\n messageId: z.string().describe('The ID of the email message to move'),\n destinationFolderId: z\n .string()\n .describe('ID or well-known folder name of the destination folder'),\n};\n","import type { Message, MailFolder, Recipient } from '@microsoft/microsoft-graph-types';\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';\nimport { acquireToken } from '../../auth/device-code-flow.js';\nimport { getGraphClient } from '../../graph/client.js';\nimport { collectAllPages } from '../../utils/pagination.js';\nimport { formatResponse, formatError } from '../../utils/formatting.js';\nimport { parseGraphError } from '../../utils/errors.js';\n\ninterface SearchEmailsParams {\n query?: string;\n from?: string;\n startDate?: string;\n endDate?: string;\n folder?: string;\n top?: number;\n}\n\nexport async function handleSearchEmails(params: SearchEmailsParams): Promise<CallToolResult> {\n try {\n const token = await acquireToken();\n const client = getGraphClient(token);\n\n const folderSegment = params.folder !== undefined ? `/me/mailFolders/${params.folder}/messages` : '/me/messages';\n let request = client.api(folderSegment);\n\n if (params.query !== undefined) {\n request = request.search(`\"${params.query}\"`);\n }\n\n const filters: string[] = [];\n if (params.from !== undefined) {\n filters.push(`from/emailAddress/address eq '${params.from}'`);\n }\n if (params.startDate !== undefined) {\n filters.push(`receivedDateTime ge ${params.startDate}T00:00:00Z`);\n }\n if (params.endDate !== undefined) {\n filters.push(`receivedDateTime le ${params.endDate}T23:59:59Z`);\n }\n if (filters.length > 0) {\n request = request.filter(filters.join(' and '));\n }\n\n if (params.top !== undefined) {\n request = request.top(params.top);\n }\n\n request = request.select('id,subject,from,receivedDateTime,bodyPreview,isRead,flag,hasAttachments');\n\n const response = await request.get() as { value?: Message[] };\n return formatResponse(response.value ?? []);\n } catch (err) {\n return formatError(parseGraphError(err));\n }\n}\n\nexport async function handleReadEmail(messageId: string): Promise<CallToolResult> {\n try {\n const token = await acquireToken();\n const client = getGraphClient(token);\n const message = await client\n .api(`/me/messages/${messageId}`)\n .select('id,subject,from,toRecipients,ccRecipients,receivedDateTime,body,isRead,flag,hasAttachments')\n .get() as Message;\n return formatResponse(message);\n } catch (err) {\n return formatError(parseGraphError(err));\n }\n}\n\ninterface SendEmailParams {\n to: string[];\n subject: string;\n body: string;\n cc?: string[];\n bcc?: string[];\n contentType?: 'text' | 'html';\n}\n\nfunction toRecipients(emails: string[]): Recipient[] {\n return emails.map((address) => ({ emailAddress: { address } }));\n}\n\nexport async function handleSendEmail(params: SendEmailParams): Promise<CallToolResult> {\n try {\n const token = await acquireToken();\n const client = getGraphClient(token);\n\n const contentType = params.contentType ?? 'text';\n\n const message = {\n message: {\n subject: params.subject,\n body: { contentType, content: params.body },\n toRecipients: toRecipients(params.to),\n ...(params.cc !== undefined && { ccRecipients: toRecipients(params.cc) }),\n ...(params.bcc !== undefined && { bccRecipients: toRecipients(params.bcc) }),\n },\n };\n\n await client.api('/me/sendMail').post(message);\n return formatResponse({ sent: true, subject: params.subject });\n } catch (err) {\n return formatError(parseGraphError(err));\n }\n}\n\nexport async function handleFlagEmail(\n messageId: string,\n flagStatus: 'flagged' | 'complete' | 'notFlagged',\n): Promise<CallToolResult> {\n try {\n const token = await acquireToken();\n const client = getGraphClient(token);\n const updated = await client\n .api(`/me/messages/${messageId}`)\n .patch({ flag: { flagStatus } }) as Message;\n return formatResponse(updated);\n } catch (err) {\n return formatError(parseGraphError(err));\n }\n}\n\nexport async function handleListMailFolders(): Promise<CallToolResult> {\n try {\n const token = await acquireToken();\n const client = getGraphClient(token);\n const folders = await collectAllPages<MailFolder>(client, '/me/mailFolders');\n return formatResponse(folders);\n } catch (err) {\n return formatError(parseGraphError(err));\n }\n}\n\nexport async function handleMoveEmail(\n messageId: string,\n destinationFolderId: string,\n): Promise<CallToolResult> {\n try {\n const token = await acquireToken();\n const client = getGraphClient(token);\n const moved = await client\n .api(`/me/messages/${messageId}/move`)\n .post({ destinationId: destinationFolderId }) as Message;\n return formatResponse(moved);\n } catch (err) {\n return formatError(parseGraphError(err));\n }\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport {\n SearchEmailsSchema,\n ReadEmailSchema,\n SendEmailSchema,\n FlagEmailSchema,\n MoveEmailSchema,\n} from './schemas.js';\nimport {\n handleSearchEmails,\n handleReadEmail,\n handleSendEmail,\n handleFlagEmail,\n handleListMailFolders,\n handleMoveEmail,\n} from './handlers.js';\n\nexport function register(server: McpServer): void {\n server.tool(\n 'search_emails',\n 'Search emails by query, sender, date range, or folder',\n SearchEmailsSchema,\n async (params) => handleSearchEmails(params),\n );\n\n server.tool(\n 'read_email',\n 'Read the full content of an email message by ID',\n ReadEmailSchema,\n async ({ messageId }) => handleReadEmail(messageId),\n );\n\n server.tool(\n 'send_email',\n 'Send an email to one or more recipients',\n SendEmailSchema,\n async (params) => handleSendEmail(params),\n );\n\n server.tool(\n 'flag_email',\n 'Set the flag status on an email (flagged, complete, or notFlagged)',\n FlagEmailSchema,\n async ({ messageId, flagStatus }) => handleFlagEmail(messageId, flagStatus),\n );\n\n server.tool(\n 'list_mail_folders',\n 'List all mail folders for the signed-in user',\n {},\n async () => handleListMailFolders(),\n );\n\n server.tool(\n 'move_email',\n 'Move an email to a different mail folder',\n MoveEmailSchema,\n async ({ messageId, destinationFolderId }) =>\n handleMoveEmail(messageId, destinationFolderId),\n );\n}\n","import { z } from 'zod';\n\nconst EmailAddressSchema = z.object({\n address: z.string().describe('Email address'),\n name: z.string().optional().describe('Display name for this email address'),\n});\n\nexport const SearchContactsSchema = {\n query: z.string().describe('Search query (matches against name, email, company, etc.)'),\n top: z\n .number()\n .int()\n .min(1)\n .max(100)\n .optional()\n .describe('Maximum number of contacts to return (1-100)'),\n};\n\nexport const GetContactSchema = {\n contactId: z.string().describe('The ID of the contact'),\n};\n\nexport const CreateContactSchema = {\n givenName: z.string().describe('Contact first name'),\n surname: z.string().optional().describe('Contact last name'),\n emailAddresses: z\n .array(EmailAddressSchema)\n .optional()\n .describe('Email addresses for the contact'),\n businessPhones: z.array(z.string()).optional().describe('Business phone numbers'),\n jobTitle: z.string().optional().describe('Job title'),\n companyName: z.string().optional().describe('Company or organization name'),\n};\n\nexport const UpdateContactSchema = {\n contactId: z.string().describe('The ID of the contact to update'),\n givenName: z.string().optional().describe('Updated first name'),\n surname: z.string().optional().describe('Updated last name'),\n emailAddresses: z\n .array(EmailAddressSchema)\n .optional()\n .describe('Updated email addresses'),\n businessPhones: z.array(z.string()).optional().describe('Updated business phone numbers'),\n jobTitle: z.string().optional().describe('Updated job title'),\n companyName: z.string().optional().describe('Updated company name'),\n};\n","import type { Contact } from '@microsoft/microsoft-graph-types';\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';\nimport { acquireToken } from '../../auth/device-code-flow.js';\nimport { getGraphClient } from '../../graph/client.js';\nimport { formatResponse, formatError } from '../../utils/formatting.js';\nimport { parseGraphError } from '../../utils/errors.js';\n\ninterface ContactEmailAddress {\n address: string;\n name?: string;\n}\n\nexport async function handleSearchContacts(\n query: string,\n top?: number,\n): Promise<CallToolResult> {\n try {\n const token = await acquireToken();\n const client = getGraphClient(token);\n\n let request = client\n .api('/me/contacts')\n .search(`\"${query}\"`)\n .select('id,displayName,givenName,surname,emailAddresses,businessPhones,jobTitle,companyName');\n\n if (top !== undefined) {\n request = request.top(top);\n }\n\n const response = await request.get() as { value?: Contact[] };\n return formatResponse(response.value ?? []);\n } catch (err) {\n return formatError(parseGraphError(err));\n }\n}\n\nexport async function handleGetContact(contactId: string): Promise<CallToolResult> {\n try {\n const token = await acquireToken();\n const client = getGraphClient(token);\n const contact = await client\n .api(`/me/contacts/${contactId}`)\n .get() as Contact;\n return formatResponse(contact);\n } catch (err) {\n return formatError(parseGraphError(err));\n }\n}\n\ninterface CreateContactParams {\n givenName: string;\n surname?: string;\n emailAddresses?: ContactEmailAddress[];\n businessPhones?: string[];\n jobTitle?: string;\n companyName?: string;\n}\n\nexport async function handleCreateContact(params: CreateContactParams): Promise<CallToolResult> {\n try {\n const token = await acquireToken();\n const client = getGraphClient(token);\n\n const body: Partial<Contact> = {\n givenName: params.givenName,\n };\n\n if (params.surname !== undefined) body.surname = params.surname;\n if (params.emailAddresses !== undefined) body.emailAddresses = params.emailAddresses;\n if (params.businessPhones !== undefined) body.businessPhones = params.businessPhones;\n if (params.jobTitle !== undefined) body.jobTitle = params.jobTitle;\n if (params.companyName !== undefined) body.companyName = params.companyName;\n\n const created = await client.api('/me/contacts').post(body) as Contact;\n return formatResponse(created);\n } catch (err) {\n return formatError(parseGraphError(err));\n }\n}\n\ninterface UpdateContactParams {\n contactId: string;\n givenName?: string;\n surname?: string;\n emailAddresses?: ContactEmailAddress[];\n businessPhones?: string[];\n jobTitle?: string;\n companyName?: string;\n}\n\nexport async function handleUpdateContact(params: UpdateContactParams): Promise<CallToolResult> {\n try {\n const token = await acquireToken();\n const client = getGraphClient(token);\n\n const patch: Partial<Contact> = {};\n\n if (params.givenName !== undefined) patch.givenName = params.givenName;\n if (params.surname !== undefined) patch.surname = params.surname;\n if (params.emailAddresses !== undefined) patch.emailAddresses = params.emailAddresses;\n if (params.businessPhones !== undefined) patch.businessPhones = params.businessPhones;\n if (params.jobTitle !== undefined) patch.jobTitle = params.jobTitle;\n if (params.companyName !== undefined) patch.companyName = params.companyName;\n\n const updated = await client\n .api(`/me/contacts/${params.contactId}`)\n .patch(patch) as Contact;\n\n return formatResponse(updated);\n } catch (err) {\n return formatError(parseGraphError(err));\n }\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport {\n SearchContactsSchema,\n GetContactSchema,\n CreateContactSchema,\n UpdateContactSchema,\n} from './schemas.js';\nimport {\n handleSearchContacts,\n handleGetContact,\n handleCreateContact,\n handleUpdateContact,\n} from './handlers.js';\n\nexport function register(server: McpServer): void {\n server.tool(\n 'search_contacts',\n 'Search contacts by name, email, company, or other fields',\n SearchContactsSchema,\n async ({ query, top }) => handleSearchContacts(query, top),\n );\n\n server.tool(\n 'get_contact',\n 'Get a single contact by ID',\n GetContactSchema,\n async ({ contactId }) => handleGetContact(contactId),\n );\n\n server.tool(\n 'create_contact',\n 'Create a new contact in the signed-in user\\'s contacts',\n CreateContactSchema,\n async (params) => handleCreateContact(params),\n );\n\n server.tool(\n 'update_contact',\n 'Update an existing contact (name, email, phone, title, company)',\n UpdateContactSchema,\n async (params) => handleUpdateContact(params),\n );\n}\n","declare const __PACKAGE_VERSION__: string;\nexport const VERSION: string =\n typeof __PACKAGE_VERSION__ !== 'undefined' ? __PACKAGE_VERSION__ : '0.0.0-dev';\n"],"mappings":"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","names":["z","register","z","register","z","register","register"]}
@@ -0,0 +1,72 @@
1
+ import {
2
+ runAuthCommand
3
+ } from "./chunk-JEMHJMEL.js";
4
+
5
+ // src/setup/index.ts
6
+ import fs from "fs";
7
+ import path from "path";
8
+ import os from "os";
9
+
10
+ // src/setup/prompts.ts
11
+ import { createInterface } from "readline";
12
+ import { createReadStream } from "fs";
13
+ function createRl() {
14
+ let input;
15
+ try {
16
+ input = createReadStream("/dev/tty");
17
+ } catch {
18
+ input = process.stdin;
19
+ }
20
+ return createInterface({
21
+ input,
22
+ output: process.stderr,
23
+ terminal: true
24
+ });
25
+ }
26
+ async function question(prompt) {
27
+ const rl = createRl();
28
+ return new Promise((resolve) => {
29
+ rl.question(prompt, (answer) => {
30
+ rl.close();
31
+ resolve(answer.trim());
32
+ });
33
+ });
34
+ }
35
+ async function confirm(prompt, defaultYes = false) {
36
+ const hint = defaultYes ? "[Y/n]" : "[y/N]";
37
+ const answer = await question(`${prompt} ${hint}: `);
38
+ if (answer === "") {
39
+ return defaultYes;
40
+ }
41
+ return answer.toLowerCase().startsWith("y");
42
+ }
43
+
44
+ // src/setup/index.ts
45
+ var TOKEN_CACHE_PATH = path.join(os.homedir(), ".config", "m365-mcp", "token-cache.json");
46
+ function stderr(msg) {
47
+ process.stderr.write(msg + "\n");
48
+ }
49
+ async function runSetupCommand() {
50
+ stderr("m365-mcp \u2014 Microsoft 365 for Claude");
51
+ stderr("");
52
+ stderr("This will grant access to:");
53
+ stderr(" \u2022 Mail (read, send)");
54
+ stderr(" \u2022 Calendar (read, create, update)");
55
+ stderr(" \u2022 Tasks (read, create, update, delete)");
56
+ stderr(" \u2022 Contacts (read, create, update)");
57
+ stderr("");
58
+ const cacheExists = fs.existsSync(TOKEN_CACHE_PATH);
59
+ if (cacheExists) {
60
+ const reauth = await confirm("You're already signed in. Re-authenticate?", false);
61
+ if (!reauth) {
62
+ stderr("Setup cancelled.");
63
+ return;
64
+ }
65
+ }
66
+ await runAuthCommand();
67
+ stderr("Setup complete! Add m365-mcp to your Claude Desktop or Claude Code config to get started.");
68
+ }
69
+ export {
70
+ runSetupCommand
71
+ };
72
+ //# sourceMappingURL=setup-K6EYBEFH.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/setup/index.ts","../src/setup/prompts.ts"],"sourcesContent":["import fs from 'fs';\nimport path from 'path';\nimport os from 'os';\nimport { runAuthCommand } from '../auth/device-code-flow.js';\nimport { confirm } from './prompts.js';\n\nconst TOKEN_CACHE_PATH = path.join(os.homedir(), '.config', 'm365-mcp', 'token-cache.json');\n\nfunction stderr(msg: string): void {\n process.stderr.write(msg + '\\n');\n}\n\nexport async function runSetupCommand(): Promise<void> {\n stderr('m365-mcp — Microsoft 365 for Claude');\n stderr('');\n stderr('This will grant access to:');\n stderr(' • Mail (read, send)');\n stderr(' • Calendar (read, create, update)');\n stderr(' • Tasks (read, create, update, delete)');\n stderr(' • Contacts (read, create, update)');\n stderr('');\n\n const cacheExists = fs.existsSync(TOKEN_CACHE_PATH);\n if (cacheExists) {\n const reauth = await confirm(\"You're already signed in. Re-authenticate?\", false);\n if (!reauth) {\n stderr('Setup cancelled.');\n return;\n }\n }\n\n await runAuthCommand();\n stderr('Setup complete! Add m365-mcp to your Claude Desktop or Claude Code config to get started.');\n}\n","import { createInterface } from 'readline';\nimport { createReadStream } from 'fs';\n\nfunction createRl(): ReturnType<typeof createInterface> {\n // Read from /dev/tty directly so stdin is not consumed when running as MCP server.\n // Fall back to process.stdin if /dev/tty is unavailable (CI, Windows, etc.).\n let input: NodeJS.ReadableStream;\n try {\n input = createReadStream('/dev/tty');\n } catch {\n input = process.stdin;\n }\n\n return createInterface({\n input,\n output: process.stderr,\n terminal: true,\n });\n}\n\nexport async function question(prompt: string): Promise<string> {\n const rl = createRl();\n return new Promise<string>((resolve) => {\n rl.question(prompt, (answer) => {\n rl.close();\n resolve(answer.trim());\n });\n });\n}\n\nexport async function confirm(prompt: string, defaultYes = false): Promise<boolean> {\n const hint = defaultYes ? '[Y/n]' : '[y/N]';\n const answer = await question(`${prompt} ${hint}: `);\n if (answer === '') {\n return defaultYes;\n }\n return answer.toLowerCase().startsWith('y');\n}\n"],"mappings":";;;;;AAAA,OAAO,QAAQ;AACf,OAAO,UAAU;AACjB,OAAO,QAAQ;;;ACFf,SAAS,uBAAuB;AAChC,SAAS,wBAAwB;AAEjC,SAAS,WAA+C;AAGtD,MAAI;AACJ,MAAI;AACF,YAAQ,iBAAiB,UAAU;AAAA,EACrC,QAAQ;AACN,YAAQ,QAAQ;AAAA,EAClB;AAEA,SAAO,gBAAgB;AAAA,IACrB;AAAA,IACA,QAAQ,QAAQ;AAAA,IAChB,UAAU;AAAA,EACZ,CAAC;AACH;AAEA,eAAsB,SAAS,QAAiC;AAC9D,QAAM,KAAK,SAAS;AACpB,SAAO,IAAI,QAAgB,CAAC,YAAY;AACtC,OAAG,SAAS,QAAQ,CAAC,WAAW;AAC9B,SAAG,MAAM;AACT,cAAQ,OAAO,KAAK,CAAC;AAAA,IACvB,CAAC;AAAA,EACH,CAAC;AACH;AAEA,eAAsB,QAAQ,QAAgB,aAAa,OAAyB;AAClF,QAAM,OAAO,aAAa,UAAU;AACpC,QAAM,SAAS,MAAM,SAAS,GAAG,MAAM,IAAI,IAAI,IAAI;AACnD,MAAI,WAAW,IAAI;AACjB,WAAO;AAAA,EACT;AACA,SAAO,OAAO,YAAY,EAAE,WAAW,GAAG;AAC5C;;;AD/BA,IAAM,mBAAmB,KAAK,KAAK,GAAG,QAAQ,GAAG,WAAW,YAAY,kBAAkB;AAE1F,SAAS,OAAO,KAAmB;AACjC,UAAQ,OAAO,MAAM,MAAM,IAAI;AACjC;AAEA,eAAsB,kBAAiC;AACrD,SAAO,0CAAqC;AAC5C,SAAO,EAAE;AACT,SAAO,4BAA4B;AACnC,SAAO,4BAAuB;AAC9B,SAAO,0CAAqC;AAC5C,SAAO,+CAA0C;AACjD,SAAO,0CAAqC;AAC5C,SAAO,EAAE;AAET,QAAM,cAAc,GAAG,WAAW,gBAAgB;AAClD,MAAI,aAAa;AACf,UAAM,SAAS,MAAM,QAAQ,8CAA8C,KAAK;AAChF,QAAI,CAAC,QAAQ;AACX,aAAO,kBAAkB;AACzB;AAAA,IACF;AAAA,EACF;AAEA,QAAM,eAAe;AACrB,SAAO,2FAA2F;AACpG;","names":[]}
package/package.json ADDED
@@ -0,0 +1,66 @@
1
+ {
2
+ "name": "@joshluedeman/m365-mcp",
3
+ "version": "0.1.0",
4
+ "description": "Microsoft 365 MCP server — Mail, Calendar, Tasks, Contacts via Microsoft Graph",
5
+ "type": "module",
6
+ "bin": {
7
+ "m365-mcp": "./dist/index.cjs"
8
+ },
9
+ "scripts": {
10
+ "dev": "tsx src/index.ts",
11
+ "build": "tsup",
12
+ "lint": "eslint src",
13
+ "typecheck": "tsc --noEmit",
14
+ "test": "vitest run",
15
+ "test:watch": "vitest",
16
+ "test:coverage": "vitest run --coverage"
17
+ },
18
+ "vitest": {
19
+ "environment": "node",
20
+ "include": ["tests/**/*.test.ts"]
21
+ },
22
+ "dependencies": {
23
+ "@azure/msal-node": "^5.2.2",
24
+ "@microsoft/microsoft-graph-client": "^3.0.7",
25
+ "@microsoft/microsoft-graph-types": "^2.43.1",
26
+ "@modelcontextprotocol/sdk": "^1.29.0",
27
+ "zod": "^4.4.3"
28
+ },
29
+ "devDependencies": {
30
+ "@types/node": "^25.9.1",
31
+ "@typescript-eslint/eslint-plugin": "^8.59.4",
32
+ "@typescript-eslint/parser": "^8.59.4",
33
+ "@vitest/coverage-v8": "^3.2.4",
34
+ "eslint": "^10.4.0",
35
+ "tsup": "^8.5.1",
36
+ "tsx": "^4.22.3",
37
+ "typescript": "^6.0.3",
38
+ "vitest": "^3.2.4"
39
+ },
40
+ "engines": {
41
+ "node": ">=18.0.0"
42
+ },
43
+ "files": [
44
+ "dist"
45
+ ],
46
+ "publishConfig": {
47
+ "access": "public"
48
+ },
49
+ "keywords": [
50
+ "mcp",
51
+ "microsoft365",
52
+ "graph-api",
53
+ "claude",
54
+ "ai"
55
+ ],
56
+ "license": "MIT",
57
+ "author": "Josh Luedeman",
58
+ "homepage": "https://github.com/joshluedeman/m365-mcp",
59
+ "repository": {
60
+ "type": "git",
61
+ "url": "https://github.com/joshluedeman/m365-mcp.git"
62
+ },
63
+ "bugs": {
64
+ "url": "https://github.com/joshluedeman/m365-mcp/issues"
65
+ }
66
+ }