@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.
- package/ARCHITECTURE.md +225 -0
- package/CHANGELOG.md +188 -0
- package/LICENSE +21 -0
- package/README.md +164 -0
- package/SECURITY.md +64 -0
- package/dist/auth/confirmation_tokens.d.ts +38 -0
- package/dist/auth/confirmation_tokens.d.ts.map +1 -0
- package/dist/auth/confirmation_tokens.js +85 -0
- package/dist/auth/confirmation_tokens.js.map +1 -0
- package/dist/auth/keyring.d.ts +20 -0
- package/dist/auth/keyring.d.ts.map +1 -0
- package/dist/auth/keyring.js +41 -0
- package/dist/auth/keyring.js.map +1 -0
- package/dist/auth/msal.d.ts +42 -0
- package/dist/auth/msal.d.ts.map +1 -0
- package/dist/auth/msal.js +96 -0
- package/dist/auth/msal.js.map +1 -0
- package/dist/auth/setup.d.ts +18 -0
- package/dist/auth/setup.d.ts.map +1 -0
- package/dist/auth/setup.js +110 -0
- package/dist/auth/setup.js.map +1 -0
- package/dist/client/graph.d.ts +30 -0
- package/dist/client/graph.d.ts.map +1 -0
- package/dist/client/graph.js +38 -0
- package/dist/client/graph.js.map +1 -0
- package/dist/index.d.ts +54 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +131 -0
- package/dist/index.js.map +1 -0
- package/dist/tools/cancel_event.d.ts +18 -0
- package/dist/tools/cancel_event.d.ts.map +1 -0
- package/dist/tools/cancel_event.js +95 -0
- package/dist/tools/cancel_event.js.map +1 -0
- package/dist/tools/copy_file.d.ts +39 -0
- package/dist/tools/copy_file.d.ts.map +1 -0
- package/dist/tools/copy_file.js +168 -0
- package/dist/tools/copy_file.js.map +1 -0
- package/dist/tools/create_event.d.ts +29 -0
- package/dist/tools/create_event.d.ts.map +1 -0
- package/dist/tools/create_event.js +144 -0
- package/dist/tools/create_event.js.map +1 -0
- package/dist/tools/decline_event.d.ts +18 -0
- package/dist/tools/decline_event.d.ts.map +1 -0
- package/dist/tools/decline_event.js +105 -0
- package/dist/tools/decline_event.js.map +1 -0
- package/dist/tools/delete_file.d.ts +28 -0
- package/dist/tools/delete_file.d.ts.map +1 -0
- package/dist/tools/delete_file.js +103 -0
- package/dist/tools/delete_file.js.map +1 -0
- package/dist/tools/download_file.d.ts +43 -0
- package/dist/tools/download_file.d.ts.map +1 -0
- package/dist/tools/download_file.js +133 -0
- package/dist/tools/download_file.js.map +1 -0
- package/dist/tools/get_event.d.ts +27 -0
- package/dist/tools/get_event.d.ts.map +1 -0
- package/dist/tools/get_event.js +55 -0
- package/dist/tools/get_event.js.map +1 -0
- package/dist/tools/index.d.ts +13 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +61 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/list_calendars.d.ts +26 -0
- package/dist/tools/list_calendars.d.ts.map +1 -0
- package/dist/tools/list_calendars.js +60 -0
- package/dist/tools/list_calendars.js.map +1 -0
- package/dist/tools/list_drives.d.ts +27 -0
- package/dist/tools/list_drives.d.ts.map +1 -0
- package/dist/tools/list_drives.js +58 -0
- package/dist/tools/list_drives.js.map +1 -0
- package/dist/tools/list_events.d.ts +51 -0
- package/dist/tools/list_events.d.ts.map +1 -0
- package/dist/tools/list_events.js +119 -0
- package/dist/tools/list_events.js.map +1 -0
- package/dist/tools/list_items.d.ts +31 -0
- package/dist/tools/list_items.d.ts.map +1 -0
- package/dist/tools/list_items.js +81 -0
- package/dist/tools/list_items.js.map +1 -0
- package/dist/tools/move_file.d.ts +18 -0
- package/dist/tools/move_file.d.ts.map +1 -0
- package/dist/tools/move_file.js +60 -0
- package/dist/tools/move_file.js.map +1 -0
- package/dist/tools/search_events.d.ts +25 -0
- package/dist/tools/search_events.d.ts.map +1 -0
- package/dist/tools/search_events.js +71 -0
- package/dist/tools/search_events.js.map +1 -0
- package/dist/tools/search_events_content.d.ts +32 -0
- package/dist/tools/search_events_content.d.ts.map +1 -0
- package/dist/tools/search_events_content.js +106 -0
- package/dist/tools/search_events_content.js.map +1 -0
- package/dist/tools/search_files.d.ts +30 -0
- package/dist/tools/search_files.d.ts.map +1 -0
- package/dist/tools/search_files.js +82 -0
- package/dist/tools/search_files.js.map +1 -0
- package/dist/tools/update_event.d.ts +25 -0
- package/dist/tools/update_event.d.ts.map +1 -0
- package/dist/tools/update_event.js +123 -0
- package/dist/tools/update_event.js.map +1 -0
- package/dist/tools/upload_file.d.ts +38 -0
- package/dist/tools/upload_file.d.ts.map +1 -0
- package/dist/tools/upload_file.js +152 -0
- package/dist/tools/upload_file.js.map +1 -0
- package/dist/types/tool.d.ts +32 -0
- package/dist/types/tool.d.ts.map +1 -0
- package/dist/types/tool.js +10 -0
- package/dist/types/tool.js.map +1 -0
- package/dist/types/validators.d.ts +44 -0
- package/dist/types/validators.d.ts.map +1 -0
- package/dist/types/validators.js +78 -0
- package/dist/types/validators.js.map +1 -0
- package/package.json +72 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get_event.d.ts","sourceRoot":"","sources":["../../src/tools/get_event.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAIH,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAElD,OAAO,KAAK,EAAE,IAAI,EAA6C,MAAM,kBAAkB,CAAC;AAoBxF,UAAU,SAAU,SAAQ,UAAU,CAAC,OAAO,cAAc,CAAC;IAC3D,iBAAiB,EAAE,MAAM,CAAC;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,cAAc,EAAE,OAAO,CAAC;IACxB,UAAU,EAAE,OAAO,CAAC;CACrB;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAYrE;AAgBD,eAAO,MAAM,YAAY,EAAE,IAA8B,CAAC"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool: m365-graph:get_event
|
|
3
|
+
*
|
|
4
|
+
* Fetch a single event's full detail (including the full body,
|
|
5
|
+
* attendees with response statuses, location, recurrence rule for
|
|
6
|
+
* series masters). Wraps Graph `/me/events/{id}`.
|
|
7
|
+
*
|
|
8
|
+
* Required Graph scope: `Calendars.Read` (delegated). Read-only.
|
|
9
|
+
*
|
|
10
|
+
* Input:
|
|
11
|
+
* event_id (string, required) — id from list_events / search_events
|
|
12
|
+
*
|
|
13
|
+
* Output: full event summary plus `body` (the long-form HTML/text
|
|
14
|
+
* preview, capped) and `recurrence` (the recurrence rule if any).
|
|
15
|
+
*/
|
|
16
|
+
import { summarizeEvent } from "./list_events.js";
|
|
17
|
+
import { validateRequiredString } from "../types/validators.js";
|
|
18
|
+
const BODY_CHAR_CAP = 8_000;
|
|
19
|
+
const definition = {
|
|
20
|
+
name: "m365-graph:get_event",
|
|
21
|
+
description: "Fetch full details for a single event — body, attendees with response statuses, location, recurrence rule. Body is capped at 8000 chars; use the webLink for full content. Read-only.",
|
|
22
|
+
inputSchema: {
|
|
23
|
+
type: "object",
|
|
24
|
+
properties: {
|
|
25
|
+
event_id: {
|
|
26
|
+
type: "string",
|
|
27
|
+
description: "Event ID from list_events or search_events.",
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
required: ["event_id"],
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
export function expandEvent(event) {
|
|
34
|
+
const summary = summarizeEvent(event);
|
|
35
|
+
const body = event.body;
|
|
36
|
+
const bodyContent = String(body?.content ?? "");
|
|
37
|
+
const truncated = bodyContent.length > BODY_CHAR_CAP;
|
|
38
|
+
return {
|
|
39
|
+
...summary,
|
|
40
|
+
body_content_type: String(body?.contentType ?? "text"),
|
|
41
|
+
body: truncated ? bodyContent.slice(0, BODY_CHAR_CAP) : bodyContent,
|
|
42
|
+
body_truncated: truncated,
|
|
43
|
+
recurrence: event.recurrence ?? null,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
const handler = async (graph, args) => {
|
|
47
|
+
const eventId = validateRequiredString(args.event_id, "event_id");
|
|
48
|
+
const event = await graph.api(`/me/events/${encodeURIComponent(eventId)}`).get();
|
|
49
|
+
const result = expandEvent(event);
|
|
50
|
+
return {
|
|
51
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
52
|
+
};
|
|
53
|
+
};
|
|
54
|
+
export const getEventTool = { definition, handler };
|
|
55
|
+
//# sourceMappingURL=get_event.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get_event.js","sourceRoot":"","sources":["../../src/tools/get_event.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAIH,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AAGhE,MAAM,aAAa,GAAG,KAAK,CAAC;AAE5B,MAAM,UAAU,GAAmB;IACjC,IAAI,EAAE,sBAAsB;IAC5B,WAAW,EACT,uLAAuL;IACzL,WAAW,EAAE;QACX,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACV,QAAQ,EAAE;gBACR,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,6CAA6C;aAC3D;SACF;QACD,QAAQ,EAAE,CAAC,UAAU,CAAC;KACvB;CACF,CAAC;AASF,MAAM,UAAU,WAAW,CAAC,KAA8B;IACxD,MAAM,OAAO,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC;IACtC,MAAM,IAAI,GAAG,KAAK,CAAC,IAA2C,CAAC;IAC/D,MAAM,WAAW,GAAG,MAAM,CAAC,IAAI,EAAE,OAAO,IAAI,EAAE,CAAC,CAAC;IAChD,MAAM,SAAS,GAAG,WAAW,CAAC,MAAM,GAAG,aAAa,CAAC;IACrD,OAAO;QACL,GAAG,OAAO;QACV,iBAAiB,EAAE,MAAM,CAAC,IAAI,EAAE,WAAW,IAAI,MAAM,CAAC;QACtD,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,EAAE,aAAa,CAAC,CAAC,CAAC,CAAC,WAAW;QACnE,cAAc,EAAE,SAAS;QACzB,UAAU,EAAE,KAAK,CAAC,UAAU,IAAI,IAAI;KACrC,CAAC;AACJ,CAAC;AAED,MAAM,OAAO,GAAgB,KAAK,EAChC,KAAa,EACb,IAA6B,EACN,EAAE;IACzB,MAAM,OAAO,GAAG,sBAAsB,CAAC,IAAI,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;IAElE,MAAM,KAAK,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,cAAc,kBAAkB,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC;IACjF,MAAM,MAAM,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC;IAElC,OAAO;QACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;KACnE,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,YAAY,GAAS,EAAE,UAAU,EAAE,OAAO,EAAE,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool registry — single source of truth for which tools the server
|
|
3
|
+
* exposes. Both the tools/list handler and the tools/call dispatcher
|
|
4
|
+
* read from this module.
|
|
5
|
+
*
|
|
6
|
+
* Each new tool: add an import here + push into ALL_TOOLS. The
|
|
7
|
+
* dispatcher in src/index.ts builds a map from tool name to handler
|
|
8
|
+
* once at startup; no per-call registration overhead.
|
|
9
|
+
*/
|
|
10
|
+
import type { Tool } from "../types/tool.js";
|
|
11
|
+
export declare const ALL_TOOLS: ReadonlyArray<Tool>;
|
|
12
|
+
export declare function buildHandlerMap(tools: ReadonlyArray<Tool>): Map<string, Tool["handler"]>;
|
|
13
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAuB7C,eAAO,MAAM,SAAS,EAAE,aAAa,CAAC,IAAI,CAsBzC,CAAC;AAEF,wBAAgB,eAAe,CAAC,KAAK,EAAE,aAAa,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,CAMxF"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool registry — single source of truth for which tools the server
|
|
3
|
+
* exposes. Both the tools/list handler and the tools/call dispatcher
|
|
4
|
+
* read from this module.
|
|
5
|
+
*
|
|
6
|
+
* Each new tool: add an import here + push into ALL_TOOLS. The
|
|
7
|
+
* dispatcher in src/index.ts builds a map from tool name to handler
|
|
8
|
+
* once at startup; no per-call registration overhead.
|
|
9
|
+
*/
|
|
10
|
+
// Files — read
|
|
11
|
+
import { downloadFileTool } from "./download_file.js";
|
|
12
|
+
import { listDrivesTool } from "./list_drives.js";
|
|
13
|
+
import { listItemsTool } from "./list_items.js";
|
|
14
|
+
import { searchFilesTool } from "./search_files.js";
|
|
15
|
+
// Files — write
|
|
16
|
+
import { copyFileTool } from "./copy_file.js";
|
|
17
|
+
import { deleteFileTool } from "./delete_file.js";
|
|
18
|
+
import { moveFileTool } from "./move_file.js";
|
|
19
|
+
import { uploadFileTool } from "./upload_file.js";
|
|
20
|
+
// Calendars — read
|
|
21
|
+
import { getEventTool } from "./get_event.js";
|
|
22
|
+
import { listCalendarsTool } from "./list_calendars.js";
|
|
23
|
+
import { listEventsTool } from "./list_events.js";
|
|
24
|
+
import { searchEventsTool } from "./search_events.js";
|
|
25
|
+
import { searchEventsContentTool } from "./search_events_content.js";
|
|
26
|
+
// Calendars — write
|
|
27
|
+
import { cancelEventTool } from "./cancel_event.js";
|
|
28
|
+
import { createEventTool } from "./create_event.js";
|
|
29
|
+
import { declineEventTool } from "./decline_event.js";
|
|
30
|
+
import { updateEventTool } from "./update_event.js";
|
|
31
|
+
export const ALL_TOOLS = [
|
|
32
|
+
// Files — read
|
|
33
|
+
listDrivesTool,
|
|
34
|
+
listItemsTool,
|
|
35
|
+
searchFilesTool,
|
|
36
|
+
downloadFileTool,
|
|
37
|
+
// Files — write
|
|
38
|
+
uploadFileTool,
|
|
39
|
+
copyFileTool,
|
|
40
|
+
moveFileTool,
|
|
41
|
+
deleteFileTool,
|
|
42
|
+
// Calendars — read
|
|
43
|
+
listCalendarsTool,
|
|
44
|
+
listEventsTool,
|
|
45
|
+
searchEventsTool,
|
|
46
|
+
searchEventsContentTool,
|
|
47
|
+
getEventTool,
|
|
48
|
+
// Calendars — write
|
|
49
|
+
createEventTool,
|
|
50
|
+
updateEventTool,
|
|
51
|
+
cancelEventTool,
|
|
52
|
+
declineEventTool,
|
|
53
|
+
];
|
|
54
|
+
export function buildHandlerMap(tools) {
|
|
55
|
+
const m = new Map();
|
|
56
|
+
for (const t of tools) {
|
|
57
|
+
m.set(t.definition.name, t.handler);
|
|
58
|
+
}
|
|
59
|
+
return m;
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,eAAe;AACf,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,gBAAgB;AAChB,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,mBAAmB;AACnB,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,uBAAuB,EAAE,MAAM,4BAA4B,CAAC;AACrE,oBAAoB;AACpB,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEpD,MAAM,CAAC,MAAM,SAAS,GAAwB;IAC5C,eAAe;IACf,cAAc;IACd,aAAa;IACb,eAAe;IACf,gBAAgB;IAChB,gBAAgB;IAChB,cAAc;IACd,YAAY;IACZ,YAAY;IACZ,cAAc;IACd,mBAAmB;IACnB,iBAAiB;IACjB,cAAc;IACd,gBAAgB;IAChB,uBAAuB;IACvB,YAAY;IACZ,oBAAoB;IACpB,eAAe;IACf,eAAe;IACf,eAAe;IACf,gBAAgB;CACjB,CAAC;AAEF,MAAM,UAAU,eAAe,CAAC,KAA0B;IACxD,MAAM,CAAC,GAAG,IAAI,GAAG,EAA2B,CAAC;IAC7C,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;QACtB,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC;IACtC,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool: m365-graph:list_calendars
|
|
3
|
+
*
|
|
4
|
+
* List the user's calendars (primary calendar + any group / shared
|
|
5
|
+
* calendars they have access to). Wraps Graph `/me/calendars`.
|
|
6
|
+
*
|
|
7
|
+
* Required Graph scope: `Calendars.Read` (delegated). Read-only.
|
|
8
|
+
*
|
|
9
|
+
* Output: JSON list of calendars with id, name, color, owner,
|
|
10
|
+
* canEdit, canShare, isDefaultCalendar.
|
|
11
|
+
*/
|
|
12
|
+
import type { Tool } from "../types/tool.js";
|
|
13
|
+
interface CalendarSummary {
|
|
14
|
+
id: string;
|
|
15
|
+
name: string;
|
|
16
|
+
color: string;
|
|
17
|
+
owner_name: string | null;
|
|
18
|
+
owner_email: string | null;
|
|
19
|
+
is_default: boolean;
|
|
20
|
+
can_edit: boolean;
|
|
21
|
+
can_share: boolean;
|
|
22
|
+
}
|
|
23
|
+
export declare function summarizeCalendar(cal: Record<string, unknown>): CalendarSummary;
|
|
24
|
+
export declare const listCalendarsTool: Tool;
|
|
25
|
+
export {};
|
|
26
|
+
//# sourceMappingURL=list_calendars.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list_calendars.d.ts","sourceRoot":"","sources":["../../src/tools/list_calendars.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAKH,OAAO,KAAK,EAAE,IAAI,EAA6C,MAAM,kBAAkB,CAAC;AAoBxF,UAAU,eAAe;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,UAAU,EAAE,OAAO,CAAC;IACpB,QAAQ,EAAE,OAAO,CAAC;IAClB,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,eAAe,CAY/E;AA0BD,eAAO,MAAM,iBAAiB,EAAE,IAA8B,CAAC"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool: m365-graph:list_calendars
|
|
3
|
+
*
|
|
4
|
+
* List the user's calendars (primary calendar + any group / shared
|
|
5
|
+
* calendars they have access to). Wraps Graph `/me/calendars`.
|
|
6
|
+
*
|
|
7
|
+
* Required Graph scope: `Calendars.Read` (delegated). Read-only.
|
|
8
|
+
*
|
|
9
|
+
* Output: JSON list of calendars with id, name, color, owner,
|
|
10
|
+
* canEdit, canShare, isDefaultCalendar.
|
|
11
|
+
*/
|
|
12
|
+
import { validateOptionalInteger } from "../types/validators.js";
|
|
13
|
+
const definition = {
|
|
14
|
+
name: "m365-graph:list_calendars",
|
|
15
|
+
description: "List the user's calendars: their primary calendar plus any group or shared calendars they have access to. Read-only. Use the returned id with list_events / search_events / get_event to scope to a specific calendar.",
|
|
16
|
+
inputSchema: {
|
|
17
|
+
type: "object",
|
|
18
|
+
properties: {
|
|
19
|
+
limit: {
|
|
20
|
+
type: "integer",
|
|
21
|
+
minimum: 1,
|
|
22
|
+
maximum: 100,
|
|
23
|
+
description: "Maximum number of calendars to return (default 50).",
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
required: [],
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
export function summarizeCalendar(cal) {
|
|
30
|
+
const owner = cal.owner;
|
|
31
|
+
return {
|
|
32
|
+
id: String(cal.id ?? ""),
|
|
33
|
+
name: String(cal.name ?? ""),
|
|
34
|
+
color: String(cal.color ?? "auto"),
|
|
35
|
+
owner_name: owner?.name ?? null,
|
|
36
|
+
owner_email: owner?.address ?? null,
|
|
37
|
+
is_default: Boolean(cal.isDefaultCalendar),
|
|
38
|
+
can_edit: Boolean(cal.canEdit),
|
|
39
|
+
can_share: Boolean(cal.canShare),
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
const handler = async (graph, args) => {
|
|
43
|
+
const limit = validateOptionalInteger(args.limit, "limit", {
|
|
44
|
+
min: 1,
|
|
45
|
+
max: 100,
|
|
46
|
+
default: 50,
|
|
47
|
+
});
|
|
48
|
+
const response = await graph.api("/me/calendars").top(limit).get();
|
|
49
|
+
const items = Array.isArray(response?.value) ? response.value : [];
|
|
50
|
+
const calendars = items.map((c) => summarizeCalendar(c));
|
|
51
|
+
const result = {
|
|
52
|
+
count: calendars.length,
|
|
53
|
+
calendars,
|
|
54
|
+
};
|
|
55
|
+
return {
|
|
56
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
57
|
+
};
|
|
58
|
+
};
|
|
59
|
+
export const listCalendarsTool = { definition, handler };
|
|
60
|
+
//# sourceMappingURL=list_calendars.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list_calendars.js","sourceRoot":"","sources":["../../src/tools/list_calendars.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAIH,OAAO,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AAGjE,MAAM,UAAU,GAAmB;IACjC,IAAI,EAAE,2BAA2B;IACjC,WAAW,EACT,wNAAwN;IAC1N,WAAW,EAAE;QACX,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACV,KAAK,EAAE;gBACL,IAAI,EAAE,SAAS;gBACf,OAAO,EAAE,CAAC;gBACV,OAAO,EAAE,GAAG;gBACZ,WAAW,EAAE,qDAAqD;aACnE;SACF;QACD,QAAQ,EAAE,EAAE;KACb;CACF,CAAC;AAaF,MAAM,UAAU,iBAAiB,CAAC,GAA4B;IAC5D,MAAM,KAAK,GAAG,GAAG,CAAC,KAA4C,CAAC;IAC/D,OAAO;QACL,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,CAAC;QACxB,IAAI,EAAE,MAAM,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC;QAC5B,KAAK,EAAE,MAAM,CAAC,GAAG,CAAC,KAAK,IAAI,MAAM,CAAC;QAClC,UAAU,EAAG,KAAK,EAAE,IAA2B,IAAI,IAAI;QACvD,WAAW,EAAG,KAAK,EAAE,OAA8B,IAAI,IAAI;QAC3D,UAAU,EAAE,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC;QAC1C,QAAQ,EAAE,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC;QAC9B,SAAS,EAAE,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC;KACjC,CAAC;AACJ,CAAC;AAED,MAAM,OAAO,GAAgB,KAAK,EAChC,KAAa,EACb,IAA6B,EACN,EAAE;IACzB,MAAM,KAAK,GAAG,uBAAuB,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,EAAE;QACzD,GAAG,EAAE,CAAC;QACN,GAAG,EAAE,GAAG;QACR,OAAO,EAAE,EAAE;KACZ,CAAC,CAAC;IAEH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,CAAC;IACnE,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;IACnE,MAAM,SAAS,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAA0B,EAAE,EAAE,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,CAAC;IAElF,MAAM,MAAM,GAAG;QACb,KAAK,EAAE,SAAS,CAAC,MAAM;QACvB,SAAS;KACV,CAAC;IAEF,OAAO;QACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;KACnE,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,iBAAiB,GAAS,EAAE,UAAU,EAAE,OAAO,EAAE,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool: m365-graph:list_drives
|
|
3
|
+
*
|
|
4
|
+
* Returns the drives the authenticated user has access to:
|
|
5
|
+
* - Their primary OneDrive (`/me/drive`)
|
|
6
|
+
* - Other drives accessible to them (`/me/drives`), which includes
|
|
7
|
+
* SharePoint document libraries the user is a member of.
|
|
8
|
+
*
|
|
9
|
+
* Required Graph scope: `Files.Read` (delegated). No write side-effects.
|
|
10
|
+
*
|
|
11
|
+
* This is the simplest read-only tool, used to validate the auth +
|
|
12
|
+
* Graph plumbing end-to-end. Subsequent tools (search, list items,
|
|
13
|
+
* download, etc.) follow the same pattern: typed input, typed output,
|
|
14
|
+
* single Graph URL surface, no caller-supplied paths.
|
|
15
|
+
*/
|
|
16
|
+
import type { Tool } from "../types/tool.js";
|
|
17
|
+
interface DriveSummary {
|
|
18
|
+
id: string;
|
|
19
|
+
driveType: string;
|
|
20
|
+
name: string;
|
|
21
|
+
webUrl: string;
|
|
22
|
+
owner: string | null;
|
|
23
|
+
}
|
|
24
|
+
export declare function summarizeDrive(drive: Record<string, unknown>): DriveSummary;
|
|
25
|
+
export declare const listDrivesTool: Tool;
|
|
26
|
+
export {};
|
|
27
|
+
//# sourceMappingURL=list_drives.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list_drives.d.ts","sourceRoot":"","sources":["../../src/tools/list_drives.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAIH,OAAO,KAAK,EAAE,IAAI,EAA6C,MAAM,kBAAkB,CAAC;AAaxF,UAAU,YAAY;IACpB,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,YAAY,CAe3E;AAsBD,eAAO,MAAM,cAAc,EAAE,IAA8B,CAAC"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool: m365-graph:list_drives
|
|
3
|
+
*
|
|
4
|
+
* Returns the drives the authenticated user has access to:
|
|
5
|
+
* - Their primary OneDrive (`/me/drive`)
|
|
6
|
+
* - Other drives accessible to them (`/me/drives`), which includes
|
|
7
|
+
* SharePoint document libraries the user is a member of.
|
|
8
|
+
*
|
|
9
|
+
* Required Graph scope: `Files.Read` (delegated). No write side-effects.
|
|
10
|
+
*
|
|
11
|
+
* This is the simplest read-only tool, used to validate the auth +
|
|
12
|
+
* Graph plumbing end-to-end. Subsequent tools (search, list items,
|
|
13
|
+
* download, etc.) follow the same pattern: typed input, typed output,
|
|
14
|
+
* single Graph URL surface, no caller-supplied paths.
|
|
15
|
+
*/
|
|
16
|
+
const definition = {
|
|
17
|
+
name: "m365-graph:list_drives",
|
|
18
|
+
description: "List the drives the authenticated user has access to. Returns the user's primary OneDrive plus any shared SharePoint document libraries they're a member of. Read-only.",
|
|
19
|
+
inputSchema: {
|
|
20
|
+
type: "object",
|
|
21
|
+
properties: {},
|
|
22
|
+
required: [],
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
export function summarizeDrive(drive) {
|
|
26
|
+
const owner = drive.owner;
|
|
27
|
+
const ownerUser = owner?.user;
|
|
28
|
+
const ownerGroup = owner?.group;
|
|
29
|
+
const ownerName = ownerUser?.displayName ??
|
|
30
|
+
ownerGroup?.displayName ??
|
|
31
|
+
null;
|
|
32
|
+
return {
|
|
33
|
+
id: String(drive.id ?? ""),
|
|
34
|
+
driveType: String(drive.driveType ?? ""),
|
|
35
|
+
name: String(drive.name ?? ""),
|
|
36
|
+
webUrl: String(drive.webUrl ?? ""),
|
|
37
|
+
owner: ownerName,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
const handler = async (graph) => {
|
|
41
|
+
const primary = await graph.api("/me/drive").get();
|
|
42
|
+
const all = await graph.api("/me/drives").get();
|
|
43
|
+
const driveList = Array.isArray(all?.value) ? all.value : [];
|
|
44
|
+
const result = {
|
|
45
|
+
primary: summarizeDrive(primary),
|
|
46
|
+
accessible: driveList.map((d) => summarizeDrive(d)),
|
|
47
|
+
};
|
|
48
|
+
return {
|
|
49
|
+
content: [
|
|
50
|
+
{
|
|
51
|
+
type: "text",
|
|
52
|
+
text: JSON.stringify(result, null, 2),
|
|
53
|
+
},
|
|
54
|
+
],
|
|
55
|
+
};
|
|
56
|
+
};
|
|
57
|
+
export const listDrivesTool = { definition, handler };
|
|
58
|
+
//# sourceMappingURL=list_drives.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list_drives.js","sourceRoot":"","sources":["../../src/tools/list_drives.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAMH,MAAM,UAAU,GAAmB;IACjC,IAAI,EAAE,wBAAwB;IAC9B,WAAW,EACT,yKAAyK;IAC3K,WAAW,EAAE;QACX,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE,EAAE;QACd,QAAQ,EAAE,EAAE;KACb;CACF,CAAC;AAUF,MAAM,UAAU,cAAc,CAAC,KAA8B;IAC3D,MAAM,KAAK,GAAG,KAAK,CAAC,KAA4C,CAAC;IACjE,MAAM,SAAS,GAAG,KAAK,EAAE,IAA2C,CAAC;IACrE,MAAM,UAAU,GAAG,KAAK,EAAE,KAA4C,CAAC;IACvE,MAAM,SAAS,GACZ,SAAS,EAAE,WAAkC;QAC7C,UAAU,EAAE,WAAkC;QAC/C,IAAI,CAAC;IACP,OAAO;QACL,EAAE,EAAE,MAAM,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,CAAC;QAC1B,SAAS,EAAE,MAAM,CAAC,KAAK,CAAC,SAAS,IAAI,EAAE,CAAC;QACxC,IAAI,EAAE,MAAM,CAAC,KAAK,CAAC,IAAI,IAAI,EAAE,CAAC;QAC9B,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,MAAM,IAAI,EAAE,CAAC;QAClC,KAAK,EAAE,SAAS;KACjB,CAAC;AACJ,CAAC;AAED,MAAM,OAAO,GAAgB,KAAK,EAAE,KAAa,EAAyB,EAAE;IAC1E,MAAM,OAAO,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,GAAG,EAAE,CAAC;IACnD,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,GAAG,EAAE,CAAC;IAChD,MAAM,SAAS,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;IAE7D,MAAM,MAAM,GAAG;QACb,OAAO,EAAE,cAAc,CAAC,OAAO,CAAC;QAChC,UAAU,EAAE,SAAS,CAAC,GAAG,CAAC,CAAC,CAA0B,EAAE,EAAE,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC;KAC7E,CAAC;IAEF,OAAO;QACL,OAAO,EAAE;YACP;gBACE,IAAI,EAAE,MAAM;gBACZ,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;aACtC;SACF;KACF,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,cAAc,GAAS,EAAE,UAAU,EAAE,OAAO,EAAE,CAAC"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool: m365-graph:list_events
|
|
3
|
+
*
|
|
4
|
+
* List events in a date window. Uses Graph `/me/calendarView`
|
|
5
|
+
* (or `/me/calendars/{id}/calendarView` for a specific calendar)
|
|
6
|
+
* which **expands recurrences** — each occurrence appears as its own
|
|
7
|
+
* event, which is what humans + agents almost always want when asked
|
|
8
|
+
* "what's on my calendar tomorrow?". Compare to `/me/events` which
|
|
9
|
+
* returns recurrence series masters.
|
|
10
|
+
*
|
|
11
|
+
* Required Graph scope: `Calendars.Read` (delegated). Read-only.
|
|
12
|
+
*
|
|
13
|
+
* Input:
|
|
14
|
+
* start (ISO date/datetime, required)
|
|
15
|
+
* end (ISO date/datetime, required)
|
|
16
|
+
* calendar_id (string, optional)
|
|
17
|
+
* limit (integer 1..200, default 100)
|
|
18
|
+
*
|
|
19
|
+
* Output: JSON list of events with id, subject, start, end, organizer,
|
|
20
|
+
* attendees, location, body_preview, is_all_day, web_url.
|
|
21
|
+
*/
|
|
22
|
+
import type { Tool } from "../types/tool.js";
|
|
23
|
+
interface AttendeeSummary {
|
|
24
|
+
name: string;
|
|
25
|
+
email: string;
|
|
26
|
+
type: string;
|
|
27
|
+
response: string;
|
|
28
|
+
}
|
|
29
|
+
interface EventSummary {
|
|
30
|
+
id: string;
|
|
31
|
+
subject: string;
|
|
32
|
+
body_preview: string;
|
|
33
|
+
start: {
|
|
34
|
+
datetime: string;
|
|
35
|
+
timezone: string;
|
|
36
|
+
};
|
|
37
|
+
end: {
|
|
38
|
+
datetime: string;
|
|
39
|
+
timezone: string;
|
|
40
|
+
};
|
|
41
|
+
is_all_day: boolean;
|
|
42
|
+
location: string | null;
|
|
43
|
+
organizer_name: string | null;
|
|
44
|
+
organizer_email: string | null;
|
|
45
|
+
attendees: AttendeeSummary[];
|
|
46
|
+
webLink: string;
|
|
47
|
+
}
|
|
48
|
+
export declare function summarizeEvent(event: Record<string, unknown>): EventSummary;
|
|
49
|
+
export declare const listEventsTool: Tool;
|
|
50
|
+
export {};
|
|
51
|
+
//# sourceMappingURL=list_events.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list_events.d.ts","sourceRoot":"","sources":["../../src/tools/list_events.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AASH,OAAO,KAAK,EAAE,IAAI,EAA6C,MAAM,kBAAkB,CAAC;AAkCxF,UAAU,eAAe;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,UAAU,YAAY;IACpB,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IAC9C,GAAG,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IAC5C,UAAU,EAAE,OAAO,CAAC;IACpB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,SAAS,EAAE,eAAe,EAAE,CAAC;IAC7B,OAAO,EAAE,MAAM,CAAC;CACjB;AAaD,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,YAAY,CA0B3E;AAyCD,eAAO,MAAM,cAAc,EAAE,IAA8B,CAAC"}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool: m365-graph:list_events
|
|
3
|
+
*
|
|
4
|
+
* List events in a date window. Uses Graph `/me/calendarView`
|
|
5
|
+
* (or `/me/calendars/{id}/calendarView` for a specific calendar)
|
|
6
|
+
* which **expands recurrences** — each occurrence appears as its own
|
|
7
|
+
* event, which is what humans + agents almost always want when asked
|
|
8
|
+
* "what's on my calendar tomorrow?". Compare to `/me/events` which
|
|
9
|
+
* returns recurrence series masters.
|
|
10
|
+
*
|
|
11
|
+
* Required Graph scope: `Calendars.Read` (delegated). Read-only.
|
|
12
|
+
*
|
|
13
|
+
* Input:
|
|
14
|
+
* start (ISO date/datetime, required)
|
|
15
|
+
* end (ISO date/datetime, required)
|
|
16
|
+
* calendar_id (string, optional)
|
|
17
|
+
* limit (integer 1..200, default 100)
|
|
18
|
+
*
|
|
19
|
+
* Output: JSON list of events with id, subject, start, end, organizer,
|
|
20
|
+
* attendees, location, body_preview, is_all_day, web_url.
|
|
21
|
+
*/
|
|
22
|
+
import { validateOptionalInteger, validateOptionalString, validateRequiredISODate, } from "../types/validators.js";
|
|
23
|
+
const definition = {
|
|
24
|
+
name: "m365-graph:list_events",
|
|
25
|
+
description: "List events in a date window from the user's primary calendar (or a specified calendar_id). Recurrences are expanded — each occurrence is one event in the response. Read-only.",
|
|
26
|
+
inputSchema: {
|
|
27
|
+
type: "object",
|
|
28
|
+
properties: {
|
|
29
|
+
start: {
|
|
30
|
+
type: "string",
|
|
31
|
+
description: "Window start, ISO 8601 (e.g. '2026-05-04' or '2026-05-04T00:00:00Z').",
|
|
32
|
+
},
|
|
33
|
+
end: {
|
|
34
|
+
type: "string",
|
|
35
|
+
description: "Window end, ISO 8601. Exclusive upper bound is recommended (e.g. midnight of the day after the last day you want).",
|
|
36
|
+
},
|
|
37
|
+
calendar_id: {
|
|
38
|
+
type: "string",
|
|
39
|
+
description: "Optional calendar id from list_calendars. Defaults to /me's primary calendar.",
|
|
40
|
+
},
|
|
41
|
+
limit: {
|
|
42
|
+
type: "integer",
|
|
43
|
+
minimum: 1,
|
|
44
|
+
maximum: 200,
|
|
45
|
+
description: "Maximum events to return (default 100).",
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
required: ["start", "end"],
|
|
49
|
+
},
|
|
50
|
+
};
|
|
51
|
+
function summarizeAttendee(a) {
|
|
52
|
+
const email = a.emailAddress;
|
|
53
|
+
const status = a.status;
|
|
54
|
+
return {
|
|
55
|
+
name: email?.name ?? "",
|
|
56
|
+
email: email?.address ?? "",
|
|
57
|
+
type: String(a.type ?? "required"),
|
|
58
|
+
response: String(status?.response ?? "none"),
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
export function summarizeEvent(event) {
|
|
62
|
+
const start = event.start;
|
|
63
|
+
const end = event.end;
|
|
64
|
+
const location = event.location;
|
|
65
|
+
const organizer = event.organizer;
|
|
66
|
+
const orgEmail = organizer?.emailAddress;
|
|
67
|
+
const attendees = Array.isArray(event.attendees) ? event.attendees : [];
|
|
68
|
+
return {
|
|
69
|
+
id: String(event.id ?? ""),
|
|
70
|
+
subject: String(event.subject ?? ""),
|
|
71
|
+
body_preview: String(event.bodyPreview ?? ""),
|
|
72
|
+
start: {
|
|
73
|
+
datetime: String(start?.dateTime ?? ""),
|
|
74
|
+
timezone: String(start?.timeZone ?? ""),
|
|
75
|
+
},
|
|
76
|
+
end: {
|
|
77
|
+
datetime: String(end?.dateTime ?? ""),
|
|
78
|
+
timezone: String(end?.timeZone ?? ""),
|
|
79
|
+
},
|
|
80
|
+
is_all_day: Boolean(event.isAllDay),
|
|
81
|
+
location: location?.displayName || null,
|
|
82
|
+
organizer_name: orgEmail?.name ?? null,
|
|
83
|
+
organizer_email: orgEmail?.address ?? null,
|
|
84
|
+
attendees: attendees.map((a) => summarizeAttendee(a)),
|
|
85
|
+
webLink: String(event.webLink ?? ""),
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
const handler = async (graph, args) => {
|
|
89
|
+
const start = validateRequiredISODate(args.start, "start");
|
|
90
|
+
const end = validateRequiredISODate(args.end, "end");
|
|
91
|
+
const calendarId = validateOptionalString(args.calendar_id, "calendar_id");
|
|
92
|
+
const limit = validateOptionalInteger(args.limit, "limit", {
|
|
93
|
+
min: 1,
|
|
94
|
+
max: 200,
|
|
95
|
+
default: 100,
|
|
96
|
+
});
|
|
97
|
+
const apiBase = calendarId
|
|
98
|
+
? `/me/calendars/${encodeURIComponent(calendarId)}/calendarView`
|
|
99
|
+
: "/me/calendarView";
|
|
100
|
+
const response = await graph
|
|
101
|
+
.api(apiBase)
|
|
102
|
+
.query({ startDateTime: start, endDateTime: end })
|
|
103
|
+
.top(limit)
|
|
104
|
+
.orderby("start/dateTime")
|
|
105
|
+
.get();
|
|
106
|
+
const items = Array.isArray(response?.value) ? response.value : [];
|
|
107
|
+
const events = items.map((e) => summarizeEvent(e));
|
|
108
|
+
const result = {
|
|
109
|
+
calendar_id: calendarId ?? null,
|
|
110
|
+
window: { start, end },
|
|
111
|
+
count: events.length,
|
|
112
|
+
events,
|
|
113
|
+
};
|
|
114
|
+
return {
|
|
115
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
116
|
+
};
|
|
117
|
+
};
|
|
118
|
+
export const listEventsTool = { definition, handler };
|
|
119
|
+
//# sourceMappingURL=list_events.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list_events.js","sourceRoot":"","sources":["../../src/tools/list_events.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool: m365-graph:list_items
|
|
3
|
+
*
|
|
4
|
+
* List the children of a folder (root or specified item) in a drive.
|
|
5
|
+
* Wraps Graph `/drives/{id}/items/{item-id}/children` (or
|
|
6
|
+
* `/me/drive/root/children` when no item_id is provided).
|
|
7
|
+
*
|
|
8
|
+
* Required Graph scope: `Files.Read` (delegated). Read-only.
|
|
9
|
+
*
|
|
10
|
+
* Input:
|
|
11
|
+
* drive_id (string, optional) — drive to list; default = /me/drive
|
|
12
|
+
* item_id (string, optional) — folder ID; default = drive root
|
|
13
|
+
* limit (integer, 1..100) — max items; default 50
|
|
14
|
+
*
|
|
15
|
+
* Output: JSON list of items with name, type (file|folder), size,
|
|
16
|
+
* lastModified, webUrl.
|
|
17
|
+
*/
|
|
18
|
+
import type { Tool } from "../types/tool.js";
|
|
19
|
+
interface DriveItemSummary {
|
|
20
|
+
id: string;
|
|
21
|
+
name: string;
|
|
22
|
+
type: "file" | "folder";
|
|
23
|
+
size: number;
|
|
24
|
+
child_count: number | null;
|
|
25
|
+
lastModified: string;
|
|
26
|
+
webUrl: string;
|
|
27
|
+
}
|
|
28
|
+
export declare function summarizeDriveItem(item: Record<string, unknown>): DriveItemSummary;
|
|
29
|
+
export declare const listItemsTool: Tool;
|
|
30
|
+
export {};
|
|
31
|
+
//# sourceMappingURL=list_items.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list_items.d.ts","sourceRoot":"","sources":["../../src/tools/list_items.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAQH,OAAO,KAAK,EAAE,IAAI,EAA6C,MAAM,kBAAkB,CAAC;AA6BxF,UAAU,gBAAgB;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,GAAG,QAAQ,CAAC;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,gBAAgB,CAWlF;AAmCD,eAAO,MAAM,aAAa,EAAE,IAA8B,CAAC"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool: m365-graph:list_items
|
|
3
|
+
*
|
|
4
|
+
* List the children of a folder (root or specified item) in a drive.
|
|
5
|
+
* Wraps Graph `/drives/{id}/items/{item-id}/children` (or
|
|
6
|
+
* `/me/drive/root/children` when no item_id is provided).
|
|
7
|
+
*
|
|
8
|
+
* Required Graph scope: `Files.Read` (delegated). Read-only.
|
|
9
|
+
*
|
|
10
|
+
* Input:
|
|
11
|
+
* drive_id (string, optional) — drive to list; default = /me/drive
|
|
12
|
+
* item_id (string, optional) — folder ID; default = drive root
|
|
13
|
+
* limit (integer, 1..100) — max items; default 50
|
|
14
|
+
*
|
|
15
|
+
* Output: JSON list of items with name, type (file|folder), size,
|
|
16
|
+
* lastModified, webUrl.
|
|
17
|
+
*/
|
|
18
|
+
import { validateOptionalInteger, validateOptionalString, } from "../types/validators.js";
|
|
19
|
+
const definition = {
|
|
20
|
+
name: "m365-graph:list_items",
|
|
21
|
+
description: "List the immediate children (files + folders) of a folder in a drive. Defaults to the root of the user's primary OneDrive; pass drive_id and/or item_id to navigate elsewhere. Read-only.",
|
|
22
|
+
inputSchema: {
|
|
23
|
+
type: "object",
|
|
24
|
+
properties: {
|
|
25
|
+
drive_id: {
|
|
26
|
+
type: "string",
|
|
27
|
+
description: "Optional drive ID. Defaults to the user's primary OneDrive.",
|
|
28
|
+
},
|
|
29
|
+
item_id: {
|
|
30
|
+
type: "string",
|
|
31
|
+
description: "Optional folder item ID. Defaults to the drive root. Pass an item ID returned by a previous list_items / search_files call to navigate into subfolders.",
|
|
32
|
+
},
|
|
33
|
+
limit: {
|
|
34
|
+
type: "integer",
|
|
35
|
+
minimum: 1,
|
|
36
|
+
maximum: 100,
|
|
37
|
+
description: "Maximum number of children to return (default 50).",
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
required: [],
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
export function summarizeDriveItem(item) {
|
|
44
|
+
const folder = item.folder;
|
|
45
|
+
return {
|
|
46
|
+
id: String(item.id ?? ""),
|
|
47
|
+
name: String(item.name ?? ""),
|
|
48
|
+
type: folder !== undefined ? "folder" : "file",
|
|
49
|
+
size: Number(item.size ?? 0),
|
|
50
|
+
child_count: folder !== undefined ? Number(folder.childCount ?? 0) : null,
|
|
51
|
+
lastModified: String(item.lastModifiedDateTime ?? ""),
|
|
52
|
+
webUrl: String(item.webUrl ?? ""),
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
const handler = async (graph, args) => {
|
|
56
|
+
const driveId = validateOptionalString(args.drive_id, "drive_id");
|
|
57
|
+
const itemId = validateOptionalString(args.item_id, "item_id");
|
|
58
|
+
const limit = validateOptionalInteger(args.limit, "limit", {
|
|
59
|
+
min: 1,
|
|
60
|
+
max: 100,
|
|
61
|
+
default: 50,
|
|
62
|
+
});
|
|
63
|
+
const driveRoot = driveId ? `/drives/${encodeURIComponent(driveId)}` : "/me/drive";
|
|
64
|
+
const itemPath = itemId
|
|
65
|
+
? `${driveRoot}/items/${encodeURIComponent(itemId)}/children`
|
|
66
|
+
: `${driveRoot}/root/children`;
|
|
67
|
+
const response = await graph.api(itemPath).top(limit).get();
|
|
68
|
+
const items = Array.isArray(response?.value) ? response.value : [];
|
|
69
|
+
const summaries = items.map((i) => summarizeDriveItem(i));
|
|
70
|
+
const result = {
|
|
71
|
+
drive_id: driveId ?? null,
|
|
72
|
+
item_id: itemId ?? null,
|
|
73
|
+
count: summaries.length,
|
|
74
|
+
items: summaries,
|
|
75
|
+
};
|
|
76
|
+
return {
|
|
77
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
78
|
+
};
|
|
79
|
+
};
|
|
80
|
+
export const listItemsTool = { definition, handler };
|
|
81
|
+
//# sourceMappingURL=list_items.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list_items.js","sourceRoot":"","sources":["../../src/tools/list_items.ts"],"names":[],"mappings":"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"}
|