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,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Token refresh via headless browser.
|
|
3
|
+
*
|
|
4
|
+
* Teams uses SPA OAuth2 which restricts refresh tokens to browser-based CORS
|
|
5
|
+
* requests. We open a headless browser with saved session state, let MSAL
|
|
6
|
+
* silently refresh tokens, then save the updated state. Seamless to the user.
|
|
7
|
+
*/
|
|
8
|
+
import { TOKEN_REFRESH_THRESHOLD_MS } from '../constants.js';
|
|
9
|
+
import { ErrorCode, createError } from '../types/errors.js';
|
|
10
|
+
import { ok, err } from '../types/result.js';
|
|
11
|
+
import { extractSubstrateToken, clearTokenCache, } from './token-extractor.js';
|
|
12
|
+
import { hasSessionState, isSessionLikelyExpired, } from './session-store.js';
|
|
13
|
+
/**
|
|
14
|
+
* Refreshes tokens by opening a headless browser with saved session state.
|
|
15
|
+
* MSAL only refreshes tokens when an API call requires them, so we trigger
|
|
16
|
+
* a search via ensureAuthenticated to force token acquisition.
|
|
17
|
+
*/
|
|
18
|
+
export async function refreshTokensViaBrowser() {
|
|
19
|
+
// Check we have a session to work with
|
|
20
|
+
if (!hasSessionState()) {
|
|
21
|
+
return err(createError(ErrorCode.AUTH_REQUIRED, 'No session state available. Please run teams_login to authenticate.', { suggestions: ['Call teams_login to authenticate'] }));
|
|
22
|
+
}
|
|
23
|
+
if (isSessionLikelyExpired()) {
|
|
24
|
+
return err(createError(ErrorCode.AUTH_EXPIRED, 'Session is too old and likely expired. Please re-authenticate.', { suggestions: ['Call teams_login to re-authenticate'] }));
|
|
25
|
+
}
|
|
26
|
+
// Get current token expiry for comparison
|
|
27
|
+
const beforeToken = extractSubstrateToken();
|
|
28
|
+
if (!beforeToken) {
|
|
29
|
+
return err(createError(ErrorCode.AUTH_REQUIRED, 'No token found in session. Please run teams_login to authenticate.', { suggestions: ['Call teams_login to authenticate'] }));
|
|
30
|
+
}
|
|
31
|
+
const previousExpiry = beforeToken.expiry;
|
|
32
|
+
// Import browser functions dynamically to avoid circular dependencies
|
|
33
|
+
const { createBrowserContext, closeBrowser } = await import('../browser/context.js');
|
|
34
|
+
let manager = null;
|
|
35
|
+
try {
|
|
36
|
+
// Open headless browser with saved session
|
|
37
|
+
manager = await createBrowserContext({ headless: true });
|
|
38
|
+
// Import auth functions
|
|
39
|
+
const { ensureAuthenticated } = await import('../browser/auth.js');
|
|
40
|
+
// Use the same auth flow that works for login - this triggers token acquisition
|
|
41
|
+
// showOverlay: false since headless browser has no visible window
|
|
42
|
+
// headless: true to fail fast if user interaction is required
|
|
43
|
+
await ensureAuthenticated(manager.page, manager.context, (msg) => {
|
|
44
|
+
// Silent logging for headless refresh
|
|
45
|
+
console.log(`[token-refresh] ${msg}`);
|
|
46
|
+
}, false, true);
|
|
47
|
+
// Close browser (ensureAuthenticated already saved the session)
|
|
48
|
+
await closeBrowser(manager, false);
|
|
49
|
+
manager = null;
|
|
50
|
+
// Clear our token cache to force re-extraction from the new session
|
|
51
|
+
clearTokenCache();
|
|
52
|
+
// Extract the new token to verify we still have valid tokens
|
|
53
|
+
const afterToken = extractSubstrateToken();
|
|
54
|
+
if (!afterToken) {
|
|
55
|
+
return err(createError(ErrorCode.AUTH_EXPIRED, 'Token refresh failed - no token found after refresh attempt.', { suggestions: ['Call teams_login to re-authenticate'] }));
|
|
56
|
+
}
|
|
57
|
+
const newExpiry = afterToken.expiry;
|
|
58
|
+
const minutesGained = Math.round((newExpiry.getTime() - previousExpiry.getTime()) / 1000 / 60);
|
|
59
|
+
// Check if the token was close to expiry and needed refresh
|
|
60
|
+
const wasCloseToExpiry = previousExpiry.getTime() - Date.now() < TOKEN_REFRESH_THRESHOLD_MS;
|
|
61
|
+
// If we needed a refresh but didn't get one, that's an error
|
|
62
|
+
if (wasCloseToExpiry && newExpiry.getTime() <= previousExpiry.getTime()) {
|
|
63
|
+
return err(createError(ErrorCode.AUTH_EXPIRED, 'Token was not refreshed despite being close to expiry. Session may need re-authentication.', { suggestions: ['Call teams_login to re-authenticate'] }));
|
|
64
|
+
}
|
|
65
|
+
return ok({
|
|
66
|
+
newExpiry,
|
|
67
|
+
previousExpiry,
|
|
68
|
+
minutesGained,
|
|
69
|
+
refreshNeeded: wasCloseToExpiry,
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
catch (error) {
|
|
73
|
+
// Clean up browser if still open
|
|
74
|
+
if (manager) {
|
|
75
|
+
try {
|
|
76
|
+
await closeBrowser(manager, false);
|
|
77
|
+
}
|
|
78
|
+
catch {
|
|
79
|
+
// Ignore cleanup errors
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
83
|
+
return err(createError(ErrorCode.UNKNOWN, `Token refresh via browser failed: ${message}`, { suggestions: ['Call teams_login to re-authenticate'] }));
|
|
84
|
+
}
|
|
85
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Authentication handling for Microsoft Teams.
|
|
3
|
+
* Manages login detection and manual authentication flows.
|
|
4
|
+
*/
|
|
5
|
+
import type { Page, BrowserContext } from 'playwright';
|
|
6
|
+
export interface AuthStatus {
|
|
7
|
+
isAuthenticated: boolean;
|
|
8
|
+
isOnLoginPage: boolean;
|
|
9
|
+
currentUrl: string;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Gets the current authentication status.
|
|
13
|
+
*/
|
|
14
|
+
export declare function getAuthStatus(page: Page): Promise<AuthStatus>;
|
|
15
|
+
/**
|
|
16
|
+
* Navigates to Teams and checks authentication status.
|
|
17
|
+
*
|
|
18
|
+
* Uses a fast redirect-based detection: if we're not redirected to a login
|
|
19
|
+
* page within a few seconds, the session is valid. This is much faster than
|
|
20
|
+
* waiting for the full Teams SPA to render (which can take 30+ seconds).
|
|
21
|
+
*
|
|
22
|
+
* Returns isAuthenticated: false if we can't confirm we're on Teams, to avoid
|
|
23
|
+
* silently failing with an invisible browser stuck on an unexpected page.
|
|
24
|
+
*/
|
|
25
|
+
export declare function navigateToTeams(page: Page): Promise<AuthStatus>;
|
|
26
|
+
/**
|
|
27
|
+
* Waits for the user to complete manual authentication.
|
|
28
|
+
* Returns when authenticated or throws after timeout.
|
|
29
|
+
*
|
|
30
|
+
* @param page - The page to monitor
|
|
31
|
+
* @param context - Browser context for saving session
|
|
32
|
+
* @param timeoutMs - Maximum time to wait (default: 5 minutes)
|
|
33
|
+
* @param onProgress - Callback for progress updates
|
|
34
|
+
* @param showOverlay - Whether to show progress overlay (default: true for visible browsers)
|
|
35
|
+
*/
|
|
36
|
+
export declare function waitForManualLogin(page: Page, context: BrowserContext, timeoutMs?: number, onProgress?: (message: string) => void, showOverlay?: boolean): Promise<void>;
|
|
37
|
+
/**
|
|
38
|
+
* Performs a full authentication flow:
|
|
39
|
+
* 1. Navigate to Teams
|
|
40
|
+
* 2. Check if already authenticated
|
|
41
|
+
* 3. If not, wait for manual login (or throw if headless)
|
|
42
|
+
*
|
|
43
|
+
* @param page - The page to use
|
|
44
|
+
* @param context - Browser context for session management
|
|
45
|
+
* @param onProgress - Callback for progress updates
|
|
46
|
+
* @param showOverlay - Whether to show progress overlay (default: true for visible browsers)
|
|
47
|
+
* @param headless - If true, throw immediately if user interaction is required (default: false)
|
|
48
|
+
*/
|
|
49
|
+
export declare function ensureAuthenticated(page: Page, context: BrowserContext, onProgress?: (message: string) => void, showOverlay?: boolean, headless?: boolean): Promise<void>;
|
|
50
|
+
/**
|
|
51
|
+
* Forces a new login by clearing session and navigating to Teams.
|
|
52
|
+
*/
|
|
53
|
+
export declare function forceNewLogin(page: Page, context: BrowserContext, onProgress?: (message: string) => void): Promise<void>;
|