msteams-mcp 0.2.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.
Files changed (80) hide show
  1. package/README.md +229 -0
  2. package/dist/__fixtures__/api-responses.d.ts +228 -0
  3. package/dist/__fixtures__/api-responses.js +217 -0
  4. package/dist/api/chatsvc-api.d.ts +171 -0
  5. package/dist/api/chatsvc-api.js +459 -0
  6. package/dist/api/csa-api.d.ts +44 -0
  7. package/dist/api/csa-api.js +148 -0
  8. package/dist/api/index.d.ts +6 -0
  9. package/dist/api/index.js +6 -0
  10. package/dist/api/substrate-api.d.ts +50 -0
  11. package/dist/api/substrate-api.js +305 -0
  12. package/dist/auth/crypto.d.ts +32 -0
  13. package/dist/auth/crypto.js +66 -0
  14. package/dist/auth/index.d.ts +6 -0
  15. package/dist/auth/index.js +6 -0
  16. package/dist/auth/session-store.d.ts +82 -0
  17. package/dist/auth/session-store.js +136 -0
  18. package/dist/auth/token-extractor.d.ts +69 -0
  19. package/dist/auth/token-extractor.js +330 -0
  20. package/dist/browser/auth.d.ts +43 -0
  21. package/dist/browser/auth.js +232 -0
  22. package/dist/browser/context.d.ts +40 -0
  23. package/dist/browser/context.js +121 -0
  24. package/dist/browser/session.d.ts +34 -0
  25. package/dist/browser/session.js +92 -0
  26. package/dist/constants.d.ts +54 -0
  27. package/dist/constants.js +72 -0
  28. package/dist/index.d.ts +8 -0
  29. package/dist/index.js +12 -0
  30. package/dist/research/explore.d.ts +11 -0
  31. package/dist/research/explore.js +267 -0
  32. package/dist/research/search-research.d.ts +17 -0
  33. package/dist/research/search-research.js +317 -0
  34. package/dist/server.d.ts +64 -0
  35. package/dist/server.js +291 -0
  36. package/dist/teams/api-interceptor.d.ts +54 -0
  37. package/dist/teams/api-interceptor.js +391 -0
  38. package/dist/teams/direct-api.d.ts +321 -0
  39. package/dist/teams/direct-api.js +1305 -0
  40. package/dist/teams/messages.d.ts +14 -0
  41. package/dist/teams/messages.js +142 -0
  42. package/dist/teams/search.d.ts +40 -0
  43. package/dist/teams/search.js +458 -0
  44. package/dist/test/cli.d.ts +12 -0
  45. package/dist/test/cli.js +328 -0
  46. package/dist/test/debug-search.d.ts +10 -0
  47. package/dist/test/debug-search.js +147 -0
  48. package/dist/test/manual-test.d.ts +11 -0
  49. package/dist/test/manual-test.js +160 -0
  50. package/dist/test/mcp-harness.d.ts +17 -0
  51. package/dist/test/mcp-harness.js +427 -0
  52. package/dist/tools/auth-tools.d.ts +26 -0
  53. package/dist/tools/auth-tools.js +127 -0
  54. package/dist/tools/index.d.ts +45 -0
  55. package/dist/tools/index.js +12 -0
  56. package/dist/tools/message-tools.d.ts +139 -0
  57. package/dist/tools/message-tools.js +433 -0
  58. package/dist/tools/people-tools.d.ts +46 -0
  59. package/dist/tools/people-tools.js +123 -0
  60. package/dist/tools/registry.d.ts +23 -0
  61. package/dist/tools/registry.js +61 -0
  62. package/dist/tools/search-tools.d.ts +79 -0
  63. package/dist/tools/search-tools.js +168 -0
  64. package/dist/types/errors.d.ts +58 -0
  65. package/dist/types/errors.js +132 -0
  66. package/dist/types/result.d.ts +43 -0
  67. package/dist/types/result.js +51 -0
  68. package/dist/types/teams.d.ts +79 -0
  69. package/dist/types/teams.js +5 -0
  70. package/dist/utils/api-config.d.ts +66 -0
  71. package/dist/utils/api-config.js +113 -0
  72. package/dist/utils/auth-guards.d.ts +29 -0
  73. package/dist/utils/auth-guards.js +54 -0
  74. package/dist/utils/http.d.ts +29 -0
  75. package/dist/utils/http.js +111 -0
  76. package/dist/utils/parsers.d.ts +187 -0
  77. package/dist/utils/parsers.js +574 -0
  78. package/dist/utils/parsers.test.d.ts +7 -0
  79. package/dist/utils/parsers.test.js +360 -0
  80. package/package.json +58 -0
