| 1 | import type { ServerView } from "./types"; |
| 2 | |
| 3 | export function canUseNativeMCPOAuth(s: ServerView): boolean { |
| 4 | const transport = (s.transport || "").trim().toLowerCase(); |
| 5 | if (s.authConfigured || !["http", "streamable-http", "streamable_http"].includes(transport)) return false; |
| 6 | try { |
| 7 | const parsed = new URL((s.url || s.authUrl || "").trim()); |
| 8 | if (parsed.username || parsed.password || parsed.hash) return false; |
| 9 | for (const key of parsed.searchParams.keys()) { |
| 10 | if (isAuthQueryKey(key)) return false; |
| 11 | } |
| 12 | if (parsed.protocol === "https:") return true; |
| 13 | if (parsed.protocol !== "http:") return false; |
| 14 | const host = parsed.hostname.toLowerCase().replace(/^\[|\]$/g, ""); |
| 15 | return host === "localhost" || host === "127.0.0.1" || host === "::1"; |
| 16 | } catch { |
| 17 | return false; |
| 18 | } |
| 19 | } |
| 20 | |
| 21 | function isAuthQueryKey(key: string): boolean { |
| 22 | const normalized = key.trim().toLowerCase().replace(/[\-_ ]/g, ""); |
| 23 | if ([ |
| 24 | "auth", "authorization", "bearer", "credential", "credentials", "key", "sig", "signature", "hmac", |
| 25 | "token", "accesstoken", "idtoken", "refreshtoken", "apikey", "accesskey", "secretkey", |
| 26 | "subscriptionkey", "clientsecret", "password", "passwd", |
| 27 | ].includes(normalized)) return true; |
| 28 | return ["token", "secret", "password", "passwd", "apikey", "signature"].some((suffix) => normalized.endsWith(suffix)); |
| 29 | } |
| 30 |