msteams-mcp 0.2.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.
Potentially problematic release.
This version of msteams-mcp might be problematic. Click here for more details.
- package/LICENSE +21 -0
- package/README.md +261 -0
- package/dist/__fixtures__/api-responses.d.ts +254 -0
- package/dist/__fixtures__/api-responses.js +245 -0
- package/dist/api/calendar-api.d.ts +66 -0
- package/dist/api/calendar-api.js +179 -0
- package/dist/api/chatsvc-api.d.ts +352 -0
- package/dist/api/chatsvc-api.js +1100 -0
- package/dist/api/csa-api.d.ts +64 -0
- package/dist/api/csa-api.js +200 -0
- package/dist/api/index.d.ts +7 -0
- package/dist/api/index.js +7 -0
- package/dist/api/substrate-api.d.ts +50 -0
- package/dist/api/substrate-api.js +305 -0
- package/dist/auth/crypto.d.ts +32 -0
- package/dist/auth/crypto.js +66 -0
- package/dist/auth/index.d.ts +7 -0
- package/dist/auth/index.js +7 -0
- package/dist/auth/session-store.d.ts +87 -0
- package/dist/auth/session-store.js +230 -0
- package/dist/auth/token-extractor.d.ts +185 -0
- package/dist/auth/token-extractor.js +674 -0
- package/dist/auth/token-refresh.d.ts +25 -0
- package/dist/auth/token-refresh.js +85 -0
- package/dist/browser/auth.d.ts +53 -0
- package/dist/browser/auth.js +603 -0
- package/dist/browser/context.d.ts +40 -0
- package/dist/browser/context.js +122 -0
- package/dist/constants.d.ts +104 -0
- package/dist/constants.js +195 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +12 -0
- package/dist/research/auth-research.d.ts +10 -0
- package/dist/research/auth-research.js +175 -0
- package/dist/research/explore.d.ts +11 -0
- package/dist/research/explore.js +270 -0
- package/dist/research/search-research.d.ts +17 -0
- package/dist/research/search-research.js +317 -0
- package/dist/server.d.ts +66 -0
- package/dist/server.js +295 -0
- package/dist/test/debug-search.d.ts +10 -0
- package/dist/test/debug-search.js +147 -0
- package/dist/test/mcp-harness.d.ts +17 -0
- package/dist/test/mcp-harness.js +474 -0
- package/dist/tools/auth-tools.d.ts +26 -0
- package/dist/tools/auth-tools.js +191 -0
- package/dist/tools/index.d.ts +56 -0
- package/dist/tools/index.js +34 -0
- package/dist/tools/meeting-tools.d.ts +33 -0
- package/dist/tools/meeting-tools.js +64 -0
- package/dist/tools/message-tools.d.ts +269 -0
- package/dist/tools/message-tools.js +856 -0
- package/dist/tools/people-tools.d.ts +46 -0
- package/dist/tools/people-tools.js +112 -0
- package/dist/tools/registry.d.ts +23 -0
- package/dist/tools/registry.js +63 -0
- package/dist/tools/search-tools.d.ts +91 -0
- package/dist/tools/search-tools.js +222 -0
- package/dist/types/errors.d.ts +58 -0
- package/dist/types/errors.js +132 -0
- package/dist/types/result.d.ts +43 -0
- package/dist/types/result.js +51 -0
- package/dist/types/server.d.ts +27 -0
- package/dist/types/server.js +7 -0
- package/dist/types/teams.d.ts +85 -0
- package/dist/types/teams.js +4 -0
- package/dist/utils/api-config.d.ts +103 -0
- package/dist/utils/api-config.js +158 -0
- package/dist/utils/auth-guards.d.ts +67 -0
- package/dist/utils/auth-guards.js +147 -0
- package/dist/utils/http.d.ts +29 -0
- package/dist/utils/http.js +112 -0
- package/dist/utils/parsers.d.ts +247 -0
- package/dist/utils/parsers.js +731 -0
- package/dist/utils/parsers.test.d.ts +7 -0
- package/dist/utils/parsers.test.js +511 -0
- package/package.json +62 -0
|
@@ -0,0 +1,856 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Messaging-related tool handlers.
|
|
3
|
+
*/
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
import { sendMessage, saveMessage, unsaveMessage, getOneOnOneChatId, createGroupChat, editMessage, deleteMessage, getUnreadStatus, markAsRead, getActivityFeed, addReaction, removeReaction, getSavedMessages, getFollowedThreads, } from '../api/chatsvc-api.js';
|
|
6
|
+
import { getFavorites, addFavorite, removeFavorite, getCustomEmojis } from '../api/csa-api.js';
|
|
7
|
+
import { SELF_CHAT_ID, MAX_UNREAD_AGGREGATE_CHECK, MAX_THREAD_LIMIT, STANDARD_EMOJIS } from '../constants.js';
|
|
8
|
+
import { ErrorCode } from '../types/errors.js';
|
|
9
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
10
|
+
// Schemas
|
|
11
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
12
|
+
export const SendMessageInputSchema = z.object({
|
|
13
|
+
content: z.string().min(1, 'Message content cannot be empty'),
|
|
14
|
+
conversationId: z.string().optional().default(SELF_CHAT_ID),
|
|
15
|
+
replyToMessageId: z.string().optional(),
|
|
16
|
+
});
|
|
17
|
+
export const FavoriteInputSchema = z.object({
|
|
18
|
+
conversationId: z.string().min(1, 'Conversation ID cannot be empty'),
|
|
19
|
+
});
|
|
20
|
+
export const SaveMessageInputSchema = z.object({
|
|
21
|
+
conversationId: z.string().min(1, 'Conversation ID cannot be empty'),
|
|
22
|
+
messageId: z.string().min(1, 'Message ID cannot be empty'),
|
|
23
|
+
rootMessageId: z.string().optional(),
|
|
24
|
+
});
|
|
25
|
+
export const GetChatInputSchema = z.object({
|
|
26
|
+
userId: z.string().min(1, 'User ID cannot be empty'),
|
|
27
|
+
});
|
|
28
|
+
export const CreateGroupChatInputSchema = z.object({
|
|
29
|
+
userIds: z.array(z.string().min(1)).min(2, 'At least 2 user IDs are required for a group chat'),
|
|
30
|
+
topic: z.string().optional(),
|
|
31
|
+
});
|
|
32
|
+
export const EditMessageInputSchema = z.object({
|
|
33
|
+
conversationId: z.string().min(1, 'Conversation ID cannot be empty'),
|
|
34
|
+
messageId: z.string().min(1, 'Message ID cannot be empty'),
|
|
35
|
+
content: z.string().min(1, 'Content cannot be empty'),
|
|
36
|
+
});
|
|
37
|
+
export const DeleteMessageInputSchema = z.object({
|
|
38
|
+
conversationId: z.string().min(1, 'Conversation ID cannot be empty'),
|
|
39
|
+
messageId: z.string().min(1, 'Message ID cannot be empty'),
|
|
40
|
+
});
|
|
41
|
+
export const GetUnreadInputSchema = z.object({
|
|
42
|
+
conversationId: z.string().optional(),
|
|
43
|
+
});
|
|
44
|
+
export const MarkAsReadInputSchema = z.object({
|
|
45
|
+
conversationId: z.string().min(1, 'Conversation ID cannot be empty'),
|
|
46
|
+
messageId: z.string().min(1, 'Message ID cannot be empty'),
|
|
47
|
+
});
|
|
48
|
+
export const GetActivityInputSchema = z.object({
|
|
49
|
+
limit: z.number().min(1).max(200).optional(),
|
|
50
|
+
});
|
|
51
|
+
export const SearchEmojiInputSchema = z.object({
|
|
52
|
+
query: z.string().min(1, 'Search query cannot be empty'),
|
|
53
|
+
});
|
|
54
|
+
export const AddReactionInputSchema = z.object({
|
|
55
|
+
conversationId: z.string().min(1, 'Conversation ID cannot be empty'),
|
|
56
|
+
messageId: z.string().min(1, 'Message ID cannot be empty'),
|
|
57
|
+
emoji: z.string().min(1, 'Emoji key cannot be empty'),
|
|
58
|
+
});
|
|
59
|
+
export const RemoveReactionInputSchema = z.object({
|
|
60
|
+
conversationId: z.string().min(1, 'Conversation ID cannot be empty'),
|
|
61
|
+
messageId: z.string().min(1, 'Message ID cannot be empty'),
|
|
62
|
+
emoji: z.string().min(1, 'Emoji key cannot be empty'),
|
|
63
|
+
});
|
|
64
|
+
export const GetSavedMessagesInputSchema = z.object({
|
|
65
|
+
limit: z.number().min(1).max(MAX_THREAD_LIMIT).optional(),
|
|
66
|
+
});
|
|
67
|
+
export const GetFollowedThreadsInputSchema = z.object({
|
|
68
|
+
limit: z.number().min(1).max(MAX_THREAD_LIMIT).optional(),
|
|
69
|
+
});
|
|
70
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
71
|
+
// Tool Definitions
|
|
72
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
73
|
+
const sendMessageToolDefinition = {
|
|
74
|
+
name: 'teams_send_message',
|
|
75
|
+
description: 'Send a message to a Teams conversation. Supports @mentions using @[Name](mri) syntax inline. Example: "Hey @[John Smith](8:orgid:abc...), check this". Get MRI from teams_search_people. Defaults to self-notes (48:notes). For channel thread replies, provide replyToMessageId.',
|
|
76
|
+
inputSchema: {
|
|
77
|
+
type: 'object',
|
|
78
|
+
properties: {
|
|
79
|
+
content: {
|
|
80
|
+
type: 'string',
|
|
81
|
+
description: 'The message content. For @mentions, use @[DisplayName](mri) syntax. Example: "Hey @[John Smith](8:orgid:abc...), can you review this?"',
|
|
82
|
+
},
|
|
83
|
+
conversationId: {
|
|
84
|
+
type: 'string',
|
|
85
|
+
description: 'The conversation ID to send to. Use "48:notes" for self-chat (default), or a channel/chat conversation ID.',
|
|
86
|
+
},
|
|
87
|
+
replyToMessageId: {
|
|
88
|
+
type: 'string',
|
|
89
|
+
description: 'For channel thread replies: the message ID of the thread root. Use serverMessageId from teams_send_message, id from teams_get_thread, or messageId from teams_search.',
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
required: ['content'],
|
|
93
|
+
},
|
|
94
|
+
};
|
|
95
|
+
const getFavoritesToolDefinition = {
|
|
96
|
+
name: 'teams_get_favorites',
|
|
97
|
+
description: 'Get the user\'s favourite/pinned conversations in Teams. Returns conversation IDs with display names (channel name, chat topic, or participant names) and type (Channel, Chat, Meeting).',
|
|
98
|
+
inputSchema: {
|
|
99
|
+
type: 'object',
|
|
100
|
+
properties: {},
|
|
101
|
+
},
|
|
102
|
+
};
|
|
103
|
+
const addFavoriteToolDefinition = {
|
|
104
|
+
name: 'teams_add_favorite',
|
|
105
|
+
description: 'Add a conversation to the user\'s favourites/pinned list.',
|
|
106
|
+
inputSchema: {
|
|
107
|
+
type: 'object',
|
|
108
|
+
properties: {
|
|
109
|
+
conversationId: {
|
|
110
|
+
type: 'string',
|
|
111
|
+
description: 'The conversation ID to pin (e.g., "19:abc@thread.tacv2")',
|
|
112
|
+
},
|
|
113
|
+
},
|
|
114
|
+
required: ['conversationId'],
|
|
115
|
+
},
|
|
116
|
+
};
|
|
117
|
+
const removeFavoriteToolDefinition = {
|
|
118
|
+
name: 'teams_remove_favorite',
|
|
119
|
+
description: 'Remove a conversation from the user\'s favourites/pinned list.',
|
|
120
|
+
inputSchema: {
|
|
121
|
+
type: 'object',
|
|
122
|
+
properties: {
|
|
123
|
+
conversationId: {
|
|
124
|
+
type: 'string',
|
|
125
|
+
description: 'The conversation ID to unpin',
|
|
126
|
+
},
|
|
127
|
+
},
|
|
128
|
+
required: ['conversationId'],
|
|
129
|
+
},
|
|
130
|
+
};
|
|
131
|
+
const saveMessageToolDefinition = {
|
|
132
|
+
name: 'teams_save_message',
|
|
133
|
+
description: 'Save (bookmark) a message in Teams. Saved messages can be accessed later from the Saved view in Teams.',
|
|
134
|
+
inputSchema: {
|
|
135
|
+
type: 'object',
|
|
136
|
+
properties: {
|
|
137
|
+
conversationId: {
|
|
138
|
+
type: 'string',
|
|
139
|
+
description: 'The conversation ID containing the message',
|
|
140
|
+
},
|
|
141
|
+
messageId: {
|
|
142
|
+
type: 'string',
|
|
143
|
+
description: 'The message ID to save. Use: serverMessageId from teams_send_message, id from teams_get_thread, or messageId from teams_search.',
|
|
144
|
+
},
|
|
145
|
+
rootMessageId: {
|
|
146
|
+
type: 'string',
|
|
147
|
+
description: 'For channel threaded replies only: the ID of the thread root post. Not needed for top-level posts or non-channel conversations.',
|
|
148
|
+
},
|
|
149
|
+
},
|
|
150
|
+
required: ['conversationId', 'messageId'],
|
|
151
|
+
},
|
|
152
|
+
};
|
|
153
|
+
const unsaveMessageToolDefinition = {
|
|
154
|
+
name: 'teams_unsave_message',
|
|
155
|
+
description: 'Remove a saved (bookmarked) message in Teams.',
|
|
156
|
+
inputSchema: {
|
|
157
|
+
type: 'object',
|
|
158
|
+
properties: {
|
|
159
|
+
conversationId: {
|
|
160
|
+
type: 'string',
|
|
161
|
+
description: 'The conversation ID containing the message',
|
|
162
|
+
},
|
|
163
|
+
messageId: {
|
|
164
|
+
type: 'string',
|
|
165
|
+
description: 'The message ID to unsave',
|
|
166
|
+
},
|
|
167
|
+
rootMessageId: {
|
|
168
|
+
type: 'string',
|
|
169
|
+
description: 'For channel threaded replies only: the ID of the thread root post. Not needed for top-level posts or non-channel conversations.',
|
|
170
|
+
},
|
|
171
|
+
},
|
|
172
|
+
required: ['conversationId', 'messageId'],
|
|
173
|
+
},
|
|
174
|
+
};
|
|
175
|
+
const getChatToolDefinition = {
|
|
176
|
+
name: 'teams_get_chat',
|
|
177
|
+
description: 'Get the conversation ID for a 1:1 chat with a person. Use this to start a new chat or find an existing one. The conversation ID can then be used with teams_send_message to send messages.',
|
|
178
|
+
inputSchema: {
|
|
179
|
+
type: 'object',
|
|
180
|
+
properties: {
|
|
181
|
+
userId: {
|
|
182
|
+
type: 'string',
|
|
183
|
+
description: 'The user\'s identifier. Can be: MRI (8:orgid:guid), object ID with tenant (guid@tenantId), or raw object ID (guid). Get this from teams_search_people results.',
|
|
184
|
+
},
|
|
185
|
+
},
|
|
186
|
+
required: ['userId'],
|
|
187
|
+
},
|
|
188
|
+
};
|
|
189
|
+
const createGroupChatToolDefinition = {
|
|
190
|
+
name: 'teams_create_group_chat',
|
|
191
|
+
description: 'Create a new group chat with multiple people. Returns a conversation ID for use with teams_send_message. You are automatically included as a member. For 1:1 chats, use teams_get_chat instead.',
|
|
192
|
+
inputSchema: {
|
|
193
|
+
type: 'object',
|
|
194
|
+
properties: {
|
|
195
|
+
userIds: {
|
|
196
|
+
type: 'array',
|
|
197
|
+
items: { type: 'string' },
|
|
198
|
+
description: 'Array of OTHER users to add (at least 2, not including yourself). Can be: MRI (8:orgid:guid), object ID with tenant (guid@tenantId), or raw GUID. Get these from teams_search_people or teams_get_frequent_contacts.',
|
|
199
|
+
minItems: 2,
|
|
200
|
+
},
|
|
201
|
+
topic: {
|
|
202
|
+
type: 'string',
|
|
203
|
+
description: 'Optional chat name/topic. If omitted, Teams shows member names.',
|
|
204
|
+
},
|
|
205
|
+
},
|
|
206
|
+
required: ['userIds'],
|
|
207
|
+
},
|
|
208
|
+
};
|
|
209
|
+
const editMessageToolDefinition = {
|
|
210
|
+
name: 'teams_edit_message',
|
|
211
|
+
description: 'Edit one of your own messages. You can only edit messages you sent. The API will reject attempts to edit other users\' messages.',
|
|
212
|
+
inputSchema: {
|
|
213
|
+
type: 'object',
|
|
214
|
+
properties: {
|
|
215
|
+
conversationId: {
|
|
216
|
+
type: 'string',
|
|
217
|
+
description: 'The conversation ID containing the message',
|
|
218
|
+
},
|
|
219
|
+
messageId: {
|
|
220
|
+
type: 'string',
|
|
221
|
+
description: 'The message ID to edit. Use: serverMessageId from teams_send_message, id from teams_get_thread, or messageId from teams_search.',
|
|
222
|
+
},
|
|
223
|
+
content: {
|
|
224
|
+
type: 'string',
|
|
225
|
+
description: 'The new content for the message. Can include basic HTML formatting.',
|
|
226
|
+
},
|
|
227
|
+
},
|
|
228
|
+
required: ['conversationId', 'messageId', 'content'],
|
|
229
|
+
},
|
|
230
|
+
};
|
|
231
|
+
const deleteMessageToolDefinition = {
|
|
232
|
+
name: 'teams_delete_message',
|
|
233
|
+
description: 'Delete one of your own messages (soft delete - the message remains but content becomes empty). You can only delete messages you sent, unless you are a channel owner/moderator.',
|
|
234
|
+
inputSchema: {
|
|
235
|
+
type: 'object',
|
|
236
|
+
properties: {
|
|
237
|
+
conversationId: {
|
|
238
|
+
type: 'string',
|
|
239
|
+
description: 'The conversation ID containing the message',
|
|
240
|
+
},
|
|
241
|
+
messageId: {
|
|
242
|
+
type: 'string',
|
|
243
|
+
description: 'The message ID to delete. Use: serverMessageId from teams_send_message, id from teams_get_thread, or messageId from teams_search.',
|
|
244
|
+
},
|
|
245
|
+
},
|
|
246
|
+
required: ['conversationId', 'messageId'],
|
|
247
|
+
},
|
|
248
|
+
};
|
|
249
|
+
const getUnreadToolDefinition = {
|
|
250
|
+
name: 'teams_get_unread',
|
|
251
|
+
description: 'Get unread message status. Without parameters, returns aggregate unread counts across all favourite/pinned conversations. With a conversationId, returns unread status for that specific conversation.',
|
|
252
|
+
inputSchema: {
|
|
253
|
+
type: 'object',
|
|
254
|
+
properties: {
|
|
255
|
+
conversationId: {
|
|
256
|
+
type: 'string',
|
|
257
|
+
description: 'Optional. A specific conversation ID to check. If omitted, checks all favourites.',
|
|
258
|
+
},
|
|
259
|
+
},
|
|
260
|
+
},
|
|
261
|
+
};
|
|
262
|
+
const markAsReadToolDefinition = {
|
|
263
|
+
name: 'teams_mark_read',
|
|
264
|
+
description: 'Mark a conversation as read up to a specific message. This updates your read position so messages up to (and including) the specified message are marked as read.',
|
|
265
|
+
inputSchema: {
|
|
266
|
+
type: 'object',
|
|
267
|
+
properties: {
|
|
268
|
+
conversationId: {
|
|
269
|
+
type: 'string',
|
|
270
|
+
description: 'The conversation ID to mark as read',
|
|
271
|
+
},
|
|
272
|
+
messageId: {
|
|
273
|
+
type: 'string',
|
|
274
|
+
description: 'The message ID to mark as read up to (all messages up to this point will be marked read)',
|
|
275
|
+
},
|
|
276
|
+
},
|
|
277
|
+
required: ['conversationId', 'messageId'],
|
|
278
|
+
},
|
|
279
|
+
};
|
|
280
|
+
const getActivityToolDefinition = {
|
|
281
|
+
name: 'teams_get_activity',
|
|
282
|
+
description: 'Get the user\'s activity feed - mentions, reactions, replies, and other notifications. Returns recent activity items with sender, content, and source conversation context.',
|
|
283
|
+
inputSchema: {
|
|
284
|
+
type: 'object',
|
|
285
|
+
properties: {
|
|
286
|
+
limit: {
|
|
287
|
+
type: 'number',
|
|
288
|
+
description: 'Maximum number of activity items to return (default: 50, max: 200)',
|
|
289
|
+
},
|
|
290
|
+
},
|
|
291
|
+
},
|
|
292
|
+
};
|
|
293
|
+
const searchEmojiToolDefinition = {
|
|
294
|
+
name: 'teams_search_emoji',
|
|
295
|
+
description: 'Search for emojis by name or keyword. Returns both standard Teams emojis and custom organisation emojis, indicating which is which. Use the returned key with teams_add_reaction.',
|
|
296
|
+
inputSchema: {
|
|
297
|
+
type: 'object',
|
|
298
|
+
properties: {
|
|
299
|
+
query: {
|
|
300
|
+
type: 'string',
|
|
301
|
+
description: 'Search term (e.g., "thumbs", "heart", "laugh", "cat")',
|
|
302
|
+
},
|
|
303
|
+
},
|
|
304
|
+
required: ['query'],
|
|
305
|
+
},
|
|
306
|
+
};
|
|
307
|
+
const addReactionToolDefinition = {
|
|
308
|
+
name: 'teams_add_reaction',
|
|
309
|
+
description: 'Add an emoji reaction to a message. Common reactions: like (👍), heart (❤️), laugh (😂), surprised (😮), sad (😢), angry (😠). Use teams_search_emoji to find other emojis.',
|
|
310
|
+
inputSchema: {
|
|
311
|
+
type: 'object',
|
|
312
|
+
properties: {
|
|
313
|
+
conversationId: {
|
|
314
|
+
type: 'string',
|
|
315
|
+
description: 'The conversation ID containing the message',
|
|
316
|
+
},
|
|
317
|
+
messageId: {
|
|
318
|
+
type: 'string',
|
|
319
|
+
description: 'The message ID to react to. Use: serverMessageId from teams_send_message, id from teams_get_thread, or messageId from teams_search. NOT the messageId from teams_send_message (that is client-generated and will fail).',
|
|
320
|
+
},
|
|
321
|
+
emoji: {
|
|
322
|
+
type: 'string',
|
|
323
|
+
description: 'The emoji key (e.g., "like", "heart", "laugh"). Get from teams_search_emoji or use common ones directly.',
|
|
324
|
+
},
|
|
325
|
+
},
|
|
326
|
+
required: ['conversationId', 'messageId', 'emoji'],
|
|
327
|
+
},
|
|
328
|
+
};
|
|
329
|
+
const removeReactionToolDefinition = {
|
|
330
|
+
name: 'teams_remove_reaction',
|
|
331
|
+
description: 'Remove an emoji reaction from a message.',
|
|
332
|
+
inputSchema: {
|
|
333
|
+
type: 'object',
|
|
334
|
+
properties: {
|
|
335
|
+
conversationId: {
|
|
336
|
+
type: 'string',
|
|
337
|
+
description: 'The conversation ID containing the message',
|
|
338
|
+
},
|
|
339
|
+
messageId: {
|
|
340
|
+
type: 'string',
|
|
341
|
+
description: 'The message ID to remove the reaction from. Use: serverMessageId from teams_send_message, id from teams_get_thread, or messageId from teams_search.',
|
|
342
|
+
},
|
|
343
|
+
emoji: {
|
|
344
|
+
type: 'string',
|
|
345
|
+
description: 'The emoji key to remove (e.g., "like", "heart")',
|
|
346
|
+
},
|
|
347
|
+
},
|
|
348
|
+
required: ['conversationId', 'messageId', 'emoji'],
|
|
349
|
+
},
|
|
350
|
+
};
|
|
351
|
+
const getSavedMessagesToolDefinition = {
|
|
352
|
+
name: 'teams_get_saved_messages',
|
|
353
|
+
description: 'Get the list of messages the user has saved (bookmarked) in Teams. Returns references to saved messages with source conversation IDs and direct links. Use teams_get_thread with the sourceConversationId to fetch actual message content.',
|
|
354
|
+
inputSchema: {
|
|
355
|
+
type: 'object',
|
|
356
|
+
properties: {
|
|
357
|
+
limit: {
|
|
358
|
+
type: 'number',
|
|
359
|
+
description: 'Maximum number of saved messages to return (default: 50, max: 200)',
|
|
360
|
+
},
|
|
361
|
+
},
|
|
362
|
+
},
|
|
363
|
+
};
|
|
364
|
+
const getFollowedThreadsToolDefinition = {
|
|
365
|
+
name: 'teams_get_followed_threads',
|
|
366
|
+
description: 'Get the list of threads the user is following in Teams. Returns references to followed threads with source conversation IDs and direct links. Use teams_get_thread with the sourceConversationId to fetch actual thread content.',
|
|
367
|
+
inputSchema: {
|
|
368
|
+
type: 'object',
|
|
369
|
+
properties: {
|
|
370
|
+
limit: {
|
|
371
|
+
type: 'number',
|
|
372
|
+
description: 'Maximum number of followed threads to return (default: 50, max: 200)',
|
|
373
|
+
},
|
|
374
|
+
},
|
|
375
|
+
},
|
|
376
|
+
};
|
|
377
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
378
|
+
// Handlers
|
|
379
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
380
|
+
async function handleSendMessage(input, _ctx) {
|
|
381
|
+
const result = await sendMessage(input.conversationId, input.content, {
|
|
382
|
+
replyToMessageId: input.replyToMessageId,
|
|
383
|
+
});
|
|
384
|
+
if (!result.ok) {
|
|
385
|
+
return { success: false, error: result.error };
|
|
386
|
+
}
|
|
387
|
+
// The timestamp is the server-assigned ID - use this for reactions, threading, edits, etc.
|
|
388
|
+
const serverMessageId = result.value.timestamp ? String(result.value.timestamp) : undefined;
|
|
389
|
+
const response = {
|
|
390
|
+
messageId: result.value.messageId,
|
|
391
|
+
timestamp: result.value.timestamp,
|
|
392
|
+
conversationId: input.conversationId,
|
|
393
|
+
};
|
|
394
|
+
// Always include serverMessageId - this is the ID to use for reactions, edits, etc.
|
|
395
|
+
if (serverMessageId) {
|
|
396
|
+
response.serverMessageId = serverMessageId;
|
|
397
|
+
}
|
|
398
|
+
// Include replyToMessageId in response if this was a thread reply
|
|
399
|
+
if (input.replyToMessageId) {
|
|
400
|
+
response.replyToMessageId = input.replyToMessageId;
|
|
401
|
+
response.note = 'Message posted as a reply to the thread. Use serverMessageId (not messageId) for reactions, edits, or threading.';
|
|
402
|
+
}
|
|
403
|
+
else if (serverMessageId) {
|
|
404
|
+
response.note = 'Use serverMessageId (not messageId) for reactions, edits, or threading.';
|
|
405
|
+
}
|
|
406
|
+
return { success: true, data: response };
|
|
407
|
+
}
|
|
408
|
+
async function handleGetFavorites(_input, _ctx) {
|
|
409
|
+
const result = await getFavorites();
|
|
410
|
+
if (!result.ok) {
|
|
411
|
+
return { success: false, error: result.error };
|
|
412
|
+
}
|
|
413
|
+
return {
|
|
414
|
+
success: true,
|
|
415
|
+
data: {
|
|
416
|
+
count: result.value.favorites.length,
|
|
417
|
+
favorites: result.value.favorites,
|
|
418
|
+
},
|
|
419
|
+
};
|
|
420
|
+
}
|
|
421
|
+
async function handleAddFavorite(input, _ctx) {
|
|
422
|
+
const result = await addFavorite(input.conversationId);
|
|
423
|
+
if (!result.ok) {
|
|
424
|
+
return { success: false, error: result.error };
|
|
425
|
+
}
|
|
426
|
+
return {
|
|
427
|
+
success: true,
|
|
428
|
+
data: {
|
|
429
|
+
message: `Added ${input.conversationId} to favourites`,
|
|
430
|
+
},
|
|
431
|
+
};
|
|
432
|
+
}
|
|
433
|
+
async function handleRemoveFavorite(input, _ctx) {
|
|
434
|
+
const result = await removeFavorite(input.conversationId);
|
|
435
|
+
if (!result.ok) {
|
|
436
|
+
return { success: false, error: result.error };
|
|
437
|
+
}
|
|
438
|
+
return {
|
|
439
|
+
success: true,
|
|
440
|
+
data: {
|
|
441
|
+
message: `Removed ${input.conversationId} from favourites`,
|
|
442
|
+
},
|
|
443
|
+
};
|
|
444
|
+
}
|
|
445
|
+
async function handleSaveMessage(input, _ctx) {
|
|
446
|
+
const result = await saveMessage(input.conversationId, input.messageId, input.rootMessageId);
|
|
447
|
+
if (!result.ok) {
|
|
448
|
+
return { success: false, error: result.error };
|
|
449
|
+
}
|
|
450
|
+
return {
|
|
451
|
+
success: true,
|
|
452
|
+
data: {
|
|
453
|
+
message: 'Message saved',
|
|
454
|
+
conversationId: input.conversationId,
|
|
455
|
+
messageId: input.messageId,
|
|
456
|
+
},
|
|
457
|
+
};
|
|
458
|
+
}
|
|
459
|
+
async function handleUnsaveMessage(input, _ctx) {
|
|
460
|
+
const result = await unsaveMessage(input.conversationId, input.messageId, input.rootMessageId);
|
|
461
|
+
if (!result.ok) {
|
|
462
|
+
return { success: false, error: result.error };
|
|
463
|
+
}
|
|
464
|
+
return {
|
|
465
|
+
success: true,
|
|
466
|
+
data: {
|
|
467
|
+
message: 'Message unsaved',
|
|
468
|
+
conversationId: input.conversationId,
|
|
469
|
+
messageId: input.messageId,
|
|
470
|
+
},
|
|
471
|
+
};
|
|
472
|
+
}
|
|
473
|
+
async function handleGetChat(input, _ctx) {
|
|
474
|
+
const result = getOneOnOneChatId(input.userId);
|
|
475
|
+
if (!result.ok) {
|
|
476
|
+
return { success: false, error: result.error };
|
|
477
|
+
}
|
|
478
|
+
return {
|
|
479
|
+
success: true,
|
|
480
|
+
data: {
|
|
481
|
+
conversationId: result.value.conversationId,
|
|
482
|
+
otherUserId: result.value.otherUserId,
|
|
483
|
+
currentUserId: result.value.currentUserId,
|
|
484
|
+
note: 'Use this conversationId with teams_send_message to send a message. The conversation is created automatically when the first message is sent.',
|
|
485
|
+
},
|
|
486
|
+
};
|
|
487
|
+
}
|
|
488
|
+
async function handleCreateGroupChat(input, _ctx) {
|
|
489
|
+
const result = await createGroupChat(input.userIds, input.topic);
|
|
490
|
+
if (!result.ok) {
|
|
491
|
+
return { success: false, error: result.error };
|
|
492
|
+
}
|
|
493
|
+
return {
|
|
494
|
+
success: true,
|
|
495
|
+
data: {
|
|
496
|
+
conversationId: result.value.conversationId,
|
|
497
|
+
members: result.value.members,
|
|
498
|
+
topic: result.value.topic,
|
|
499
|
+
note: 'Use this conversationId with teams_send_message to send messages to the group.',
|
|
500
|
+
},
|
|
501
|
+
};
|
|
502
|
+
}
|
|
503
|
+
async function handleEditMessage(input, _ctx) {
|
|
504
|
+
const result = await editMessage(input.conversationId, input.messageId, input.content);
|
|
505
|
+
if (!result.ok) {
|
|
506
|
+
return { success: false, error: result.error };
|
|
507
|
+
}
|
|
508
|
+
return {
|
|
509
|
+
success: true,
|
|
510
|
+
data: {
|
|
511
|
+
message: 'Message edited successfully',
|
|
512
|
+
conversationId: result.value.conversationId,
|
|
513
|
+
messageId: result.value.messageId,
|
|
514
|
+
},
|
|
515
|
+
};
|
|
516
|
+
}
|
|
517
|
+
async function handleDeleteMessage(input, _ctx) {
|
|
518
|
+
const result = await deleteMessage(input.conversationId, input.messageId);
|
|
519
|
+
if (!result.ok) {
|
|
520
|
+
return { success: false, error: result.error };
|
|
521
|
+
}
|
|
522
|
+
return {
|
|
523
|
+
success: true,
|
|
524
|
+
data: {
|
|
525
|
+
message: 'Message deleted successfully',
|
|
526
|
+
conversationId: result.value.conversationId,
|
|
527
|
+
messageId: result.value.messageId,
|
|
528
|
+
},
|
|
529
|
+
};
|
|
530
|
+
}
|
|
531
|
+
async function handleGetUnread(input, _ctx) {
|
|
532
|
+
// If a specific conversation is provided, just check that one
|
|
533
|
+
if (input.conversationId) {
|
|
534
|
+
const result = await getUnreadStatus(input.conversationId);
|
|
535
|
+
if (!result.ok) {
|
|
536
|
+
return { success: false, error: result.error };
|
|
537
|
+
}
|
|
538
|
+
return {
|
|
539
|
+
success: true,
|
|
540
|
+
data: {
|
|
541
|
+
conversationId: result.value.conversationId,
|
|
542
|
+
unreadCount: result.value.unreadCount,
|
|
543
|
+
lastReadMessageId: result.value.lastReadMessageId,
|
|
544
|
+
latestMessageId: result.value.latestMessageId,
|
|
545
|
+
},
|
|
546
|
+
};
|
|
547
|
+
}
|
|
548
|
+
// Aggregate mode: check all favourites
|
|
549
|
+
const favResult = await getFavorites();
|
|
550
|
+
if (!favResult.ok) {
|
|
551
|
+
return { success: false, error: favResult.error };
|
|
552
|
+
}
|
|
553
|
+
const favorites = favResult.value.favorites;
|
|
554
|
+
const conversations = [];
|
|
555
|
+
let totalUnread = 0;
|
|
556
|
+
let checkedCount = 0;
|
|
557
|
+
let errorCount = 0;
|
|
558
|
+
// Check unread status for each favourite (limit to prevent timeout)
|
|
559
|
+
const maxToCheck = MAX_UNREAD_AGGREGATE_CHECK;
|
|
560
|
+
for (const fav of favorites.slice(0, maxToCheck)) {
|
|
561
|
+
const unreadResult = await getUnreadStatus(fav.conversationId);
|
|
562
|
+
checkedCount++;
|
|
563
|
+
if (unreadResult.ok) {
|
|
564
|
+
if (unreadResult.value.unreadCount > 0) {
|
|
565
|
+
conversations.push({
|
|
566
|
+
conversationId: fav.conversationId,
|
|
567
|
+
displayName: fav.displayName,
|
|
568
|
+
conversationType: fav.conversationType,
|
|
569
|
+
unreadCount: unreadResult.value.unreadCount,
|
|
570
|
+
});
|
|
571
|
+
totalUnread += unreadResult.value.unreadCount;
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
else {
|
|
575
|
+
errorCount++;
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
// If all checks failed, return an error rather than misleading success
|
|
579
|
+
if (checkedCount > 0 && errorCount === checkedCount) {
|
|
580
|
+
return {
|
|
581
|
+
success: false,
|
|
582
|
+
error: {
|
|
583
|
+
code: ErrorCode.API_ERROR,
|
|
584
|
+
message: `Failed to check unread status for all ${checkedCount} favourites`,
|
|
585
|
+
retryable: true,
|
|
586
|
+
suggestions: ['Check authentication status with teams_status', 'Try teams_login to refresh session'],
|
|
587
|
+
},
|
|
588
|
+
};
|
|
589
|
+
}
|
|
590
|
+
return {
|
|
591
|
+
success: true,
|
|
592
|
+
data: {
|
|
593
|
+
totalUnread,
|
|
594
|
+
conversationsWithUnread: conversations.length,
|
|
595
|
+
conversations,
|
|
596
|
+
checked: checkedCount,
|
|
597
|
+
totalFavorites: favorites.length,
|
|
598
|
+
errors: errorCount > 0 ? errorCount : undefined,
|
|
599
|
+
note: favorites.length > maxToCheck
|
|
600
|
+
? `Checked first ${maxToCheck} of ${favorites.length} favourites`
|
|
601
|
+
: undefined,
|
|
602
|
+
},
|
|
603
|
+
};
|
|
604
|
+
}
|
|
605
|
+
async function handleMarkAsRead(input, _ctx) {
|
|
606
|
+
const result = await markAsRead(input.conversationId, input.messageId);
|
|
607
|
+
if (!result.ok) {
|
|
608
|
+
return { success: false, error: result.error };
|
|
609
|
+
}
|
|
610
|
+
return {
|
|
611
|
+
success: true,
|
|
612
|
+
data: {
|
|
613
|
+
message: 'Conversation marked as read',
|
|
614
|
+
conversationId: result.value.conversationId,
|
|
615
|
+
markedUpTo: result.value.markedUpTo,
|
|
616
|
+
},
|
|
617
|
+
};
|
|
618
|
+
}
|
|
619
|
+
async function handleGetActivity(input, _ctx) {
|
|
620
|
+
const result = await getActivityFeed({ limit: input.limit });
|
|
621
|
+
if (!result.ok) {
|
|
622
|
+
return { success: false, error: result.error };
|
|
623
|
+
}
|
|
624
|
+
return {
|
|
625
|
+
success: true,
|
|
626
|
+
data: {
|
|
627
|
+
count: result.value.activities.length,
|
|
628
|
+
activities: result.value.activities,
|
|
629
|
+
syncState: result.value.syncState,
|
|
630
|
+
},
|
|
631
|
+
};
|
|
632
|
+
}
|
|
633
|
+
async function handleSearchEmoji(input, _ctx) {
|
|
634
|
+
const query = input.query.toLowerCase();
|
|
635
|
+
// Search standard emojis
|
|
636
|
+
const standardMatches = STANDARD_EMOJIS.filter(emoji => emoji.key.toLowerCase().includes(query) ||
|
|
637
|
+
emoji.description.toLowerCase().includes(query)).map(emoji => ({
|
|
638
|
+
key: emoji.key,
|
|
639
|
+
description: emoji.description,
|
|
640
|
+
type: 'standard',
|
|
641
|
+
category: emoji.category,
|
|
642
|
+
}));
|
|
643
|
+
// Try to get custom emojis
|
|
644
|
+
let customMatches = [];
|
|
645
|
+
const customResult = await getCustomEmojis();
|
|
646
|
+
if (customResult.ok) {
|
|
647
|
+
customMatches = customResult.value.emojis
|
|
648
|
+
.filter(emoji => emoji.shortcut.toLowerCase().includes(query) ||
|
|
649
|
+
emoji.description.toLowerCase().includes(query))
|
|
650
|
+
.map(emoji => ({
|
|
651
|
+
key: emoji.id,
|
|
652
|
+
description: emoji.description,
|
|
653
|
+
type: 'custom',
|
|
654
|
+
shortcut: emoji.shortcut,
|
|
655
|
+
}));
|
|
656
|
+
}
|
|
657
|
+
// Combine results, standard first
|
|
658
|
+
const results = [...standardMatches, ...customMatches];
|
|
659
|
+
return {
|
|
660
|
+
success: true,
|
|
661
|
+
data: {
|
|
662
|
+
query: input.query,
|
|
663
|
+
count: results.length,
|
|
664
|
+
emojis: results,
|
|
665
|
+
note: results.length === 0
|
|
666
|
+
? 'No emojis found. Try a different search term.'
|
|
667
|
+
: 'Use the "key" value with teams_add_reaction.',
|
|
668
|
+
},
|
|
669
|
+
};
|
|
670
|
+
}
|
|
671
|
+
async function handleAddReaction(input, _ctx) {
|
|
672
|
+
const result = await addReaction(input.conversationId, input.messageId, input.emoji);
|
|
673
|
+
if (!result.ok) {
|
|
674
|
+
return { success: false, error: result.error };
|
|
675
|
+
}
|
|
676
|
+
return {
|
|
677
|
+
success: true,
|
|
678
|
+
data: {
|
|
679
|
+
message: `Added ${input.emoji} reaction`,
|
|
680
|
+
conversationId: result.value.conversationId,
|
|
681
|
+
messageId: result.value.messageId,
|
|
682
|
+
emoji: result.value.emoji,
|
|
683
|
+
},
|
|
684
|
+
};
|
|
685
|
+
}
|
|
686
|
+
async function handleRemoveReaction(input, _ctx) {
|
|
687
|
+
const result = await removeReaction(input.conversationId, input.messageId, input.emoji);
|
|
688
|
+
if (!result.ok) {
|
|
689
|
+
return { success: false, error: result.error };
|
|
690
|
+
}
|
|
691
|
+
return {
|
|
692
|
+
success: true,
|
|
693
|
+
data: {
|
|
694
|
+
message: `Removed ${input.emoji} reaction`,
|
|
695
|
+
conversationId: result.value.conversationId,
|
|
696
|
+
messageId: result.value.messageId,
|
|
697
|
+
emoji: result.value.emoji,
|
|
698
|
+
},
|
|
699
|
+
};
|
|
700
|
+
}
|
|
701
|
+
async function handleGetSavedMessages(input, _ctx) {
|
|
702
|
+
const result = await getSavedMessages({ limit: input.limit });
|
|
703
|
+
if (!result.ok) {
|
|
704
|
+
return { success: false, error: result.error };
|
|
705
|
+
}
|
|
706
|
+
return {
|
|
707
|
+
success: true,
|
|
708
|
+
data: {
|
|
709
|
+
count: result.value.messages.length,
|
|
710
|
+
messages: result.value.messages.map(msg => ({
|
|
711
|
+
content: msg.content,
|
|
712
|
+
contentType: msg.contentType,
|
|
713
|
+
sender: msg.sender,
|
|
714
|
+
timestamp: msg.timestamp,
|
|
715
|
+
sourceConversationId: msg.sourceConversationId,
|
|
716
|
+
sourceMessageId: msg.sourceMessageId,
|
|
717
|
+
messageLink: msg.messageLink,
|
|
718
|
+
})),
|
|
719
|
+
},
|
|
720
|
+
};
|
|
721
|
+
}
|
|
722
|
+
async function handleGetFollowedThreads(input, _ctx) {
|
|
723
|
+
const result = await getFollowedThreads({ limit: input.limit });
|
|
724
|
+
if (!result.ok) {
|
|
725
|
+
return { success: false, error: result.error };
|
|
726
|
+
}
|
|
727
|
+
return {
|
|
728
|
+
success: true,
|
|
729
|
+
data: {
|
|
730
|
+
count: result.value.threads.length,
|
|
731
|
+
threads: result.value.threads.map(thread => ({
|
|
732
|
+
content: thread.content,
|
|
733
|
+
contentType: thread.contentType,
|
|
734
|
+
sender: thread.sender,
|
|
735
|
+
timestamp: thread.timestamp,
|
|
736
|
+
sourceConversationId: thread.sourceConversationId,
|
|
737
|
+
sourcePostId: thread.sourcePostId,
|
|
738
|
+
messageLink: thread.messageLink,
|
|
739
|
+
})),
|
|
740
|
+
},
|
|
741
|
+
};
|
|
742
|
+
}
|
|
743
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
744
|
+
// Exports
|
|
745
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
746
|
+
export const sendMessageTool = {
|
|
747
|
+
definition: sendMessageToolDefinition,
|
|
748
|
+
schema: SendMessageInputSchema,
|
|
749
|
+
handler: handleSendMessage,
|
|
750
|
+
};
|
|
751
|
+
export const getFavoritesTool = {
|
|
752
|
+
definition: getFavoritesToolDefinition,
|
|
753
|
+
schema: z.object({}),
|
|
754
|
+
handler: handleGetFavorites,
|
|
755
|
+
};
|
|
756
|
+
export const addFavoriteTool = {
|
|
757
|
+
definition: addFavoriteToolDefinition,
|
|
758
|
+
schema: FavoriteInputSchema,
|
|
759
|
+
handler: handleAddFavorite,
|
|
760
|
+
};
|
|
761
|
+
export const removeFavoriteTool = {
|
|
762
|
+
definition: removeFavoriteToolDefinition,
|
|
763
|
+
schema: FavoriteInputSchema,
|
|
764
|
+
handler: handleRemoveFavorite,
|
|
765
|
+
};
|
|
766
|
+
export const saveMessageTool = {
|
|
767
|
+
definition: saveMessageToolDefinition,
|
|
768
|
+
schema: SaveMessageInputSchema,
|
|
769
|
+
handler: handleSaveMessage,
|
|
770
|
+
};
|
|
771
|
+
export const unsaveMessageTool = {
|
|
772
|
+
definition: unsaveMessageToolDefinition,
|
|
773
|
+
schema: SaveMessageInputSchema,
|
|
774
|
+
handler: handleUnsaveMessage,
|
|
775
|
+
};
|
|
776
|
+
export const getChatTool = {
|
|
777
|
+
definition: getChatToolDefinition,
|
|
778
|
+
schema: GetChatInputSchema,
|
|
779
|
+
handler: handleGetChat,
|
|
780
|
+
};
|
|
781
|
+
export const createGroupChatTool = {
|
|
782
|
+
definition: createGroupChatToolDefinition,
|
|
783
|
+
schema: CreateGroupChatInputSchema,
|
|
784
|
+
handler: handleCreateGroupChat,
|
|
785
|
+
};
|
|
786
|
+
export const editMessageTool = {
|
|
787
|
+
definition: editMessageToolDefinition,
|
|
788
|
+
schema: EditMessageInputSchema,
|
|
789
|
+
handler: handleEditMessage,
|
|
790
|
+
};
|
|
791
|
+
export const deleteMessageTool = {
|
|
792
|
+
definition: deleteMessageToolDefinition,
|
|
793
|
+
schema: DeleteMessageInputSchema,
|
|
794
|
+
handler: handleDeleteMessage,
|
|
795
|
+
};
|
|
796
|
+
export const getUnreadTool = {
|
|
797
|
+
definition: getUnreadToolDefinition,
|
|
798
|
+
schema: GetUnreadInputSchema,
|
|
799
|
+
handler: handleGetUnread,
|
|
800
|
+
};
|
|
801
|
+
export const markAsReadTool = {
|
|
802
|
+
definition: markAsReadToolDefinition,
|
|
803
|
+
schema: MarkAsReadInputSchema,
|
|
804
|
+
handler: handleMarkAsRead,
|
|
805
|
+
};
|
|
806
|
+
export const getActivityTool = {
|
|
807
|
+
definition: getActivityToolDefinition,
|
|
808
|
+
schema: GetActivityInputSchema,
|
|
809
|
+
handler: handleGetActivity,
|
|
810
|
+
};
|
|
811
|
+
export const searchEmojiTool = {
|
|
812
|
+
definition: searchEmojiToolDefinition,
|
|
813
|
+
schema: SearchEmojiInputSchema,
|
|
814
|
+
handler: handleSearchEmoji,
|
|
815
|
+
};
|
|
816
|
+
export const addReactionTool = {
|
|
817
|
+
definition: addReactionToolDefinition,
|
|
818
|
+
schema: AddReactionInputSchema,
|
|
819
|
+
handler: handleAddReaction,
|
|
820
|
+
};
|
|
821
|
+
export const removeReactionTool = {
|
|
822
|
+
definition: removeReactionToolDefinition,
|
|
823
|
+
schema: RemoveReactionInputSchema,
|
|
824
|
+
handler: handleRemoveReaction,
|
|
825
|
+
};
|
|
826
|
+
export const getSavedMessagesTool = {
|
|
827
|
+
definition: getSavedMessagesToolDefinition,
|
|
828
|
+
schema: GetSavedMessagesInputSchema,
|
|
829
|
+
handler: handleGetSavedMessages,
|
|
830
|
+
};
|
|
831
|
+
export const getFollowedThreadsTool = {
|
|
832
|
+
definition: getFollowedThreadsToolDefinition,
|
|
833
|
+
schema: GetFollowedThreadsInputSchema,
|
|
834
|
+
handler: handleGetFollowedThreads,
|
|
835
|
+
};
|
|
836
|
+
/** All message-related tools. */
|
|
837
|
+
export const messageTools = [
|
|
838
|
+
sendMessageTool,
|
|
839
|
+
getFavoritesTool,
|
|
840
|
+
addFavoriteTool,
|
|
841
|
+
removeFavoriteTool,
|
|
842
|
+
saveMessageTool,
|
|
843
|
+
unsaveMessageTool,
|
|
844
|
+
getChatTool,
|
|
845
|
+
createGroupChatTool,
|
|
846
|
+
editMessageTool,
|
|
847
|
+
deleteMessageTool,
|
|
848
|
+
getUnreadTool,
|
|
849
|
+
markAsReadTool,
|
|
850
|
+
getActivityTool,
|
|
851
|
+
searchEmojiTool,
|
|
852
|
+
addReactionTool,
|
|
853
|
+
removeReactionTool,
|
|
854
|
+
getSavedMessagesTool,
|
|
855
|
+
getFollowedThreadsTool,
|
|
856
|
+
];
|