ax-audit 4.2.1 → 6.0.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/CHANGELOG.md +19 -0
- package/README.md +39 -4
- package/dist/baseline.js +1 -1
- package/dist/baseline.js.map +1 -1
- package/dist/check-ids.js +1 -1
- package/dist/check-ids.js.map +1 -1
- package/dist/cli.js +1 -1
- package/dist/cli.js.map +1 -1
- package/dist/constants.d.ts +1 -85
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +0 -135
- package/dist/constants.js.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/license.d.ts +8 -0
- package/dist/license.d.ts.map +1 -0
- package/dist/license.js +18 -0
- package/dist/license.js.map +1 -0
- package/dist/metadata.d.ts +6 -0
- package/dist/metadata.d.ts.map +1 -0
- package/dist/metadata.js +205 -0
- package/dist/metadata.js.map +1 -0
- package/dist/orchestrator.d.ts +1 -0
- package/dist/orchestrator.d.ts.map +1 -1
- package/dist/orchestrator.js +134 -56
- package/dist/orchestrator.js.map +1 -1
- package/dist/scorer.js +2 -2
- package/dist/scorer.js.map +1 -1
- package/dist/types.d.ts +4 -0
- package/dist/types.d.ts.map +1 -1
- package/docs/api.md +14 -3
- package/docs/architecture.md +9 -98
- package/docs/ci.md +19 -0
- package/docs/cli.md +11 -0
- package/docs/faq.md +18 -0
- package/docs/getting-started.md +33 -1
- package/package.json +5 -5
- package/dist/checks/agent-access.d.ts +0 -33
- package/dist/checks/agent-access.d.ts.map +0 -1
- package/dist/checks/agent-access.js +0 -256
- package/dist/checks/agent-access.js.map +0 -1
- package/dist/checks/agent-card.d.ts +0 -37
- package/dist/checks/agent-card.d.ts.map +0 -1
- package/dist/checks/agent-card.js +0 -352
- package/dist/checks/agent-card.js.map +0 -1
- package/dist/checks/agent-operability.d.ts +0 -66
- package/dist/checks/agent-operability.d.ts.map +0 -1
- package/dist/checks/agent-operability.js +0 -383
- package/dist/checks/agent-operability.js.map +0 -1
- package/dist/checks/agent-skills.d.ts +0 -24
- package/dist/checks/agent-skills.d.ts.map +0 -1
- package/dist/checks/agent-skills.js +0 -316
- package/dist/checks/agent-skills.js.map +0 -1
- package/dist/checks/ai-catalog.d.ts +0 -28
- package/dist/checks/ai-catalog.d.ts.map +0 -1
- package/dist/checks/ai-catalog.js +0 -254
- package/dist/checks/ai-catalog.js.map +0 -1
- package/dist/checks/ai-directives.d.ts +0 -57
- package/dist/checks/ai-directives.d.ts.map +0 -1
- package/dist/checks/ai-directives.js +0 -263
- package/dist/checks/ai-directives.js.map +0 -1
- package/dist/checks/api-discovery.d.ts +0 -26
- package/dist/checks/api-discovery.d.ts.map +0 -1
- package/dist/checks/api-discovery.js +0 -432
- package/dist/checks/api-discovery.js.map +0 -1
- package/dist/checks/auth-discovery.d.ts +0 -28
- package/dist/checks/auth-discovery.d.ts.map +0 -1
- package/dist/checks/auth-discovery.js +0 -302
- package/dist/checks/auth-discovery.js.map +0 -1
- package/dist/checks/commerce-discovery.d.ts +0 -40
- package/dist/checks/commerce-discovery.d.ts.map +0 -1
- package/dist/checks/commerce-discovery.js +0 -295
- package/dist/checks/commerce-discovery.js.map +0 -1
- package/dist/checks/content-negotiation.d.ts +0 -4
- package/dist/checks/content-negotiation.d.ts.map +0 -1
- package/dist/checks/content-negotiation.js +0 -253
- package/dist/checks/content-negotiation.js.map +0 -1
- package/dist/checks/crawl-efficiency.d.ts +0 -16
- package/dist/checks/crawl-efficiency.d.ts.map +0 -1
- package/dist/checks/crawl-efficiency.js +0 -186
- package/dist/checks/crawl-efficiency.js.map +0 -1
- package/dist/checks/frontmatter.d.ts +0 -34
- package/dist/checks/frontmatter.d.ts.map +0 -1
- package/dist/checks/frontmatter.js +0 -100
- package/dist/checks/frontmatter.js.map +0 -1
- package/dist/checks/html-rendering.d.ts +0 -21
- package/dist/checks/html-rendering.d.ts.map +0 -1
- package/dist/checks/html-rendering.js +0 -221
- package/dist/checks/html-rendering.js.map +0 -1
- package/dist/checks/html-utils.d.ts +0 -66
- package/dist/checks/html-utils.d.ts.map +0 -1
- package/dist/checks/html-utils.js +0 -139
- package/dist/checks/html-utils.js.map +0 -1
- package/dist/checks/http-headers.d.ts +0 -11
- package/dist/checks/http-headers.d.ts.map +0 -1
- package/dist/checks/http-headers.js +0 -249
- package/dist/checks/http-headers.js.map +0 -1
- package/dist/checks/http-hygiene.d.ts +0 -26
- package/dist/checks/http-hygiene.d.ts.map +0 -1
- package/dist/checks/http-hygiene.js +0 -257
- package/dist/checks/http-hygiene.js.map +0 -1
- package/dist/checks/index.d.ts +0 -3
- package/dist/checks/index.d.ts.map +0 -1
- package/dist/checks/index.js +0 -55
- package/dist/checks/index.js.map +0 -1
- package/dist/checks/llms-txt.d.ts +0 -19
- package/dist/checks/llms-txt.d.ts.map +0 -1
- package/dist/checks/llms-txt.js +0 -281
- package/dist/checks/llms-txt.js.map +0 -1
- package/dist/checks/mcp-discovery.d.ts +0 -30
- package/dist/checks/mcp-discovery.d.ts.map +0 -1
- package/dist/checks/mcp-discovery.js +0 -523
- package/dist/checks/mcp-discovery.js.map +0 -1
- package/dist/checks/meta-tags.d.ts +0 -17
- package/dist/checks/meta-tags.d.ts.map +0 -1
- package/dist/checks/meta-tags.js +0 -188
- package/dist/checks/meta-tags.js.map +0 -1
- package/dist/checks/robots-parser.d.ts +0 -110
- package/dist/checks/robots-parser.d.ts.map +0 -1
- package/dist/checks/robots-parser.js +0 -277
- package/dist/checks/robots-parser.js.map +0 -1
- package/dist/checks/robots-txt.d.ts +0 -6
- package/dist/checks/robots-txt.d.ts.map +0 -1
- package/dist/checks/robots-txt.js +0 -367
- package/dist/checks/robots-txt.js.map +0 -1
- package/dist/checks/rsl.d.ts +0 -4
- package/dist/checks/rsl.d.ts.map +0 -1
- package/dist/checks/rsl.js +0 -242
- package/dist/checks/rsl.js.map +0 -1
- package/dist/checks/security-txt.d.ts +0 -4
- package/dist/checks/security-txt.d.ts.map +0 -1
- package/dist/checks/security-txt.js +0 -81
- package/dist/checks/security-txt.js.map +0 -1
- package/dist/checks/seo-basics.d.ts +0 -13
- package/dist/checks/seo-basics.d.ts.map +0 -1
- package/dist/checks/seo-basics.js +0 -221
- package/dist/checks/seo-basics.js.map +0 -1
- package/dist/checks/sitemap.d.ts +0 -12
- package/dist/checks/sitemap.d.ts.map +0 -1
- package/dist/checks/sitemap.js +0 -240
- package/dist/checks/sitemap.js.map +0 -1
- package/dist/checks/structured-data.d.ts +0 -4
- package/dist/checks/structured-data.d.ts.map +0 -1
- package/dist/checks/structured-data.js +0 -408
- package/dist/checks/structured-data.js.map +0 -1
- package/dist/checks/structured-fields.d.ts +0 -46
- package/dist/checks/structured-fields.d.ts.map +0 -1
- package/dist/checks/structured-fields.js +0 -112
- package/dist/checks/structured-fields.js.map +0 -1
- package/dist/checks/surface.d.ts +0 -59
- package/dist/checks/surface.d.ts.map +0 -1
- package/dist/checks/surface.js +0 -106
- package/dist/checks/surface.js.map +0 -1
- package/dist/checks/tls-https.d.ts +0 -13
- package/dist/checks/tls-https.d.ts.map +0 -1
- package/dist/checks/tls-https.js +0 -163
- package/dist/checks/tls-https.js.map +0 -1
- package/dist/checks/usage-policy.d.ts +0 -53
- package/dist/checks/usage-policy.d.ts.map +0 -1
- package/dist/checks/usage-policy.js +0 -339
- package/dist/checks/usage-policy.js.map +0 -1
- package/dist/checks/utils.d.ts +0 -40
- package/dist/checks/utils.d.ts.map +0 -1
- package/dist/checks/utils.js +0 -74
- package/dist/checks/utils.js.map +0 -1
- package/dist/checks/waf.d.ts +0 -75
- package/dist/checks/waf.d.ts.map +0 -1
- package/dist/checks/waf.js +0 -203
- package/dist/checks/waf.js.map +0 -1
- package/dist/checks/webmcp.d.ts +0 -55
- package/dist/checks/webmcp.d.ts.map +0 -1
- package/dist/checks/webmcp.js +0 -209
- package/dist/checks/webmcp.js.map +0 -1
- package/dist/checks/well-known.d.ts +0 -38
- package/dist/checks/well-known.d.ts.map +0 -1
- package/dist/checks/well-known.js +0 -202
- package/dist/checks/well-known.js.map +0 -1
- package/dist/fetcher.d.ts +0 -15
- package/dist/fetcher.d.ts.map +0 -1
- package/dist/fetcher.js +0 -127
- package/dist/fetcher.js.map +0 -1
- package/dist/guide-urls.d.ts +0 -2
- package/dist/guide-urls.d.ts.map +0 -1
- package/dist/guide-urls.js +0 -5
- package/dist/guide-urls.js.map +0 -1
- package/docs/roadmap.md +0 -367
|
@@ -1,523 +0,0 @@
|
|
|
1
|
-
import { AI_CATALOG_ENTRY_TYPES, MCP_PROTOCOL_VERSIONS, MCP_REMOTE_TYPES, MCP_SERVER_CARD_MEDIA_TYPE, MCP_SERVER_CARD_REQUIRED, MCP_STALE_PROTOCOL_VERSIONS, } from '../constants.js';
|
|
2
|
-
import { guideUrl } from '../guide-urls.js';
|
|
3
|
-
import { buildResult, checkContentType, isHtmlDocument, notApplicable } from './utils.js';
|
|
4
|
-
import { hasMcpSurface } from './surface.js';
|
|
5
|
-
import { standingNote } from './well-known.js';
|
|
6
|
-
/**
|
|
7
|
-
* "mcp-discovery" — how an agent finds this site's MCP server.
|
|
8
|
-
*
|
|
9
|
-
* ax-audit used to look for `/.well-known/mcp.json` and validate a `tools[]`
|
|
10
|
-
* array inside it. That path was never part of the Model Context Protocol
|
|
11
|
-
* specification — it was a plausible-looking convention that several tools,
|
|
12
|
-
* this one included, recommended before the ecosystem settled. Advertising
|
|
13
|
-
* static tool lists was the wrong idea anyway: tools come from a live
|
|
14
|
-
* `tools/list` call, and a copy in a static file starts drifting the day it is
|
|
15
|
-
* written.
|
|
16
|
-
*
|
|
17
|
-
* What actually emerged is the **server card**: a small document identifying
|
|
18
|
-
* the server and listing its remote endpoints, deliberately without tools.
|
|
19
|
-
* SEP-2127 and the `experimental-ext-server-card` repository recommend serving
|
|
20
|
-
* it at `<streamable-http-url>/server-card`, or referencing it from
|
|
21
|
-
* `/.well-known/ai-catalog.json`. Cloudflare and Mintlify serve one at
|
|
22
|
-
* `/.well-known/mcp/server-card.json`.
|
|
23
|
-
*
|
|
24
|
-
* All of that is still draft, and drafts get renamed — so this check probes the
|
|
25
|
-
* whole chain, labels each hit with its standing, and never treats one draft
|
|
26
|
-
* path as the single correct answer.
|
|
27
|
-
*
|
|
28
|
-
* Scoring note for 3.x: a site whose only MCP document is the legacy
|
|
29
|
-
* `/.well-known/mcp.json` is validated with the pre-3.7 rules, so its score is
|
|
30
|
-
* exactly what 3.6 produced. The path itself is reported, not penalised.
|
|
31
|
-
*/
|
|
32
|
-
export const meta = {
|
|
33
|
-
id: 'mcp-discovery',
|
|
34
|
-
name: 'MCP Discovery',
|
|
35
|
-
description: 'Checks how AI agents discover this site’s Model Context Protocol server',
|
|
36
|
-
category: 'protocols',
|
|
37
|
-
aliases: ['mcp'],
|
|
38
|
-
};
|
|
39
|
-
const MECHANISM_LABEL = {
|
|
40
|
-
'ai-catalog': '/.well-known/ai-catalog.json entry',
|
|
41
|
-
'well-known-server-card': '/.well-known/mcp/server-card.json',
|
|
42
|
-
'well-known-server-cards': '/.well-known/mcp/server-cards.json',
|
|
43
|
-
'endpoint-server-card': '<endpoint>/server-card',
|
|
44
|
-
'legacy-manifest': '/.well-known/mcp.json',
|
|
45
|
-
};
|
|
46
|
-
/** Endpoint paths worth trying a server card against, in order of convention strength. */
|
|
47
|
-
const ENDPOINT_CANDIDATES = ['/mcp', '/api/mcp', '/sse'];
|
|
48
|
-
/**
|
|
49
|
-
* Fetch a probe path, treating an HTML response as "not present". An SPA
|
|
50
|
-
* catch-all answers every unknown path with its index shell, and accepting one
|
|
51
|
-
* would report a malformed server card on a site that has no MCP server at all.
|
|
52
|
-
*/
|
|
53
|
-
async function fetchIfPresent(ctx, path) {
|
|
54
|
-
const res = await ctx.fetch(`${ctx.url}${path}`);
|
|
55
|
-
if (!res.ok || res.body.trim().length === 0)
|
|
56
|
-
return null;
|
|
57
|
-
return isHtmlDocument(res.body) ? null : res;
|
|
58
|
-
}
|
|
59
|
-
/**
|
|
60
|
-
* Walk the discovery chain. Returns every mechanism that produced a document,
|
|
61
|
-
* so the report can say which ones work and which are missing rather than
|
|
62
|
-
* stopping at the first hit.
|
|
63
|
-
*/
|
|
64
|
-
async function locate(ctx) {
|
|
65
|
-
const found = [];
|
|
66
|
-
const catalog = await fetchIfPresent(ctx, '/.well-known/ai-catalog.json');
|
|
67
|
-
if (catalog !== null && mentionsMcpEntry(catalog.body)) {
|
|
68
|
-
found.push({ mechanism: 'ai-catalog', path: '/.well-known/ai-catalog.json', res: catalog });
|
|
69
|
-
}
|
|
70
|
-
for (const [mechanism, path] of [
|
|
71
|
-
['well-known-server-card', '/.well-known/mcp/server-card.json'],
|
|
72
|
-
['well-known-server-cards', '/.well-known/mcp/server-cards.json'],
|
|
73
|
-
]) {
|
|
74
|
-
const res = await fetchIfPresent(ctx, path);
|
|
75
|
-
if (res !== null)
|
|
76
|
-
found.push({ mechanism, path, res });
|
|
77
|
-
}
|
|
78
|
-
for (const endpoint of ENDPOINT_CANDIDATES) {
|
|
79
|
-
const path = `${endpoint}/server-card`;
|
|
80
|
-
const res = await fetchIfPresent(ctx, path);
|
|
81
|
-
if (res !== null) {
|
|
82
|
-
found.push({ mechanism: 'endpoint-server-card', path, res });
|
|
83
|
-
break;
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
const legacy = await fetchIfPresent(ctx, '/.well-known/mcp.json');
|
|
87
|
-
if (legacy !== null)
|
|
88
|
-
found.push({ mechanism: 'legacy-manifest', path: '/.well-known/mcp.json', res: legacy });
|
|
89
|
-
return found;
|
|
90
|
-
}
|
|
91
|
-
/** Does an ai-catalog document reference an MCP server card? */
|
|
92
|
-
function mentionsMcpEntry(body) {
|
|
93
|
-
try {
|
|
94
|
-
const data = JSON.parse(body);
|
|
95
|
-
const entries = Array.isArray(data.entries) ? data.entries : [];
|
|
96
|
-
return entries.some((e) => String(e.type ?? '') === MCP_SERVER_CARD_MEDIA_TYPE);
|
|
97
|
-
}
|
|
98
|
-
catch {
|
|
99
|
-
return false;
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
export default async function check(ctx) {
|
|
103
|
-
const start = performance.now();
|
|
104
|
-
const findings = [];
|
|
105
|
-
const found = await locate(ctx);
|
|
106
|
-
if (found.length === 0) {
|
|
107
|
-
const surface = await hasMcpSurface(ctx);
|
|
108
|
-
if (!surface.found) {
|
|
109
|
-
findings.push({
|
|
110
|
-
status: 'pass',
|
|
111
|
-
message: 'No MCP server — MCP discovery does not apply to this site',
|
|
112
|
-
detail: 'A server card describes an MCP server so agents can find it. A site that runs none has nothing to ' +
|
|
113
|
-
'advertise. Run with --profile mcp to audit as though it did.',
|
|
114
|
-
});
|
|
115
|
-
return notApplicable(meta, findings, start);
|
|
116
|
-
}
|
|
117
|
-
findings.push({
|
|
118
|
-
status: 'fail',
|
|
119
|
-
message: 'MCP server present but not discoverable',
|
|
120
|
-
detail: `Evidence of a server: ${surface.reason}.`,
|
|
121
|
-
hint: 'Agents have to be told the URL by a human. Publish a server card so they can find it. ' +
|
|
122
|
-
'Serve it at <your-mcp-endpoint>/server-card with Content-Type: application/mcp-server-card+json, and ' +
|
|
123
|
-
'reference it from /.well-known/ai-catalog.json. A card declares $schema, name (reverse-DNS), version, ' +
|
|
124
|
-
'description and remotes[] — not tools, which agents read live from tools/list.',
|
|
125
|
-
learnMoreUrl: guideUrl(meta.id, 'not-found'),
|
|
126
|
-
});
|
|
127
|
-
return buildResult(meta, 0, findings, start);
|
|
128
|
-
}
|
|
129
|
-
const modern = found.filter((f) => f.mechanism !== 'legacy-manifest');
|
|
130
|
-
// A site whose only document is the pre-standard manifest is scored exactly
|
|
131
|
-
// as 3.6 scored it, so the correction to the discovery model cannot move an
|
|
132
|
-
// existing score. The path itself is reported, not penalised.
|
|
133
|
-
if (modern.length === 0) {
|
|
134
|
-
return validateLegacyManifest(found[0], findings, start);
|
|
135
|
-
}
|
|
136
|
-
findings.push({
|
|
137
|
-
status: 'pass',
|
|
138
|
-
message: `MCP server discoverable via ${modern.map((m) => MECHANISM_LABEL[m.mechanism]).join(' + ')}`,
|
|
139
|
-
detail: standingNote(modern[0].path),
|
|
140
|
-
});
|
|
141
|
-
if (found.some((f) => f.mechanism === 'legacy-manifest')) {
|
|
142
|
-
findings.push({
|
|
143
|
-
status: 'warn',
|
|
144
|
-
message: '/.well-known/mcp.json is also served, and is not a specified path',
|
|
145
|
-
detail: standingNote('/.well-known/mcp.json'),
|
|
146
|
-
hint: 'Now that a server card is published, the ad-hoc manifest can be removed to avoid two sources of truth.',
|
|
147
|
-
learnMoreUrl: guideUrl(meta.id, 'legacy-manifest'),
|
|
148
|
-
});
|
|
149
|
-
}
|
|
150
|
-
return validateServerCard(modern[0], findings, start);
|
|
151
|
-
}
|
|
152
|
-
/** Validate a server card per the MCP server-card extension schema. */
|
|
153
|
-
function validateServerCard(located, findings, start) {
|
|
154
|
-
let score = 100;
|
|
155
|
-
const { res, path, mechanism } = located;
|
|
156
|
-
const acceptable = mechanism === 'ai-catalog'
|
|
157
|
-
? ['application/json', 'application/ai-catalog+json']
|
|
158
|
-
: ['application/json', MCP_SERVER_CARD_MEDIA_TYPE];
|
|
159
|
-
const ctFinding = checkContentType(res, acceptable, {
|
|
160
|
-
checkId: meta.id,
|
|
161
|
-
resourceLabel: path,
|
|
162
|
-
anchor: 'wrong-content-type',
|
|
163
|
-
});
|
|
164
|
-
if (ctFinding) {
|
|
165
|
-
findings.push(ctFinding);
|
|
166
|
-
score -= 5;
|
|
167
|
-
}
|
|
168
|
-
let data;
|
|
169
|
-
try {
|
|
170
|
-
data = JSON.parse(res.body);
|
|
171
|
-
}
|
|
172
|
-
catch {
|
|
173
|
-
findings.push({
|
|
174
|
-
status: 'fail',
|
|
175
|
-
message: `Invalid JSON in ${path}`,
|
|
176
|
-
hint: 'Fix the JSON syntax. Validate with a JSON linter.',
|
|
177
|
-
learnMoreUrl: guideUrl(meta.id, 'invalid-json'),
|
|
178
|
-
});
|
|
179
|
-
return buildResult(meta, 10, findings, start);
|
|
180
|
-
}
|
|
181
|
-
findings.push({ status: 'pass', message: 'Valid JSON' });
|
|
182
|
-
if (mechanism === 'ai-catalog') {
|
|
183
|
-
return validateCatalog(data, findings, score, start);
|
|
184
|
-
}
|
|
185
|
-
// `server-cards.json` holds an array; a single card is the object itself.
|
|
186
|
-
const cards = Array.isArray(data.servers)
|
|
187
|
-
? data.servers
|
|
188
|
-
: Array.isArray(data)
|
|
189
|
-
? data
|
|
190
|
-
: [data];
|
|
191
|
-
if (cards.length > 1) {
|
|
192
|
-
findings.push({ status: 'pass', message: `${cards.length} server cards declared` });
|
|
193
|
-
}
|
|
194
|
-
for (const card of cards) {
|
|
195
|
-
score = validateOneCard(card, cards.length > 1, findings, score);
|
|
196
|
-
}
|
|
197
|
-
if (res.headers['access-control-allow-origin']) {
|
|
198
|
-
findings.push({ status: 'pass', message: 'CORS enabled on the server card' });
|
|
199
|
-
}
|
|
200
|
-
else {
|
|
201
|
-
findings.push({
|
|
202
|
-
status: 'warn',
|
|
203
|
-
message: 'No CORS headers on the server card',
|
|
204
|
-
hint: 'Add Access-Control-Allow-Origin: * so browser-based agents can read the card. The extension recommends it alongside Cache-Control: public, max-age=3600.',
|
|
205
|
-
learnMoreUrl: guideUrl(meta.id, 'no-cors'),
|
|
206
|
-
});
|
|
207
|
-
score -= 10;
|
|
208
|
-
}
|
|
209
|
-
return buildResult(meta, score, findings, start);
|
|
210
|
-
}
|
|
211
|
-
/** Fields required of every server card. */
|
|
212
|
-
function validateOneCard(card, multiple, findings, score) {
|
|
213
|
-
const label = multiple ? `"${String(card.name ?? 'unnamed')}"` : 'Server card';
|
|
214
|
-
for (const field of MCP_SERVER_CARD_REQUIRED) {
|
|
215
|
-
if (card[field] !== undefined && card[field] !== null && card[field] !== '')
|
|
216
|
-
continue;
|
|
217
|
-
findings.push({
|
|
218
|
-
status: 'fail',
|
|
219
|
-
message: `${label}: required field "${field}" missing`,
|
|
220
|
-
hint: `A server card must declare ${MCP_SERVER_CARD_REQUIRED.join(', ')}.`,
|
|
221
|
-
learnMoreUrl: guideUrl(meta.id, 'missing-field'),
|
|
222
|
-
});
|
|
223
|
-
score -= 15;
|
|
224
|
-
}
|
|
225
|
-
// Names are reverse-DNS so servers from different publishers cannot collide
|
|
226
|
-
// in a registry: `io.github.acme/weather`, `com.example.docs`.
|
|
227
|
-
const name = typeof card.name === 'string' ? card.name : '';
|
|
228
|
-
if (name !== '' && !/^[a-z0-9][a-z0-9.-]*\.[a-z0-9-]+(\/[a-z0-9._-]+)?$/i.test(name)) {
|
|
229
|
-
findings.push({
|
|
230
|
-
status: 'warn',
|
|
231
|
-
message: `${label}: name "${name}" is not in reverse-DNS form`,
|
|
232
|
-
hint: 'Use a reverse-DNS name such as com.example/docs or io.github.owner/server, so the server is globally unambiguous in a registry.',
|
|
233
|
-
learnMoreUrl: guideUrl(meta.id, 'name-format'),
|
|
234
|
-
});
|
|
235
|
-
score -= 5;
|
|
236
|
-
}
|
|
237
|
-
else if (name !== '') {
|
|
238
|
-
findings.push({ status: 'pass', message: `${label}: name "${name}"` });
|
|
239
|
-
}
|
|
240
|
-
score = validateRemotes(card, label, findings, score);
|
|
241
|
-
if (card.tools !== undefined) {
|
|
242
|
-
findings.push({
|
|
243
|
-
status: 'warn',
|
|
244
|
-
message: `${label}: declares tools[], which a server card does not carry`,
|
|
245
|
-
hint: 'Tool lists come from a live tools/list call. A static copy drifts from the server, so the card schema deliberately omits it.',
|
|
246
|
-
learnMoreUrl: guideUrl(meta.id, 'tools-in-card'),
|
|
247
|
-
});
|
|
248
|
-
}
|
|
249
|
-
if (typeof card.websiteUrl === 'string' || typeof card.repository === 'object') {
|
|
250
|
-
findings.push({ status: 'pass', message: `${label}: provenance declared (websiteUrl / repository)` });
|
|
251
|
-
}
|
|
252
|
-
return score;
|
|
253
|
-
}
|
|
254
|
-
/** Remote endpoints: how an agent actually connects. */
|
|
255
|
-
function validateRemotes(card, label, findings, score) {
|
|
256
|
-
const remotes = Array.isArray(card.remotes) ? card.remotes : [];
|
|
257
|
-
if (remotes.length === 0) {
|
|
258
|
-
findings.push({
|
|
259
|
-
status: 'warn',
|
|
260
|
-
message: `${label}: no remotes[] declared`,
|
|
261
|
-
hint: 'Declare at least one remote so an agent knows where to connect: { "type": "streamable-http", "url": "https://example.com/mcp", "supportedProtocolVersions": ["2026-07-28"] }.',
|
|
262
|
-
learnMoreUrl: guideUrl(meta.id, 'no-remotes'),
|
|
263
|
-
});
|
|
264
|
-
return score - 15;
|
|
265
|
-
}
|
|
266
|
-
findings.push({ status: 'pass', message: `${label}: ${remotes.length} remote endpoint(s) declared` });
|
|
267
|
-
const badType = remotes.map((r) => String(r.type ?? '')).filter((t) => !MCP_REMOTE_TYPES.includes(t));
|
|
268
|
-
if (badType.length > 0) {
|
|
269
|
-
findings.push({
|
|
270
|
-
status: 'warn',
|
|
271
|
-
message: `${label}: remote with an unrecognised transport type`,
|
|
272
|
-
detail: badType.map((t) => t || '(missing)').join(', '),
|
|
273
|
-
hint: `Transports are ${MCP_REMOTE_TYPES.join(' and ')}. SSE is the legacy transport; new servers use streamable-http.`,
|
|
274
|
-
learnMoreUrl: guideUrl(meta.id, 'remote-type'),
|
|
275
|
-
});
|
|
276
|
-
score -= 5;
|
|
277
|
-
}
|
|
278
|
-
const noUrl = remotes.filter((r) => typeof r.url !== 'string' || r.url === '').length;
|
|
279
|
-
if (noUrl > 0) {
|
|
280
|
-
findings.push({
|
|
281
|
-
status: 'fail',
|
|
282
|
-
message: `${label}: ${noUrl} remote(s) missing a url`,
|
|
283
|
-
hint: 'Every remote needs an absolute https:// URL.',
|
|
284
|
-
learnMoreUrl: guideUrl(meta.id, 'remote-url'),
|
|
285
|
-
});
|
|
286
|
-
score -= 10;
|
|
287
|
-
}
|
|
288
|
-
const declaredVersions = remotes.flatMap((r) => Array.isArray(r.supportedProtocolVersions) ? r.supportedProtocolVersions.map(String) : []);
|
|
289
|
-
if (declaredVersions.length === 0) {
|
|
290
|
-
findings.push({
|
|
291
|
-
status: 'warn',
|
|
292
|
-
message: `${label}: no supportedProtocolVersions declared`,
|
|
293
|
-
hint: `Declare which MCP revisions the server speaks, newest first. Current: ${MCP_PROTOCOL_VERSIONS[0]}.`,
|
|
294
|
-
learnMoreUrl: guideUrl(meta.id, 'no-protocol-version'),
|
|
295
|
-
});
|
|
296
|
-
score -= 10;
|
|
297
|
-
return score;
|
|
298
|
-
}
|
|
299
|
-
const unknown = declaredVersions.filter((v) => !MCP_PROTOCOL_VERSIONS.includes(v));
|
|
300
|
-
if (unknown.length > 0) {
|
|
301
|
-
findings.push({
|
|
302
|
-
status: 'warn',
|
|
303
|
-
message: `${label}: unrecognised MCP protocol version(s)`,
|
|
304
|
-
detail: unknown.join(', '),
|
|
305
|
-
hint: `Released revisions are ${MCP_PROTOCOL_VERSIONS.join(', ')}.`,
|
|
306
|
-
learnMoreUrl: guideUrl(meta.id, 'unknown-protocol-version'),
|
|
307
|
-
});
|
|
308
|
-
score -= 5;
|
|
309
|
-
}
|
|
310
|
-
const known = declaredVersions.filter((v) => MCP_PROTOCOL_VERSIONS.includes(v));
|
|
311
|
-
if (known.length > 0 && known.every((v) => MCP_STALE_PROTOCOL_VERSIONS.includes(v))) {
|
|
312
|
-
findings.push({
|
|
313
|
-
status: 'warn',
|
|
314
|
-
message: `${label}: only pre-2025-06 protocol revisions supported`,
|
|
315
|
-
detail: known.join(', '),
|
|
316
|
-
hint: `The current revision is ${MCP_PROTOCOL_VERSIONS[0]}, which removed sessions and initialize and added server/discover. Clients on newer revisions may not negotiate down.`,
|
|
317
|
-
learnMoreUrl: guideUrl(meta.id, 'stale-protocol-version'),
|
|
318
|
-
});
|
|
319
|
-
score -= 10;
|
|
320
|
-
}
|
|
321
|
-
else if (known.includes(MCP_PROTOCOL_VERSIONS[0])) {
|
|
322
|
-
findings.push({
|
|
323
|
-
status: 'pass',
|
|
324
|
-
message: `${label}: supports the current MCP revision (${MCP_PROTOCOL_VERSIONS[0]})`,
|
|
325
|
-
});
|
|
326
|
-
}
|
|
327
|
-
return score;
|
|
328
|
-
}
|
|
329
|
-
/** Validate an ai-catalog document that points at MCP entries. */
|
|
330
|
-
function validateCatalog(data, findings, score, start) {
|
|
331
|
-
const entries = Array.isArray(data.entries) ? data.entries : [];
|
|
332
|
-
const mcpEntries = entries.filter((e) => String(e.type ?? '') === MCP_SERVER_CARD_MEDIA_TYPE);
|
|
333
|
-
findings.push({
|
|
334
|
-
status: 'pass',
|
|
335
|
-
message: `AI catalog lists ${mcpEntries.length} MCP server card entry(ies) of ${entries.length} total`,
|
|
336
|
-
});
|
|
337
|
-
if (data.specVersion === undefined) {
|
|
338
|
-
findings.push({
|
|
339
|
-
status: 'warn',
|
|
340
|
-
message: 'AI catalog has no specVersion',
|
|
341
|
-
hint: 'Declare "specVersion": "1.0" so consumers know which catalog revision to expect.',
|
|
342
|
-
learnMoreUrl: guideUrl(meta.id, 'catalog-no-version'),
|
|
343
|
-
});
|
|
344
|
-
score -= 5;
|
|
345
|
-
}
|
|
346
|
-
const incomplete = mcpEntries.filter((e) => !e.identifier || (!e.url && !e.data));
|
|
347
|
-
if (incomplete.length > 0) {
|
|
348
|
-
findings.push({
|
|
349
|
-
status: 'warn',
|
|
350
|
-
message: `${incomplete.length} catalog entry(ies) missing identifier or url/data`,
|
|
351
|
-
hint: 'Each entry needs an identifier, a type, and either an inline data object or a url pointing at the document.',
|
|
352
|
-
learnMoreUrl: guideUrl(meta.id, 'catalog-entry'),
|
|
353
|
-
});
|
|
354
|
-
score -= 10;
|
|
355
|
-
}
|
|
356
|
-
const unknownTypes = entries
|
|
357
|
-
.map((e) => String(e.type ?? ''))
|
|
358
|
-
.filter((t) => t !== '' && !Object.keys(AI_CATALOG_ENTRY_TYPES).includes(t));
|
|
359
|
-
if (unknownTypes.length > 0) {
|
|
360
|
-
findings.push({
|
|
361
|
-
status: 'warn',
|
|
362
|
-
message: 'Catalog entry with an unrecognised type',
|
|
363
|
-
detail: [...new Set(unknownTypes)].join(', '),
|
|
364
|
-
hint: `Known entry types: ${Object.keys(AI_CATALOG_ENTRY_TYPES).join(', ')}.`,
|
|
365
|
-
learnMoreUrl: guideUrl(meta.id, 'catalog-entry-type'),
|
|
366
|
-
});
|
|
367
|
-
score -= 5;
|
|
368
|
-
}
|
|
369
|
-
return buildResult(meta, score, findings, start);
|
|
370
|
-
}
|
|
371
|
-
/**
|
|
372
|
-
* The pre-3.7 validation, applied unchanged to a site whose only MCP document
|
|
373
|
-
* is `/.well-known/mcp.json`. Reproducing the old rules exactly is what lets
|
|
374
|
-
* 3.7 correct the discovery model without moving anybody's score.
|
|
375
|
-
*/
|
|
376
|
-
function validateLegacyManifest(located, findings, start) {
|
|
377
|
-
let score = 100;
|
|
378
|
-
const { res } = located;
|
|
379
|
-
findings.push({ status: 'pass', message: '/.well-known/mcp.json exists' });
|
|
380
|
-
findings.push({
|
|
381
|
-
status: 'warn',
|
|
382
|
-
message: '/.well-known/mcp.json is not a specified discovery path',
|
|
383
|
-
detail: standingNote('/.well-known/mcp.json'),
|
|
384
|
-
hint: 'Publish a server card at <your-mcp-endpoint>/server-card with Content-Type: application/mcp-server-card+json, ' +
|
|
385
|
-
'and reference it from /.well-known/ai-catalog.json. Keep this file until your clients have migrated.',
|
|
386
|
-
learnMoreUrl: guideUrl(meta.id, 'legacy-manifest'),
|
|
387
|
-
});
|
|
388
|
-
const ctFinding = checkContentType(res, ['application/json'], {
|
|
389
|
-
checkId: meta.id,
|
|
390
|
-
resourceLabel: '/.well-known/mcp.json',
|
|
391
|
-
anchor: 'wrong-content-type',
|
|
392
|
-
});
|
|
393
|
-
if (ctFinding) {
|
|
394
|
-
findings.push(ctFinding);
|
|
395
|
-
score -= 5;
|
|
396
|
-
}
|
|
397
|
-
let data;
|
|
398
|
-
try {
|
|
399
|
-
data = JSON.parse(res.body);
|
|
400
|
-
}
|
|
401
|
-
catch {
|
|
402
|
-
findings.push({
|
|
403
|
-
status: 'fail',
|
|
404
|
-
message: 'Invalid JSON',
|
|
405
|
-
hint: 'Fix the JSON syntax in your mcp.json file. Validate with a JSON linter.',
|
|
406
|
-
learnMoreUrl: guideUrl(meta.id, 'invalid-json'),
|
|
407
|
-
});
|
|
408
|
-
return buildResult(meta, 10, findings, start);
|
|
409
|
-
}
|
|
410
|
-
findings.push({ status: 'pass', message: 'Valid JSON' });
|
|
411
|
-
if (data.name) {
|
|
412
|
-
findings.push({ status: 'pass', message: `Server name: "${String(data.name)}"` });
|
|
413
|
-
}
|
|
414
|
-
else {
|
|
415
|
-
findings.push({
|
|
416
|
-
status: 'warn',
|
|
417
|
-
message: 'Missing server name',
|
|
418
|
-
hint: 'Add a "name" field identifying your MCP server.',
|
|
419
|
-
learnMoreUrl: guideUrl(meta.id, 'missing-name'),
|
|
420
|
-
});
|
|
421
|
-
score -= 10;
|
|
422
|
-
}
|
|
423
|
-
if (data.description) {
|
|
424
|
-
findings.push({ status: 'pass', message: 'Server description present' });
|
|
425
|
-
}
|
|
426
|
-
else {
|
|
427
|
-
findings.push({
|
|
428
|
-
status: 'warn',
|
|
429
|
-
message: 'Missing server description',
|
|
430
|
-
hint: 'Add a "description" field explaining what your MCP server does.',
|
|
431
|
-
learnMoreUrl: guideUrl(meta.id, 'missing-description'),
|
|
432
|
-
});
|
|
433
|
-
score -= 5;
|
|
434
|
-
}
|
|
435
|
-
if (Array.isArray(data.tools) && data.tools.length > 0) {
|
|
436
|
-
const tools = data.tools;
|
|
437
|
-
findings.push({ status: 'pass', message: `${tools.length} tool(s) defined` });
|
|
438
|
-
const described = tools.filter((t) => t.description);
|
|
439
|
-
if (described.length === tools.length) {
|
|
440
|
-
findings.push({ status: 'pass', message: 'All tools have descriptions' });
|
|
441
|
-
}
|
|
442
|
-
else if (described.length > 0) {
|
|
443
|
-
findings.push({
|
|
444
|
-
status: 'warn',
|
|
445
|
-
message: `${described.length}/${tools.length} tools have descriptions`,
|
|
446
|
-
hint: 'Add a "description" to each tool so agents understand what it does.',
|
|
447
|
-
learnMoreUrl: guideUrl(meta.id, 'missing-tool-descriptions'),
|
|
448
|
-
});
|
|
449
|
-
score -= 5;
|
|
450
|
-
}
|
|
451
|
-
else {
|
|
452
|
-
findings.push({
|
|
453
|
-
status: 'warn',
|
|
454
|
-
message: 'No tools have descriptions',
|
|
455
|
-
hint: 'Add a "description" to each tool. Descriptions are how an agent decides which tool to call.',
|
|
456
|
-
learnMoreUrl: guideUrl(meta.id, 'no-tool-descriptions'),
|
|
457
|
-
});
|
|
458
|
-
score -= 10;
|
|
459
|
-
}
|
|
460
|
-
}
|
|
461
|
-
else if (Array.isArray(data.tools)) {
|
|
462
|
-
findings.push({
|
|
463
|
-
status: 'warn',
|
|
464
|
-
message: 'Tools array is empty',
|
|
465
|
-
hint: 'Add at least one tool with name, description and inputSchema.',
|
|
466
|
-
learnMoreUrl: guideUrl(meta.id, 'empty-tools'),
|
|
467
|
-
});
|
|
468
|
-
score -= 15;
|
|
469
|
-
}
|
|
470
|
-
else {
|
|
471
|
-
findings.push({
|
|
472
|
-
status: 'warn',
|
|
473
|
-
message: 'No tools array defined',
|
|
474
|
-
hint: 'Add a "tools" array. Each tool should have name, description and inputSchema.',
|
|
475
|
-
learnMoreUrl: guideUrl(meta.id, 'no-tools'),
|
|
476
|
-
});
|
|
477
|
-
score -= 15;
|
|
478
|
-
}
|
|
479
|
-
if (Array.isArray(data.resources) && data.resources.length > 0) {
|
|
480
|
-
findings.push({ status: 'pass', message: `${data.resources.length} resource(s) defined` });
|
|
481
|
-
}
|
|
482
|
-
else {
|
|
483
|
-
findings.push({
|
|
484
|
-
status: 'warn',
|
|
485
|
-
message: 'No resources defined',
|
|
486
|
-
hint: 'Add a "resources" array listing the data your MCP server exposes.',
|
|
487
|
-
learnMoreUrl: guideUrl(meta.id, 'no-resources'),
|
|
488
|
-
});
|
|
489
|
-
score -= 5;
|
|
490
|
-
}
|
|
491
|
-
if (Array.isArray(data.prompts) && data.prompts.length > 0) {
|
|
492
|
-
findings.push({ status: 'pass', message: `${data.prompts.length} prompt(s) defined` });
|
|
493
|
-
}
|
|
494
|
-
if (data.version || data.protocolVersion) {
|
|
495
|
-
findings.push({ status: 'pass', message: `Protocol version: ${String(data.protocolVersion ?? data.version)}` });
|
|
496
|
-
}
|
|
497
|
-
else {
|
|
498
|
-
findings.push({
|
|
499
|
-
status: 'warn',
|
|
500
|
-
message: 'No protocol version specified',
|
|
501
|
-
hint: `Add a "protocolVersion" field declaring MCP spec compatibility. Current revision: ${MCP_PROTOCOL_VERSIONS[0]}.`,
|
|
502
|
-
learnMoreUrl: guideUrl(meta.id, 'no-version'),
|
|
503
|
-
});
|
|
504
|
-
score -= 5;
|
|
505
|
-
}
|
|
506
|
-
if (data.authentication) {
|
|
507
|
-
findings.push({ status: 'pass', message: 'Authentication configuration present' });
|
|
508
|
-
}
|
|
509
|
-
if (res.headers['access-control-allow-origin']) {
|
|
510
|
-
findings.push({ status: 'pass', message: 'CORS enabled on MCP endpoint' });
|
|
511
|
-
}
|
|
512
|
-
else {
|
|
513
|
-
findings.push({
|
|
514
|
-
status: 'warn',
|
|
515
|
-
message: 'No CORS headers on MCP endpoint',
|
|
516
|
-
hint: 'Add Access-Control-Allow-Origin: * so browser-based agents can fetch the document.',
|
|
517
|
-
learnMoreUrl: guideUrl(meta.id, 'no-cors'),
|
|
518
|
-
});
|
|
519
|
-
score -= 10;
|
|
520
|
-
}
|
|
521
|
-
return buildResult(meta, score, findings, start);
|
|
522
|
-
}
|
|
523
|
-
//# sourceMappingURL=mcp-discovery.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"mcp-discovery.js","sourceRoot":"","sources":["../../src/checks/mcp-discovery.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,sBAAsB,EACtB,qBAAqB,EACrB,gBAAgB,EAChB,0BAA0B,EAC1B,wBAAwB,EACxB,2BAA2B,GAC5B,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAE5C,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC1F,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE/C;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,CAAC,MAAM,IAAI,GAAc;IAC7B,EAAE,EAAE,eAAe;IACnB,IAAI,EAAE,eAAe;IACrB,WAAW,EAAE,yEAAyE;IACtF,QAAQ,EAAE,WAAW;IACrB,OAAO,EAAE,CAAC,KAAK,CAAC;CACjB,CAAC;AAgBF,MAAM,eAAe,GAA8B;IACjD,YAAY,EAAE,oCAAoC;IAClD,wBAAwB,EAAE,mCAAmC;IAC7D,yBAAyB,EAAE,oCAAoC;IAC/D,sBAAsB,EAAE,wBAAwB;IAChD,iBAAiB,EAAE,uBAAuB;CAC3C,CAAC;AAEF,0FAA0F;AAC1F,MAAM,mBAAmB,GAAG,CAAC,MAAM,EAAE,UAAU,EAAE,MAAM,CAAC,CAAC;AAEzD;;;;GAIG;AACH,KAAK,UAAU,cAAc,CAAC,GAAiB,EAAE,IAAY;IAC3D,MAAM,GAAG,GAAG,MAAM,GAAG,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,GAAG,GAAG,IAAI,EAAE,CAAC,CAAC;IACjD,IAAI,CAAC,GAAG,CAAC,EAAE,IAAI,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACzD,OAAO,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC;AAC/C,CAAC;AAED;;;;GAIG;AACH,KAAK,UAAU,MAAM,CAAC,GAAiB;IACrC,MAAM,KAAK,GAAc,EAAE,CAAC;IAE5B,MAAM,OAAO,GAAG,MAAM,cAAc,CAAC,GAAG,EAAE,8BAA8B,CAAC,CAAC;IAC1E,IAAI,OAAO,KAAK,IAAI,IAAI,gBAAgB,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QACvD,KAAK,CAAC,IAAI,CAAC,EAAE,SAAS,EAAE,YAAY,EAAE,IAAI,EAAE,8BAA8B,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,CAAC;IAC9F,CAAC;IAED,KAAK,MAAM,CAAC,SAAS,EAAE,IAAI,CAAC,IAAI;QAC9B,CAAC,wBAAwB,EAAE,mCAAmC,CAAC;QAC/D,CAAC,yBAAyB,EAAE,oCAAoC,CAAC;KACzC,EAAE,CAAC;QAC3B,MAAM,GAAG,GAAG,MAAM,cAAc,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QAC5C,IAAI,GAAG,KAAK,IAAI;YAAE,KAAK,CAAC,IAAI,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC;IACzD,CAAC;IAED,KAAK,MAAM,QAAQ,IAAI,mBAAmB,EAAE,CAAC;QAC3C,MAAM,IAAI,GAAG,GAAG,QAAQ,cAAc,CAAC;QACvC,MAAM,GAAG,GAAG,MAAM,cAAc,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QAC5C,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;YACjB,KAAK,CAAC,IAAI,CAAC,EAAE,SAAS,EAAE,sBAAsB,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC;YAC7D,MAAM;QACR,CAAC;IACH,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,GAAG,EAAE,uBAAuB,CAAC,CAAC;IAClE,IAAI,MAAM,KAAK,IAAI;QAAE,KAAK,CAAC,IAAI,CAAC,EAAE,SAAS,EAAE,iBAAiB,EAAE,IAAI,EAAE,uBAAuB,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC,CAAC;IAE9G,OAAO,KAAK,CAAC;AACf,CAAC;AAED,gEAAgE;AAChE,SAAS,gBAAgB,CAAC,IAAY;IACpC,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAA4B,CAAC;QACzD,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAE,IAAI,CAAC,OAAqC,CAAC,CAAC,CAAC,EAAE,CAAC;QAC/F,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC,KAAK,0BAA0B,CAAC,CAAC;IAClF,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,MAAM,CAAC,OAAO,CAAC,KAAK,UAAU,KAAK,CAAC,GAAiB;IACnD,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC;IAChC,MAAM,QAAQ,GAAc,EAAE,CAAC;IAE/B,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,GAAG,CAAC,CAAC;IAEhC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,MAAM,OAAO,GAAG,MAAM,aAAa,CAAC,GAAG,CAAC,CAAC;QACzC,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;YACnB,QAAQ,CAAC,IAAI,CAAC;gBACZ,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE,2DAA2D;gBACpE,MAAM,EACJ,oGAAoG;oBACpG,8DAA8D;aACjE,CAAC,CAAC;YACH,OAAO,aAAa,CAAC,IAAI,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC;QAC9C,CAAC;QAED,QAAQ,CAAC,IAAI,CAAC;YACZ,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,yCAAyC;YAClD,MAAM,EAAE,yBAAyB,OAAO,CAAC,MAAM,GAAG;YAClD,IAAI,EACF,wFAAwF;gBACxF,uGAAuG;gBACvG,wGAAwG;gBACxG,gFAAgF;YAClF,YAAY,EAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,EAAE,WAAW,CAAC;SAC7C,CAAC,CAAC;QACH,OAAO,WAAW,CAAC,IAAI,EAAE,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC;IAC/C,CAAC;IAED,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,KAAK,iBAAiB,CAAC,CAAC;IAEtE,4EAA4E;IAC5E,4EAA4E;IAC5E,8DAA8D;IAC9D,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,OAAO,sBAAsB,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC;IAC3D,CAAC;IAED,QAAQ,CAAC,IAAI,CAAC;QACZ,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,+BAA+B,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,eAAe,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE;QACrG,MAAM,EAAE,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;KACrC,CAAC,CAAC;IAEH,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,KAAK,iBAAiB,CAAC,EAAE,CAAC;QACzD,QAAQ,CAAC,IAAI,CAAC;YACZ,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,mEAAmE;YAC5E,MAAM,EAAE,YAAY,CAAC,uBAAuB,CAAC;YAC7C,IAAI,EAAE,wGAAwG;YAC9G,YAAY,EAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,EAAE,iBAAiB,CAAC;SACnD,CAAC,CAAC;IACL,CAAC;IAED,OAAO,kBAAkB,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC;AACxD,CAAC;AAED,uEAAuE;AACvE,SAAS,kBAAkB,CAAC,OAAgB,EAAE,QAAmB,EAAE,KAAa;IAC9E,IAAI,KAAK,GAAG,GAAG,CAAC;IAChB,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,OAAO,CAAC;IAEzC,MAAM,UAAU,GACd,SAAS,KAAK,YAAY;QACxB,CAAC,CAAC,CAAC,kBAAkB,EAAE,6BAA6B,CAAC;QACrD,CAAC,CAAC,CAAC,kBAAkB,EAAE,0BAA0B,CAAC,CAAC;IACvD,MAAM,SAAS,GAAG,gBAAgB,CAAC,GAAG,EAAE,UAAU,EAAE;QAClD,OAAO,EAAE,IAAI,CAAC,EAAE;QAChB,aAAa,EAAE,IAAI;QACnB,MAAM,EAAE,oBAAoB;KAC7B,CAAC,CAAC;IACH,IAAI,SAAS,EAAE,CAAC;QACd,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACzB,KAAK,IAAI,CAAC,CAAC;IACb,CAAC;IAED,IAAI,IAA6B,CAAC;IAClC,IAAI,CAAC;QACH,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAA4B,CAAC;IACzD,CAAC;IAAC,MAAM,CAAC;QACP,QAAQ,CAAC,IAAI,CAAC;YACZ,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,mBAAmB,IAAI,EAAE;YAClC,IAAI,EAAE,mDAAmD;YACzD,YAAY,EAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,EAAE,cAAc,CAAC;SAChD,CAAC,CAAC;QACH,OAAO,WAAW,CAAC,IAAI,EAAE,EAAE,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC;IAChD,CAAC;IACD,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,EAAE,CAAC,CAAC;IAEzD,IAAI,SAAS,KAAK,YAAY,EAAE,CAAC;QAC/B,OAAO,eAAe,CAAC,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;IACvD,CAAC;IAED,0EAA0E;IAC1E,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC;QACvC,CAAC,CAAE,IAAI,CAAC,OAAqC;QAC7C,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC;YACnB,CAAC,CAAE,IAAkC;YACrC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IAEb,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACrB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,KAAK,CAAC,MAAM,wBAAwB,EAAE,CAAC,CAAC;IACtF,CAAC;IAED,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,KAAK,GAAG,eAAe,CAAC,IAAI,EAAE,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC;IACnE,CAAC;IAED,IAAI,GAAG,CAAC,OAAO,CAAC,6BAA6B,CAAC,EAAE,CAAC;QAC/C,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,iCAAiC,EAAE,CAAC,CAAC;IAChF,CAAC;SAAM,CAAC;QACN,QAAQ,CAAC,IAAI,CAAC;YACZ,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,oCAAoC;YAC7C,IAAI,EAAE,0JAA0J;YAChK,YAAY,EAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,CAAC;SAC3C,CAAC,CAAC;QACH,KAAK,IAAI,EAAE,CAAC;IACd,CAAC;IAED,OAAO,WAAW,CAAC,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC;AACnD,CAAC;AAED,4CAA4C;AAC5C,SAAS,eAAe,CAAC,IAA6B,EAAE,QAAiB,EAAE,QAAmB,EAAE,KAAa;IAC3G,MAAM,KAAK,GAAG,QAAQ,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,IAAI,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,aAAa,CAAC;IAE/E,KAAK,MAAM,KAAK,IAAI,wBAAwB,EAAE,CAAC;QAC7C,IAAI,IAAI,CAAC,KAAK,CAAC,KAAK,SAAS,IAAI,IAAI,CAAC,KAAK,CAAC,KAAK,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE;YAAE,SAAS;QACtF,QAAQ,CAAC,IAAI,CAAC;YACZ,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,GAAG,KAAK,qBAAqB,KAAK,WAAW;YACtD,IAAI,EAAE,8BAA8B,wBAAwB,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG;YAC1E,YAAY,EAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,EAAE,eAAe,CAAC;SACjD,CAAC,CAAC;QACH,KAAK,IAAI,EAAE,CAAC;IACd,CAAC;IAED,4EAA4E;IAC5E,+DAA+D;IAC/D,MAAM,IAAI,GAAG,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;IAC5D,IAAI,IAAI,KAAK,EAAE,IAAI,CAAC,qDAAqD,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QACrF,QAAQ,CAAC,IAAI,CAAC;YACZ,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,GAAG,KAAK,WAAW,IAAI,8BAA8B;YAC9D,IAAI,EAAE,iIAAiI;YACvI,YAAY,EAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,EAAE,aAAa,CAAC;SAC/C,CAAC,CAAC;QACH,KAAK,IAAI,CAAC,CAAC;IACb,CAAC;SAAM,IAAI,IAAI,KAAK,EAAE,EAAE,CAAC;QACvB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,KAAK,WAAW,IAAI,GAAG,EAAE,CAAC,CAAC;IACzE,CAAC;IAED,KAAK,GAAG,eAAe,CAAC,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC;IAEtD,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;QAC7B,QAAQ,CAAC,IAAI,CAAC;YACZ,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,GAAG,KAAK,wDAAwD;YACzE,IAAI,EAAE,8HAA8H;YACpI,YAAY,EAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,EAAE,eAAe,CAAC;SACjD,CAAC,CAAC;IACL,CAAC;IAED,IAAI,OAAO,IAAI,CAAC,UAAU,KAAK,QAAQ,IAAI,OAAO,IAAI,CAAC,UAAU,KAAK,QAAQ,EAAE,CAAC;QAC/E,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,KAAK,iDAAiD,EAAE,CAAC,CAAC;IACxG,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED,wDAAwD;AACxD,SAAS,eAAe,CAAC,IAA6B,EAAE,KAAa,EAAE,QAAmB,EAAE,KAAa;IACvG,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAE,IAAI,CAAC,OAAqC,CAAC,CAAC,CAAC,EAAE,CAAC;IAE/F,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,QAAQ,CAAC,IAAI,CAAC;YACZ,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,GAAG,KAAK,yBAAyB;YAC1C,IAAI,EAAE,+KAA+K;YACrL,YAAY,EAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,EAAE,YAAY,CAAC;SAC9C,CAAC,CAAC;QACH,OAAO,KAAK,GAAG,EAAE,CAAC;IACpB,CAAC;IAED,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,KAAK,KAAK,OAAO,CAAC,MAAM,8BAA8B,EAAE,CAAC,CAAC;IAEtG,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;IACtG,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvB,QAAQ,CAAC,IAAI,CAAC;YACZ,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,GAAG,KAAK,8CAA8C;YAC/D,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,WAAW,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;YACvD,IAAI,EAAE,kBAAkB,gBAAgB,CAAC,IAAI,CAAC,OAAO,CAAC,iEAAiE;YACvH,YAAY,EAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,EAAE,aAAa,CAAC;SAC/C,CAAC,CAAC;QACH,KAAK,IAAI,CAAC,CAAC;IACb,CAAC;IAED,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,GAAG,KAAK,QAAQ,IAAI,CAAC,CAAC,GAAG,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC;IACtF,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;QACd,QAAQ,CAAC,IAAI,CAAC;YACZ,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,GAAG,KAAK,KAAK,KAAK,0BAA0B;YACrD,IAAI,EAAE,8CAA8C;YACpD,YAAY,EAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,EAAE,YAAY,CAAC;SAC9C,CAAC,CAAC;QACH,KAAK,IAAI,EAAE,CAAC;IACd,CAAC;IAED,MAAM,gBAAgB,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAC7C,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,yBAAyB,CAAC,CAAC,CAAC,CAAE,CAAC,CAAC,yBAAuC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CACzG,CAAC;IAEF,IAAI,gBAAgB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAClC,QAAQ,CAAC,IAAI,CAAC;YACZ,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,GAAG,KAAK,yCAAyC;YAC1D,IAAI,EAAE,yEAAyE,qBAAqB,CAAC,CAAC,CAAC,GAAG;YAC1G,YAAY,EAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,EAAE,qBAAqB,CAAC;SACvD,CAAC,CAAC;QACH,KAAK,IAAI,EAAE,CAAC;QACZ,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,OAAO,GAAG,gBAAgB,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,qBAAqB,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;IACnF,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvB,QAAQ,CAAC,IAAI,CAAC;YACZ,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,GAAG,KAAK,wCAAwC;YACzD,MAAM,EAAE,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC;YAC1B,IAAI,EAAE,0BAA0B,qBAAqB,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG;YACnE,YAAY,EAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,EAAE,0BAA0B,CAAC;SAC5D,CAAC,CAAC;QACH,KAAK,IAAI,CAAC,CAAC;IACb,CAAC;IAED,MAAM,KAAK,GAAG,gBAAgB,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,qBAAqB,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;IAChF,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,2BAA2B,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACpF,QAAQ,CAAC,IAAI,CAAC;YACZ,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,GAAG,KAAK,iDAAiD;YAClE,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC;YACxB,IAAI,EAAE,2BAA2B,qBAAqB,CAAC,CAAC,CAAC,uHAAuH;YAChL,YAAY,EAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,EAAE,wBAAwB,CAAC;SAC1D,CAAC,CAAC;QACH,KAAK,IAAI,EAAE,CAAC;IACd,CAAC;SAAM,IAAI,KAAK,CAAC,QAAQ,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACpD,QAAQ,CAAC,IAAI,CAAC;YACZ,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,GAAG,KAAK,wCAAwC,qBAAqB,CAAC,CAAC,CAAC,GAAG;SACrF,CAAC,CAAC;IACL,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED,kEAAkE;AAClE,SAAS,eAAe,CACtB,IAA6B,EAC7B,QAAmB,EACnB,KAAa,EACb,KAAa;IAEb,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAE,IAAI,CAAC,OAAqC,CAAC,CAAC,CAAC,EAAE,CAAC;IAC/F,MAAM,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC,KAAK,0BAA0B,CAAC,CAAC;IAE9F,QAAQ,CAAC,IAAI,CAAC;QACZ,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,oBAAoB,UAAU,CAAC,MAAM,kCAAkC,OAAO,CAAC,MAAM,QAAQ;KACvG,CAAC,CAAC;IAEH,IAAI,IAAI,CAAC,WAAW,KAAK,SAAS,EAAE,CAAC;QACnC,QAAQ,CAAC,IAAI,CAAC;YACZ,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,+BAA+B;YACxC,IAAI,EAAE,kFAAkF;YACxF,YAAY,EAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,EAAE,oBAAoB,CAAC;SACtD,CAAC,CAAC;QACH,KAAK,IAAI,CAAC,CAAC;IACb,CAAC;IAED,MAAM,UAAU,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,UAAU,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IAClF,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1B,QAAQ,CAAC,IAAI,CAAC;YACZ,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,GAAG,UAAU,CAAC,MAAM,oDAAoD;YACjF,IAAI,EAAE,6GAA6G;YACnH,YAAY,EAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,EAAE,eAAe,CAAC;SACjD,CAAC,CAAC;QACH,KAAK,IAAI,EAAE,CAAC;IACd,CAAC;IAED,MAAM,YAAY,GAAG,OAAO;SACzB,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;SAChC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/E,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC5B,QAAQ,CAAC,IAAI,CAAC;YACZ,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,yCAAyC;YAClD,MAAM,EAAE,CAAC,GAAG,IAAI,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;YAC7C,IAAI,EAAE,sBAAsB,MAAM,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG;YAC7E,YAAY,EAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,EAAE,oBAAoB,CAAC;SACtD,CAAC,CAAC;QACH,KAAK,IAAI,CAAC,CAAC;IACb,CAAC;IAED,OAAO,WAAW,CAAC,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC;AACnD,CAAC;AAED;;;;GAIG;AACH,SAAS,sBAAsB,CAAC,OAAgB,EAAE,QAAmB,EAAE,KAAa;IAClF,IAAI,KAAK,GAAG,GAAG,CAAC;IAChB,MAAM,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC;IAExB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,8BAA8B,EAAE,CAAC,CAAC;IAC3E,QAAQ,CAAC,IAAI,CAAC;QACZ,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,yDAAyD;QAClE,MAAM,EAAE,YAAY,CAAC,uBAAuB,CAAC;QAC7C,IAAI,EACF,gHAAgH;YAChH,sGAAsG;QACxG,YAAY,EAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,EAAE,iBAAiB,CAAC;KACnD,CAAC,CAAC;IAEH,MAAM,SAAS,GAAG,gBAAgB,CAAC,GAAG,EAAE,CAAC,kBAAkB,CAAC,EAAE;QAC5D,OAAO,EAAE,IAAI,CAAC,EAAE;QAChB,aAAa,EAAE,uBAAuB;QACtC,MAAM,EAAE,oBAAoB;KAC7B,CAAC,CAAC;IACH,IAAI,SAAS,EAAE,CAAC;QACd,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACzB,KAAK,IAAI,CAAC,CAAC;IACb,CAAC;IAED,IAAI,IAA6B,CAAC;IAClC,IAAI,CAAC;QACH,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAA4B,CAAC;IACzD,CAAC;IAAC,MAAM,CAAC;QACP,QAAQ,CAAC,IAAI,CAAC;YACZ,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,cAAc;YACvB,IAAI,EAAE,yEAAyE;YAC/E,YAAY,EAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,EAAE,cAAc,CAAC;SAChD,CAAC,CAAC;QACH,OAAO,WAAW,CAAC,IAAI,EAAE,EAAE,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC;IAChD,CAAC;IACD,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,EAAE,CAAC,CAAC;IAEzD,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;QACd,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,iBAAiB,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;IACpF,CAAC;SAAM,CAAC;QACN,QAAQ,CAAC,IAAI,CAAC;YACZ,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,qBAAqB;YAC9B,IAAI,EAAE,iDAAiD;YACvD,YAAY,EAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,EAAE,cAAc,CAAC;SAChD,CAAC,CAAC;QACH,KAAK,IAAI,EAAE,CAAC;IACd,CAAC;IAED,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;QACrB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,4BAA4B,EAAE,CAAC,CAAC;IAC3E,CAAC;SAAM,CAAC;QACN,QAAQ,CAAC,IAAI,CAAC;YACZ,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,4BAA4B;YACrC,IAAI,EAAE,iEAAiE;YACvE,YAAY,EAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,EAAE,qBAAqB,CAAC;SACvD,CAAC,CAAC;QACH,KAAK,IAAI,CAAC,CAAC;IACb,CAAC;IAED,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAkC,CAAC;QACtD,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,KAAK,CAAC,MAAM,kBAAkB,EAAE,CAAC,CAAC;QAE9E,MAAM,SAAS,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC;QACrD,IAAI,SAAS,CAAC,MAAM,KAAK,KAAK,CAAC,MAAM,EAAE,CAAC;YACtC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,6BAA6B,EAAE,CAAC,CAAC;QAC5E,CAAC;aAAM,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAChC,QAAQ,CAAC,IAAI,CAAC;gBACZ,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE,GAAG,SAAS,CAAC,MAAM,IAAI,KAAK,CAAC,MAAM,0BAA0B;gBACtE,IAAI,EAAE,qEAAqE;gBAC3E,YAAY,EAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,EAAE,2BAA2B,CAAC;aAC7D,CAAC,CAAC;YACH,KAAK,IAAI,CAAC,CAAC;QACb,CAAC;aAAM,CAAC;YACN,QAAQ,CAAC,IAAI,CAAC;gBACZ,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE,4BAA4B;gBACrC,IAAI,EAAE,6FAA6F;gBACnG,YAAY,EAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,EAAE,sBAAsB,CAAC;aACxD,CAAC,CAAC;YACH,KAAK,IAAI,EAAE,CAAC;QACd,CAAC;IACH,CAAC;SAAM,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QACrC,QAAQ,CAAC,IAAI,CAAC;YACZ,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,sBAAsB;YAC/B,IAAI,EAAE,+DAA+D;YACrE,YAAY,EAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,EAAE,aAAa,CAAC;SAC/C,CAAC,CAAC;QACH,KAAK,IAAI,EAAE,CAAC;IACd,CAAC;SAAM,CAAC;QACN,QAAQ,CAAC,IAAI,CAAC;YACZ,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,wBAAwB;YACjC,IAAI,EAAE,+EAA+E;YACrF,YAAY,EAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,EAAE,UAAU,CAAC;SAC5C,CAAC,CAAC;QACH,KAAK,IAAI,EAAE,CAAC;IACd,CAAC;IAED,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,IAAI,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC/D,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,sBAAsB,EAAE,CAAC,CAAC;IAC7F,CAAC;SAAM,CAAC;QACN,QAAQ,CAAC,IAAI,CAAC;YACZ,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,sBAAsB;YAC/B,IAAI,EAAE,mEAAmE;YACzE,YAAY,EAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,EAAE,cAAc,CAAC;SAChD,CAAC,CAAC;QACH,KAAK,IAAI,CAAC,CAAC;IACb,CAAC;IAED,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC3D,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,oBAAoB,EAAE,CAAC,CAAC;IACzF,CAAC;IAED,IAAI,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,eAAe,EAAE,CAAC;QACzC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,qBAAqB,MAAM,CAAC,IAAI,CAAC,eAAe,IAAI,IAAI,CAAC,OAAO,CAAC,EAAE,EAAE,CAAC,CAAC;IAClH,CAAC;SAAM,CAAC;QACN,QAAQ,CAAC,IAAI,CAAC;YACZ,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,+BAA+B;YACxC,IAAI,EAAE,qFAAqF,qBAAqB,CAAC,CAAC,CAAC,GAAG;YACtH,YAAY,EAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,EAAE,YAAY,CAAC;SAC9C,CAAC,CAAC;QACH,KAAK,IAAI,CAAC,CAAC;IACb,CAAC;IAED,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;QACxB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,sCAAsC,EAAE,CAAC,CAAC;IACrF,CAAC;IAED,IAAI,GAAG,CAAC,OAAO,CAAC,6BAA6B,CAAC,EAAE,CAAC;QAC/C,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,8BAA8B,EAAE,CAAC,CAAC;IAC7E,CAAC;SAAM,CAAC;QACN,QAAQ,CAAC,IAAI,CAAC;YACZ,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,iCAAiC;YAC1C,IAAI,EAAE,oFAAoF;YAC1F,YAAY,EAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,CAAC;SAC3C,CAAC,CAAC;QACH,KAAK,IAAI,EAAE,CAAC;IACd,CAAC;IAED,OAAO,WAAW,CAAC,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC;AACnD,CAAC"}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import type { CheckContext, CheckResult, CheckMeta } from '../types.js';
|
|
2
|
-
/**
|
|
3
|
-
* "meta-tags" — AI-discovery and identity meta/link tags inside the HTML <head>.
|
|
4
|
-
*
|
|
5
|
-
* Scope:
|
|
6
|
-
* - Custom AI namespace (`ai:summary`, `ai:content_type`, `ai:author`, `ai:api`, `ai:agent_card`)
|
|
7
|
-
* - `<link rel="alternate">` pointing to llms.txt and agent.json
|
|
8
|
-
* - `rel="me"` identity links (IndieAuth / Mastodon-style verification)
|
|
9
|
-
* - OpenGraph completeness (`og:title`, `og:description`, `og:image`, `og:url`, `og:type`)
|
|
10
|
-
* - Twitter Card completeness (`twitter:card`, `twitter:title`, `twitter:description`, `twitter:image`)
|
|
11
|
-
*
|
|
12
|
-
* Title/description quality and canonical/lang/charset live in the `seo-basics` check
|
|
13
|
-
* to avoid double-penalty.
|
|
14
|
-
*/
|
|
15
|
-
export declare const meta: CheckMeta;
|
|
16
|
-
export default function check(ctx: CheckContext): Promise<CheckResult>;
|
|
17
|
-
//# sourceMappingURL=meta-tags.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"meta-tags.d.ts","sourceRoot":"","sources":["../../src/checks/meta-tags.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,SAAS,EAAW,MAAM,aAAa,CAAC;AAIjF;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,IAAI,EAAE,SAIlB,CAAC;AAUF,wBAA8B,KAAK,CAAC,GAAG,EAAE,YAAY,GAAG,OAAO,CAAC,WAAW,CAAC,CAqJ3E"}
|