@juvantlabs/m365-graph-mcp-server 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.
Files changed (110) hide show
  1. package/ARCHITECTURE.md +225 -0
  2. package/CHANGELOG.md +188 -0
  3. package/LICENSE +21 -0
  4. package/README.md +164 -0
  5. package/SECURITY.md +64 -0
  6. package/dist/auth/confirmation_tokens.d.ts +38 -0
  7. package/dist/auth/confirmation_tokens.d.ts.map +1 -0
  8. package/dist/auth/confirmation_tokens.js +85 -0
  9. package/dist/auth/confirmation_tokens.js.map +1 -0
  10. package/dist/auth/keyring.d.ts +20 -0
  11. package/dist/auth/keyring.d.ts.map +1 -0
  12. package/dist/auth/keyring.js +41 -0
  13. package/dist/auth/keyring.js.map +1 -0
  14. package/dist/auth/msal.d.ts +42 -0
  15. package/dist/auth/msal.d.ts.map +1 -0
  16. package/dist/auth/msal.js +96 -0
  17. package/dist/auth/msal.js.map +1 -0
  18. package/dist/auth/setup.d.ts +18 -0
  19. package/dist/auth/setup.d.ts.map +1 -0
  20. package/dist/auth/setup.js +110 -0
  21. package/dist/auth/setup.js.map +1 -0
  22. package/dist/client/graph.d.ts +30 -0
  23. package/dist/client/graph.d.ts.map +1 -0
  24. package/dist/client/graph.js +38 -0
  25. package/dist/client/graph.js.map +1 -0
  26. package/dist/index.d.ts +54 -0
  27. package/dist/index.d.ts.map +1 -0
  28. package/dist/index.js +131 -0
  29. package/dist/index.js.map +1 -0
  30. package/dist/tools/cancel_event.d.ts +18 -0
  31. package/dist/tools/cancel_event.d.ts.map +1 -0
  32. package/dist/tools/cancel_event.js +95 -0
  33. package/dist/tools/cancel_event.js.map +1 -0
  34. package/dist/tools/copy_file.d.ts +39 -0
  35. package/dist/tools/copy_file.d.ts.map +1 -0
  36. package/dist/tools/copy_file.js +168 -0
  37. package/dist/tools/copy_file.js.map +1 -0
  38. package/dist/tools/create_event.d.ts +29 -0
  39. package/dist/tools/create_event.d.ts.map +1 -0
  40. package/dist/tools/create_event.js +144 -0
  41. package/dist/tools/create_event.js.map +1 -0
  42. package/dist/tools/decline_event.d.ts +18 -0
  43. package/dist/tools/decline_event.d.ts.map +1 -0
  44. package/dist/tools/decline_event.js +105 -0
  45. package/dist/tools/decline_event.js.map +1 -0
  46. package/dist/tools/delete_file.d.ts +28 -0
  47. package/dist/tools/delete_file.d.ts.map +1 -0
  48. package/dist/tools/delete_file.js +103 -0
  49. package/dist/tools/delete_file.js.map +1 -0
  50. package/dist/tools/download_file.d.ts +43 -0
  51. package/dist/tools/download_file.d.ts.map +1 -0
  52. package/dist/tools/download_file.js +133 -0
  53. package/dist/tools/download_file.js.map +1 -0
  54. package/dist/tools/get_event.d.ts +27 -0
  55. package/dist/tools/get_event.d.ts.map +1 -0
  56. package/dist/tools/get_event.js +55 -0
  57. package/dist/tools/get_event.js.map +1 -0
  58. package/dist/tools/index.d.ts +13 -0
  59. package/dist/tools/index.d.ts.map +1 -0
  60. package/dist/tools/index.js +61 -0
  61. package/dist/tools/index.js.map +1 -0
  62. package/dist/tools/list_calendars.d.ts +26 -0
  63. package/dist/tools/list_calendars.d.ts.map +1 -0
  64. package/dist/tools/list_calendars.js +60 -0
  65. package/dist/tools/list_calendars.js.map +1 -0
  66. package/dist/tools/list_drives.d.ts +27 -0
  67. package/dist/tools/list_drives.d.ts.map +1 -0
  68. package/dist/tools/list_drives.js +58 -0
  69. package/dist/tools/list_drives.js.map +1 -0
  70. package/dist/tools/list_events.d.ts +51 -0
  71. package/dist/tools/list_events.d.ts.map +1 -0
  72. package/dist/tools/list_events.js +119 -0
  73. package/dist/tools/list_events.js.map +1 -0
  74. package/dist/tools/list_items.d.ts +31 -0
  75. package/dist/tools/list_items.d.ts.map +1 -0
  76. package/dist/tools/list_items.js +81 -0
  77. package/dist/tools/list_items.js.map +1 -0
  78. package/dist/tools/move_file.d.ts +18 -0
  79. package/dist/tools/move_file.d.ts.map +1 -0
  80. package/dist/tools/move_file.js +60 -0
  81. package/dist/tools/move_file.js.map +1 -0
  82. package/dist/tools/search_events.d.ts +25 -0
  83. package/dist/tools/search_events.d.ts.map +1 -0
  84. package/dist/tools/search_events.js +71 -0
  85. package/dist/tools/search_events.js.map +1 -0
  86. package/dist/tools/search_events_content.d.ts +32 -0
  87. package/dist/tools/search_events_content.d.ts.map +1 -0
  88. package/dist/tools/search_events_content.js +106 -0
  89. package/dist/tools/search_events_content.js.map +1 -0
  90. package/dist/tools/search_files.d.ts +30 -0
  91. package/dist/tools/search_files.d.ts.map +1 -0
  92. package/dist/tools/search_files.js +82 -0
  93. package/dist/tools/search_files.js.map +1 -0
  94. package/dist/tools/update_event.d.ts +25 -0
  95. package/dist/tools/update_event.d.ts.map +1 -0
  96. package/dist/tools/update_event.js +123 -0
  97. package/dist/tools/update_event.js.map +1 -0
  98. package/dist/tools/upload_file.d.ts +38 -0
  99. package/dist/tools/upload_file.d.ts.map +1 -0
  100. package/dist/tools/upload_file.js +152 -0
  101. package/dist/tools/upload_file.js.map +1 -0
  102. package/dist/types/tool.d.ts +32 -0
  103. package/dist/types/tool.d.ts.map +1 -0
  104. package/dist/types/tool.js +10 -0
  105. package/dist/types/tool.js.map +1 -0
  106. package/dist/types/validators.d.ts +44 -0
  107. package/dist/types/validators.d.ts.map +1 -0
  108. package/dist/types/validators.js +78 -0
  109. package/dist/types/validators.js.map +1 -0
  110. package/package.json +72 -0
