()
| 269 | | { status: 'already_authorized' } |
| 270 | |
| 271 | export function useStartMcpOauth() { |
| 272 | return useMutation<StartMcpOauthMutationResult, Error, { serverId: string; workspaceId: string }>( |
| 273 | { |
| 274 | mutationFn: async ({ serverId, workspaceId }) => { |
| 275 | const result = await requestJson(startMcpOauthContract, { |
| 276 | query: { serverId, workspaceId }, |
| 277 | }) |
| 278 | if (result.status === 'already_authorized') return { status: 'already_authorized' } |
| 279 | |
| 280 | const parsedUrl = new URL(result.authorizationUrl) |
| 281 | const isLoopbackHttp = |
| 282 | parsedUrl.protocol === 'http:' && isLoopbackHostname(parsedUrl.hostname) |
| 283 | if (parsedUrl.protocol !== 'https:' && !isLoopbackHttp) { |
| 284 | throw new Error('Authorization URL must use HTTPS') |
| 285 | } |
| 286 | const popup = window.open( |
| 287 | result.authorizationUrl, |
| 288 | `mcp-oauth-${serverId}`, |
| 289 | 'width=560,height=720,resizable=yes,scrollbars=yes' |
| 290 | ) |
| 291 | if (!popup) { |
| 292 | throw new Error('Popup blocked. Please allow popups for this site and retry.') |
| 293 | } |
| 294 | return { status: 'redirect', popup } |
| 295 | }, |
| 296 | } |
| 297 | ) |
| 298 | } |
| 299 | |
| 300 | interface DeleteMcpServerParams { |
| 301 | workspaceId: string |
no test coverage detected