| import axios from 'axios' |
| import { logForDebugging } from '../../utils/debug.js' |
| import { errorMessage } from '../../utils/errors.js' |
|
|
| type RegistryServer = { |
| server: { |
| remotes?: Array<{ url: string }> |
| } |
| } |
|
|
| type RegistryResponse = { |
| servers: RegistryServer[] |
| } |
|
|
| |
| |
| let officialUrls: Set<string> | undefined = undefined |
|
|
| function normalizeUrl(url: string): string | undefined { |
| try { |
| const u = new URL(url) |
| u.search = '' |
| return u.toString().replace(/\/$/, '') |
| } catch { |
| return undefined |
| } |
| } |
|
|
| |
| |
| |
| |
| export async function prefetchOfficialMcpUrls(): Promise<void> { |
| if (process.env.CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC) { |
| return |
| } |
|
|
| try { |
| const response = await axios.get<RegistryResponse>( |
| 'https://api.anthropic.com/mcp-registry/v0/servers?version=latest&visibility=commercial', |
| { timeout: 5000 }, |
| ) |
|
|
| const urls = new Set<string>() |
| for (const entry of response.data.servers) { |
| for (const remote of entry.server.remotes ?? []) { |
| const normalized = normalizeUrl(remote.url) |
| if (normalized) { |
| urls.add(normalized) |
| } |
| } |
| } |
| officialUrls = urls |
| logForDebugging(`[mcp-registry] Loaded ${urls.size} official MCP URLs`) |
| } catch (error) { |
| logForDebugging(`Failed to fetch MCP registry: ${errorMessage(error)}`, { |
| level: 'error', |
| }) |
| } |
| } |
|
|
| |
| |
| |
| |
| export function isOfficialMcpUrl(normalizedUrl: string): boolean { |
| return officialUrls?.has(normalizedUrl) ?? false |
| } |
|
|
| export function resetOfficialMcpUrlsForTesting(): void { |
| officialUrls = undefined |
| } |
|
|