@@ -0,0 +1,187 @@
1
+ /**
2
+ * Pure parsing functions for Teams API responses.
3
+ *
4
+ * These functions transform raw API responses into our internal types.
5
+ * They are extracted here for testability - no side effects or external dependencies.
6
+ */
7
+ import type { TeamsSearchResult } from '../types/teams.js';
8
+ /** Person search result from Substrate suggestions API. */
9
+ export interface PersonSearchResult {
10
+ id: string;
11
+ mri: string;
12
+ displayName: string;
13
+ email?: string;
14
+ givenName?: string;
15
+ surname?: string;
16
+ jobTitle?: string;
17
+ department?: string;
18
+ companyName?: string;
19
+ }
20
+ /** User profile extracted from JWT tokens. */
21
+ export interface UserProfile {
22
+ id: string;
23
+ mri: string;
24
+ email: string;
25
+ displayName: string;
26
+ givenName?: string;
27
+ surname?: string;
28
+ tenantId?: string;
29
+ }
30
+ /**
31
+ * Strips HTML tags from content for display.
32
+ */
33
+ export declare function stripHtml(html: string): string;
34
+ /**
35
+ * Builds a deep link to open a message in Teams.
36
+ *
37
+ * Format: https://teams.microsoft.com/l/message/{conversationId}/{messageTimestamp}
38
+ *
39
+ * @param conversationId - The conversation/thread ID (e.g., "19:xxx@thread.tacv2")
40
+ * @param messageTimestamp - The message timestamp in epoch milliseconds
41
+ */
42
+ export declare function buildMessageLink(conversationId: string, messageTimestamp: string | number): string;
43
+ /**
44
+ * Extracts a timestamp-based message ID from various sources.
45
+ * Teams uses epoch milliseconds as message IDs in URLs.
46
+ *
47
+ * IMPORTANT: For channel threaded replies, the ;messageid= in ClientConversationId
48
+ * is the PARENT thread's ID, not this message's ID. We must prefer the actual
49
+ * message timestamp (DateTimeReceived/DateTimeSent) for accurate deep links.
50
+ */
51
+ export declare function extractMessageTimestamp(source: Record<string, unknown> | undefined, timestamp?: string): string | undefined;
52
+ /**
53
+ * Parses a person suggestion from the Substrate API response.
54
+ *
55
+ * The API can return IDs in various formats:
56
+ * - GUID with tenant: "ab76f827-...@tenant.onmicrosoft.com"
57
+ * - Base64-encoded GUID: "93qkaTtFGWpUHjyRafgdhg=="
58
+ */
59
+ export declare function parsePersonSuggestion(item: Record<string, unknown>): PersonSearchResult | null;
60
+ /**
61
+ * Parses a v2 query result item into a search result.
62
+ */
63
+ export declare function parseV2Result(item: Record<string, unknown>): TeamsSearchResult | null;
64
+ /**
65
+ * Parses user profile from a JWT payload.
66
+ *
67
+ * @param payload - Decoded JWT payload object
68
+ * @returns User profile or null if required fields are missing
69
+ */
70
+ export declare function parseJwtProfile(payload: Record<string, unknown>): UserProfile | null;
71
+ /**
72
+ * Calculates token expiry status from an expiry timestamp.
73
+ *
74
+ * @param expiryMs - Token expiry time in milliseconds since epoch
75
+ * @param nowMs - Current time in milliseconds (for testing)
76
+ * @returns Token status including whether it's valid and time remaining
77
+ */
78
+ export declare function calculateTokenStatus(expiryMs: number, nowMs?: number): {
79
+ isValid: boolean;
80
+ expiresAt: string;
81
+ minutesRemaining: number;
82
+ };
83
+ /**
84
+ * Parses the pagination result from a search API response.
85
+ *
86
+ * @param entitySets - Raw EntitySets array from API response
87
+ * @param from - Starting offset used in request
88
+ * @param size - Page size used in request
89
+ * @returns Parsed results and pagination metadata
90
+ */
91
+ export declare function parseSearchResults(entitySets: unknown[] | undefined, from: number, size: number): {
92
+ results: TeamsSearchResult[];
93
+ total?: number;
94
+ };
95
+ /**
96
+ * Parses people search results from the Groups/Suggestions structure.
97
+ *
98
+ * @param groups - Raw Groups array from suggestions API response
99
+ * @returns Array of parsed person results
100
+ */
101
+ export declare function parsePeopleResults(groups: unknown[] | undefined): PersonSearchResult[];
102
+ /** Channel search result from Substrate suggestions API or Teams List API. */
103
+ export interface ChannelSearchResult {
104
+ channelId: string;
105
+ channelName: string;
106
+ teamName: string;
107
+ teamId: string;
108
+ channelType: string;
109
+ description?: string;
110
+ isMember?: boolean;
111
+ }
112
+ /**
113
+ * Parses a single channel suggestion from the API response.
114
+ *
115
+ * @param suggestion - Raw suggestion object from API
116
+ * @returns Parsed channel result or null if required fields are missing
117
+ */
118
+ export declare function parseChannelSuggestion(suggestion: Record<string, unknown>): ChannelSearchResult | null;
119
+ /**
120
+ * Parses channel search results from the Groups/Suggestions structure.
121
+ *
122
+ * @param groups - Raw Groups array from suggestions API response
123
+ * @returns Array of parsed channel results
124
+ */
125
+ export declare function parseChannelResults(groups: unknown[] | undefined): ChannelSearchResult[];
126
+ /** Team with channels from the Teams List API response. */
127
+ export interface TeamWithChannels {
128
+ teamId: string;
129
+ teamName: string;
130
+ threadId: string;
131
+ description?: string;
132
+ channels: ChannelSearchResult[];
133
+ }
134
+ /**
135
+ * Parses the Teams List API response to extract all teams and channels.
136
+ *
137
+ * @param data - Raw response data from /api/csa/{region}/api/v3/teams/users/me
138
+ * @returns Array of teams with their channels
139
+ */
140
+ export declare function parseTeamsList(data: Record<string, unknown> | undefined): TeamWithChannels[];
141
+ /**
142
+ * Filters channels from the Teams List by name.
143
+ *
144
+ * @param teams - Array of teams with channels from parseTeamsList
145
+ * @param query - Search query (case-insensitive partial match)
146
+ * @returns Matching channels flattened into a single array
147
+ */
148
+ export declare function filterChannelsByName(teams: TeamWithChannels[], query: string): ChannelSearchResult[];
149
+ /**
150
+ * Decodes a base64-encoded GUID to its standard string representation.
151
+ *
152
+ * Microsoft encodes GUIDs as 16 bytes with little-endian ordering for the
153
+ * first three groups (Data1, Data2, Data3).
154
+ *
155
+ * @param base64 - Base64-encoded GUID (typically 24 chars with == padding)
156
+ * @returns The GUID string in standard format, or null if invalid
157
+ */
158
+ export declare function decodeBase64Guid(base64: string): string | null;
159
+ /**
160
+ * Extracts the Azure AD object ID (GUID) from various formats.
161
+ *
162
+ * Handles:
163
+ * - MRI format: "8:orgid:ab76f827-27e2-4c67-a765-f1a53145fa24"
164
+ * - MRI with base64: "8:orgid:93qkaTtFGWpUHjyRafgdhg=="
165
+ * - Skype ID format: "orgid:ab76f827-27e2-4c67-a765-f1a53145fa24"
166
+ * - ID with tenant: "ab76f827-27e2-4c67-a765-f1a53145fa24@56b731a8-..."
167
+ * - Raw GUID: "ab76f827-27e2-4c67-a765-f1a53145fa24"
168
+ * - Base64-encoded GUID: "93qkaTtFGWpUHjyRafgdhg=="
169
+ *
170
+ * @param identifier - User identifier in any supported format
171
+ * @returns The extracted GUID or null if invalid format
172
+ */
173
+ export declare function extractObjectId(identifier: string): string | null;
174
+ /**
175
+ * Builds a 1:1 conversation ID from two user object IDs.
176
+ *
177
+ * The conversation ID format for 1:1 chats in Teams is:
178
+ * `19:{userId1}_{userId2}@unq.gbl.spaces`
179
+ *
180
+ * The user IDs are sorted lexicographically to ensure consistency -
181
+ * both participants will generate the same conversation ID.
182
+ *
183
+ * @param userId1 - First user's object ID (GUID, MRI, or ID with tenant)
184
+ * @param userId2 - Second user's object ID (GUID, MRI, or ID with tenant)
185
+ * @returns The constructed conversation ID, or null if either ID is invalid
186
+ */
187
+ export declare function buildOneOnOneConversationId(userId1: string, userId2: string): string | null;