@softeria/ms-365-mcp-server 0.24.6 → 0.26.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.
@@ -3,7 +3,8 @@
3
3
  "pathPattern": "/me/messages",
4
4
  "method": "get",
5
5
  "toolName": "list-mail-messages",
6
- "scopes": ["Mail.Read"]
6
+ "scopes": ["Mail.Read"],
7
+ "llmTip": "CRITICAL: When searching emails, the $search parameter value MUST be wrapped in double quotes. Format: $search=\"your search query here\". Use KQL (Keyword Query Language) syntax to search specific properties: 'from:', 'subject:', 'body:', 'to:', 'cc:', 'bcc:', 'attachment:', 'hasAttachments:', 'importance:', 'received:', 'sent:'. Examples: $search=\"from:john@example.com\" | $search=\"subject:meeting AND hasAttachments:true\" | $search=\"body:urgent AND received>=2024-01-01\" | $search=\"from:john AND importance:high\". Remember: ALWAYS wrap the entire search expression in double quotes! Reference: https://learn.microsoft.com/en-us/graph/search-query-parameter"
7
8
  },
8
9
  {
9
10
  "pathPattern": "/me/mailFolders",
@@ -15,7 +16,8 @@
15
16
  "pathPattern": "/me/mailFolders/{mailFolder-id}/messages",
16
17
  "method": "get",
17
18
  "toolName": "list-mail-folder-messages",
18
- "scopes": ["Mail.Read"]
19
+ "scopes": ["Mail.Read"],
20
+ "llmTip": "CRITICAL: When searching emails, the $search parameter value MUST be wrapped in double quotes. Format: $search=\"your search query here\". Use KQL (Keyword Query Language) syntax to search specific properties: 'from:', 'subject:', 'body:', 'to:', 'cc:', 'bcc:', 'attachment:', 'hasAttachments:', 'importance:', 'received:', 'sent:'. Examples: $search=\"from:john@example.com\" | $search=\"subject:meeting AND hasAttachments:true\" | $search=\"body:urgent AND received>=2024-01-01\" | $search=\"from:alice AND importance:high\". Remember: ALWAYS wrap the entire search expression in double quotes! Reference: https://learn.microsoft.com/en-us/graph/search-query-parameter"
19
21
  },
20
22
  {
21
23
  "pathPattern": "/me/messages/{message-id}",
@@ -27,19 +29,22 @@
27
29
  "pathPattern": "/me/sendMail",
28
30
  "method": "post",
29
31
  "toolName": "send-mail",
30
- "scopes": ["Mail.Send"]
32
+ "scopes": ["Mail.Send"],
33
+ "llmTip": "CRITICAL: Do not try to guess the email address of the recipients. Use the list-users tool to find the email address of the recipients."
31
34
  },
32
35
  {
33
36
  "pathPattern": "/users/{user-id}/messages",
34
37
  "method": "get",
35
38
  "toolName": "list-shared-mailbox-messages",
36
- "workScopes": ["Mail.Read.Shared"]
39
+ "workScopes": ["Mail.Read.Shared"],
40
+ "llmTip": "CRITICAL: When searching emails, the $search parameter value MUST be wrapped in double quotes. Format: $search=\"your search query here\". Use KQL (Keyword Query Language) syntax to search specific properties: 'from:', 'subject:', 'body:', 'to:', 'cc:', 'bcc:', 'attachment:', 'hasAttachments:', 'importance:', 'received:', 'sent:'. Examples: $search=\"from:john@example.com\" | $search=\"subject:meeting AND hasAttachments:true\" | $search=\"body:urgent AND received>=2024-01-01\" | $search=\"from:alice AND importance:high\". Remember: ALWAYS wrap the entire search expression in double quotes! Reference: https://learn.microsoft.com/en-us/graph/search-query-parameter"
37
41
  },
38
42
  {
39
43
  "pathPattern": "/users/{user-id}/mailFolders/{mailFolder-id}/messages",
40
44
  "method": "get",
41
45
  "toolName": "list-shared-mailbox-folder-messages",
42
- "workScopes": ["Mail.Read.Shared"]
46
+ "workScopes": ["Mail.Read.Shared"],
47
+ "llmTip": "CRITICAL: When searching emails, the $search parameter value MUST be wrapped in double quotes. Format: $search=\"your search query here\". Use KQL (Keyword Query Language) syntax to search specific properties: 'from:', 'subject:', 'body:', 'to:', 'cc:', 'bcc:', 'attachment:', 'hasAttachments:', 'importance:', 'received:', 'sent:'. Examples: $search=\"from:john@example.com\" | $search=\"subject:meeting AND hasAttachments:true\" | $search=\"body:urgent AND received>=2024-01-01\" | $search=\"from:alice AND importance:high\". Remember: ALWAYS wrap the entire search expression in double quotes! Reference: https://learn.microsoft.com/en-us/graph/search-query-parameter"
43
48
  },
