UNPKG

mcp-wayback-machine

Version:

MCP server and CLI tool for interacting with the Wayback Machine without API keys

109 lines 4.15 kB
/** * Check Archive Status tool - Check if a URL has been archived */ import { z } from 'zod'; import { fetchWithTimeout, HttpError, parseJsonResponse } from '../utils/http.js'; import { validateUrl } from '../utils/validation.js'; import { waybackRateLimiter } from '../utils/rate-limit.js'; export const CheckArchiveStatusSchema = z.object({ url: z.string().url().describe('The URL to check'), }); /** * Check if a URL has been archived and get statistics */ export async function checkArchiveStatus(input) { const { url } = input; try { // Validate URL const validatedUrl = validateUrl(url); // Check rate limit await waybackRateLimiter.waitForSlot(); // Use the Sparkline API for statistics const apiUrl = new URL('https://web.archive.org/__wb/sparkline'); apiUrl.searchParams.set('url', validatedUrl); apiUrl.searchParams.set('collection', 'web'); apiUrl.searchParams.set('output', 'json'); waybackRateLimiter.recordRequest(); const response = await fetchWithTimeout(apiUrl.toString(), { headers: { 'User-Agent': 'mcp-wayback-machine/0.1.0', }, }); const data = await parseJsonResponse(response); if (data.first_ts) { // Calculate yearly totals const yearlyCaptures = {}; if (data.years) { for (const [year, months] of Object.entries(data.years)) { yearlyCaptures[year] = months.reduce((sum, count) => sum + count, 0); } } // Format timestamps const formatDate = (ts) => { if (ts.length >= 8) { const year = ts.substring(0, 4); const month = ts.substring(4, 6); const day = ts.substring(6, 8); return `${year}-${month}-${day}`; } return ts; }; return { success: true, message: `${validatedUrl} has been archived ${data.captures || 0} times`, isArchived: true, firstCapture: formatDate(data.first_ts), lastCapture: data.last_ts ? formatDate(data.last_ts) : undefined, totalCaptures: data.captures || 0, yearlyCaptures, }; } // Also check using availability API as fallback const availUrl = new URL('https://archive.org/wayback/available'); availUrl.searchParams.set('url', validatedUrl); waybackRateLimiter.recordRequest(); const availResponse = await fetchWithTimeout(availUrl.toString(), { headers: { 'User-Agent': 'mcp-wayback-machine/0.1.0', }, }); const availData = await parseJsonResponse(availResponse); if (availData.archived_snapshots?.closest?.available) { return { success: true, message: `${validatedUrl} has been archived`, isArchived: true, lastCapture: availData.archived_snapshots.closest.timestamp, }; } return { success: true, message: `${validatedUrl} has not been archived`, isArchived: false, totalCaptures: 0, }; } catch (error) { if (error instanceof HttpError) { if (error.status === 404) { return { success: true, message: `${url} has not been archived`, isArchived: false, totalCaptures: 0, }; } return { success: false, message: `Failed to check archive status: ${error.message}`, isArchived: false, }; } return { success: false, message: `Failed to check archive status: ${error instanceof Error ? error.message : 'Unknown error'}`, isArchived: false, }; } } //# sourceMappingURL=status.js.map