feat: Add onPopupWindow callback and update README (#32)

* feat: Add onPopupWindow callback and update README

* feat: Pass window reference to onPopupWindow callback

---------

Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
This commit is contained in:
Glen Maddern 2025-07-24 17:23:52 +10:00 • committed by GitHub
commit 043efbcf12
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 18 additions and 0 deletions

View file

@ -227,6 +227,7 @@ function useMcp(options: UseMcpOptions): UseMcpResult
| `autoReconnect` | `boolean \| number` | Auto reconnect if an established connection is lost, with delay in ms (default: 3000) |
| `transportType` | `'auto' \| 'http' \| 'sse'` | Transport type preference: 'auto' (HTTP with SSE fallback), 'http' (HTTP only), 'sse' (SSE only) (default: 'auto') |
| `preventAutoAuth` | `boolean` | Prevent automatic authentication popup on initial connection (default: false) |
| `onPopupWindow` | `(url: string, features: string, window: Window \| null) => void` | Callback invoked just after the authentication popup window is opened |
#### Return Value

View file

@ -15,6 +15,7 @@ export class BrowserOAuthClientProvider implements OAuthClientProvider {
readonly clientName: string
readonly clientUri: string
readonly callbackUrl: string
readonly onPopupWindow: ((url: string, features: string, window: Window | null) => void) | undefined
constructor(
serverUrl: string,
@ -23,6 +24,7 @@ export class BrowserOAuthClientProvider implements OAuthClientProvider {
clientName?: string
clientUri?: string
callbackUrl?: string
onPopupWindow?: (url: string, features: string, window: Window | null) => void
} = {},
) {
this.serverUrl = serverUrl
@ -34,6 +36,7 @@ export class BrowserOAuthClientProvider implements OAuthClientProvider {
options.callbackUrl ||
(typeof window !== 'undefined' ? new URL('/oauth/callback', window.location.origin).toString() : '/oauth/callback'),
)
this.onPopupWindow = options.onPopupWindow
}
// --- SDK Interface Methods ---
@ -169,6 +172,11 @@ export class BrowserOAuthClientProvider implements OAuthClientProvider {
try {
const popup = window.open(sanitizedAuthUrl, `mcp_auth_${this.serverUrlHash}`, popupFeatures)
// If a callback is provided, invoke it after opening the popup
if (this.onPopupWindow) {
this.onPopupWindow(sanitizedAuthUrl, popupFeatures, popup)
}
if (!popup || popup.closed || typeof popup.closed === 'undefined') {
console.warn(
`[${this.storageKeyPrefix}] Popup likely blocked by browser. Manual navigation might be required using the stored URL.`,

View file

@ -30,6 +30,12 @@ export type UseMcpOptions = {
transportType?: 'auto' | 'http' | 'sse'
/** Prevent automatic authentication popup on initial connection (default: false) */
preventAutoAuth?: boolean
/**
* Callback function that is invoked just before the authentication popup window is opened.
* @param url The URL that will be opened in the popup.
* @param features The features string for the popup window.
*/
onPopupWindow?: (url: string, features: string, window: Window | null) => void
}
export type UseMcpResult = {

View file

@ -47,6 +47,7 @@ export function useMcp(options: UseMcpOptions): UseMcpResult {
autoReconnect = DEFAULT_RECONNECT_DELAY,
transportType = 'auto',
preventAutoAuth = false,
onPopupWindow,
} = options
const [state, setState] = useState<UseMcpResult['state']>('discovering')
@ -176,6 +177,7 @@ export function useMcp(options: UseMcpOptions): UseMcpResult {
clientName,
clientUri,
callbackUrl,
onPopupWindow,
})
addLog('debug', 'BrowserOAuthClientProvider initialized in connect.')
}
@ -779,6 +781,7 @@ export function useMcp(options: UseMcpOptions): UseMcpResult {
clientName,
clientUri,
callbackUrl,
onPopupWindow,
})
addLog('debug', 'BrowserOAuthClientProvider initialized/updated on mount/option change.')
}