44
49
  {
45
50
  "pathPattern": "/users/{user-id}/messages/{message-id}",
@@ -51,13 +56,15 @@
51
56
  "pathPattern": "/users/{user-id}/sendMail",
52
57
  "method": "post",
53
58
  "toolName": "send-shared-mailbox-mail",
54
- "workScopes": ["Mail.Send.Shared"]
59
+ "workScopes": ["Mail.Send.Shared"],
60
+ "llmTip": "CRITICAL: Do not try to guess the email address of the recipients. Use the list-users tool to find the email address of the recipients."
55
61
  },
56
62
  {
57
63
  "pathPattern": "/users",
58
64
  "method": "get",
59
65
  "toolName": "list-users",
60
- "workScopes": ["User.Read.All"]
66
+ "workScopes": ["User.Read.All"],
67
+ "llmTip": "CRITICAL: This request requires the ConsistencyLevel header set to eventual. When searching users, the $search parameter value MUST be wrapped in double quotes. Format: $search=\"your search query here\". Use KQL (Keyword Query Language) syntax to search specific properties: 'displayName:'. Examples: $search=\"displayName:john\" | $search=\"displayName:john\" OR \"displayName:jane\". Remember: ALWAYS wrap the entire search expression in double quotes and set the ConsistencyLevel header to eventual! Reference: https://learn.microsoft.com/en-us/graph/search-query-parameter"
61
68
  },
62
69
  {
63
70
  "pathPattern": "/me/messages",
@@ -105,25 +112,29 @@
105
112
  "pathPattern": "/me/events",
106
113
  "method": "get",
107
114
  "toolName": "list-calendar-events",
108
- "scopes": ["Calendars.Read"]
115
+ "scopes": ["Calendars.Read"],
116
+ "supportsTimezone": true
109
117
  },
110
118
  {
111
119
  "pathPattern": "/me/events/{event-id}",
112
120
  "method": "get",
113
121
  "toolName": "get-calendar-event",
114
- "scopes": ["Calendars.Read"]
122
+ "scopes": ["Calendars.Read"],
123
+ "supportsTimezone": true
115
124
  },
116
125
  {
117
126
  "pathPattern": "/me/events",
118
127
  "method": "post",
119
128
  "toolName": "create-calendar-event",
120
- "scopes": ["Calendars.ReadWrite"]
129
+ "scopes": ["Calendars.ReadWrite"],
130
+ "llmTip": "CRITICAL: Do not try to guess the email address of the recipients. Use the list-users tool to find the email address of the recipients."
121
131
  },
122
132
  {
123
133
  "pathPattern": "/me/events/{event-id}",
124
134
  "method": "patch",
125
135
  "toolName": "update-calendar-event",
126
- "scopes": ["Calendars.ReadWrite"]
136
+ "scopes": ["Calendars.ReadWrite"],
137
+ "llmTip": "CRITICAL: Do not try to guess the email address of the recipients. Use the list-users tool to find the email address of the recipients."
127
138
  },
128
139
  {
129
140
  "pathPattern": "/me/events/{event-id}",
@@ -135,25 +146,29 @@
135
146
  "pathPattern": "/me/calendars/{calendar-id}/events",
136
147
  "method": "get",
137
148
  "toolName": "list-specific-calendar-events",
138
- "scopes": ["Calendars.Read"]
149
+ "scopes": ["Calendars.Read"],
150
+ "supportsTimezone": true
139
151
  },
140
152
  {
141
153
  "pathPattern": "/me/calendars/{calendar-id}/events/{event-id}",
142
154
  "method": "get",
143
155
  "toolName": "get-specific-calendar-event",
144
- "scopes": ["Calendars.Read"]
156
+ "scopes": ["Calendars.Read"],
157
+ "supportsTimezone": true
145
158
  },
146
159
  {
147
160
  "pathPattern": "/me/calendars/{calendar-id}/events",
148
161
  "method": "post",
149
162
  "toolName": "create-specific-calendar-event",
150
- "scopes": ["Calendars.ReadWrite"]
163
+ "scopes": ["Calendars.ReadWrite"],
164
+ "llmTip": "CRITICAL: Do not try to guess the email address of the recipients. Use the list-users tool to find the email address of the recipients."
151
165
  },
