agent-ready-mcp 0.5.3 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/mcp-server.mjs +100 -6
- package/package.json +1 -1
package/dist/mcp-server.mjs
CHANGED
|
@@ -23093,6 +23093,50 @@ async function call(config2, opts) {
|
|
|
23093
23093
|
}
|
|
23094
23094
|
return payload;
|
|
23095
23095
|
}
|
|
23096
|
+
async function postAnonScan(config2, url2) {
|
|
23097
|
+
const path = "/api/scan";
|
|
23098
|
+
let res;
|
|
23099
|
+
try {
|
|
23100
|
+
res = await fetch(`${config2.baseUrl}${path}`, {
|
|
23101
|
+
method: "POST",
|
|
23102
|
+
headers: {
|
|
23103
|
+
"Content-Type": "application/json",
|
|
23104
|
+
Accept: "application/json"
|
|
23105
|
+
},
|
|
23106
|
+
body: JSON.stringify({ url: url2 }),
|
|
23107
|
+
signal: AbortSignal.timeout(config2.scanTimeoutMs)
|
|
23108
|
+
});
|
|
23109
|
+
} catch (err) {
|
|
23110
|
+
if (err instanceof Error && err.name === "TimeoutError") {
|
|
23111
|
+
throw new ApiError(
|
|
23112
|
+
"timeout",
|
|
23113
|
+
`Request to ${path} timed out after ${config2.scanTimeoutMs}ms.`
|
|
23114
|
+
);
|
|
23115
|
+
}
|
|
23116
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
23117
|
+
throw new ApiError("network_error", `Network error calling ${path}: ${message}`);
|
|
23118
|
+
}
|
|
23119
|
+
const text = await res.text();
|
|
23120
|
+
let payload = null;
|
|
23121
|
+
if (text.length > 0) {
|
|
23122
|
+
try {
|
|
23123
|
+
payload = JSON.parse(text);
|
|
23124
|
+
} catch {
|
|
23125
|
+
}
|
|
23126
|
+
}
|
|
23127
|
+
if (!res.ok) {
|
|
23128
|
+
const body = payload && typeof payload === "object" ? payload : null;
|
|
23129
|
+
let message = typeof body?.error === "string" && body.error ? body.error : text || `HTTP ${res.status} from ${path}`;
|
|
23130
|
+
if (res.status === 429) {
|
|
23131
|
+
if (typeof body?.resetAt === "string") {
|
|
23132
|
+
message += ` Quota resets ${body.resetAt.slice(0, 10)}.`;
|
|
23133
|
+
}
|
|
23134
|
+
throw new ApiError("quota_exhausted", message, res.status);
|
|
23135
|
+
}
|
|
23136
|
+
throw new ApiError(`http_${res.status}`, message, res.status);
|
|
23137
|
+
}
|
|
23138
|
+
return payload;
|
|
23139
|
+
}
|
|
23096
23140
|
async function postScan(config2, body) {
|
|
23097
23141
|
return call(config2, {
|
|
23098
23142
|
method: "POST",
|
|
@@ -31357,10 +31401,26 @@ Discover-then-validate: when the relevant well-known endpoint returns 404, the c
|
|
|
31357
31401
|
| C19 | MPP challenge params |
|
|
31358
31402
|
| C20 | AP2 payment protocol support |
|
|
31359
31403
|
| C21 | ACP profile (/.well-known/acp.json) |
|
|
31404
|
+
|
|
31405
|
+
## Accessibility checks (9)
|
|
31406
|
+
|
|
31407
|
+
Run over the homepage DOM (v1). WCAG-grounded accessibility-tree signals \u2014 image text alternatives, form labels, control names \u2014 plus a static layout-stability (CLS) proxy. Scored into a separate \`accessibilityScore\`, a distinct suite from the 69 checks above: accessibility is WCAG, not the Vercel Agent Readability Spec, so it never moves the Vercel score.
|
|
31408
|
+
|
|
31409
|
+
| ID | Check |
|
|
31410
|
+
|---|---|
|
|
31411
|
+
| A1 | Images have text alternatives |
|
|
31412
|
+
| A2 | Form controls have labels |
|
|
31413
|
+
| A3 | Controls have accessible names |
|
|
31414
|
+
| A4 | Media declares explicit dimensions |
|
|
31415
|
+
| A5 | ARIA name references resolve |
|
|
31416
|
+
| A6 | Iframes have an accessible name |
|
|
31417
|
+
| A7 | Heading hierarchy is well-formed |
|
|
31418
|
+
| A8 | No positive tabindex |
|
|
31419
|
+
| A9 | Pinch-zoom is not disabled |
|
|
31360
31420
|
`;
|
|
31361
31421
|
var LLMS_TXT = `# Agent Ready
|
|
31362
31422
|
|
|
31363
|
-
> Agent Ready is a free tool that scores any website against the Vercel Agent Readability Spec, the llmstxt.org specification, and agent-protocol specs (MCP, A2A, agents.json). It runs 69 checks and provides actionable fix guidance for every failing check.
|
|
31423
|
+
> Agent Ready is a free tool that scores any website against the Vercel Agent Readability Spec, the llmstxt.org specification, and agent-protocol specs (MCP, A2A, agents.json). It runs 69 checks \u2014 plus a separate accessibility sub-score from 9 WCAG 2.2 / layout-stability checks \u2014 and provides actionable fix guidance for every failing check.
|
|
31364
31424
|
|
|
31365
31425
|
This resource mirrors agent-ready.dev's own /llms.txt so MCP clients can introspect the same surface that ChatGPT, Perplexity, and other AI agents see when discovering Agent Ready as a tool.
|
|
31366
31426
|
|
|
@@ -31421,6 +31481,10 @@ Agent Ready's checks map to the specifications below. Each entry links to the ca
|
|
|
31421
31481
|
- **Agent Skills Discovery** _(pre-standard)_ \u2014 A /.well-known/agent-skills/index.json manifest advertising installable agent skills. Pre-standard (Cloudflare RFC v0.2.0). Canonical: <https://github.com/cloudflare/agent-skills-discovery-rfc/blob/main/README.md> Checks: C15.
|
|
31422
31482
|
- **Content parity (anti-cloaking)** _(behavioural)_ \u2014 Not a published spec \u2014 a behavioural check comparing the AI-bot response to the baseline to detect cloaking (serving agents different content than humans). Canonical: _none published_ Checks: C16.
|
|
31423
31483
|
- **Agent-driven UI (A2UI)** _(pre-standard)_ \u2014 MCP-Apps / OpenAI Apps SDK UI surfaces declared on an MCP Server Card, letting agents render interactive widgets inline. Emerging. Canonical: <https://modelcontextprotocol.io> Checks: C17.
|
|
31484
|
+
|
|
31485
|
+
## Accessibility
|
|
31486
|
+
|
|
31487
|
+
- **WCAG 2.2 + layout stability** \u2014 The accessibility tree \u2014 image text alternatives, form labels, control names, resolved ARIA references, named iframes, a clean heading outline \u2014 is what assistive tech and AI agents parse to act on a page; explicit media dimensions and enabled zoom keep it stable and usable (with a static CLS proxy). Scored as a separate accessibilityScore, not part of the Vercel score. Canonical: <https://www.w3.org/TR/WCAG22/> Checks: A1\u2013A9.
|
|
31424
31488
|
`;
|
|
31425
31489
|
|
|
31426
31490
|
// src/resources.ts
|
|
@@ -31448,7 +31512,7 @@ function registerResources(server) {
|
|
|
31448
31512
|
"agent-ready://checks",
|
|
31449
31513
|
{
|
|
31450
31514
|
title: "Check registry",
|
|
31451
|
-
description: "Reference table of all 69 checks Agent Ready runs, grouped by category (site, page, llms.txt, protocol). Each row pairs the stable check ID (e.g. P11, S15, L9, C3) with its human-readable name. Use this to identify a check by id when interpreting scan results.",
|
|
31515
|
+
description: "Reference table of all 69 checks Agent Ready runs, grouped by category (site, page, llms.txt, protocol), plus the 9-check accessibility suite scored as a separate accessibility sub-score. Each row pairs the stable check ID (e.g. P11, S15, L9, C3, A7) with its human-readable name. Use this to identify a check by id when interpreting scan results.",
|
|
31452
31516
|
mimeType: "text/markdown"
|
|
31453
31517
|
},
|
|
31454
31518
|
async () => ({
|
|
@@ -31511,7 +31575,31 @@ var POLL_INTERVAL_MS = 2e3;
|
|
|
31511
31575
|
async function sleep(ms) {
|
|
31512
31576
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
31513
31577
|
}
|
|
31578
|
+
var ANON_TIER_NOTE = "Scanned on the anonymous free tier (3 scans per 30 days per IP, 25-page depth). A Pro API key (AGENT_READY_API_KEY) unlocks 50 scans/month, 250-page depth, scan history via get_scan, and weekly monitoring \u2014 https://agent-ready.dev/pricing";
|
|
31514
31579
|
async function scanSite(config2, input) {
|
|
31580
|
+
if (!config2.apiKey) {
|
|
31581
|
+
let res;
|
|
31582
|
+
try {
|
|
31583
|
+
res = await postAnonScan(config2, input.url);
|
|
31584
|
+
} catch (err) {
|
|
31585
|
+
if (err instanceof ApiError) {
|
|
31586
|
+
const hint = err.status === 429 ? " Set a Pro API key (AGENT_READY_API_KEY, from https://agent-ready.dev/dashboard/api-keys) to remove the anonymous cap." : "";
|
|
31587
|
+
throw new ToolError(err.code, err.message + hint);
|
|
31588
|
+
}
|
|
31589
|
+
throw err;
|
|
31590
|
+
}
|
|
31591
|
+
if (!res || typeof res !== "object" || !res.scan) {
|
|
31592
|
+
throw new ToolError(
|
|
31593
|
+
"invalid_response",
|
|
31594
|
+
"Anonymous scan returned no scan payload from /api/scan."
|
|
31595
|
+
);
|
|
31596
|
+
}
|
|
31597
|
+
const payload = { ...res.scan, message: ANON_TIER_NOTE };
|
|
31598
|
+
return {
|
|
31599
|
+
content: [{ type: "text", text: JSON.stringify(payload) }],
|
|
31600
|
+
structuredContent: payload
|
|
31601
|
+
};
|
|
31602
|
+
}
|
|
31515
31603
|
let placeholder;
|
|
31516
31604
|
try {
|
|
31517
31605
|
placeholder = await postScan(config2, {
|
|
@@ -31585,6 +31673,12 @@ async function getScanById(config2, input) {
|
|
|
31585
31673
|
if (err.status === 404) {
|
|
31586
31674
|
throw new ToolError("not_found", `Scan ${input.id} not found.`);
|
|
31587
31675
|
}
|
|
31676
|
+
if (err.code === "missing_api_key") {
|
|
31677
|
+
throw new ToolError(
|
|
31678
|
+
"missing_api_key",
|
|
31679
|
+
"get_scan needs a Pro API key (scan history is account-scoped). scan_site works without one on the anonymous tier and returns its result inline. Keys: https://agent-ready.dev/dashboard/api-keys"
|
|
31680
|
+
);
|
|
31681
|
+
}
|
|
31588
31682
|
throw new ToolError(err.code, err.message);
|
|
31589
31683
|
}
|
|
31590
31684
|
throw err;
|
|
@@ -31734,7 +31828,7 @@ var validateStructuredDataInputShape = {
|
|
|
31734
31828
|
// src/server.ts
|
|
31735
31829
|
var SERVER_INFO = {
|
|
31736
31830
|
name: "agent-ready",
|
|
31737
|
-
version: "0.
|
|
31831
|
+
version: "0.6.0"
|
|
31738
31832
|
};
|
|
31739
31833
|
function createMcpServer(config2) {
|
|
31740
31834
|
const server = new McpServer(SERVER_INFO);
|
|
@@ -31748,7 +31842,7 @@ function createMcpServer(config2) {
|
|
|
31748
31842
|
"scan_site",
|
|
31749
31843
|
{
|
|
31750
31844
|
title: "Scan a site for AI agent readability",
|
|
31751
|
-
description: "Runs the agent-ready.dev scanner against a URL and returns structured results: Vercel score, llmstxt.org score, and per-check findings with remediation hints.
|
|
31845
|
+
description: "Runs the agent-ready.dev scanner against a URL and returns structured results: Vercel score, llmstxt.org score, and per-check findings with remediation hints. Works without an API key on the anonymous free tier (3 scans/30 days per IP, 25-page depth, synchronous). With a Pro AGENT_READY_API_KEY it scans deeper (up to 250 pages) and may take up to ~60s; if the local poll deadline elapses, the tool returns the scan id and asks you to poll with get_scan.",
|
|
31752
31846
|
inputSchema: scanSiteInputShape,
|
|
31753
31847
|
outputSchema: scanOutputShape,
|
|
31754
31848
|
annotations: READ_ONLY_OPEN_WORLD
|
|
@@ -31765,7 +31859,7 @@ function createMcpServer(config2) {
|
|
|
31765
31859
|
"get_scan",
|
|
31766
31860
|
{
|
|
31767
31861
|
title: "Get a previous scan by id",
|
|
31768
|
-
description: "Fetches a completed or in-progress scan by its id.
|
|
31862
|
+
description: "Fetches a completed or in-progress scan by its id. Requires a Pro API key \u2014 scan history is account-scoped. (Anonymous scan_site calls return their result inline, so keyless use never needs this tool.)",
|
|
31769
31863
|
inputSchema: getScanInputShape,
|
|
31770
31864
|
outputSchema: scanOutputShape,
|
|
31771
31865
|
annotations: READ_ONLY_OPEN_WORLD
|
|
@@ -31833,7 +31927,7 @@ async function main() {
|
|
|
31833
31927
|
const config2 = createConfig();
|
|
31834
31928
|
if (!config2.apiKey) {
|
|
31835
31929
|
process.stderr.write(
|
|
31836
|
-
"agent-ready-mcp started without AGENT_READY_API_KEY \u2014
|
|
31930
|
+
"agent-ready-mcp started without AGENT_READY_API_KEY \u2014 scan_site runs on the anonymous free tier (3 scans per 30 days per IP, 25-page depth); get_scan needs a Pro key. Issue one at https://agent-ready.dev/dashboard/api-keys for deeper scans, history, and monitoring.\n"
|
|
31837
31931
|
);
|
|
31838
31932
|
}
|
|
31839
31933
|
const server = createMcpServer(config2);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agent-ready-mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"mcpName": "io.github.mlava/agent-ready-mcp",
|
|
5
5
|
"description": "MCP server for Agent Ready — scan any URL for AI-readability against the Vercel Agent Readability Spec, the llmstxt.org standard, and agent-protocol manifests (MCP server cards, A2A, agents.json, agent-permissions.json, UCP, x402, NLWeb). 69 checks with per-check fix guidance.",
|
|
6
6
|
"license": "MIT",
|