Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 | 2x 7x 2x 16x 4x 4x 3x 1x 2x 1x 16x 5x 5x 4x 2x 2x 2x 1x | import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import * as z from "zod/v4";
import type { IsAgentReadyClient } from "../client.js";
import { formatScanResult } from "../format.js";
import { toTextResult, toErrorResult } from "../tool-result.js";
const isScanCompleted = (result: { status: string }): boolean =>
result.status === "completed" || result.status === "failed";
export const registerScanTools = (server: McpServer, client: IsAgentReadyClient): void => {
server.registerTool(
"scan_website",
{
title: "Scan Website for AI Agent Readiness",
description:
"Trigger a new scan of a website for AI agent readiness. The scan runs asynchronously and typically takes 15-30 seconds. If a recent scan exists (within 1 hour), returns cached results. Use get_scan_results to poll for completed results.",
annotations: { readOnlyHint: false, destructiveHint: false, openWorldHint: true },
inputSchema: z.object({
url: z
.string()
.min(1)
.describe("The full URL to scan (must be http:// or https://)"),
}),
},
async ({ url }) => {
try {
const result = await client.createScan(url);
if (isScanCompleted(result)) {
return toTextResult(
`Recent scan found (cached):\n\n${formatScanResult(result as Parameters<typeof formatScanResult>[0])}`,
{ type: "cached_result", ...result },
);
}
return toTextResult(
[
`Scan enqueued for ${result.domain}`,
`Status: ${result.status}`,
`ID: ${result.id}`,
"message" in result ? `Message: ${result.message}` : "",
"",
`Poll with get_scan_results for domain "${result.domain}" to check when results are ready.`,
]
.filter(Boolean)
.join("\n"),
{ type: "enqueued", id: result.id, domain: result.domain, status: result.status },
);
} catch (error) {
return toErrorResult(error);
}
},
);
server.registerTool(
"get_scan_results",
{
title: "Get Scan Results",
description:
"Get the latest scan results for a domain, including overall score, letter grade, per-category breakdowns, and individual checkpoint results with actionable recommendations. Returns a pending status if the scan is still in progress.",
annotations: { readOnlyHint: true, destructiveHint: false, openWorldHint: true },
inputSchema: z.object({
domain: z
.string()
.min(1)
.describe("The domain to get scan results for (e.g., example.com)"),
}),
},
async ({ domain }) => {
try {
const result = await client.getScanResults(domain);
if (!isScanCompleted(result)) {
const message = "message" in result ? String(result.message) : "";
return toTextResult(
[
`Scan for ${result.domain} is ${result.status}.`,
message,
"",
"Poll again in a few seconds to check for completion.",
]
.filter(Boolean)
.join("\n"),
{ type: "pending", id: result.id, domain: result.domain, status: result.status },
);
}
return toTextResult(
formatScanResult(result as Parameters<typeof formatScanResult>[0]),
{ type: "completed", ...result },
);
} catch (error) {
return toErrorResult(error);
}
},
);
};
|