diff --git a/src/lib/agent-runner.ts b/src/lib/agent-runner.ts index 3f6f058..0b31dba 100644 --- a/src/lib/agent-runner.ts +++ b/src/lib/agent-runner.ts @@ -132,9 +132,14 @@ export async function runAgentWizard( const spinner = clack.spinner(); // Determine MCP URL: CLI flag > env var > production default + // Use EU subdomain for EU users to work around Claude Code's OAuth bug + // See: https://github.com/anthropics/claude-code/issues/2267 const mcpUrl = options.localMcp ? 'http://localhost:8787/mcp' - : process.env.MCP_URL || 'https://mcp.posthog.com/mcp'; + : process.env.MCP_URL || + (cloudRegion === 'eu' + ? 'https://mcp-eu.posthog.com/mcp' + : 'https://mcp.posthog.com/mcp'); const agent = initializeAgent( { diff --git a/src/steps/add-mcp-server-to-clients/__tests__/defaults.test.ts b/src/steps/add-mcp-server-to-clients/__tests__/defaults.test.ts index 5101277..862e39c 100644 --- a/src/steps/add-mcp-server-to-clients/__tests__/defaults.test.ts +++ b/src/steps/add-mcp-server-to-clients/__tests__/defaults.test.ts @@ -28,9 +28,9 @@ describe('defaults', () => { ); }); - it('should add region param for EU region', () => { + it('should use EU subdomain for EU region', () => { const url = buildMCPUrl('streamable-http', undefined, false, 'eu'); - expect(url).toBe('https://mcp.posthog.com/mcp?region=eu'); + expect(url).toBe('https://mcp-eu.posthog.com/mcp'); }); it('should not add region param for US region (default)', () => { @@ -43,11 +43,9 @@ describe('defaults', () => { expect(url).toBe('http://localhost:8787/mcp'); }); - it('should combine features and region params', () => { + it('should combine EU subdomain with features param', () => { const url = buildMCPUrl('streamable-http', ['dashboards'], false, 'eu'); - expect(url).toBe( - 'https://mcp.posthog.com/mcp?features=dashboards®ion=eu', - ); + expect(url).toBe('https://mcp-eu.posthog.com/mcp?features=dashboards'); }); }); @@ -78,7 +76,7 @@ describe('defaults', () => { expect(config).not.toHaveProperty('env'); }); - it('should include region in URL for EU users in OAuth mode', () => { + it('should use EU subdomain for EU users in OAuth mode', () => { const config = getDefaultServerConfig( undefined, 'streamable-http', @@ -86,7 +84,7 @@ describe('defaults', () => { false, 'eu', ); - expect(config.args).toContain('https://mcp.posthog.com/mcp?region=eu'); + expect(config.args).toContain('https://mcp-eu.posthog.com/mcp'); }); }); @@ -112,7 +110,7 @@ describe('defaults', () => { expect(config).not.toHaveProperty('headers'); }); - it('should include region in URL for EU users', () => { + it('should use EU subdomain for EU users', () => { const config = getNativeHTTPServerConfig( undefined, 'streamable-http', @@ -120,7 +118,7 @@ describe('defaults', () => { false, 'eu', ); - expect(config.url).toBe('https://mcp.posthog.com/mcp?region=eu'); + expect(config.url).toBe('https://mcp-eu.posthog.com/mcp'); }); }); }); diff --git a/src/steps/add-mcp-server-to-clients/defaults.ts b/src/steps/add-mcp-server-to-clients/defaults.ts index 3557e99..b9410e7 100644 --- a/src/steps/add-mcp-server-to-clients/defaults.ts +++ b/src/steps/add-mcp-server-to-clients/defaults.ts @@ -77,7 +77,14 @@ export const buildMCPUrl = ( local?: boolean, region?: CloudRegion, ) => { - const host = local ? 'http://localhost:8787' : 'https://mcp.posthog.com'; + // Use subdomain for EU to work around Claude Code's OAuth bug where it ignores + // the authorization_servers field and fetches /.well-known/oauth-authorization-server + // directly from the MCP server hostname. See: https://github.com/anthropics/claude-code/issues/2267 + const host = local + ? 'http://localhost:8787' + : region === 'eu' + ? 'https://mcp-eu.posthog.com' + : 'https://mcp.posthog.com'; const baseUrl = `${host}/${type === 'sse' ? 'sse' : 'mcp'}`; const isAllFeaturesSelected = @@ -96,13 +103,6 @@ export const buildMCPUrl = ( params.push(`features=${selectedFeatures.join(',')}`); } - // Add region param for non-US regions to route OAuth to the correct authorization server. - // US is the default, so we only need to specify region for EU users. - // Not needed in local mode since local dev always uses the same auth server. - if (region && region !== 'us' && !local) { - params.push(`region=${region}`); - } - return params.length > 0 ? `${baseUrl}?${params.join('&')}` : baseUrl; };