UNPKG

mcp-wayback-machine

Version:

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

94 lines (92 loc) 3.91 kB
/** * * Check Archive Status tool — Checks archival statistics for URLs. */ import * as z from "zod"; import { AvailabilityResponse, SparklineResponse } from "../schemas.js"; import { HttpError } from "../utils/http.js"; import { HttpUrl } from "../utils/validation.js"; export const CheckArchiveStatus = z.object({ url: HttpUrl.meta({ description: "The URL to check archival status for" }), }); /** * * Check if a URL has been archived and get capture statistics. */ export async function checkArchiveStatus(input, ctx) { const { url } = input; try { // Try sparkline API first for detailed statistics const sparklineUrl = `https://web.archive.org/__wb/sparkline?url=${encodeURIComponent(url)}&collection=web&output=json`; const sparklineData = await ctx.fetchJSON(sparklineUrl, SparklineResponse); if (sparklineData.years !== undefined) { const years = Object.keys(sparklineData.years).sort(); if (years.length > 0) { const yearlyCaptures = {}; let totalCaptures = 0; for (const year of years) { const yearData = sparklineData.years[year]; if (!yearData) continue; const count = yearData["timeseries-csp"].reduce((sum, val) => sum + val, 0); yearlyCaptures[year] = count; totalCaptures += count; } // Get last capture date from availability API const availUrl = `https://archive.org/wayback/available?url=${encodeURIComponent(url)}`; const availData = await ctx.fetchJSON(availUrl, AvailabilityResponse); const result = { success: true, message: `Archive status for ${url}`, isArchived: true, firstCapture: `${String(years[0])}-01-01`, totalCaptures, yearlyCaptures, }; if (availData.archived_snapshots.closest?.timestamp !== undefined) { const ts = availData.archived_snapshots.closest.timestamp; result.lastCapture = `${ts.slice(0, 4)}-${ts.slice(4, 6)}-${ts.slice(6, 8)}`; } return result; } } // Fall back to availability API const availUrl = `https://archive.org/wayback/available?url=${encodeURIComponent(url)}`; const availData = await ctx.fetchJSON(availUrl, AvailabilityResponse); if (availData.archived_snapshots.closest?.available) { const snapshot = availData.archived_snapshots.closest; return { success: true, message: `${url} has been archived`, isArchived: true, lastCapture: `${snapshot.timestamp.slice(0, 4)}-${snapshot.timestamp.slice(4, 6)}-${snapshot.timestamp.slice(6, 8)}`, }; } return { success: true, message: `${url} has not been archived`, isArchived: false, }; } catch (error) { if (error instanceof HttpError && error.status === 404) { return { success: true, message: `${url} has not been archived`, isArchived: false, }; } if (error instanceof HttpError) { 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