From dc565c0f74ce033e9e95b740ce4c882687362e44 Mon Sep 17 00:00:00 2001 From: Glen Maddern Date: Wed, 23 Jul 2025 21:11:30 +1000 Subject: [PATCH 1/2] Got the CF agent demo server showing a permission dialog. Works manually in inspector --- examples/servers/cf-agents/src/index.ts | 46 +++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/examples/servers/cf-agents/src/index.ts b/examples/servers/cf-agents/src/index.ts index f474d0f..81f43ae 100644 --- a/examples/servers/cf-agents/src/index.ts +++ b/examples/servers/cf-agents/src/index.ts @@ -155,7 +155,53 @@ const app = new Hono<{ app.get('/authorize', async (c) => { const oauthReqInfo = await c.env.OAUTH_PROVIDER.parseAuthRequest(c.req.raw) + const url = new URL(c.req.url) + + const approveHref = url.toString() + return c.html(/*html*/ ` + + + Authorize access + +
+

Authorize access

+

Allow Unknown client to access your calculator?

+
+
+ + +
+ +
+ +
+ `) +}) + +app.post('/authorize', async (c) => { const email = 'example@dotcom.com' + const formData = await c.req.formData() + const oauthReqInfoRaw = formData.get('oauthReqInfo') + if (!oauthReqInfoRaw || typeof oauthReqInfoRaw !== 'string') { + return c.text('Missing oauthReqInfo', 400) + } + let oauthReqInfo + try { + oauthReqInfo = JSON.parse(decodeURIComponent(oauthReqInfoRaw)) + } catch (e) { + return c.text('Invalid oauthReqInfo', 400) + } const { redirectTo } = await c.env.OAUTH_PROVIDER.completeAuthorization({ request: oauthReqInfo, userId: email, From d1ffa9ff34ba55da5df584be085fd57dc8cf2847 Mon Sep 17 00:00:00 2001 From: Glen Maddern Date: Thu, 24 Jul 2025 17:01:43 +1000 Subject: [PATCH 2/2] Clicking on the approval dialog, tests pass already --- test/integration/test-utils.ts | 53 ++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/test/integration/test-utils.ts b/test/integration/test-utils.ts index fb820e8..496ebe5 100644 --- a/test/integration/test-utils.ts +++ b/test/integration/test-utils.ts @@ -159,6 +159,59 @@ export async function connectToMCPServer( // Wait for connection attempt to complete await page.waitForTimeout(1000) + // Check for OAuth popup and handle it - try multiple times to catch different OAuth flows + let oauthHandled = false + for (let popupAttempt = 0; popupAttempt < 5 && !oauthHandled; popupAttempt++) { + try { + // Look for OAuth popup by checking for new pages + const context = page.context() + const initialPages = context.pages() + + // Wait a bit to see if OAuth popup appears + await page.waitForTimeout(1000) + + const currentPages = context.pages() + if (currentPages.length > initialPages.length) { + // OAuth popup appeared, find it + const popup = currentPages.find((p) => p !== page && p.url().includes('/authorize')) + if (popup) { + console.log('🔐 OAuth popup detected, clicking Approve button...') + // Wait for the approval form to load + await popup.waitForSelector('button.approve', { timeout: 5000 }) + // Click the Approve button + await popup.click('button.approve') + console.log('✅ Clicked Approve button') + // Wait for popup to close + await popup.waitForEvent('close', { timeout: 10000 }) + console.log('🔒 OAuth popup closed') + oauthHandled = true + break + } + } + + // Also check if there's a popup that opened that we haven't detected yet + const allPages = context.pages() + for (const possiblePopup of allPages) { + if (possiblePopup !== page && possiblePopup.url().includes('/authorize')) { + console.log('🔐 Found OAuth popup on retry, clicking Approve button...') + await possiblePopup.waitForSelector('button.approve', { timeout: 5000 }) + await possiblePopup.click('button.approve') + console.log('✅ Clicked Approve button') + await possiblePopup.waitForEvent('close', { timeout: 10000 }) + console.log('🔒 OAuth popup closed') + oauthHandled = true + break + } + } + } catch (e) { + console.log(`â„šī¸ OAuth popup attempt ${popupAttempt + 1} failed:`, e.message) + } + } + + if (!oauthHandled) { + console.log('â„šī¸ No OAuth popup detected after multiple attempts') + } + // Check for connection status let attempts = 0 const maxAttempts = 20