@softeria/ms-365-mcp-server 0.46.2 → 0.47.1
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/auth.js +50 -27
- package/dist/endpoints.json +77 -0
- package/dist/generated/client.js +421 -0
- package/logs/mcp-server.log +10 -10
- package/package.json +1 -1
- package/src/endpoints.json +77 -0
package/dist/auth.js
CHANGED
|
@@ -48,6 +48,30 @@ function ensureParentDir(filePath) {
|
|
|
48
48
|
const dir = path.dirname(filePath);
|
|
49
49
|
fs.mkdirSync(dir, { recursive: true, mode: 448 });
|
|
50
50
|
}
|
|
51
|
+
function wrapCache(data) {
|
|
52
|
+
return JSON.stringify({ _cacheEnvelope: true, data, savedAt: Date.now() });
|
|
53
|
+
}
|
|
54
|
+
function unwrapCache(raw) {
|
|
55
|
+
try {
|
|
56
|
+
const parsed = JSON.parse(raw);
|
|
57
|
+
if (parsed._cacheEnvelope && typeof parsed.data === "string") {
|
|
58
|
+
return { data: parsed.data, savedAt: parsed.savedAt };
|
|
59
|
+
}
|
|
60
|
+
} catch {
|
|
61
|
+
}
|
|
62
|
+
return { data: raw };
|
|
63
|
+
}
|
|
64
|
+
function pickNewest(keytarRaw, fileRaw) {
|
|
65
|
+
if (!keytarRaw && !fileRaw) return void 0;
|
|
66
|
+
if (keytarRaw && !fileRaw) return unwrapCache(keytarRaw).data;
|
|
67
|
+
if (!keytarRaw && fileRaw) return unwrapCache(fileRaw).data;
|
|
68
|
+
const kt = unwrapCache(keytarRaw);
|
|
69
|
+
const file = unwrapCache(fileRaw);
|
|
70
|
+
if (kt.savedAt === void 0 && file.savedAt === void 0) return kt.data;
|
|
71
|
+
if (kt.savedAt !== void 0 && file.savedAt === void 0) return kt.data;
|
|
72
|
+
if (kt.savedAt === void 0 && file.savedAt !== void 0) return file.data;
|
|
73
|
+
return kt.savedAt >= file.savedAt ? kt.data : file.data;
|
|
74
|
+
}
|
|
51
75
|
function createMsalConfig(secrets) {
|
|
52
76
|
const cloudEndpoints = getCloudEndpoints(secrets.cloudType);
|
|
53
77
|
return {
|
|
@@ -126,24 +150,21 @@ class AuthManager {
|
|
|
126
150
|
}
|
|
127
151
|
async loadTokenCache() {
|
|
128
152
|
try {
|
|
129
|
-
let
|
|
153
|
+
let keytarRaw;
|
|
130
154
|
try {
|
|
131
155
|
const kt = await getKeytar();
|
|
132
156
|
if (kt) {
|
|
133
|
-
|
|
134
|
-
if (cachedData) {
|
|
135
|
-
cacheData = cachedData;
|
|
136
|
-
}
|
|
157
|
+
keytarRaw = await kt.getPassword(SERVICE_NAME, TOKEN_CACHE_ACCOUNT) ?? void 0;
|
|
137
158
|
}
|
|
138
159
|
} catch (keytarError) {
|
|
139
|
-
logger.warn(
|
|
140
|
-
`Keychain access failed, falling back to file storage: ${keytarError.message}`
|
|
141
|
-
);
|
|
160
|
+
logger.warn(`Keychain access failed: ${keytarError.message}`);
|
|
142
161
|
}
|
|
162
|
+
let fileRaw;
|
|
143
163
|
const cachePath = getTokenCachePath();
|
|
144
|
-
if (
|
|
145
|
-
|
|
164
|
+
if (existsSync(cachePath)) {
|
|
165
|
+
fileRaw = readFileSync(cachePath, "utf8");
|
|
146
166
|
}
|
|
167
|
+
const cacheData = pickNewest(keytarRaw, fileRaw);
|
|
147
168
|
if (cacheData) {
|
|
148
169
|
this.msalApp.getTokenCache().deserialize(cacheData);
|
|
149
170
|
}
|
|
@@ -154,24 +175,23 @@ class AuthManager {
|
|
|
154
175
|
}
|
|
155
176
|
async loadSelectedAccount() {
|
|
156
177
|
try {
|
|
157
|
-
let
|
|
178
|
+
let keytarRaw;
|
|
158
179
|
try {
|
|
159
180
|
const kt = await getKeytar();
|
|
160
181
|
if (kt) {
|
|
161
|
-
|
|
162
|
-
if (cachedData) {
|
|
163
|
-
selectedAccountData = cachedData;
|
|
164
|
-
}
|
|
182
|
+
keytarRaw = await kt.getPassword(SERVICE_NAME, SELECTED_ACCOUNT_KEY) ?? void 0;
|
|
165
183
|
}
|
|
166
184
|
} catch (keytarError) {
|
|
167
185
|
logger.warn(
|
|
168
|
-
`Keychain access failed for selected account
|
|
186
|
+
`Keychain access failed for selected account: ${keytarError.message}`
|
|
169
187
|
);
|
|
170
188
|
}
|
|
189
|
+
let fileRaw;
|
|
171
190
|
const accountPath = getSelectedAccountPath();
|
|
172
|
-
if (
|
|
173
|
-
|
|
191
|
+
if (existsSync(accountPath)) {
|
|
192
|
+
fileRaw = readFileSync(accountPath, "utf8");
|
|
174
193
|
}
|
|
194
|
+
const selectedAccountData = pickNewest(keytarRaw, fileRaw);
|
|
175
195
|
if (selectedAccountData) {
|
|
176
196
|
const parsed = JSON.parse(selectedAccountData);
|
|
177
197
|
this.selectedAccountId = parsed.accountId;
|
|
@@ -183,15 +203,15 @@ class AuthManager {
|
|
|
183
203
|
}
|
|
184
204
|
async saveTokenCache() {
|
|
185
205
|
try {
|
|
186
|
-
const
|
|
206
|
+
const stamped = wrapCache(this.msalApp.getTokenCache().serialize());
|
|
187
207
|
try {
|
|
188
208
|
const kt = await getKeytar();
|
|
189
209
|
if (kt) {
|
|
190
|
-
await kt.setPassword(SERVICE_NAME, TOKEN_CACHE_ACCOUNT,
|
|
210
|
+
await kt.setPassword(SERVICE_NAME, TOKEN_CACHE_ACCOUNT, stamped);
|
|
191
211
|
} else {
|
|
192
212
|
const cachePath = getTokenCachePath();
|
|
193
213
|
ensureParentDir(cachePath);
|
|
194
|
-
fs.writeFileSync(cachePath,
|
|
214
|
+
fs.writeFileSync(cachePath, stamped, { mode: 384 });
|
|
195
215
|
}
|
|
196
216
|
} catch (keytarError) {
|
|
197
217
|
logger.warn(
|
|
@@ -199,7 +219,7 @@ class AuthManager {
|
|
|
199
219
|
);
|
|
200
220
|
const cachePath = getTokenCachePath();
|
|
201
221
|
ensureParentDir(cachePath);
|
|
202
|
-
fs.writeFileSync(cachePath,
|
|
222
|
+
fs.writeFileSync(cachePath, stamped, { mode: 384 });
|
|
203
223
|
}
|
|
204
224
|
} catch (error) {
|
|
205
225
|
logger.error(`Error saving token cache: ${error.message}`);
|
|
@@ -207,15 +227,15 @@ class AuthManager {
|
|
|
207
227
|
}
|
|
208
228
|
async saveSelectedAccount() {
|
|
209
229
|
try {
|
|
210
|
-
const
|
|
230
|
+
const stamped = wrapCache(JSON.stringify({ accountId: this.selectedAccountId }));
|
|
211
231
|
try {
|
|
212
232
|
const kt = await getKeytar();
|
|
213
233
|
if (kt) {
|
|
214
|
-
await kt.setPassword(SERVICE_NAME, SELECTED_ACCOUNT_KEY,
|
|
234
|
+
await kt.setPassword(SERVICE_NAME, SELECTED_ACCOUNT_KEY, stamped);
|
|
215
235
|
} else {
|
|
216
236
|
const accountPath = getSelectedAccountPath();
|
|
217
237
|
ensureParentDir(accountPath);
|
|
218
|
-
fs.writeFileSync(accountPath,
|
|
238
|
+
fs.writeFileSync(accountPath, stamped, { mode: 384 });
|
|
219
239
|
}
|
|
220
240
|
} catch (keytarError) {
|
|
221
241
|
logger.warn(
|
|
@@ -223,7 +243,7 @@ class AuthManager {
|
|
|
223
243
|
);
|
|
224
244
|
const accountPath = getSelectedAccountPath();
|
|
225
245
|
ensureParentDir(accountPath);
|
|
226
|
-
fs.writeFileSync(accountPath,
|
|
246
|
+
fs.writeFileSync(accountPath, stamped, { mode: 384 });
|
|
227
247
|
}
|
|
228
248
|
} catch (error) {
|
|
229
249
|
logger.error(`Error saving selected account: ${error.message}`);
|
|
@@ -524,5 +544,8 @@ export {
|
|
|
524
544
|
buildScopesFromEndpoints,
|
|
525
545
|
auth_default as default,
|
|
526
546
|
getSelectedAccountPath,
|
|
527
|
-
getTokenCachePath
|
|
547
|
+
getTokenCachePath,
|
|
548
|
+
pickNewest,
|
|
549
|
+
unwrapCache,
|
|
550
|
+
wrapCache
|
|
528
551
|
};
|
package/dist/endpoints.json
CHANGED
|
@@ -658,6 +658,62 @@
|
|
|
658
658
|
"toolName": "list-team-members",
|
|
659
659
|
"workScopes": ["TeamMember.Read.All"]
|
|
660
660
|
},
|
|
661
|
+
{
|
|
662
|
+
"pathPattern": "/teams/{team-id}/tags",
|
|
663
|
+
"method": "get",
|
|
664
|
+
"toolName": "list-team-tags",
|
|
665
|
+
"workScopes": ["TeamworkTag.Read.All"],
|
|
666
|
+
"llmTip": "List all tags in a team. Returns tag id, displayName, memberCount, and tagType (standard or scheduled). Use list-joined-teams to find the team ID first."
|
|
667
|
+
},
|
|
668
|
+
{
|
|
669
|
+
"pathPattern": "/teams/{team-id}/tags",
|
|
670
|
+
"method": "post",
|
|
671
|
+
"toolName": "create-team-tag",
|
|
672
|
+
"workScopes": ["TeamworkTag.ReadWrite.All"],
|
|
673
|
+
"llmTip": "Create a new tag in a team. Body requires displayName (max 40 chars) and an optional members array (max 25 at creation, each with a userId). Use list-team-members to find user IDs. Add more members individually with add-team-tag-member after creation."
|
|
674
|
+
},
|
|
675
|
+
{
|
|
676
|
+
"pathPattern": "/teams/{team-id}/tags/{teamworkTag-id}",
|
|
677
|
+
"method": "get",
|
|
678
|
+
"toolName": "get-team-tag",
|
|
679
|
+
"workScopes": ["TeamworkTag.Read.All"],
|
|
680
|
+
"llmTip": "Get details of a specific tag including displayName, memberCount, and tagType. Use list-team-tags to find the tag ID."
|
|
681
|
+
},
|
|
682
|
+
{
|
|
683
|
+
"pathPattern": "/teams/{team-id}/tags/{teamworkTag-id}",
|
|
684
|
+
"method": "patch",
|
|
685
|
+
"toolName": "update-team-tag",
|
|
686
|
+
"workScopes": ["TeamworkTag.ReadWrite.All"],
|
|
687
|
+
"llmTip": "Update a tag's displayName (max 40 chars). Use list-team-tags to find the tag ID."
|
|
688
|
+
},
|
|
689
|
+
{
|
|
690
|
+
"pathPattern": "/teams/{team-id}/tags/{teamworkTag-id}",
|
|
691
|
+
"method": "delete",
|
|
692
|
+
"toolName": "delete-team-tag",
|
|
693
|
+
"workScopes": ["TeamworkTag.ReadWrite.All"],
|
|
694
|
+
"llmTip": "Permanently delete a tag from a team. This action is irreversible. Use list-team-tags to find the tag ID."
|
|
695
|
+
},
|
|
696
|
+
{
|
|
697
|
+
"pathPattern": "/teams/{team-id}/tags/{teamworkTag-id}/members",
|
|
698
|
+
"method": "get",
|
|
699
|
+
"toolName": "list-team-tag-members",
|
|
700
|
+
"workScopes": ["TeamworkTag.Read.All"],
|
|
701
|
+
"llmTip": "List all members of a specific tag. Returns member id, displayName, tenantId, and userId. Use list-team-tags to find the tag ID."
|
|
702
|
+
},
|
|
703
|
+
{
|
|
704
|
+
"pathPattern": "/teams/{team-id}/tags/{teamworkTag-id}/members",
|
|
705
|
+
"method": "post",
|
|
706
|
+
"toolName": "add-team-tag-member",
|
|
707
|
+
"workScopes": ["TeamworkTag.ReadWrite.All"],
|
|
708
|
+
"llmTip": "Add a member to an existing tag. Body requires userId. Use list-team-members to find the user ID. Max 200 members per tag. Note: this operation requires application permissions (delegated not supported)."
|
|
709
|
+
},
|
|
710
|
+
{
|
|
711
|
+
"pathPattern": "/teams/{team-id}/tags/{teamworkTag-id}/members/{teamworkTagMember-id}",
|
|
712
|
+
"method": "delete",
|
|
713
|
+
"toolName": "remove-team-tag-member",
|
|
714
|
+
"workScopes": ["TeamworkTag.ReadWrite.All"],
|
|
715
|
+
"llmTip": "Remove a member from a tag. Use list-team-tag-members to find the member ID."
|
|
716
|
+
},
|
|
661
717
|
{
|
|
662
718
|
"pathPattern": "/chats/{chat-id}/messages/{chatMessage-id}/replies",
|
|
663
719
|
"method": "get",
|
|
@@ -792,6 +848,27 @@
|
|
|
792
848
|
"returnDownloadUrl": true,
|
|
793
849
|
"llmTip": "Returns a temporary download URL for the meeting recording in MP4 format. Use the download URL to access the video file. The recording may be large — do not attempt to stream it inline."
|
|
794
850
|
},
|
|
851
|
+
{
|
|
852
|
+
"pathPattern": "/me/onlineMeetings/{onlineMeeting-id}/attendanceReports",
|
|
853
|
+
"method": "get",
|
|
854
|
+
"toolName": "list-meeting-attendance-reports",
|
|
855
|
+
"workScopes": ["OnlineMeetingArtifact.Read.All"],
|
|
856
|
+
"llmTip": "Lists attendance reports for a meeting. Each report has meetingStartDateTime, meetingEndDateTime, totalParticipantCount. For recurring meetings, there is one report per occurrence. Get the meeting ID first via list-online-meetings."
|
|
857
|
+
},
|
|
858
|
+
{
|
|
859
|
+
"pathPattern": "/me/onlineMeetings/{onlineMeeting-id}/attendanceReports/{meetingAttendanceReport-id}",
|
|
860
|
+
"method": "get",
|
|
861
|
+
"toolName": "get-meeting-attendance-report",
|
|
862
|
+
"workScopes": ["OnlineMeetingArtifact.Read.All"],
|
|
863
|
+
"llmTip": "Gets a specific attendance report with totalParticipantCount, meetingStartDateTime, meetingEndDateTime."
|
|
864
|
+
},
|
|
865
|
+
{
|
|
866
|
+
"pathPattern": "/me/onlineMeetings/{onlineMeeting-id}/attendanceReports/{meetingAttendanceReport-id}/attendanceRecords",
|
|
867
|
+
"method": "get",
|
|
868
|
+
"toolName": "list-meeting-attendance-records",
|
|
869
|
+
"workScopes": ["OnlineMeetingArtifact.Read.All"],
|
|
870
|
+
"llmTip": "Lists individual attendance records for a meeting report. Each record has: identity (displayName), emailAddress, role (Organizer/Presenter/Attendee), totalAttendanceInSeconds, and attendanceIntervals with joinDateTime/leaveDateTime. Use to determine who attended, how long, and when they joined/left."
|
|
871
|
+
},
|
|
795
872
|
{
|
|
796
873
|
"pathPattern": "/groups/{group-id}/conversations",
|
|
797
874
|
"method": "get",
|
package/dist/generated/client.js
CHANGED
|
@@ -2873,6 +2873,69 @@ const microsoft_graph_onlineMeetingCollectionResponse = z.object({
|
|
|
2873
2873
|
"@odata.nextLink": z.string().nullable(),
|
|
2874
2874
|
value: z.array(microsoft_graph_onlineMeeting)
|
|
2875
2875
|
}).partial().passthrough();
|
|
2876
|
+
const microsoft_graph_virtualEventExternalInformation = z.object({
|
|
2877
|
+
applicationId: z.string().describe("Identifier of the application that hosts the externalEventId. Read-only.").nullish(),
|
|
2878
|
+
externalEventId: z.string().describe(
|
|
2879
|
+
"The identifier for a virtualEventExternalInformation object that associates the virtual event with an event ID in an external application. This association bundles all the information (both supported and not supported in virtualEvent) into one virtual event object. Optional. If set, the maximum supported length is 256 characters."
|
|
2880
|
+
).nullish()
|
|
2881
|
+
}).passthrough();
|
|
2882
|
+
const microsoft_graph_attendanceInterval = z.object({
|
|
2883
|
+
durationInSeconds: z.number().gte(-2147483648).lte(2147483647).describe(
|
|
2884
|
+
"Duration of the meeting interval in seconds; that is, the difference between joinDateTime and leaveDateTime."
|
|
2885
|
+
).nullish(),
|
|
2886
|
+
joinDateTime: z.string().regex(
|
|
2887
|
+
/^[0-9]{4,}-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])T([01][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]([.][0-9]{1,12})?(Z|[+-][0-9][0-9]:[0-9][0-9])$/
|
|
2888
|
+
).datetime({ offset: true }).describe("The time the attendee joined in UTC.").nullish(),
|
|
2889
|
+
leaveDateTime: z.string().regex(
|
|
2890
|
+
/^[0-9]{4,}-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])T([01][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]([.][0-9]{1,12})?(Z|[+-][0-9][0-9]:[0-9][0-9])$/
|
|
2891
|
+
).datetime({ offset: true }).describe("The time the attendee left in UTC.").nullish()
|
|
2892
|
+
}).passthrough();
|
|
2893
|
+
const microsoft_graph_virtualEventExternalRegistrationInformation = z.object({
|
|
2894
|
+
referrer: z.string().describe(
|
|
2895
|
+
"A URL or string that represents the location from which the registrant registered. Optional."
|
|
2896
|
+
).nullish(),
|
|
2897
|
+
registrationId: z.string().describe(
|
|
2898
|
+
"The identifier for a virtualEventExternalRegistrationInformation object. Optional. If set, the maximum supported length is 256 characters."
|
|
2899
|
+
).nullish()
|
|
2900
|
+
}).passthrough();
|
|
2901
|
+
const microsoft_graph_attendanceRecord = z.object({
|
|
2902
|
+
id: z.string().describe("The unique identifier for an entity. Read-only.").optional(),
|
|
2903
|
+
attendanceIntervals: z.array(microsoft_graph_attendanceInterval).describe("List of time periods between joining and leaving a meeting.").optional(),
|
|
2904
|
+
emailAddress: z.string().describe("Email address of the user associated with this attendance record.").nullish(),
|
|
2905
|
+
externalRegistrationInformation: microsoft_graph_virtualEventExternalRegistrationInformation.optional(),
|
|
2906
|
+
identity: microsoft_graph_identity.optional(),
|
|
2907
|
+
registrationId: z.string().describe(
|
|
2908
|
+
"Unique identifier of a virtualEventRegistration that is available to all participants registered for the virtualEventWebinar."
|
|
2909
|
+
).nullish(),
|
|
2910
|
+
role: z.string().describe(
|
|
2911
|
+
"Role of the attendee. The possible values are: None, Attendee, Presenter, and Organizer."
|
|
2912
|
+
).nullish(),
|
|
2913
|
+
totalAttendanceInSeconds: z.number().gte(-2147483648).lte(2147483647).describe("Total duration of the attendances in seconds.").nullish()
|
|
2914
|
+
}).passthrough();
|
|
2915
|
+
const microsoft_graph_meetingAttendanceReport = z.object({
|
|
2916
|
+
id: z.string().describe("The unique identifier for an entity. Read-only.").optional(),
|
|
2917
|
+
externalEventInformation: z.array(microsoft_graph_virtualEventExternalInformation).describe(
|
|
2918
|
+
"The external information of a virtual event. Returned only for event organizers or coorganizers. Read-only."
|
|
2919
|
+
).optional(),
|
|
2920
|
+
meetingEndDateTime: z.string().regex(
|
|
2921
|
+
/^[0-9]{4,}-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])T([01][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]([.][0-9]{1,12})?(Z|[+-][0-9][0-9]:[0-9][0-9])$/
|
|
2922
|
+
).datetime({ offset: true }).describe("UTC time when the meeting ended. Read-only.").nullish(),
|
|
2923
|
+
meetingStartDateTime: z.string().regex(
|
|
2924
|
+
/^[0-9]{4,}-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])T([01][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]([.][0-9]{1,12})?(Z|[+-][0-9][0-9]:[0-9][0-9])$/
|
|
2925
|
+
).datetime({ offset: true }).describe("UTC time when the meeting started. Read-only.").nullish(),
|
|
2926
|
+
totalParticipantCount: z.number().gte(-2147483648).lte(2147483647).describe("Total number of participants. Read-only.").nullish(),
|
|
2927
|
+
attendanceRecords: z.array(microsoft_graph_attendanceRecord).describe("List of attendance records of an attendance report. Read-only.").optional()
|
|
2928
|
+
}).passthrough();
|
|
2929
|
+
const microsoft_graph_meetingAttendanceReportCollectionResponse = z.object({
|
|
2930
|
+
"@odata.count": z.number().int().nullable(),
|
|
2931
|
+
"@odata.nextLink": z.string().nullable(),
|
|
2932
|
+
value: z.array(microsoft_graph_meetingAttendanceReport)
|
|
2933
|
+
}).partial().passthrough();
|
|
2934
|
+
const microsoft_graph_attendanceRecordCollectionResponse = z.object({
|
|
2935
|
+
"@odata.count": z.number().int().nullable(),
|
|
2936
|
+
"@odata.nextLink": z.string().nullable(),
|
|
2937
|
+
value: z.array(microsoft_graph_attendanceRecord)
|
|
2938
|
+
}).partial().passthrough();
|
|
2876
2939
|
const microsoft_graph_callRecording = z.object({
|
|
2877
2940
|
id: z.string().describe("The unique identifier for an entity. Read-only.").optional(),
|
|
2878
2941
|
callId: z.string().describe("The unique identifier for the call that is related to this recording. Read-only.").nullish(),
|
|
@@ -3496,6 +3559,34 @@ const microsoft_graph_conversationMemberCollectionResponse = z.object({
|
|
|
3496
3559
|
"@odata.nextLink": z.string().nullable(),
|
|
3497
3560
|
value: z.array(microsoft_graph_conversationMember)
|
|
3498
3561
|
}).partial().passthrough();
|
|
3562
|
+
const microsoft_graph_teamworkTagType = z.enum(["standard", "unknownFutureValue"]);
|
|
3563
|
+
const microsoft_graph_teamworkTagMember = z.object({
|
|
3564
|
+
id: z.string().describe("The unique identifier for an entity. Read-only.").optional(),
|
|
3565
|
+
displayName: z.string().describe("The member's display name.").nullish(),
|
|
3566
|
+
tenantId: z.string().describe("The ID of the tenant that the tag member is a part of.").nullish(),
|
|
3567
|
+
userId: z.string().describe("The user ID of the member.").nullish()
|
|
3568
|
+
}).passthrough();
|
|
3569
|
+
const microsoft_graph_teamworkTag = z.object({
|
|
3570
|
+
id: z.string().describe("The unique identifier for an entity. Read-only.").optional(),
|
|
3571
|
+
description: z.string().describe(
|
|
3572
|
+
"The description of the tag as it appears to the user in Microsoft Teams. A teamworkTag can't have more than 200 teamworkTagMembers."
|
|
3573
|
+
).nullish(),
|
|
3574
|
+
displayName: z.string().describe("The name of the tag as it appears to the user in Microsoft Teams.").nullish(),
|
|
3575
|
+
memberCount: z.number().gte(-2147483648).lte(2147483647).describe("The number of users assigned to the tag.").nullish(),
|
|
3576
|
+
tagType: microsoft_graph_teamworkTagType.optional(),
|
|
3577
|
+
teamId: z.string().describe("ID of the team in which the tag is defined.").nullish(),
|
|
3578
|
+
members: z.array(microsoft_graph_teamworkTagMember).describe("Users assigned to the tag.").optional()
|
|
3579
|
+
}).passthrough();
|
|
3580
|
+
const microsoft_graph_teamworkTagCollectionResponse = z.object({
|
|
3581
|
+
"@odata.count": z.number().int().nullable(),
|
|
3582
|
+
"@odata.nextLink": z.string().nullable(),
|
|
3583
|
+
value: z.array(microsoft_graph_teamworkTag)
|
|
3584
|
+
}).partial().passthrough();
|
|
3585
|
+
const microsoft_graph_teamworkTagMemberCollectionResponse = z.object({
|
|
3586
|
+
"@odata.count": z.number().int().nullable(),
|
|
3587
|
+
"@odata.nextLink": z.string().nullable(),
|
|
3588
|
+
value: z.array(microsoft_graph_teamworkTagMember)
|
|
3589
|
+
}).partial().passthrough();
|
|
3499
3590
|
const microsoft_graph_userCollectionResponse = z.object({
|
|
3500
3591
|
"@odata.count": z.number().int().nullable(),
|
|
3501
3592
|
"@odata.nextLink": z.string().nullable(),
|
|
@@ -3778,6 +3869,13 @@ const schemas = {
|
|
|
3778
3869
|
microsoft_graph_joinMeetingIdSettings,
|
|
3779
3870
|
microsoft_graph_onlineMeeting,
|
|
3780
3871
|
microsoft_graph_onlineMeetingCollectionResponse,
|
|
3872
|
+
microsoft_graph_virtualEventExternalInformation,
|
|
3873
|
+
microsoft_graph_attendanceInterval,
|
|
3874
|
+
microsoft_graph_virtualEventExternalRegistrationInformation,
|
|
3875
|
+
microsoft_graph_attendanceRecord,
|
|
3876
|
+
microsoft_graph_meetingAttendanceReport,
|
|
3877
|
+
microsoft_graph_meetingAttendanceReportCollectionResponse,
|
|
3878
|
+
microsoft_graph_attendanceRecordCollectionResponse,
|
|
3781
3879
|
microsoft_graph_callRecording,
|
|
3782
3880
|
microsoft_graph_callRecordingCollectionResponse,
|
|
3783
3881
|
microsoft_graph_callTranscript,
|
|
@@ -3849,6 +3947,11 @@ const schemas = {
|
|
|
3849
3947
|
BaseDeltaFunctionResponse,
|
|
3850
3948
|
microsoft_graph_channelCollectionResponse,
|
|
3851
3949
|
microsoft_graph_conversationMemberCollectionResponse,
|
|
3950
|
+
microsoft_graph_teamworkTagType,
|
|
3951
|
+
microsoft_graph_teamworkTagMember,
|
|
3952
|
+
microsoft_graph_teamworkTag,
|
|
3953
|
+
microsoft_graph_teamworkTagCollectionResponse,
|
|
3954
|
+
microsoft_graph_teamworkTagMemberCollectionResponse,
|
|
3852
3955
|
microsoft_graph_userCollectionResponse
|
|
3853
3956
|
};
|
|
3854
3957
|
const endpoints = makeApi([
|
|
@@ -6377,6 +6480,126 @@ resource.`,
|
|
|
6377
6480
|
],
|
|
6378
6481
|
response: z.void()
|
|
6379
6482
|
},
|
|
6483
|
+
{
|
|
6484
|
+
method: "get",
|
|
6485
|
+
path: "/me/onlineMeetings/:onlineMeetingId/attendanceReports",
|
|
6486
|
+
alias: "list-meeting-attendance-reports",
|
|
6487
|
+
description: `Get a list of meetingAttendanceReport objects for an onlineMeeting or a virtualEvent. Each time an online meeting or a virtual event ends, an attendance report is generated for that session.`,
|
|
6488
|
+
requestFormat: "json",
|
|
6489
|
+
parameters: [
|
|
6490
|
+
{
|
|
6491
|
+
name: "$top",
|
|
6492
|
+
type: "Query",
|
|
6493
|
+
schema: z.number().int().gte(0).describe("Show only the first n items").optional()
|
|
6494
|
+
},
|
|
6495
|
+
{
|
|
6496
|
+
name: "$skip",
|
|
6497
|
+
type: "Query",
|
|
6498
|
+
schema: z.number().int().gte(0).describe("Skip the first n items").optional()
|
|
6499
|
+
},
|
|
6500
|
+
{
|
|
6501
|
+
name: "$search",
|
|
6502
|
+
type: "Query",
|
|
6503
|
+
schema: z.string().describe("Search items by search phrases").optional()
|
|
6504
|
+
},
|
|
6505
|
+
{
|
|
6506
|
+
name: "$filter",
|
|
6507
|
+
type: "Query",
|
|
6508
|
+
schema: z.string().describe("Filter items by property values").optional()
|
|
6509
|
+
},
|
|
6510
|
+
{
|
|
6511
|
+
name: "$count",
|
|
6512
|
+
type: "Query",
|
|
6513
|
+
schema: z.boolean().describe("Include count of items").optional()
|
|
6514
|
+
},
|
|
6515
|
+
{
|
|
6516
|
+
name: "$orderby",
|
|
6517
|
+
type: "Query",
|
|
6518
|
+
schema: z.array(z.string()).describe("Order items by property values").optional()
|
|
6519
|
+
},
|
|
6520
|
+
{
|
|
6521
|
+
name: "$select",
|
|
6522
|
+
type: "Query",
|
|
6523
|
+
schema: z.array(z.string()).describe("Select properties to be returned").optional()
|
|
6524
|
+
},
|
|
6525
|
+
{
|
|
6526
|
+
name: "$expand",
|
|
6527
|
+
type: "Query",
|
|
6528
|
+
schema: z.array(z.string()).describe("Expand related entities").optional()
|
|
6529
|
+
}
|
|
6530
|
+
],
|
|
6531
|
+
response: z.void()
|
|
6532
|
+
},
|
|
6533
|
+
{
|
|
6534
|
+
method: "get",
|
|
6535
|
+
path: "/me/onlineMeetings/:onlineMeetingId/attendanceReports/:meetingAttendanceReportId",
|
|
6536
|
+
alias: "get-meeting-attendance-report",
|
|
6537
|
+
description: `Get the meetingAttendanceReport for an onlineMeeting or a virtualEvent. When an online meeting ends, an attendance report is generated for that session.`,
|
|
6538
|
+
requestFormat: "json",
|
|
6539
|
+
parameters: [
|
|
6540
|
+
{
|
|
6541
|
+
name: "$select",
|
|
6542
|
+
type: "Query",
|
|
6543
|
+
schema: z.array(z.string()).describe("Select properties to be returned").optional()
|
|
6544
|
+
},
|
|
6545
|
+
{
|
|
6546
|
+
name: "$expand",
|
|
6547
|
+
type: "Query",
|
|
6548
|
+
schema: z.array(z.string()).describe("Expand related entities").optional()
|
|
6549
|
+
}
|
|
6550
|
+
],
|
|
6551
|
+
response: z.void()
|
|
6552
|
+
},
|
|
6553
|
+
{
|
|
6554
|
+
method: "get",
|
|
6555
|
+
path: "/me/onlineMeetings/:onlineMeetingId/attendanceReports/:meetingAttendanceReportId/attendanceRecords",
|
|
6556
|
+
alias: "list-meeting-attendance-records",
|
|
6557
|
+
description: `Get a list of attendanceRecord objects and their properties.`,
|
|
6558
|
+
requestFormat: "json",
|
|
6559
|
+
parameters: [
|
|
6560
|
+
{
|
|
6561
|
+
name: "$top",
|
|
6562
|
+
type: "Query",
|
|
6563
|
+
schema: z.number().int().gte(0).describe("Show only the first n items").optional()
|
|
6564
|
+
},
|
|
6565
|
+
{
|
|
6566
|
+
name: "$skip",
|
|
6567
|
+
type: "Query",
|
|
6568
|
+
schema: z.number().int().gte(0).describe("Skip the first n items").optional()
|
|
6569
|
+
},
|
|
6570
|
+
{
|
|
6571
|
+
name: "$search",
|
|
6572
|
+
type: "Query",
|
|
6573
|
+
schema: z.string().describe("Search items by search phrases").optional()
|
|
6574
|
+
},
|
|
6575
|
+
{
|
|
6576
|
+
name: "$filter",
|
|
6577
|
+
type: "Query",
|
|
6578
|
+
schema: z.string().describe("Filter items by property values").optional()
|
|
6579
|
+
},
|
|
6580
|
+
{
|
|
6581
|
+
name: "$count",
|
|
6582
|
+
type: "Query",
|
|
6583
|
+
schema: z.boolean().describe("Include count of items").optional()
|
|
6584
|
+
},
|
|
6585
|
+
{
|
|
6586
|
+
name: "$orderby",
|
|
6587
|
+
type: "Query",
|
|
6588
|
+
schema: z.array(z.string()).describe("Order items by property values").optional()
|
|
6589
|
+
},
|
|
6590
|
+
{
|
|
6591
|
+
name: "$select",
|
|
6592
|
+
type: "Query",
|
|
6593
|
+
schema: z.array(z.string()).describe("Select properties to be returned").optional()
|
|
6594
|
+
},
|
|
6595
|
+
{
|
|
6596
|
+
name: "$expand",
|
|
6597
|
+
type: "Query",
|
|
6598
|
+
schema: z.array(z.string()).describe("Expand related entities").optional()
|
|
6599
|
+
}
|
|
6600
|
+
],
|
|
6601
|
+
response: z.void()
|
|
6602
|
+
},
|
|
6380
6603
|
{
|
|
6381
6604
|
method: "get",
|
|
6382
6605
|
path: "/me/onlineMeetings/:onlineMeetingId/recordings",
|
|
@@ -7734,6 +7957,204 @@ To monitor future changes, call the delta API by using the @odata.deltaLink in t
|
|
|
7734
7957
|
],
|
|
7735
7958
|
response: z.void()
|
|
7736
7959
|
},
|
|
7960
|
+
{
|
|
7961
|
+
method: "get",
|
|
7962
|
+
path: "/teams/:teamId/tags",
|
|
7963
|
+
alias: "list-team-tags",
|
|
7964
|
+
description: `Get a list of the tag objects and their properties.`,
|
|
7965
|
+
requestFormat: "json",
|
|
7966
|
+
parameters: [
|
|
7967
|
+
{
|
|
7968
|
+
name: "$top",
|
|
7969
|
+
type: "Query",
|
|
7970
|
+
schema: z.number().int().gte(0).describe("Show only the first n items").optional()
|
|
7971
|
+
},
|
|
7972
|
+
{
|
|
7973
|
+
name: "$skip",
|
|
7974
|
+
type: "Query",
|
|
7975
|
+
schema: z.number().int().gte(0).describe("Skip the first n items").optional()
|
|
7976
|
+
},
|
|
7977
|
+
{
|
|
7978
|
+
name: "$search",
|
|
7979
|
+
type: "Query",
|
|
7980
|
+
schema: z.string().describe("Search items by search phrases").optional()
|
|
7981
|
+
},
|
|
7982
|
+
{
|
|
7983
|
+
name: "$filter",
|
|
7984
|
+
type: "Query",
|
|
7985
|
+
schema: z.string().describe("Filter items by property values").optional()
|
|
7986
|
+
},
|
|
7987
|
+
{
|
|
7988
|
+
name: "$count",
|
|
7989
|
+
type: "Query",
|
|
7990
|
+
schema: z.boolean().describe("Include count of items").optional()
|
|
7991
|
+
},
|
|
7992
|
+
{
|
|
7993
|
+
name: "$orderby",
|
|
7994
|
+
type: "Query",
|
|
7995
|
+
schema: z.array(z.string()).describe("Order items by property values").optional()
|
|
7996
|
+
},
|
|
7997
|
+
{
|
|
7998
|
+
name: "$select",
|
|
7999
|
+
type: "Query",
|
|
8000
|
+
schema: z.array(z.string()).describe("Select properties to be returned").optional()
|
|
8001
|
+
},
|
|
8002
|
+
{
|
|
8003
|
+
name: "$expand",
|
|
8004
|
+
type: "Query",
|
|
8005
|
+
schema: z.array(z.string()).describe("Expand related entities").optional()
|
|
8006
|
+
}
|
|
8007
|
+
],
|
|
8008
|
+
response: z.void()
|
|
8009
|
+
},
|
|
8010
|
+
{
|
|
8011
|
+
method: "post",
|
|
8012
|
+
path: "/teams/:teamId/tags",
|
|
8013
|
+
alias: "create-team-tag",
|
|
8014
|
+
description: `Create a standard tag for members in a team.`,
|
|
8015
|
+
requestFormat: "json",
|
|
8016
|
+
parameters: [
|
|
8017
|
+
{
|
|
8018
|
+
name: "body",
|
|
8019
|
+
description: `New navigation property`,
|
|
8020
|
+
type: "Body",
|
|
8021
|
+
schema: microsoft_graph_teamworkTag
|
|
8022
|
+
}
|
|
8023
|
+
],
|
|
8024
|
+
response: z.void()
|
|
8025
|
+
},
|
|
8026
|
+
{
|
|
8027
|
+
method: "get",
|
|
8028
|
+
path: "/teams/:teamId/tags/:teamworkTagId",
|
|
8029
|
+
alias: "get-team-tag",
|
|
8030
|
+
description: `Read the properties and relationships of a tag object.`,
|
|
8031
|
+
requestFormat: "json",
|
|
8032
|
+
parameters: [
|
|
8033
|
+
{
|
|
8034
|
+
name: "$select",
|
|
8035
|
+
type: "Query",
|
|
8036
|
+
schema: z.array(z.string()).describe("Select properties to be returned").optional()
|
|
8037
|
+
},
|
|
8038
|
+
{
|
|
8039
|
+
name: "$expand",
|
|
8040
|
+
type: "Query",
|
|
8041
|
+
schema: z.array(z.string()).describe("Expand related entities").optional()
|
|
8042
|
+
}
|
|
8043
|
+
],
|
|
8044
|
+
response: z.void()
|
|
8045
|
+
},
|
|
8046
|
+
{
|
|
8047
|
+
method: "patch",
|
|
8048
|
+
path: "/teams/:teamId/tags/:teamworkTagId",
|
|
8049
|
+
alias: "update-team-tag",
|
|
8050
|
+
description: `Update the properties of a tag object.`,
|
|
8051
|
+
requestFormat: "json",
|
|
8052
|
+
parameters: [
|
|
8053
|
+
{
|
|
8054
|
+
name: "body",
|
|
8055
|
+
description: `New navigation property values`,
|
|
8056
|
+
type: "Body",
|
|
8057
|
+
schema: microsoft_graph_teamworkTag
|
|
8058
|
+
}
|
|
8059
|
+
],
|
|
8060
|
+
response: z.void()
|
|
8061
|
+
},
|
|
8062
|
+
{
|
|
8063
|
+
method: "delete",
|
|
8064
|
+
path: "/teams/:teamId/tags/:teamworkTagId",
|
|
8065
|
+
alias: "delete-team-tag",
|
|
8066
|
+
description: `Delete a tag object permanently.`,
|
|
8067
|
+
requestFormat: "json",
|
|
8068
|
+
parameters: [
|
|
8069
|
+
{
|
|
8070
|
+
name: "If-Match",
|
|
8071
|
+
type: "Header",
|
|
8072
|
+
schema: z.string().describe("ETag").optional()
|
|
8073
|
+
}
|
|
8074
|
+
],
|
|
8075
|
+
response: z.void()
|
|
8076
|
+
},
|
|
8077
|
+
{
|
|
8078
|
+
method: "get",
|
|
8079
|
+
path: "/teams/:teamId/tags/:teamworkTagId/members",
|
|
8080
|
+
alias: "list-team-tag-members",
|
|
8081
|
+
description: `Get a list of the members of a standard tag in a team and their properties.`,
|
|
8082
|
+
requestFormat: "json",
|
|
8083
|
+
parameters: [
|
|
8084
|
+
{
|
|
8085
|
+
name: "$top",
|
|
8086
|
+
type: "Query",
|
|
8087
|
+
schema: z.number().int().gte(0).describe("Show only the first n items").optional()
|
|
8088
|
+
},
|
|
8089
|
+
{
|
|
8090
|
+
name: "$skip",
|
|
8091
|
+
type: "Query",
|
|
8092
|
+
schema: z.number().int().gte(0).describe("Skip the first n items").optional()
|
|
8093
|
+
},
|
|
8094
|
+
{
|
|
8095
|
+
name: "$search",
|
|
8096
|
+
type: "Query",
|
|
8097
|
+
schema: z.string().describe("Search items by search phrases").optional()
|
|
8098
|
+
},
|
|
8099
|
+
{
|
|
8100
|
+
name: "$filter",
|
|
8101
|
+
type: "Query",
|
|
8102
|
+
schema: z.string().describe("Filter items by property values").optional()
|
|
8103
|
+
},
|
|
8104
|
+
{
|
|
8105
|
+
name: "$count",
|
|
8106
|
+
type: "Query",
|
|
8107
|
+
schema: z.boolean().describe("Include count of items").optional()
|
|
8108
|
+
},
|
|
8109
|
+
{
|
|
8110
|
+
name: "$orderby",
|
|
8111
|
+
type: "Query",
|
|
8112
|
+
schema: z.array(z.string()).describe("Order items by property values").optional()
|
|
8113
|
+
},
|
|
8114
|
+
{
|
|
8115
|
+
name: "$select",
|
|
8116
|
+
type: "Query",
|
|
8117
|
+
schema: z.array(z.string()).describe("Select properties to be returned").optional()
|
|
8118
|
+
},
|
|
8119
|
+
{
|
|
8120
|
+
name: "$expand",
|
|
8121
|
+
type: "Query",
|
|
8122
|
+
schema: z.array(z.string()).describe("Expand related entities").optional()
|
|
8123
|
+
}
|
|
8124
|
+
],
|
|
8125
|
+
response: z.void()
|
|
8126
|
+
},
|
|
8127
|
+
{
|
|
8128
|
+
method: "post",
|
|
8129
|
+
path: "/teams/:teamId/tags/:teamworkTagId/members",
|
|
8130
|
+
alias: "add-team-tag-member",
|
|
8131
|
+
description: `Create a new teamworkTagMember object in a team.`,
|
|
8132
|
+
requestFormat: "json",
|
|
8133
|
+
parameters: [
|
|
8134
|
+
{
|
|
8135
|
+
name: "body",
|
|
8136
|
+
description: `New navigation property`,
|
|
8137
|
+
type: "Body",
|
|
8138
|
+
schema: microsoft_graph_teamworkTagMember
|
|
8139
|
+
}
|
|
8140
|
+
],
|
|
8141
|
+
response: z.void()
|
|
8142
|
+
},
|
|
8143
|
+
{
|
|
8144
|
+
method: "delete",
|
|
8145
|
+
path: "/teams/:teamId/tags/:teamworkTagId/members/:teamworkTagMemberId",
|
|
8146
|
+
alias: "remove-team-tag-member",
|
|
8147
|
+
description: `Delete a member from a standard tag in a team.`,
|
|
8148
|
+
requestFormat: "json",
|
|
8149
|
+
parameters: [
|
|
8150
|
+
{
|
|
8151
|
+
name: "If-Match",
|
|
8152
|
+
type: "Header",
|
|
8153
|
+
schema: z.string().describe("ETag").optional()
|
|
8154
|
+
}
|
|
8155
|
+
],
|
|
8156
|
+
response: z.void()
|
|
8157
|
+
},
|
|
7737
8158
|
{
|
|
7738
8159
|
method: "get",
|
|
7739
8160
|
path: "/users",
|
package/logs/mcp-server.log
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
2026-03-25
|
|
2
|
-
2026-03-25
|
|
3
|
-
2026-03-25
|
|
4
|
-
2026-03-25
|
|
5
|
-
2026-03-25
|
|
6
|
-
2026-03-25
|
|
7
|
-
2026-03-25
|
|
8
|
-
2026-03-25
|
|
9
|
-
2026-03-25
|
|
10
|
-
2026-03-25
|
|
1
|
+
2026-03-25 13:58:07 INFO: [GRAPH CLIENT] Final URL being sent to Microsoft: https://graph.microsoft.com/v1.0/me
|
|
2
|
+
2026-03-25 13:58:07 INFO: [GRAPH CLIENT] Final URL being sent to Microsoft: https://graph.microsoft.com/v1.0/me
|
|
3
|
+
2026-03-25 13:58:07 INFO: [GRAPH CLIENT] Final URL being sent to Microsoft: https://graph.microsoft.com/v1.0/me
|
|
4
|
+
2026-03-25 13:58:07 INFO: [GRAPH CLIENT] Final URL being sent to Microsoft: https://graph.microsoft.com/v1.0/me/messages
|
|
5
|
+
2026-03-25 13:58:07 INFO: [GRAPH CLIENT] Final URL being sent to Microsoft: https://graph.microsoft.com/v1.0/me/calendar
|
|
6
|
+
2026-03-25 13:58:09 INFO: Using environment variables for secrets
|
|
7
|
+
2026-03-25 13:58:09 INFO: Using environment variables for secrets
|
|
8
|
+
2026-03-25 13:58:09 INFO: Using environment variables for secrets
|
|
9
|
+
2026-03-25 13:58:09 INFO: Using environment variables for secrets
|
|
10
|
+
2026-03-25 13:58:09 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.47.1",
|
|
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
|
@@ -658,6 +658,62 @@
|
|
|
658
658
|
"toolName": "list-team-members",
|
|
659
659
|
"workScopes": ["TeamMember.Read.All"]
|
|
660
660
|
},
|
|
661
|
+
{
|
|
662
|
+
"pathPattern": "/teams/{team-id}/tags",
|
|
663
|
+
"method": "get",
|
|
664
|
+
"toolName": "list-team-tags",
|
|
665
|
+
"workScopes": ["TeamworkTag.Read.All"],
|
|
666
|
+
"llmTip": "List all tags in a team. Returns tag id, displayName, memberCount, and tagType (standard or scheduled). Use list-joined-teams to find the team ID first."
|
|
667
|
+
},
|
|
668
|
+
{
|
|
669
|
+
"pathPattern": "/teams/{team-id}/tags",
|
|
670
|
+
"method": "post",
|
|
671
|
+
"toolName": "create-team-tag",
|
|
672
|
+
"workScopes": ["TeamworkTag.ReadWrite.All"],
|
|
673
|
+
"llmTip": "Create a new tag in a team. Body requires displayName (max 40 chars) and an optional members array (max 25 at creation, each with a userId). Use list-team-members to find user IDs. Add more members individually with add-team-tag-member after creation."
|
|
674
|
+
},
|
|
675
|
+
{
|
|
676
|
+
"pathPattern": "/teams/{team-id}/tags/{teamworkTag-id}",
|
|
677
|
+
"method": "get",
|
|
678
|
+
"toolName": "get-team-tag",
|
|
679
|
+
"workScopes": ["TeamworkTag.Read.All"],
|
|
680
|
+
"llmTip": "Get details of a specific tag including displayName, memberCount, and tagType. Use list-team-tags to find the tag ID."
|
|
681
|
+
},
|
|
682
|
+
{
|
|
683
|
+
"pathPattern": "/teams/{team-id}/tags/{teamworkTag-id}",
|
|
684
|
+
"method": "patch",
|
|
685
|
+
"toolName": "update-team-tag",
|
|
686
|
+
"workScopes": ["TeamworkTag.ReadWrite.All"],
|
|
687
|
+
"llmTip": "Update a tag's displayName (max 40 chars). Use list-team-tags to find the tag ID."
|
|
688
|
+
},
|
|
689
|
+
{
|
|
690
|
+
"pathPattern": "/teams/{team-id}/tags/{teamworkTag-id}",
|
|
691
|
+
"method": "delete",
|
|
692
|
+
"toolName": "delete-team-tag",
|
|
693
|
+
"workScopes": ["TeamworkTag.ReadWrite.All"],
|
|
694
|
+
"llmTip": "Permanently delete a tag from a team. This action is irreversible. Use list-team-tags to find the tag ID."
|
|
695
|
+
},
|
|
696
|
+
{
|
|
697
|
+
"pathPattern": "/teams/{team-id}/tags/{teamworkTag-id}/members",
|
|
698
|
+
"method": "get",
|
|
699
|
+
"toolName": "list-team-tag-members",
|
|
700
|
+
"workScopes": ["TeamworkTag.Read.All"],
|
|
701
|
+
"llmTip": "List all members of a specific tag. Returns member id, displayName, tenantId, and userId. Use list-team-tags to find the tag ID."
|
|
702
|
+
},
|
|
703
|
+
{
|
|
704
|
+
"pathPattern": "/teams/{team-id}/tags/{teamworkTag-id}/members",
|
|
705
|
+
"method": "post",
|
|
706
|
+
"toolName": "add-team-tag-member",
|
|
707
|
+
"workScopes": ["TeamworkTag.ReadWrite.All"],
|
|
708
|
+
"llmTip": "Add a member to an existing tag. Body requires userId. Use list-team-members to find the user ID. Max 200 members per tag. Note: this operation requires application permissions (delegated not supported)."
|
|
709
|
+
},
|
|
710
|
+
{
|
|
711
|
+
"pathPattern": "/teams/{team-id}/tags/{teamworkTag-id}/members/{teamworkTagMember-id}",
|
|
712
|
+
"method": "delete",
|
|
713
|
+
"toolName": "remove-team-tag-member",
|
|
714
|
+
"workScopes": ["TeamworkTag.ReadWrite.All"],
|
|
715
|
+
"llmTip": "Remove a member from a tag. Use list-team-tag-members to find the member ID."
|
|
716
|
+
},
|
|
661
717
|
{
|
|
662
718
|
"pathPattern": "/chats/{chat-id}/messages/{chatMessage-id}/replies",
|
|
663
719
|
"method": "get",
|
|
@@ -792,6 +848,27 @@
|
|
|
792
848
|
"returnDownloadUrl": true,
|
|
793
849
|
"llmTip": "Returns a temporary download URL for the meeting recording in MP4 format. Use the download URL to access the video file. The recording may be large — do not attempt to stream it inline."
|
|
794
850
|
},
|
|
851
|
+
{
|
|
852
|
+
"pathPattern": "/me/onlineMeetings/{onlineMeeting-id}/attendanceReports",
|
|
853
|
+
"method": "get",
|
|
854
|
+
"toolName": "list-meeting-attendance-reports",
|
|
855
|
+
"workScopes": ["OnlineMeetingArtifact.Read.All"],
|
|
856
|
+
"llmTip": "Lists attendance reports for a meeting. Each report has meetingStartDateTime, meetingEndDateTime, totalParticipantCount. For recurring meetings, there is one report per occurrence. Get the meeting ID first via list-online-meetings."
|
|
857
|
+
},
|
|
858
|
+
{
|
|
859
|
+
"pathPattern": "/me/onlineMeetings/{onlineMeeting-id}/attendanceReports/{meetingAttendanceReport-id}",
|
|
860
|
+
"method": "get",
|
|
861
|
+
"toolName": "get-meeting-attendance-report",
|
|
862
|
+
"workScopes": ["OnlineMeetingArtifact.Read.All"],
|
|
863
|
+
"llmTip": "Gets a specific attendance report with totalParticipantCount, meetingStartDateTime, meetingEndDateTime."
|
|
864
|
+
},
|
|
865
|
+
{
|
|
866
|
+
"pathPattern": "/me/onlineMeetings/{onlineMeeting-id}/attendanceReports/{meetingAttendanceReport-id}/attendanceRecords",
|
|
867
|
+
"method": "get",
|
|
868
|
+
"toolName": "list-meeting-attendance-records",
|
|
869
|
+
"workScopes": ["OnlineMeetingArtifact.Read.All"],
|
|
870
|
+
"llmTip": "Lists individual attendance records for a meeting report. Each record has: identity (displayName), emailAddress, role (Organizer/Presenter/Attendee), totalAttendanceInSeconds, and attendanceIntervals with joinDateTime/leaveDateTime. Use to determine who attended, how long, and when they joined/left."
|
|
871
|
+
},
|
|
795
872
|
{
|
|
796
873
|
"pathPattern": "/groups/{group-id}/conversations",
|
|
797
874
|
"method": "get",
|