Skip to main content
Glama
ssl-labs.ts5.03 kB
/** * SSL Labs SSL/TLS Configuration Analyzer * API v4: https://api.ssllabs.com/api/v4/analyze * Docs: https://github.com/ssllabs/ssllabs-scan/blob/master/ssllabs-api-docs-v4.md */ export interface SSLLabsOptions { /** Maximum age of cached report in hours (default: 24) */ maxAge?: number; /** Force a new assessment (default: false) */ startNew?: boolean; /** Get all endpoint details (default: true) */ all?: boolean; /** Your email address (required by API) */ email: string; } export interface SSLLabsEndpoint { ipAddress: string; serverName?: string; statusMessage: string; grade?: string; gradeTrustIgnored?: string; hasWarnings: boolean; isExceptional: boolean; progress: number; duration: number; eta?: number; delegation?: number; } export interface SSLLabsResponse { host: string; port: number; protocol: string; isPublic: boolean; status: string; statusMessage?: string; startTime: number; testTime?: number; engineVersion: string; criteriaVersion: string; endpoints?: SSLLabsEndpoint[]; } export interface SSLLabsResult { tool: 'ssl_labs'; success: boolean; status: string; grade?: string; host: string; endpoints: Array<{ ip: string; grade?: string; hasWarnings: boolean; progress: number; }>; testTime?: string; error?: string; raw?: SSLLabsResponse; } /** * Analyze SSL/TLS configuration using SSL Labs API * * IMPORTANT: This is a long-running operation. The initial request starts the scan, * and you need to poll the API until status is 'READY' or 'ERROR'. * * Rate limits: Please be considerate - poll at 5-10 second intervals. * Required: Email address in header for API access. */ export async function analyzeSSLLabs( url: string, options: SSLLabsOptions ): Promise<SSLLabsResult> { try { // Extract hostname from URL const hostname = new URL(url).hostname; // Build API URL with parameters const params = new URLSearchParams({ host: hostname, all: options.all !== false ? 'on' : 'off', }); if (options.maxAge !== undefined) { params.set('maxAge', options.maxAge.toString()); } if (options.startNew) { params.set('startNew', 'on'); } const apiUrl = `https://api.ssllabs.com/api/v4/analyze?${params.toString()}`; // Make GET request with email header const response = await fetch(apiUrl, { method: 'GET', headers: { 'email': options.email, }, }); if (!response.ok) { if (response.status === 429) { throw new Error('SSL Labs rate limit exceeded. Please wait and try again.'); } throw new Error(`SSL Labs API error: ${response.status} ${response.statusText}`); } const data: SSLLabsResponse = await response.json(); // Check if assessment is complete if (data.status === 'ERROR') { return { tool: 'ssl_labs', success: false, status: data.status, host: hostname, endpoints: [], error: data.statusMessage || 'Assessment failed', raw: data, }; } // Format endpoints const endpoints = (data.endpoints || []).map(ep => ({ ip: ep.ipAddress, grade: ep.grade, hasWarnings: ep.hasWarnings, progress: ep.progress, })); // Get best grade from all endpoints const grades = data.endpoints?.filter(ep => ep.grade).map(ep => ep.grade!) || []; const bestGrade = grades.length > 0 ? grades.sort()[0] : undefined; return { tool: 'ssl_labs', success: data.status === 'READY', status: data.status, grade: bestGrade, host: hostname, endpoints, testTime: data.testTime ? new Date(data.testTime).toISOString() : undefined, raw: data, }; } catch (error) { return { tool: 'ssl_labs', success: false, status: 'ERROR', host: new URL(url).hostname, endpoints: [], error: error instanceof Error ? error.message : String(error), }; } } /** * Poll SSL Labs until assessment is complete * Use this wrapper to automatically handle the polling loop */ export async function analyzeSSLLabsComplete( url: string, options: SSLLabsOptions, maxWaitMinutes: number = 5 ): Promise<SSLLabsResult> { const maxWaitMs = maxWaitMinutes * 60 * 1000; const startTime = Date.now(); const pollInterval = 10000; // 10 seconds let result = await analyzeSSLLabs(url, options); // Keep polling until complete or timeout while (result.status !== 'READY' && result.status !== 'ERROR') { if (Date.now() - startTime > maxWaitMs) { return { ...result, success: false, error: `Timeout: Assessment did not complete within ${maxWaitMinutes} minutes`, }; } // Wait before next poll await new Promise(resolve => setTimeout(resolve, pollInterval)); // Poll again (fromCache to get latest status) result = await analyzeSSLLabs(url, { ...options, maxAge: 0 }); } return result; }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/cordlesssteve/webby-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server