Skip to content

Commit bfc549e

Browse files
committed
fix: connection test auth, MCP URL config, Claude Code auth header
Connection test was broken: used key_preview (truncated, e.g. ci_80ba...e980) for Authorization header -- always 401 because backend hashes the full key. Fixed: ConnectionTest now receives the session JWT token from useAuth, which works with require_auth middleware. The test verifies the user's backend access, not the API key specifically. Added MCP_URL to config/api.ts (separate Railway service from API_URL). Health check now uses env-derived MCP_URL instead of hardcoded string. Claude Code snippet now includes --header flag for auth, matching how Desktop (env.API_KEY) and Cursor (headers.Authorization) handle it.
1 parent 3162b3f commit bfc549e

2 files changed

Lines changed: 19 additions & 12 deletions

File tree

frontend/src/config/api.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,9 @@ export const buildWsUrl = (path: string): string => {
5858
return `${WS_URL}${cleanPath}`
5959
}
6060

61+
// MCP server URL (separate Railway service from the API)
62+
export const MCP_URL = import.meta.env.VITE_MCP_URL || 'https://mcp.opencodeintel.com'
63+
6164
// free tier repo limit -- used in dashboard and GitHub import
6265
export const MAX_FREE_REPOS = 1
6366

frontend/src/pages/APIKeysPage.tsx

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import {
1414
DialogTitle,
1515
} from '@/components/ui/dialog'
1616
import { toast } from 'sonner'
17-
import { API_URL } from '@/config/api'
17+
import { API_URL, MCP_URL } from '@/config/api'
1818
import { cn } from '@/lib/utils'
1919

2020
interface APIKey {
@@ -168,7 +168,7 @@ function KeyCard({
168168

169169
type TestStep = { label: string; status: 'idle' | 'running' | 'pass' | 'fail' }
170170

171-
function ConnectionTest({ apiKey }: { apiKey: string | null }) {
171+
function ConnectionTest({ token }: { token: string | null }) {
172172
const [steps, setSteps] = useState<TestStep[]>([
173173
{ label: 'MCP server reachable', status: 'idle' },
174174
{ label: 'API key authenticated', status: 'idle' },
@@ -178,7 +178,7 @@ function ConnectionTest({ apiKey }: { apiKey: string | null }) {
178178
const [tested, setTested] = useState(false)
179179

180180
const runTest = useCallback(async () => {
181-
if (!apiKey || running) return
181+
if (!token || running) return
182182
setRunning(true)
183183
setTested(true)
184184
const update = (idx: number, status: TestStep['status']) =>
@@ -190,18 +190,18 @@ function ConnectionTest({ apiKey }: { apiKey: string | null }) {
190190
// Step 1: MCP health
191191
update(0, 'running')
192192
try {
193-
const res = await fetch('https://mcp.opencodeintel.com/health')
193+
const res = await fetch(`${MCP_URL}/health`)
194194
update(0, res.ok ? 'pass' : 'fail')
195195
if (!res.ok) { setRunning(false); return }
196196
} catch {
197197
update(0, 'fail'); setRunning(false); return
198198
}
199199

200-
// Step 2: Auth check
200+
// Step 2: Auth check (uses session JWT, not API key preview)
201201
update(1, 'running')
202202
try {
203203
const res = await fetch(`${API_URL}/keys`, {
204-
headers: { Authorization: `Bearer ${apiKey}` },
204+
headers: { Authorization: `Bearer ${token}` },
205205
})
206206
update(1, res.ok ? 'pass' : 'fail')
207207
if (!res.ok) { setRunning(false); return }
@@ -213,15 +213,15 @@ function ConnectionTest({ apiKey }: { apiKey: string | null }) {
213213
update(2, 'running')
214214
try {
215215
const res = await fetch(`${API_URL}/repos`, {
216-
headers: { Authorization: `Bearer ${apiKey}` },
216+
headers: { Authorization: `Bearer ${token}` },
217217
})
218218
update(2, res.ok ? 'pass' : 'fail')
219219
} catch {
220220
update(2, 'fail')
221221
}
222222

223223
setRunning(false)
224-
}, [apiKey, running])
224+
}, [token, running])
225225

226226
const allPassed = steps.every((s) => s.status === 'pass')
227227
const anyFailed = steps.some((s) => s.status === 'fail')
@@ -234,7 +234,7 @@ function ConnectionTest({ apiKey }: { apiKey: string | null }) {
234234
</span>
235235
<button
236236
onClick={runTest}
237-
disabled={!apiKey || running}
237+
disabled={!token || running}
238238
className={cn(
239239
'text-xs px-3 py-1.5 rounded-md transition-all flex items-center gap-1.5',
240240
running
@@ -287,7 +287,7 @@ function ConnectionTest({ apiKey }: { apiKey: string | null }) {
287287
)
288288
}
289289

290-
function ConnectGuide({ activeKeyPreview }: { activeKeyPreview: string | null }) {
290+
function ConnectGuide({ activeKeyPreview, sessionToken }: { activeKeyPreview: string | null; sessionToken: string | null }) {
291291
const [tab, setTab] = useState<'desktop' | 'code' | 'cursor'>('desktop')
292292

293293
const keyDisplay = activeKeyPreview || 'ci_your-key-here'
@@ -313,6 +313,7 @@ function ConnectGuide({ activeKeyPreview }: { activeKeyPreview: string | null })
313313
hint: 'Run in terminal',
314314
config: `claude mcp add codeintel \\
315315
--transport http \\
316+
--header "Authorization:Bearer ${keyDisplay}" \\
316317
https://mcp.opencodeintel.com/mcp`,
317318
},
318319
cursor: {
@@ -375,7 +376,7 @@ function ConnectGuide({ activeKeyPreview }: { activeKeyPreview: string | null })
375376
</div>
376377

377378
{/* Connection test */}
378-
<ConnectionTest apiKey={activeKeyPreview} />
379+
<ConnectionTest token={sessionToken} />
379380
</div>
380381
)
381382
}
@@ -579,7 +580,10 @@ export function APIKeysPage() {
579580

580581
{/* Connect guide */}
581582
{activeKeys.length > 0 && (
582-
<ConnectGuide activeKeyPreview={activeKeys[0]?.key_preview || null} />
583+
<ConnectGuide
584+
activeKeyPreview={activeKeys[0]?.key_preview || null}
585+
sessionToken={token}
586+
/>
583587
)}
584588

585589
{/* Generate dialog */}

0 commit comments

Comments
 (0)