@@ -0,0 +1,54 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * M365 Graph MCP Server — entrypoint.
4
+ *
5
+ * Two modes, dispatched on argv[2]:
6
+ * - `setup`: interactive OAuth flow → caches tokens in OS keychain
7
+ * - (default): stdio MCP server → reads cached tokens, serves tool
8
+ * calls over JSON-RPC framing
9
+ *
10
+ * Conforms to handbook docs/repo-types/mcp-server.md.
11
+ *
12
+ * IMPORTANT: All non-protocol output must go to stderr (`console.error`).
13
+ * Writing to stdout corrupts the MCP stdio JSON-RPC framing. CI lint
14
+ * rules enforce this in `juvantlabs/*-mcp-server` repos.
15
+ */
16
+ import { ALL_TOOLS } from "./tools/index.js";
17
+ export declare const TENANT_ID_RE: RegExp;
18
+ /**
19
+ * Validate the env vars the server needs at startup. Throws with a
20
+ * specific message on failure; main() catches + exits with stderr +
21
+ * code 1.
22
+ *
23
+ * Exported so tests can call directly with a fake env.
24
+ */
25
+ export declare function checkEnv(env?: NodeJS.ProcessEnv): void;
26
+ /**
27
+ * Execute a single tools/call request against the registered handler
28
+ * map. Wraps handler errors in an `isError: true` MCP response so the
29
+ * agent sees a structured failure instead of a thrown exception that
30
+ * tears down the JSON-RPC session.
31
+ *
32
+ * Exported for unit testing without spinning up the full MCP transport.
33
+ */
34
+ export declare function dispatchToolCall(graph: import("@microsoft/microsoft-graph-client").Client, handlers: Map<string, (typeof ALL_TOOLS)[number]["handler"]>, request: {
35
+ params: {
36
+ name: string;
37
+ arguments?: unknown;
38
+ };
39
+ }): Promise<{
40
+ content: Array<{
41
+ type: "text";
42
+ text: string;
43
+ }>;
44
+ isError?: boolean;
45
+ }>;
46
+ /**
47
+ * Subcommand dispatcher. Exported so tests can verify routing without
48
+ * actually spawning the server.
49
+ */
50
+ export declare function dispatch(argv: string[], handlers: {
51
+ setup: () => Promise<void>;
52
+ serve: () => Promise<void>;
53
+ }): Promise<void>;
54
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;GAaG;AAYH,OAAO,EAAE,SAAS,EAAmB,MAAM,kBAAkB,CAAC;AAE9D,eAAO,MAAM,YAAY,QAC0E,CAAC;AAEpG;;;;;;GAMG;AACH,wBAAgB,QAAQ,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,IAAI,CAgBnE;AAED;;;;;;;GAOG;AACH,wBAAsB,gBAAgB,CACpC,KAAK,EAAE,OAAO,mCAAmC,EAAE,MAAM,EACzD,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,CAAC,OAAO,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,CAAC,EAC5D,OAAO,EAAE;IAAE,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,OAAO,CAAA;KAAE,CAAA;CAAE,GACzD,OAAO,CAAC;IAAE,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC,CAmBhF;AAiCD;;;GAGG;AACH,wBAAsB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE;IACvD,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3B,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5B,GAAG,OAAO,CAAC,IAAI,CAAC,CAOhB"}
package/dist/index.js ADDED
@@ -0,0 +1,131 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * M365 Graph MCP Server — entrypoint.
4
+ *
5
+ * Two modes, dispatched on argv[2]:
6
+ * - `setup`: interactive OAuth flow → caches tokens in OS keychain
7
+ * - (default): stdio MCP server → reads cached tokens, serves tool
8
+ * calls over JSON-RPC framing
9
+ *
10
+ * Conforms to handbook docs/repo-types/mcp-server.md.
11
+ *
12
+ * IMPORTANT: All non-protocol output must go to stderr (`console.error`).
13
+ * Writing to stdout corrupts the MCP stdio JSON-RPC framing. CI lint
14
+ * rules enforce this in `juvantlabs/*-mcp-server` repos.
15
+ */
16
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
17
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
18
+ import { CallToolRequestSchema, ListToolsRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
19
+ import { makeMsalClient } from "./auth/msal.js";
20
+ import { runSetup } from "./auth/setup.js";
21
+ import { makeGraphClient } from "./client/graph.js";
22
+ import { ALL_TOOLS, buildHandlerMap } from "./tools/index.js";
23
+ export const TENANT_ID_RE = /^(common|organizations|consumers|[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})$/;
24
+ /**
25
+ * Validate the env vars the server needs at startup. Throws with a
26
+ * specific message on failure; main() catches + exits with stderr +
27
+ * code 1.
28
+ *
29
+ * Exported so tests can call directly with a fake env.
30
+ */
31
+ export function checkEnv(env = process.env) {
32
+ const missing = [];
33
+ if (!env.M365_CLIENT_ID)
34
+ missing.push("M365_CLIENT_ID");
35
+ if (!env.M365_CLIENT_SECRET)
36
+ missing.push("M365_CLIENT_SECRET");
37
+ if (!env.M365_TENANT_ID)
38
+ missing.push("M365_TENANT_ID");
39
+ if (missing.length > 0) {
40
+ throw new Error(`missing required env var(s): ${missing.join(", ")}. See README.md § Environment variables.`);
41
+ }
42
+ if (!TENANT_ID_RE.test(env.M365_TENANT_ID)) {
43
+ throw new Error(`M365_TENANT_ID has invalid shape: ${env.M365_TENANT_ID}. ` +
44
+ `Expected: 'common' | 'organizations' | 'consumers' | <UUID>.`);
45
+ }
46
+ }
47
+ /**
48
+ * Execute a single tools/call request against the registered handler
49
+ * map. Wraps handler errors in an `isError: true` MCP response so the
50
+ * agent sees a structured failure instead of a thrown exception that
51
+ * tears down the JSON-RPC session.
52
+ *
53
+ * Exported for unit testing without spinning up the full MCP transport.
54
+ */
55
+ export async function dispatchToolCall(graph, handlers, request) {
56
+ const { name, arguments: rawArgs } = request.params;
57
+ const handler = handlers.get(name);
58
+ if (!handler) {
59
+ throw new Error(`Unknown tool: ${name}`);
60
+ }
61
+ const args = (rawArgs ?? {});
62
+ try {
63
+ return (await handler(graph, args));
64
+ }
65
+ catch (err) {
66
+ const message = err instanceof Error ? err.message : String(err);
67
+ return {
68
+ content: [{ type: "text", text: `Error: ${message}` }],
69
+ isError: true,
70
+ };
71
+ }
72
+ }
73
+ async function runMcpServer() {
74
+ const msal = makeMsalClient();
75
+ const graph = makeGraphClient(msal);
76
+ const handlers = buildHandlerMap(ALL_TOOLS);
77
+ const logLevel = process.env.MCP_SERVER_LOG_LEVEL ?? "info";
78
+ const server = new Server({
79
+ name: "@juvantlabs/m365-graph-mcp-server",
80
+ version: "0.1.0",
81
+ }, {
82
+ capabilities: { tools: {} },
83
+ });
84
+ server.setRequestHandler(ListToolsRequestSchema, async () => ({
85
+ tools: ALL_TOOLS.map((t) => t.definition),
86
+ }));
87
+ server.setRequestHandler(CallToolRequestSchema, async (request) => dispatchToolCall(graph, handlers, request));
88
+ const transport = new StdioServerTransport();
89
+ await server.connect(transport);
90
+ console.error(`[m365-graph-mcp-server] running on stdio (log level: ${logLevel}, tenant: ${process.env.M365_TENANT_ID}, tools: ${ALL_TOOLS.length})`);
91
+ }
92
+ /**
93
+ * Subcommand dispatcher. Exported so tests can verify routing without
94
+ * actually spawning the server.
95
+ */
96
+ export async function dispatch(argv, handlers) {
97
+ const subcommand = argv[2];
98
+ if (subcommand === "setup") {
99
+ await handlers.setup();
100
+ return;
101
+ }
102
+ await handlers.serve();
103
+ }
104
+ async function main() {
105
+ try {
106
+ checkEnv();
107
+ }
108
+ catch (err) {
109
+ const message = err instanceof Error ? err.message : String(err);
110
+ console.error(`[m365-graph-mcp-server] ${message}`);
111
+ process.exit(1);
112
+ }
113
+ await dispatch(process.argv, {
114
+ setup: runSetup,
115
+ serve: runMcpServer,
116
+ });
117
+ }
118
+ // Only run main when invoked directly. Importing the module from tests
119
+ // or other code does NOT trigger startup.
120
+ const invokedDirectly = import.meta.url === `file://${process.argv[1]}` ||
121
+ // Also handle the tsx/node ESM case where argv[1] is the original .ts
122
+ import.meta.url.endsWith(process.argv[1] ?? "") ||
123
+ process.argv[1]?.endsWith("src/index.ts") === true ||
124
+ process.argv[1]?.endsWith("dist/index.js") === true;
125
+ if (invokedDirectly) {
126
+ main().catch((err) => {
127
+ console.error("[m365-graph-mcp-server] fatal:", err);
128
+ process.exit(1);
129
+ });
130
+ }
131
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Tool: m365-graph:cancel_event
3
+ *
4
+ * Cancel a meeting the user organizes. Sends a cancellation notice
5
+ * to attendees. Two-phase spec/approval pattern (see delete_file
6
+ * for the rationale): preview + confirmation_token, then execute.
7
+ *
8
+ * Note: this is for events the *user* organizes. For events where
9
+ * the user is just an attendee, the right action is to *decline*
10
+ * via Outlook (different Graph endpoint, not yet wrapped here).
11
+ * Calling cancel_event on a non-organized event will produce a
12
+ * clear Graph error.
13
+ *
14
+ * Required Graph scope: `Calendars.ReadWrite` (delegated).
15
+ */
16
+ import type { Tool } from "../types/tool.js";
17
+ export declare const cancelEventTool: Tool;
18
+ //# sourceMappingURL=cancel_event.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cancel_event.d.ts","sourceRoot":"","sources":["../../src/tools/cancel_event.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAaH,OAAO,KAAK,EAAE,IAAI,EAA6C,MAAM,kBAAkB,CAAC;AAqGxF,eAAO,MAAM,eAAe,EAAE,IAA8B,CAAC"}
@@ -0,0 +1,95 @@
1
+ /**
2
+ * Tool: m365-graph:cancel_event
3
+ *
4
+ * Cancel a meeting the user organizes. Sends a cancellation notice
5
+ * to attendees. Two-phase spec/approval pattern (see delete_file
6
+ * for the rationale): preview + confirmation_token, then execute.
7
+ *
8
+ * Note: this is for events the *user* organizes. For events where
9
+ * the user is just an attendee, the right action is to *decline*
10
+ * via Outlook (different Graph endpoint, not yet wrapped here).
11
+ * Calling cancel_event on a non-organized event will produce a
12
+ * clear Graph error.
13
+ *
14
+ * Required Graph scope: `Calendars.ReadWrite` (delegated).
15
+ */
16
+ import { consumeConfirmation, issueConfirmation, } from "../auth/confirmation_tokens.js";
17
+ import { summarizeEvent } from "./list_events.js";
18
+ import { validateOptionalString, validateRequiredString, } from "../types/validators.js";
19
+ const TOOL_NAME = "m365-graph:cancel_event";
20
+ const definition = {
21
+ name: TOOL_NAME,
22
+ description: "Cancel a meeting the user organizes (sends cancellation to attendees). Two-phase: first call returns event preview + confirmation_token; second call executes. Use this only for events the user is the organizer of — for declining as an attendee, decline in Outlook (not yet wrapped as a tool here).",
23
+ inputSchema: {
24
+ type: "object",
25
+ properties: {
26
+ event_id: { type: "string", description: "Event to cancel." },
27
+ comment: {
28
+ type: "string",
29
+ description: "Optional comment included in the cancellation notification sent to attendees.",
30
+ },
31
+ confirmation_token: {
32
+ type: "string",
33
+ description: "Omit on the first call (preview mode). Include the token returned by the preview call to execute the cancellation.",
34
+ },
35
+ },
36
+ required: ["event_id"],
37
+ },
38
+ };
39
+ const handler = async (graph, args) => {
40
+ const eventId = validateRequiredString(args.event_id, "event_id");
41
+ const comment = validateOptionalString(args.comment, "comment");
42
+ const confirmationToken = validateOptionalString(args.confirmation_token, "confirmation_token");
43
+ // Spec for confirmation includes the comment too — if the agent
44
+ // changes the comment between preview and execute, that's a
45
+ // different action and the token must be re-issued.
46
+ const spec = { event_id: eventId };
47
+ if (comment !== undefined)
48
+ spec.comment = comment;
49
+ const apiPath = `/me/events/${encodeURIComponent(eventId)}`;
50
+ // ---------- Phase 1: preview ----------
51
+ if (!confirmationToken) {
52
+ const event = (await graph.api(apiPath).get());
53
+ const summary = summarizeEvent(event);
54
+ const issued = issueConfirmation(TOOL_NAME, spec);
55
+ return {
56
+ content: [
57
+ {
58
+ type: "text",
59
+ text: JSON.stringify({
60
+ preview: {
61
+ event: summary,
62
+ cancellation_comment: comment ?? null,
63
+ ...issued,
64
+ instructions: `Re-call ${TOOL_NAME} with the SAME args (event_id${comment ? ", comment" : ""}) ` +
65
+ `plus this confirmation_token to send the cancellation notice.`,
66
+ },
67
+ }, null, 2),
68
+ },
69
+ ],
70
+ };
71
+ }
72
+ // ---------- Phase 2: execute ----------
73
+ const verdict = consumeConfirmation(confirmationToken, TOOL_NAME, spec);
74
+ if (!verdict.ok) {
75
+ throw new Error(`Refusing to cancel: confirmation_token ${verdict.error}. ` +
76
+ `Re-run without confirmation_token to get a fresh preview + token.`);
77
+ }
78
+ const cancelBody = {};
79
+ if (comment !== undefined)
80
+ cancelBody.Comment = comment;
81
+ await graph.api(`${apiPath}/cancel`).post(cancelBody);
82
+ return {
83
+ content: [
84
+ {
85
+ type: "text",
86
+ text: JSON.stringify({
87
+ cancelled: { event_id: eventId },
88
+ note: "POST /events/{id}/cancel executed. Cancellation notice sent to attendees.",
89
+ }, null, 2),
90
+ },
91
+ ],
92
+ };
93
+ };
94
+ export const cancelEventTool = { definition, handler };
95
+ //# sourceMappingURL=cancel_event.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cancel_event.js","sourceRoot":"","sources":["../../src/tools/cancel_event.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Tool: m365-graph:copy_file
3
+ *
4
+ * Copy a file or folder to a different location. Wraps Graph's async
5
+ * copy operation:
6
+ *
7
+ * POST /me/drive/items/{id}/copy → 202 + Location header
8
+ * GET <monitor URL> → poll until completed | failed
9
+ * GET <resourceLocation> → fetch the new item's metadata
10
+ *
11
+ * Polling: exponential backoff (1s → 2s → 4s → … capped at 30s)
12
+ * until completion or `wait_max_seconds` deadline. Per handbook
13
+ * anti-pattern S8, the tool never returns "initiated successfully" —
14
+ * either the copy completes (we return the new item) or we surface
15
+ * the failure / timeout to the agent.
16
+ *
17
+ * Required Graph scope: `Files.ReadWrite` (delegated).
18
+ */
19
+ import type { Tool, ToolHandler } from "../types/tool.js";
20
+ interface CopiedItemSummary {
21
+ id: string;
22
+ name: string;
23
+ size: number;
24
+ webUrl: string;
25
+ parent_id: string | null;
26
+ }
27
+ export declare function summarizeCopiedItem(item: Record<string, unknown>): CopiedItemSummary;
28
+ export interface MonitorPollResult {
29
+ status: "completed" | "failed" | "in_progress";
30
+ resource_location?: string;
31
+ percent_complete?: number;
32
+ error?: unknown;
33
+ raw: Record<string, unknown>;
34
+ }
35
+ export declare function classifyMonitorStatus(payload: Record<string, unknown>): MonitorPollResult;
36
+ declare const handler: ToolHandler;
37
+ export declare const copyFileTool: Tool;
38
+ export { handler as _copyFileHandler };
39
+ //# sourceMappingURL=copy_file.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"copy_file.d.ts","sourceRoot":"","sources":["../../src/tools/copy_file.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAYH,OAAO,KAAK,EAAE,IAAI,EAAkB,WAAW,EAAgB,MAAM,kBAAkB,CAAC;AA4BxF,UAAU,iBAAiB;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,iBAAiB,CASpF;AAMD,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,WAAW,GAAG,QAAQ,GAAG,aAAa,CAAC;IAC/C,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC9B;AAED,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,iBAAiB,CAgBzF;AAED,QAAA,MAAM,OAAO,EAAE,WA+Gd,CAAC;AAEF,eAAO,MAAM,YAAY,EAAE,IAA8B,CAAC;AAC1D,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,CAAC"}
@@ -0,0 +1,168 @@
1
+ /**
2
+ * Tool: m365-graph:copy_file
3
+ *
4
+ * Copy a file or folder to a different location. Wraps Graph's async
5
+ * copy operation:
6
+ *
7
+ * POST /me/drive/items/{id}/copy → 202 + Location header
8
+ * GET <monitor URL> → poll until completed | failed
9
+ * GET <resourceLocation> → fetch the new item's metadata
10
+ *
11
+ * Polling: exponential backoff (1s → 2s → 4s → … capped at 30s)
12
+ * until completion or `wait_max_seconds` deadline. Per handbook
13
+ * anti-pattern S8, the tool never returns "initiated successfully" —
14
+ * either the copy completes (we return the new item) or we surface
15
+ * the failure / timeout to the agent.
16
+ *
17
+ * Required Graph scope: `Files.ReadWrite` (delegated).
18
+ */
19
+ import { ResponseType, } from "@microsoft/microsoft-graph-client";
20
+ import { validateOptionalInteger, validateOptionalString, validateRequiredString, } from "../types/validators.js";
21
+ const POLL_INITIAL_MS = 1_000;
22
+ const POLL_MAX_MS = 30_000;
23
+ const definition = {
24
+ name: "m365-graph:copy_file",
25
+ description: "Copy a file or folder to a different location in a drive (or across drives). Wraps Graph's async copy: the tool polls the monitor URL until the copy completes — never returns 'initiated successfully'. Default wait is 300 seconds; configurable via wait_max_seconds.",
26
+ inputSchema: {
27
+ type: "object",
28
+ properties: {
29
+ item_id: { type: "string", description: "Source item ID (file or folder)." },
30
+ target_parent_id: { type: "string", description: "Destination folder ID." },
31
+ source_drive_id: { type: "string", description: "Optional source drive ID. Defaults to /me/drive." },
32
+ target_drive_id: { type: "string", description: "Optional target drive ID. Defaults to the source drive." },
33
+ new_name: { type: "string", description: "Optional rename during copy." },
34
+ wait_max_seconds: {
35
+ type: "integer",
36
+ minimum: 1,
37
+ maximum: 1800,
38
+ description: "Maximum seconds to poll the monitor URL before timing out (default 300).",
39
+ },
40
+ },
41
+ required: ["item_id", "target_parent_id"],
42
+ },
43
+ };
44
+ export function summarizeCopiedItem(item) {
45
+ const parent = item.parentReference;
46
+ return {
47
+ id: String(item.id ?? ""),
48
+ name: String(item.name ?? ""),
49
+ size: Number(item.size ?? 0),
50
+ webUrl: String(item.webUrl ?? ""),
51
+ parent_id: parent?.id ?? null,
52
+ };
53
+ }
54
+ function sleep(ms) {
55
+ return new Promise((resolve) => setTimeout(resolve, ms));
56
+ }
57
+ export function classifyMonitorStatus(payload) {
58
+ const status = String(payload.status ?? "").toLowerCase();
59
+ const result = {
60
+ status: status === "completed" ? "completed" : status === "failed" ? "failed" : "in_progress",
61
+ raw: payload,
62
+ };
63
+ if (typeof payload.resourceLocation === "string") {
64
+ result.resource_location = payload.resourceLocation;
65
+ }
66
+ if (typeof payload.percentageComplete === "number") {
67
+ result.percent_complete = payload.percentageComplete;
68
+ }
69
+ if (payload.error !== undefined) {
70
+ result.error = payload.error;
71
+ }
72
+ return result;
73
+ }
74
+ const handler = async (graph, args) => {
75
+ const itemId = validateRequiredString(args.item_id, "item_id");
76
+ const targetParentId = validateRequiredString(args.target_parent_id, "target_parent_id");
77
+ const sourceDriveId = validateOptionalString(args.source_drive_id, "source_drive_id");
78
+ const targetDriveId = validateOptionalString(args.target_drive_id, "target_drive_id");
79
+ const newName = validateOptionalString(args.new_name, "new_name");
80
+ const waitMaxSeconds = validateOptionalInteger(args.wait_max_seconds, "wait_max_seconds", {
81
+ min: 1,
82
+ max: 1800,
83
+ default: 300,
84
+ });
85
+ const sourcePath = sourceDriveId
86
+ ? `/drives/${encodeURIComponent(sourceDriveId)}/items/${encodeURIComponent(itemId)}`
87
+ : `/me/drive/items/${encodeURIComponent(itemId)}`;
88
+ // Fetch source metadata up-front so we know the source name (needed
89
+ // for the post-completion fallback if the monitor URL doesn't return
90
+ // resourceLocation).
91
+ const sourceItem = (await graph.api(sourcePath).get());
92
+ const effectiveName = newName ?? String(sourceItem.name ?? "");
93
+ const body = {
94
+ parentReference: targetDriveId
95
+ ? { driveId: targetDriveId, id: targetParentId }
96
+ : { id: targetParentId },
97
+ };
98
+ if (newName !== undefined)
99
+ body.name = newName;
100
+ // POST → raw response to read the Location header for the monitor URL
101
+ const raw = (await graph
102
+ .api(`${sourcePath}/copy`)
103
+ .responseType(ResponseType.RAW)
104
+ .post(body));
105
+ if (raw.status !== 202) {
106
+ throw new Error(`copy: expected 202 Accepted, got ${raw.status} ${raw.statusText}`);
107
+ }
108
+ const monitorUrl = raw.headers.get("location") ?? raw.headers.get("Location");
109
+ if (!monitorUrl) {
110
+ throw new Error("copy: 202 response missing Location header (monitor URL)");
111
+ }
112
+ const deadline = Date.now() + waitMaxSeconds * 1000;
113
+ let pollInterval = POLL_INITIAL_MS;
114
+ let last = null;
115
+ while (Date.now() < deadline) {
116
+ await sleep(pollInterval);
117
+ pollInterval = Math.min(pollInterval * 2, POLL_MAX_MS);
118
+ const payload = (await graph.api(monitorUrl).get());
119
+ last = classifyMonitorStatus(payload);
120
+ if (last.status === "completed") {
121
+ let copied = null;
122
+ if (last.resource_location) {
123
+ // Happy path: monitor URL returned a fetchable resourceLocation.
124
+ const newItem = (await graph
125
+ .api(last.resource_location)
126
+ .get());
127
+ copied = summarizeCopiedItem(newItem);
128
+ }
129
+ else {
130
+ // Graph quirk: completed responses sometimes omit resourceLocation.
131
+ // Fall back to listing the target parent and matching by name.
132
+ const targetDriveBase = targetDriveId
133
+ ? `/drives/${encodeURIComponent(targetDriveId)}`
134
+ : sourceDriveId
135
+ ? `/drives/${encodeURIComponent(sourceDriveId)}`
136
+ : "/me/drive";
137
+ const childrenPath = `${targetDriveBase}/items/${encodeURIComponent(targetParentId)}/children`;
138
+ const listing = (await graph
139
+ .api(childrenPath)
140
+ .filter(`name eq '${effectiveName.replace(/'/g, "''")}'`)
141
+ .get());
142
+ const matches = Array.isArray(listing?.value) ? listing.value : [];
143
+ if (matches.length > 0) {
144
+ copied = summarizeCopiedItem(matches[0]);
145
+ }
146
+ }
147
+ return {
148
+ content: [
149
+ {
150
+ type: "text",
151
+ text: JSON.stringify({
152
+ status: "completed",
153
+ copied,
154
+ source: { item_id: itemId, drive_id: sourceDriveId ?? null },
155
+ }, null, 2),
156
+ },
157
+ ],
158
+ };
159
+ }
160
+ if (last.status === "failed") {
161
+ throw new Error(`copy operation failed: ${JSON.stringify(last.error ?? "(no detail)")}`);
162
+ }
163
+ }
164
+ throw new Error(`copy did not complete within ${waitMaxSeconds}s. Last status: ${JSON.stringify(last?.raw ?? "(no poll yet)")}`);
165
+ };
166
+ export const copyFileTool = { definition, handler };
167
+ export { handler as _copyFileHandler };
168
+ //# sourceMappingURL=copy_file.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"copy_file.js","sourceRoot":"","sources":["../../src/tools/copy_file.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Tool: m365-graph:create_event
3
+ *
4
+ * Create a new event on the user's primary calendar (or a specified
5
+ * calendar). Wraps Graph `POST /me/events` (or
6
+ * `POST /me/calendars/{id}/events`).
7
+ *
8
+ * Required Graph scope: `Calendars.ReadWrite` (delegated).
9
+ *
10
+ * Send-invitations behavior: by default Graph DOES send meeting
11
+ * invitations to attendees on event creation. To create an event
12
+ * without sending invites, set `send_invitations: false` (we set
13
+ * `responseStatus.response: "organizer"` and don't add the user as
14
+ * attendee — but Graph still notifies the *other* attendees unless
15
+ * the calendar is configured otherwise).
16
+ *
17
+ * Defaults:
18
+ * - timezone: "UTC" if not specified (Graph requires explicit TZ)
19
+ * - body_content_type: "text"
20
+ * - is_all_day: false
21
+ * - attendee.type: "required" (when type omitted in input)
22
+ *
23
+ * No spec/approval pattern here — creation is non-destructive (worst
24
+ * case: clutter on the calendar; the agent can call cancel_event or
25
+ * the user can delete via Outlook UI).
26
+ */
27
+ import type { Tool } from "../types/tool.js";
28
+ export declare const createEventTool: Tool;
29
+ //# sourceMappingURL=create_event.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create_event.d.ts","sourceRoot":"","sources":["../../src/tools/create_event.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAWH,OAAO,KAAK,EAAE,IAAI,EAA6C,MAAM,kBAAkB,CAAC;AAmJxF,eAAO,MAAM,eAAe,EAAE,IAA8B,CAAC"}