152
166
  {
153
167
  "pathPattern": "/me/calendars/{calendar-id}/events/{event-id}",
154
168
  "method": "patch",
155
169
  "toolName": "update-specific-calendar-event",
156
- "scopes": ["Calendars.ReadWrite"]
170
+ "scopes": ["Calendars.ReadWrite"],
171
+ "llmTip": "CRITICAL: Do not try to guess the email address of the recipients. Use the list-users tool to find the email address of the recipients."
157
172
  },
158
173
  {
159
174
  "pathPattern": "/me/calendars/{calendar-id}/events/{event-id}",
@@ -165,7 +180,8 @@
165
180
  "pathPattern": "/me/calendarView",
166
181
  "method": "get",
167
182
  "toolName": "get-calendar-view",
168
- "scopes": ["Calendars.Read"]
183
+ "scopes": ["Calendars.Read"],
184
+ "supportsTimezone": true
169
185
  },
170
186
  {
171
187
  "pathPattern": "/me/calendars",
@@ -44,9 +44,20 @@ function registerGraphTools(server, graphClient, readOnly = false, enabledToolsP
44
44
  }
45
45
  paramSchema["includeHeaders"] = z.boolean().describe("Include response headers (including ETag) in the response metadata").optional();
46
46
  paramSchema["excludeResponse"] = z.boolean().describe("Exclude the full response body and only return success or failure indication").optional();
47
+ if (endpointConfig?.supportsTimezone) {
48
+ paramSchema["timezone"] = z.string().describe(
49
+ 'IANA timezone name (e.g., "America/New_York", "Europe/London", "Asia/Tokyo") for calendar event times. If not specified, times are returned in UTC.'
50
+ ).optional();
51
+ }
52
+ let toolDescription = tool.description || `Execute ${tool.method.toUpperCase()} request to ${tool.path}`;
53
+ if (endpointConfig?.llmTip) {
54
+ toolDescription += `
55
+
56
+ \u{1F4A1} TIP: ${endpointConfig.llmTip}`;
57
+ }
47
58
  server.tool(
48
59
  tool.alias,
49
- tool.description || `Execute ${tool.method.toUpperCase()} request to ${tool.path}`,
60
+ toolDescription,
50
61
  paramSchema,
51
62
  {
52
63
  title: tool.alias,
@@ -122,6 +133,10 @@ function registerGraphTools(server, graphClient, readOnly = false, enabledToolsP
122
133
  logger.info(`Set body param: ${JSON.stringify(body)}`);
123
134
  }
124
135
  }
136
+ if (endpointConfig?.supportsTimezone && params.timezone) {
137
+ headers["Prefer"] = `outlook.timezone="${params.timezone}"`;
138
+ logger.info(`Setting timezone header: Prefer: outlook.timezone="${params.timezone}"`);
139
+ }
125
140
  if (Object.keys(queryParams).length > 0) {
126
141
  const queryString = Object.entries(queryParams).map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`).join("&");
127
142
  path2 = `${path2}${path2.includes("?") ? "&" : "?"}${queryString}`;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@softeria/ms-365-mcp-server",
3
- "version": "0.24.6",
3
+ "version": "0.26.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",
@@ -3,7 +3,8 @@
3
3
  "pathPattern": "/me/messages",
4
4
  "method": "get",
5
5
  "toolName": "list-mail-messages",
6
- "scopes": ["Mail.Read"]
6
+ "scopes": ["Mail.Read"],
7
+ "llmTip": "CRITICAL: When searching emails, the $search parameter value MUST be wrapped in double quotes. Format: $search=\"your search query here\". Use KQL (Keyword Query Language) syntax to search specific properties: 'from:', 'subject:', 'body:', 'to:', 'cc:', 'bcc:', 'attachment:', 'hasAttachments:', 'importance:', 'received:', 'sent:'. Examples: $search=\"from:john@example.com\" | $search=\"subject:meeting AND hasAttachments:true\" | $search=\"body:urgent AND received>=2024-01-01\" | $search=\"from:john AND importance:high\". Remember: ALWAYS wrap the entire search expression in double quotes! Reference: https://learn.microsoft.com/en-us/graph/search-query-parameter"
7
8
  },
8
9
  {
9
10
  "pathPattern": "/me/mailFolders",
@@ -15,7 +16,8 @@
15
16
  "pathPattern": "/me/mailFolders/{mailFolder-id}/messages",
16
17
  "method": "get",
17
18
  "toolName": "list-mail-folder-messages",
18
- "scopes": ["Mail.Read"]
19
+ "scopes": ["Mail.Read"],
20
+ "llmTip": "CRITICAL: When searching emails, the $search parameter value MUST be wrapped in double quotes. Format: $search=\"your search query here\". Use KQL (Keyword Query Language) syntax to search specific properties: 'from:', 'subject:', 'body:', 'to:', 'cc:', 'bcc:', 'attachment:', 'hasAttachments:', 'importance:', 'received:', 'sent:'. Examples: $search=\"from:john@example.com\" | $search=\"subject:meeting AND hasAttachments:true\" | $search=\"body:urgent AND received>=2024-01-01\" | $search=\"from:alice AND importance:high\". Remember: ALWAYS wrap the entire search expression in double quotes! Reference: https://learn.microsoft.com/en-us/graph/search-query-parameter"
19
21
  },
20
22
  {
21
23
  "pathPattern": "/me/messages/{message-id}",
@@ -27,19 +29,22 @@
27
29
  "pathPattern": "/me/sendMail",
28
30
  "method": "post",
29
31
  "toolName": "send-mail",
30
- "scopes": ["Mail.Send"]
32
+ "scopes": ["Mail.Send"],
33
+ "llmTip": "CRITICAL: Do not try to guess the email address of the recipients. Use the list-users tool to find the email address of the recipients."
31
34
  },
32
35
  {
33
36
  "pathPattern": "/users/{user-id}/messages",
34
37
  "method": "get",
35
38
  "toolName": "list-shared-mailbox-messages",
36
- "workScopes": ["Mail.Read.Shared"]
39
+ "workScopes": ["Mail.Read.Shared"],
40
+ "llmTip": "CRITICAL: When searching emails, the $search parameter value MUST be wrapped in double quotes. Format: $search=\"your search query here\". Use KQL (Keyword Query Language) syntax to search specific properties: 'from:', 'subject:', 'body:', 'to:', 'cc:', 'bcc:', 'attachment:', 'hasAttachments:', 'importance:', 'received:', 'sent:'. Examples: $search=\"from:john@example.com\" | $search=\"subject:meeting AND hasAttachments:true\" | $search=\"body:urgent AND received>=2024-01-01\" | $search=\"from:alice AND importance:high\". Remember: ALWAYS wrap the entire search expression in double quotes! Reference: https://learn.microsoft.com/en-us/graph/search-query-parameter"
37
41
  },
38
42
  {
39
43
  "pathPattern": "/users/{user-id}/mailFolders/{mailFolder-id}/messages",
40
44
  "method": "get",
41
45
  "toolName": "list-shared-mailbox-folder-messages",
42
- "workScopes": ["Mail.Read.Shared"]
46
+ "workScopes": ["Mail.Read.Shared"],
47
+ "llmTip": "CRITICAL: When searching emails, the $search parameter value MUST be wrapped in double quotes. Format: $search=\"your search query here\". Use KQL (Keyword Query Language) syntax to search specific properties: 'from:', 'subject:', 'body:', 'to:', 'cc:', 'bcc:', 'attachment:', 'hasAttachments:', 'importance:', 'received:', 'sent:'. Examples: $search=\"from:john@example.com\" | $search=\"subject:meeting AND hasAttachments:true\" | $search=\"body:urgent AND received>=2024-01-01\" | $search=\"from:alice AND importance:high\". Remember: ALWAYS wrap the entire search expression in double quotes! Reference: https://learn.microsoft.com/en-us/graph/search-query-parameter"
43
48
  },
44
49
  {
45
50
  "pathPattern": "/users/{user-id}/messages/{message-id}",
@@ -51,13 +56,15 @@
51
56
  "pathPattern": "/users/{user-id}/sendMail",
52
57
  "method": "post",
53
58
  "toolName": "send-shared-mailbox-mail",
54
- "workScopes": ["Mail.Send.Shared"]
59
+ "workScopes": ["Mail.Send.Shared"],
60
+ "llmTip": "CRITICAL: Do not try to guess the email address of the recipients. Use the list-users tool to find the email address of the recipients."
55
61
  },
56
62
  {
57
63
  "pathPattern": "/users",
58
64
  "method": "get",
59
65
  "toolName": "list-users",
60
- "workScopes": ["User.Read.All"]
66
+ "workScopes": ["User.Read.All"],
67
+ "llmTip": "CRITICAL: This request requires the ConsistencyLevel header set to eventual. When searching users, the $search parameter value MUST be wrapped in double quotes. Format: $search=\"your search query here\". Use KQL (Keyword Query Language) syntax to search specific properties: 'displayName:'. Examples: $search=\"displayName:john\" | $search=\"displayName:john\" OR \"displayName:jane\". Remember: ALWAYS wrap the entire search expression in double quotes and set the ConsistencyLevel header to eventual! Reference: https://learn.microsoft.com/en-us/graph/search-query-parameter"
61
68
  },
62
69
  {
63
70
  "pathPattern": "/me/messages",
@@ -105,25 +112,29 @@
105
112
  "pathPattern": "/me/events",
106
113
  "method": "get",
107
114
  "toolName": "list-calendar-events",
108
- "scopes": ["Calendars.Read"]
115
+ "scopes": ["Calendars.Read"],
116
+ "supportsTimezone": true
109
117
  },
110
118
  {
111
119
  "pathPattern": "/me/events/{event-id}",
112
120
  "method": "get",
113
121
  "toolName": "get-calendar-event",
114
- "scopes": ["Calendars.Read"]
122
+ "scopes": ["Calendars.Read"],
123
+ "supportsTimezone": true
115
124
  },
116
125
  {
117
126
  "pathPattern": "/me/events",
118
127
  "method": "post",
119
128
  "toolName": "create-calendar-event",
120
- "scopes": ["Calendars.ReadWrite"]
129
+ "scopes": ["Calendars.ReadWrite"],
130
+ "llmTip": "CRITICAL: Do not try to guess the email address of the recipients. Use the list-users tool to find the email address of the recipients."
121
131
  },
122
132
  {
123
133
  "pathPattern": "/me/events/{event-id}",
124
134
  "method": "patch",
125
135
  "toolName": "update-calendar-event",
126
- "scopes": ["Calendars.ReadWrite"]
136
+ "scopes": ["Calendars.ReadWrite"],
137
+ "llmTip": "CRITICAL: Do not try to guess the email address of the recipients. Use the list-users tool to find the email address of the recipients."
127
138
  },
128
139
  {
129
140
  "pathPattern": "/me/events/{event-id}",
@@ -135,25 +146,29 @@
135
146
  "pathPattern": "/me/calendars/{calendar-id}/events",
136
147
  "method": "get",
137
148
  "toolName": "list-specific-calendar-events",
138
- "scopes": ["Calendars.Read"]
149
+ "scopes": ["Calendars.Read"],
150
+ "supportsTimezone": true
139
151
  },
140
152
  {
141
153
  "pathPattern": "/me/calendars/{calendar-id}/events/{event-id}",
142
154
  "method": "get",
143
155
  "toolName": "get-specific-calendar-event",
144
- "scopes": ["Calendars.Read"]
156
+ "scopes": ["Calendars.Read"],
157
+ "supportsTimezone": true
145
158
  },
146
159
  {
147
160
  "pathPattern": "/me/calendars/{calendar-id}/events",
148
161
  "method": "post",
149
162
  "toolName": "create-specific-calendar-event",
150
- "scopes": ["Calendars.ReadWrite"]
163
+ "scopes": ["Calendars.ReadWrite"],
164
+ "llmTip": "CRITICAL: Do not try to guess the email address of the recipients. Use the list-users tool to find the email address of the recipients."
151
165
  },
152
166
  {
153
167
  "pathPattern": "/me/calendars/{calendar-id}/events/{event-id}",
154
168
  "method": "patch",
155
169
  "toolName": "update-specific-calendar-event",
156
- "scopes": ["Calendars.ReadWrite"]
170
+ "scopes": ["Calendars.ReadWrite"],
171
+ "llmTip": "CRITICAL: Do not try to guess the email address of the recipients. Use the list-users tool to find the email address of the recipients."
157
172
  },
158
173
  {
159
174
  "pathPattern": "/me/calendars/{calendar-id}/events/{event-id}",
@@ -165,7 +180,8 @@
165
180
  "pathPattern": "/me/calendarView",
166
181
  "method": "get",
167
182
  "toolName": "get-calendar-view",
168
- "scopes": ["Calendars.Read"]
183
+ "scopes": ["Calendars.Read"],
184
+ "supportsTimezone": true
169
185
  },
170
186
  {
171
187
  "pathPattern": "/me/calendars",