@softeria/ms-365-mcp-server 0.77.0 → 0.79.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/dist/endpoints.json +32 -0
- package/dist/generated/client.js +122 -0
- package/dist/graph-client.js +43 -8
- package/dist/graph-tools.js +12 -6
- package/dist/mcp-instructions.js +25 -0
- package/dist/server.js +15 -4
- package/logs/mcp-server.log +11 -10
- package/package.json +1 -1
- package/src/endpoints.json +32 -0
package/dist/endpoints.json
CHANGED
|
@@ -352,6 +352,7 @@
|
|
|
352
352
|
"pathPattern": "/me/calendar/getSchedule",
|
|
353
353
|
"method": "post",
|
|
354
354
|
"toolName": "get-schedule",
|
|
355
|
+
"readOnly": true,
|
|
355
356
|
"workScopes": ["Calendars.Read"]
|
|
356
357
|
},
|
|
357
358
|
{
|
|
@@ -407,6 +408,7 @@
|
|
|
407
408
|
"pathPattern": "/me/findMeetingTimes",
|
|
408
409
|
"method": "post",
|
|
409
410
|
"toolName": "find-meeting-times",
|
|
411
|
+
"readOnly": true,
|
|
410
412
|
"workScopes": ["Calendars.Read.Shared"]
|
|
411
413
|
},
|
|
412
414
|
{
|
|
@@ -944,6 +946,21 @@
|
|
|
944
946
|
"toolName": "get-chat-message",
|
|
945
947
|
"workScopes": ["ChatMessage.Read"]
|
|
946
948
|
},
|
|
949
|
+
{
|
|
950
|
+
"pathPattern": "/chats/{chat-id}/messages/{chatMessage-id}/hostedContents",
|
|
951
|
+
"method": "get",
|
|
952
|
+
"toolName": "list-chat-message-hosted-contents",
|
|
953
|
+
"workScopes": ["ChatMessage.Read"],
|
|
954
|
+
"llmTip": "Lists hosted-content references (inline images, code snippets) attached to a Teams chat message. Returns an array of { id, contentType }. Use get-chat-message-hosted-content with the id to download the bytes. Hosted content IDs can also be parsed from the <img src> URL in the message body between /hostedContents/ and /$value."
|
|
955
|
+
},
|
|
956
|
+
{
|
|
957
|
+
"pathPattern": "/chats/{chat-id}/messages/{chatMessage-id}/hostedContents/{chatMessageHostedContent-id}/$value",
|
|
958
|
+
"method": "get",
|
|
959
|
+
"toolName": "get-chat-message-hosted-content",
|
|
960
|
+
"workScopes": ["ChatMessage.Read"],
|
|
961
|
+
"returnDownloadUrl": true,
|
|
962
|
+
"llmTip": "Returns raw bytes of a hosted content item (typically image/png or image/jpeg) attached to a Teams 1:1 or group chat message. Use list-chat-message-hosted-contents to discover IDs, or extract the ID from the <img src> URL in the message body."
|
|
963
|
+
},
|
|
947
964
|
{
|
|
948
965
|
"pathPattern": "/chats/{chat-id}/messages",
|
|
949
966
|
"method": "post",
|
|
@@ -1005,6 +1022,21 @@
|
|
|
1005
1022
|
"toolName": "get-channel-message",
|
|
1006
1023
|
"workScopes": ["ChannelMessage.Read.All"]
|
|
1007
1024
|
},
|
|
1025
|
+
{
|
|
1026
|
+
"pathPattern": "/teams/{team-id}/channels/{channel-id}/messages/{chatMessage-id}/hostedContents",
|
|
1027
|
+
"method": "get",
|
|
1028
|
+
"toolName": "list-channel-message-hosted-contents",
|
|
1029
|
+
"workScopes": ["ChannelMessage.Read.All"],
|
|
1030
|
+
"llmTip": "Lists hosted-content references (inline images, code snippets) attached to a Teams channel message. Returns an array of { id, contentType }. Use get-channel-message-hosted-content with the id to download bytes."
|
|
1031
|
+
},
|
|
1032
|
+
{
|
|
1033
|
+
"pathPattern": "/teams/{team-id}/channels/{channel-id}/messages/{chatMessage-id}/hostedContents/{chatMessageHostedContent-id}/$value",
|
|
1034
|
+
"method": "get",
|
|
1035
|
+
"toolName": "get-channel-message-hosted-content",
|
|
1036
|
+
"workScopes": ["ChannelMessage.Read.All"],
|
|
1037
|
+
"returnDownloadUrl": true,
|
|
1038
|
+
"llmTip": "Returns raw bytes of a hosted content item attached to a Teams channel message. Use list-channel-message-hosted-contents to discover IDs."
|
|
1039
|
+
},
|
|
1008
1040
|
{
|
|
1009
1041
|
"pathPattern": "/teams/{team-id}/channels/{channel-id}/messages",
|
|
1010
1042
|
"method": "post",
|
package/dist/generated/client.js
CHANGED
|
@@ -422,6 +422,11 @@ const microsoft_graph_chatMessageCollectionResponse = z.object({
|
|
|
422
422
|
"@odata.nextLink": z.string().nullable(),
|
|
423
423
|
value: z.array(microsoft_graph_chatMessage)
|
|
424
424
|
}).partial().passthrough();
|
|
425
|
+
const microsoft_graph_chatMessageHostedContentCollectionResponse = z.object({
|
|
426
|
+
"@odata.count": z.number().int().nullable(),
|
|
427
|
+
"@odata.nextLink": z.string().nullable(),
|
|
428
|
+
value: z.array(microsoft_graph_chatMessageHostedContent)
|
|
429
|
+
}).partial().passthrough();
|
|
425
430
|
const microsoft_graph_pinnedChatMessageInfoCollectionResponse = z.object({
|
|
426
431
|
"@odata.count": z.number().int().nullable(),
|
|
427
432
|
"@odata.nextLink": z.string().nullable(),
|
|
@@ -4303,6 +4308,7 @@ const schemas = {
|
|
|
4303
4308
|
microsoft_graph_ODataErrors_ODataError,
|
|
4304
4309
|
microsoft_graph_conversationMemberCollectionResponse,
|
|
4305
4310
|
microsoft_graph_chatMessageCollectionResponse,
|
|
4311
|
+
microsoft_graph_chatMessageHostedContentCollectionResponse,
|
|
4306
4312
|
microsoft_graph_pinnedChatMessageInfoCollectionResponse,
|
|
4307
4313
|
microsoft_graph_outOfOfficeSettings,
|
|
4308
4314
|
microsoft_graph_dateTimeTimeZone,
|
|
@@ -4840,6 +4846,64 @@ const endpoints = makeApi([
|
|
|
4840
4846
|
],
|
|
4841
4847
|
response: z.void()
|
|
4842
4848
|
},
|
|
4849
|
+
{
|
|
4850
|
+
method: "get",
|
|
4851
|
+
path: "/chats/:chatId/messages/:chatMessageId/hostedContents",
|
|
4852
|
+
alias: "list-chat-message-hosted-contents",
|
|
4853
|
+
description: `Retrieve the list of chatMessageHostedContent objects from a message. This API only lists the hosted content objects. To get the content bytes, see get chatmessage hosted content.`,
|
|
4854
|
+
requestFormat: "json",
|
|
4855
|
+
parameters: [
|
|
4856
|
+
{
|
|
4857
|
+
name: "$top",
|
|
4858
|
+
type: "Query",
|
|
4859
|
+
schema: z.number().int().gte(0).describe("Show only the first n items").optional()
|
|
4860
|
+
},
|
|
4861
|
+
{
|
|
4862
|
+
name: "$skip",
|
|
4863
|
+
type: "Query",
|
|
4864
|
+
schema: z.number().int().gte(0).describe("Skip the first n items").optional()
|
|
4865
|
+
},
|
|
4866
|
+
{
|
|
4867
|
+
name: "$search",
|
|
4868
|
+
type: "Query",
|
|
4869
|
+
schema: z.string().describe("Search items by search phrases").optional()
|
|
4870
|
+
},
|
|
4871
|
+
{
|
|
4872
|
+
name: "$filter",
|
|
4873
|
+
type: "Query",
|
|
4874
|
+
schema: z.string().describe("Filter items by property values").optional()
|
|
4875
|
+
},
|
|
4876
|
+
{
|
|
4877
|
+
name: "$count",
|
|
4878
|
+
type: "Query",
|
|
4879
|
+
schema: z.boolean().describe("Include count of items").optional()
|
|
4880
|
+
},
|
|
4881
|
+
{
|
|
4882
|
+
name: "$orderby",
|
|
4883
|
+
type: "Query",
|
|
4884
|
+
schema: z.array(z.string()).describe("Order items by property values").optional()
|
|
4885
|
+
},
|
|
4886
|
+
{
|
|
4887
|
+
name: "$select",
|
|
4888
|
+
type: "Query",
|
|
4889
|
+
schema: z.array(z.string()).describe("Select properties to be returned").optional()
|
|
4890
|
+
},
|
|
4891
|
+
{
|
|
4892
|
+
name: "$expand",
|
|
4893
|
+
type: "Query",
|
|
4894
|
+
schema: z.array(z.string()).describe("Expand related entities").optional()
|
|
4895
|
+
}
|
|
4896
|
+
],
|
|
4897
|
+
response: z.void()
|
|
4898
|
+
},
|
|
4899
|
+
{
|
|
4900
|
+
method: "get",
|
|
4901
|
+
path: "/chats/:chatId/messages/:chatMessageId/hostedContents/:chatMessageHostedContentId/$value",
|
|
4902
|
+
alias: "get-chat-message-hosted-content",
|
|
4903
|
+
description: `Retrieve the list of chatMessageHostedContent objects from a message. This API only lists the hosted content objects. To get the content bytes, see get chatmessage hosted content.`,
|
|
4904
|
+
requestFormat: "json",
|
|
4905
|
+
response: z.void()
|
|
4906
|
+
},
|
|
4843
4907
|
{
|
|
4844
4908
|
method: "get",
|
|
4845
4909
|
path: "/chats/:chatId/messages/:chatMessageId/replies",
|
|
@@ -10608,6 +10672,64 @@ To monitor future changes, call the delta API by using the @odata.deltaLink in t
|
|
|
10608
10672
|
],
|
|
10609
10673
|
response: z.void()
|
|
10610
10674
|
},
|
|
10675
|
+
{
|
|
10676
|
+
method: "get",
|
|
10677
|
+
path: "/teams/:teamId/channels/:channelId/messages/:chatMessageId/hostedContents",
|
|
10678
|
+
alias: "list-channel-message-hosted-contents",
|
|
10679
|
+
description: `Retrieve the list of chatMessageHostedContent objects from a message. This API only lists the hosted content objects. To get the content bytes, see get chatmessage hosted content.`,
|
|
10680
|
+
requestFormat: "json",
|
|
10681
|
+
parameters: [
|
|
10682
|
+
{
|
|
10683
|
+
name: "$top",
|
|
10684
|
+
type: "Query",
|
|
10685
|
+
schema: z.number().int().gte(0).describe("Show only the first n items").optional()
|
|
10686
|
+
},
|
|
10687
|
+
{
|
|
10688
|
+
name: "$skip",
|
|
10689
|
+
type: "Query",
|
|
10690
|
+
schema: z.number().int().gte(0).describe("Skip the first n items").optional()
|
|
10691
|
+
},
|
|
10692
|
+
{
|
|
10693
|
+
name: "$search",
|
|
10694
|
+
type: "Query",
|
|
10695
|
+
schema: z.string().describe("Search items by search phrases").optional()
|
|
10696
|
+
},
|
|
10697
|
+
{
|
|
10698
|
+
name: "$filter",
|
|
10699
|
+
type: "Query",
|
|
10700
|
+
schema: z.string().describe("Filter items by property values").optional()
|
|
10701
|
+
},
|
|
10702
|
+
{
|
|
10703
|
+
name: "$count",
|
|
10704
|
+
type: "Query",
|
|
10705
|
+
schema: z.boolean().describe("Include count of items").optional()
|
|
10706
|
+
},
|
|
10707
|
+
{
|
|
10708
|
+
name: "$orderby",
|
|
10709
|
+
type: "Query",
|
|
10710
|
+
schema: z.array(z.string()).describe("Order items by property values").optional()
|
|
10711
|
+
},
|
|
10712
|
+
{
|
|
10713
|
+
name: "$select",
|
|
10714
|
+
type: "Query",
|
|
10715
|
+
schema: z.array(z.string()).describe("Select properties to be returned").optional()
|
|
10716
|
+
},
|
|
10717
|
+
{
|
|
10718
|
+
name: "$expand",
|
|
10719
|
+
type: "Query",
|
|
10720
|
+
schema: z.array(z.string()).describe("Expand related entities").optional()
|
|
10721
|
+
}
|
|
10722
|
+
],
|
|
10723
|
+
response: z.void()
|
|
10724
|
+
},
|
|
10725
|
+
{
|
|
10726
|
+
method: "get",
|
|
10727
|
+
path: "/teams/:teamId/channels/:channelId/messages/:chatMessageId/hostedContents/:chatMessageHostedContentId/$value",
|
|
10728
|
+
alias: "get-channel-message-hosted-content",
|
|
10729
|
+
description: `Retrieve the list of chatMessageHostedContent objects from a message. This API only lists the hosted content objects. To get the content bytes, see get chatmessage hosted content.`,
|
|
10730
|
+
requestFormat: "json",
|
|
10731
|
+
response: z.void()
|
|
10732
|
+
},
|
|
10611
10733
|
{
|
|
10612
10734
|
method: "get",
|
|
10613
10735
|
path: "/teams/:teamId/channels/:channelId/messages/:chatMessageId/replies",
|
package/dist/graph-client.js
CHANGED
|
@@ -3,6 +3,27 @@ import { refreshAccessToken } from "./lib/microsoft-auth.js";
|
|
|
3
3
|
import { encode as toonEncode } from "@toon-format/toon";
|
|
4
4
|
import { getCloudEndpoints } from "./cloud-config.js";
|
|
5
5
|
import { getRequestTokens } from "./request-context.js";
|
|
6
|
+
function isBinaryContentType(contentType) {
|
|
7
|
+
if (!contentType) return false;
|
|
8
|
+
const lower = contentType.toLowerCase().split(";")[0].trim();
|
|
9
|
+
if (!lower) return false;
|
|
10
|
+
if (lower.startsWith("image/") || lower.startsWith("video/") || lower.startsWith("audio/") || lower.startsWith("font/")) {
|
|
11
|
+
return true;
|
|
12
|
+
}
|
|
13
|
+
if (lower === "application/octet-stream" || lower === "application/pdf") {
|
|
14
|
+
return true;
|
|
15
|
+
}
|
|
16
|
+
if (lower.startsWith("application/zip") || lower.startsWith("application/x-zip")) {
|
|
17
|
+
return true;
|
|
18
|
+
}
|
|
19
|
+
if (lower.startsWith("application/vnd.") || lower.startsWith("application/x-")) {
|
|
20
|
+
if (lower.endsWith("+json") || lower.endsWith("+xml") || lower.endsWith("+text")) {
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
return true;
|
|
24
|
+
}
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
6
27
|
class GraphClient {
|
|
7
28
|
constructor(authManager, secrets, outputFormat = "json") {
|
|
8
29
|
this.outputFormat = "json";
|
|
@@ -40,15 +61,28 @@ class GraphClient {
|
|
|
40
61
|
`Microsoft Graph API error: ${response.status} ${response.statusText} - ${await response.text()}`
|
|
41
62
|
);
|
|
42
63
|
}
|
|
43
|
-
const
|
|
64
|
+
const contentTypeHeader = response.headers?.get?.("content-type") || "";
|
|
65
|
+
const isBinaryResponse = isBinaryContentType(contentTypeHeader);
|
|
44
66
|
let result;
|
|
45
|
-
if (
|
|
46
|
-
|
|
67
|
+
if (isBinaryResponse) {
|
|
68
|
+
const buffer = Buffer.from(await response.arrayBuffer());
|
|
69
|
+
result = {
|
|
70
|
+
message: "OK!",
|
|
71
|
+
contentType: contentTypeHeader,
|
|
72
|
+
encoding: "base64",
|
|
73
|
+
contentLength: buffer.byteLength,
|
|
74
|
+
contentBytes: buffer.toString("base64")
|
|
75
|
+
};
|
|
47
76
|
} else {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
77
|
+
const text = await response.text();
|
|
78
|
+
if (text === "") {
|
|
79
|
+
result = { message: "OK!" };
|
|
80
|
+
} else {
|
|
81
|
+
try {
|
|
82
|
+
result = JSON.parse(text);
|
|
83
|
+
} catch {
|
|
84
|
+
result = { message: "OK!", rawResponse: text };
|
|
85
|
+
}
|
|
52
86
|
}
|
|
53
87
|
}
|
|
54
88
|
if (options.includeHeaders) {
|
|
@@ -205,5 +239,6 @@ class GraphClient {
|
|
|
205
239
|
}
|
|
206
240
|
var graph_client_default = GraphClient;
|
|
207
241
|
export {
|
|
208
|
-
graph_client_default as default
|
|
242
|
+
graph_client_default as default,
|
|
243
|
+
isBinaryContentType
|
|
209
244
|
};
|
package/dist/graph-tools.js
CHANGED
|
@@ -310,10 +310,13 @@ function registerGraphTools(server, graphClient, readOnly = false, enabledToolsP
|
|
|
310
310
|
skippedCount++;
|
|
311
311
|
continue;
|
|
312
312
|
}
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
313
|
+
const method = tool.method.toUpperCase();
|
|
314
|
+
if (readOnly && method !== "GET") {
|
|
315
|
+
if (!(method === "POST" && endpointConfig?.readOnly)) {
|
|
316
|
+
logger.info(`Skipping write operation ${tool.alias} in read-only mode`);
|
|
317
|
+
skippedCount++;
|
|
318
|
+
continue;
|
|
319
|
+
}
|
|
317
320
|
}
|
|
318
321
|
if (enabledToolsRegex && !enabledToolsRegex.test(tool.alias)) {
|
|
319
322
|
logger.info(`Skipping tool ${tool.alias} - doesn't match filter pattern`);
|
|
@@ -464,8 +467,11 @@ function buildToolsRegistry(readOnly, orgMode) {
|
|
|
464
467
|
if (!orgMode && endpointConfig && !endpointConfig.scopes && endpointConfig.workScopes) {
|
|
465
468
|
continue;
|
|
466
469
|
}
|
|
467
|
-
|
|
468
|
-
|
|
470
|
+
const method = tool.method.toUpperCase();
|
|
471
|
+
if (readOnly && method !== "GET") {
|
|
472
|
+
if (!(method === "POST" && endpointConfig?.readOnly)) {
|
|
473
|
+
continue;
|
|
474
|
+
}
|
|
469
475
|
}
|
|
470
476
|
toolsMap.set(tool.alias, { tool, config: endpointConfig });
|
|
471
477
|
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
function buildGeneralMcpInstructions(opts) {
|
|
2
|
+
const parts = [
|
|
3
|
+
"Microsoft 365 MCP exposes Microsoft Graph through MCP tools. Use each tool name, description, and parameter schema as the source of truth.",
|
|
4
|
+
"Microsoft Graph OData: do not combine $filter with $search on the same request. For lists, prefer modest $top (or top) and $select; avoid very large pages unless the user needs them.",
|
|
5
|
+
"Mail and message $search uses KQL; the $search query parameter value must be double-quoted per Graph (see search-query-parameter in Microsoft Graph docs).",
|
|
6
|
+
"When you need an organizational user or recipient address, resolve it with list-users (or another directory tool); do not invent SMTP addresses.",
|
|
7
|
+
"Directory $search on collections such as /users or /groups requires ConsistencyLevel: eventual when the tool exposes that header.",
|
|
8
|
+
"Teams chat and channel messages: prefer HTML contentType in the body; plain text is often mangled by Graph."
|
|
9
|
+
];
|
|
10
|
+
if (opts.readOnly) parts.push("This server is read-only; write operations are disabled.");
|
|
11
|
+
if (opts.multiAccount)
|
|
12
|
+
parts.push("Multiple accounts: pass the account parameter when required (see list-accounts).");
|
|
13
|
+
if (!opts.orgMode)
|
|
14
|
+
parts.push("Work/school-only tools require starting the server with --org-mode.");
|
|
15
|
+
return parts.join(" ");
|
|
16
|
+
}
|
|
17
|
+
const DISCOVERY_MODE_INSTRUCTIONS_ADDON = "DISCOVERY MODE ADD-ON: Graph is reached via search-tools then execute-tool (plus auth helpers). Call search-tools with short keywords, then execute-tool with tool_name exactly as returned; put Graph parameters in the parameters object. If search-tools returns no matches, retry with shorter or different keywords.";
|
|
18
|
+
function buildMcpServerInstructions(opts) {
|
|
19
|
+
const general = buildGeneralMcpInstructions(opts);
|
|
20
|
+
if (!opts.discovery) return general;
|
|
21
|
+
return `${general} ${DISCOVERY_MODE_INSTRUCTIONS_ADDON}`;
|
|
22
|
+
}
|
|
23
|
+
export {
|
|
24
|
+
buildMcpServerInstructions
|
|
25
|
+
};
|
package/dist/server.js
CHANGED
|
@@ -6,6 +6,7 @@ import express from "express";
|
|
|
6
6
|
import logger, { enableConsoleLogging } from "./logger.js";
|
|
7
7
|
import { registerAuthTools } from "./auth-tools.js";
|
|
8
8
|
import { registerGraphTools, registerDiscoveryTools } from "./graph-tools.js";
|
|
9
|
+
import { buildMcpServerInstructions } from "./mcp-instructions.js";
|
|
9
10
|
import GraphClient from "./graph-client.js";
|
|
10
11
|
import { buildScopesFromEndpoints } from "./auth.js";
|
|
11
12
|
import { MicrosoftOAuthProvider } from "./oauth-provider.js";
|
|
@@ -46,10 +47,20 @@ class MicrosoftGraphServer {
|
|
|
46
47
|
this.secrets = null;
|
|
47
48
|
}
|
|
48
49
|
createMcpServer() {
|
|
49
|
-
const server = new McpServer(
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
50
|
+
const server = new McpServer(
|
|
51
|
+
{
|
|
52
|
+
name: "Microsoft365MCP",
|
|
53
|
+
version: this.version
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
instructions: buildMcpServerInstructions({
|
|
57
|
+
discovery: Boolean(this.options.discovery),
|
|
58
|
+
orgMode: Boolean(this.options.orgMode),
|
|
59
|
+
readOnly: Boolean(this.options.readOnly),
|
|
60
|
+
multiAccount: this.multiAccount
|
|
61
|
+
})
|
|
62
|
+
}
|
|
63
|
+
);
|
|
53
64
|
const shouldRegisterAuthTools = !this.options.http || this.options.enableAuthTools;
|
|
54
65
|
if (shouldRegisterAuthTools) {
|
|
55
66
|
registerAuthTools(server, this.authManager);
|
package/logs/mcp-server.log
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
2026-04-14
|
|
2
|
-
2026-04-14
|
|
3
|
-
2026-04-14
|
|
4
|
-
2026-04-14
|
|
5
|
-
2026-04-14
|
|
6
|
-
2026-04-14
|
|
7
|
-
2026-04-14
|
|
8
|
-
2026-04-14
|
|
9
|
-
2026-04-14
|
|
10
|
-
2026-04-14
|
|
1
|
+
2026-04-14 21:28:26 INFO: [GRAPH CLIENT] Final URL being sent to Microsoft: https://graph.microsoft.com/v1.0/me
|
|
2
|
+
2026-04-14 21:28:26 INFO: [GRAPH CLIENT] Final URL being sent to Microsoft: https://graph.microsoft.com/v1.0/me
|
|
3
|
+
2026-04-14 21:28:26 INFO: [GRAPH CLIENT] Final URL being sent to Microsoft: https://graph.microsoft.com/v1.0/me
|
|
4
|
+
2026-04-14 21:28:26 INFO: [GRAPH CLIENT] Final URL being sent to Microsoft: https://graph.microsoft.com/v1.0/me/messages
|
|
5
|
+
2026-04-14 21:28:26 INFO: [GRAPH CLIENT] Final URL being sent to Microsoft: https://graph.microsoft.com/v1.0/me/calendar
|
|
6
|
+
2026-04-14 21:28:26 INFO: [GRAPH CLIENT] Final URL being sent to Microsoft: https://graph.microsoft.com/v1.0/me/photo/$value
|
|
7
|
+
2026-04-14 21:28:27 INFO: Using environment variables for secrets
|
|
8
|
+
2026-04-14 21:28:27 INFO: Using environment variables for secrets
|
|
9
|
+
2026-04-14 21:28:27 INFO: Using environment variables for secrets
|
|
10
|
+
2026-04-14 21:28:27 INFO: Using environment variables for secrets
|
|
11
|
+
2026-04-14 21:28:27 INFO: Using environment variables for secrets
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@softeria/ms-365-mcp-server",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.79.0",
|
|
4
4
|
"description": " A Model Context Protocol (MCP) server for interacting with Microsoft 365 and Office services through the Graph API",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
package/src/endpoints.json
CHANGED
|
@@ -352,6 +352,7 @@
|
|
|
352
352
|
"pathPattern": "/me/calendar/getSchedule",
|
|
353
353
|
"method": "post",
|
|
354
354
|
"toolName": "get-schedule",
|
|
355
|
+
"readOnly": true,
|
|
355
356
|
"workScopes": ["Calendars.Read"]
|
|
356
357
|
},
|
|
357
358
|
{
|
|
@@ -407,6 +408,7 @@
|
|
|
407
408
|
"pathPattern": "/me/findMeetingTimes",
|
|
408
409
|
"method": "post",
|
|
409
410
|
"toolName": "find-meeting-times",
|
|
411
|
+
"readOnly": true,
|
|
410
412
|
"workScopes": ["Calendars.Read.Shared"]
|
|
411
413
|
},
|
|
412
414
|
{
|
|
@@ -944,6 +946,21 @@
|
|
|
944
946
|
"toolName": "get-chat-message",
|
|
945
947
|
"workScopes": ["ChatMessage.Read"]
|
|
946
948
|
},
|
|
949
|
+
{
|
|
950
|
+
"pathPattern": "/chats/{chat-id}/messages/{chatMessage-id}/hostedContents",
|
|
951
|
+
"method": "get",
|
|
952
|
+
"toolName": "list-chat-message-hosted-contents",
|
|
953
|
+
"workScopes": ["ChatMessage.Read"],
|
|
954
|
+
"llmTip": "Lists hosted-content references (inline images, code snippets) attached to a Teams chat message. Returns an array of { id, contentType }. Use get-chat-message-hosted-content with the id to download the bytes. Hosted content IDs can also be parsed from the <img src> URL in the message body between /hostedContents/ and /$value."
|
|
955
|
+
},
|
|
956
|
+
{
|
|
957
|
+
"pathPattern": "/chats/{chat-id}/messages/{chatMessage-id}/hostedContents/{chatMessageHostedContent-id}/$value",
|
|
958
|
+
"method": "get",
|
|
959
|
+
"toolName": "get-chat-message-hosted-content",
|
|
960
|
+
"workScopes": ["ChatMessage.Read"],
|
|
961
|
+
"returnDownloadUrl": true,
|
|
962
|
+
"llmTip": "Returns raw bytes of a hosted content item (typically image/png or image/jpeg) attached to a Teams 1:1 or group chat message. Use list-chat-message-hosted-contents to discover IDs, or extract the ID from the <img src> URL in the message body."
|
|
963
|
+
},
|
|
947
964
|
{
|
|
948
965
|
"pathPattern": "/chats/{chat-id}/messages",
|
|
949
966
|
"method": "post",
|
|
@@ -1005,6 +1022,21 @@
|
|
|
1005
1022
|
"toolName": "get-channel-message",
|
|
1006
1023
|
"workScopes": ["ChannelMessage.Read.All"]
|
|
1007
1024
|
},
|
|
1025
|
+
{
|
|
1026
|
+
"pathPattern": "/teams/{team-id}/channels/{channel-id}/messages/{chatMessage-id}/hostedContents",
|
|
1027
|
+
"method": "get",
|
|
1028
|
+
"toolName": "list-channel-message-hosted-contents",
|
|
1029
|
+
"workScopes": ["ChannelMessage.Read.All"],
|
|
1030
|
+
"llmTip": "Lists hosted-content references (inline images, code snippets) attached to a Teams channel message. Returns an array of { id, contentType }. Use get-channel-message-hosted-content with the id to download bytes."
|
|
1031
|
+
},
|
|
1032
|
+
{
|
|
1033
|
+
"pathPattern": "/teams/{team-id}/channels/{channel-id}/messages/{chatMessage-id}/hostedContents/{chatMessageHostedContent-id}/$value",
|
|
1034
|
+
"method": "get",
|
|
1035
|
+
"toolName": "get-channel-message-hosted-content",
|
|
1036
|
+
"workScopes": ["ChannelMessage.Read.All"],
|
|
1037
|
+
"returnDownloadUrl": true,
|
|
1038
|
+
"llmTip": "Returns raw bytes of a hosted content item attached to a Teams channel message. Use list-channel-message-hosted-contents to discover IDs."
|
|
1039
|
+
},
|
|
1008
1040
|
{
|
|
1009
1041
|
"pathPattern": "/teams/{team-id}/channels/{channel-id}/messages",
|
|
1010
1042
|
"method": "post",
|