@capitalthought/agentsfirst-mcp 0.1.0 → 0.1.2
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/probe.d.ts +1 -0
- package/dist/probe.js +17 -0
- package/dist/score.js +35 -16
- package/package.json +1 -1
package/dist/probe.d.ts
CHANGED
package/dist/probe.js
CHANGED
|
@@ -344,6 +344,7 @@ export async function probeWebsite(url) {
|
|
|
344
344
|
['well_known_ai_plugin', `${origin}/.well-known/ai-plugin.json`],
|
|
345
345
|
['well_known_oauth', `${origin}/.well-known/oauth-authorization-server`],
|
|
346
346
|
['well_known_mcp', `${origin}/.well-known/mcp-server-card`],
|
|
347
|
+
['well_known_mcp_json', `${origin}/.well-known/mcp-server-card.json`],
|
|
347
348
|
['sitemap', `${origin}/sitemap.xml`],
|
|
348
349
|
['openapi_root', `${origin}/openapi.json`],
|
|
349
350
|
['openapi_v1', `${origin}/v1/openapi.json`],
|
|
@@ -378,10 +379,26 @@ export async function probeWebsite(url) {
|
|
|
378
379
|
'cohere-ai',
|
|
379
380
|
];
|
|
380
381
|
const declared = aiAgents.filter((ua) => new RegExp(`User-agent:\\s*${ua}`, 'i').test(robotsBody));
|
|
382
|
+
// Content-Signal directive (Cloudflare's emerging AI-policy convention).
|
|
383
|
+
// Format: `Content-Signal: ai-train=yes, search=yes, ai-input=yes`
|
|
384
|
+
const contentSignalLines = robotsBody.match(/^Content-Signal:\s*(.+)$/gim) ?? [];
|
|
385
|
+
const directives = {};
|
|
386
|
+
for (const line of contentSignalLines) {
|
|
387
|
+
const m = line.match(/^Content-Signal:\s*(.+)$/i);
|
|
388
|
+
const captured = m?.[1];
|
|
389
|
+
if (!captured)
|
|
390
|
+
continue;
|
|
391
|
+
for (const pair of captured.split(',')) {
|
|
392
|
+
const [k, v] = pair.split('=').map((s) => s.trim().toLowerCase());
|
|
393
|
+
if (k && v)
|
|
394
|
+
directives[k] = v;
|
|
395
|
+
}
|
|
396
|
+
}
|
|
381
397
|
out.signals.robots_analysis = {
|
|
382
398
|
ai_agents_addressed: declared,
|
|
383
399
|
address_count: declared.length,
|
|
384
400
|
blanket_disallow: /User-agent:\s*\*[\s\S]*?Disallow:\s*\//i.test(robotsBody),
|
|
401
|
+
...(Object.keys(directives).length > 0 && { content_signal_directives: directives }),
|
|
385
402
|
};
|
|
386
403
|
}
|
|
387
404
|
const homepageBody = out.signals.homepage?.body;
|
package/dist/score.js
CHANGED
|
@@ -488,22 +488,38 @@ function scoreBotAccessControl(signals) {
|
|
|
488
488
|
let pts = 0;
|
|
489
489
|
const notes = [];
|
|
490
490
|
const robots = signals.signals.robots_analysis;
|
|
491
|
-
if (robots) {
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
491
|
+
if (!robots) {
|
|
492
|
+
notes.push('No robots.txt analysis available');
|
|
493
|
+
return { pts: 0, max, status: statusFor(0, max), notes };
|
|
494
|
+
}
|
|
495
|
+
// 10 pts: Cloudflare Content-Signal directive OR equivalent AI-policy declaration.
|
|
496
|
+
// Content-Signal is the modern machine-readable convention; per-bot rules are the
|
|
497
|
+
// older convention and earn partial credit when Content-Signal is absent.
|
|
498
|
+
const cs = robots.content_signal_directives;
|
|
499
|
+
if (cs && Object.keys(cs).length > 0) {
|
|
500
|
+
pts += 10;
|
|
501
|
+
const fmt = Object.entries(cs)
|
|
502
|
+
.map(([k, v]) => `${k}=${v}`)
|
|
503
|
+
.join(', ');
|
|
504
|
+
notes.push(`Content-Signal directive declared: ${fmt}`);
|
|
505
|
+
}
|
|
506
|
+
else if (robots.address_count >= 3) {
|
|
507
|
+
pts += 5;
|
|
508
|
+
notes.push(`AI policy implicit via ${robots.address_count} per-bot rules — consider adding a Content-Signal directive for machine-readable, future-proof AI policy`);
|
|
504
509
|
}
|
|
505
510
|
else {
|
|
506
|
-
notes.push('No robots.txt
|
|
511
|
+
notes.push('No Content-Signal directive and no per-bot AI policy in robots.txt');
|
|
512
|
+
}
|
|
513
|
+
// 5 pts: per-bot granular posture (names ≥3 AI bots and is not paired with a global blanket disallow).
|
|
514
|
+
if (robots.address_count >= 3 && !robots.blanket_disallow) {
|
|
515
|
+
pts += 5;
|
|
516
|
+
notes.push(`Per-bot granular posture for ${robots.address_count} named bots`);
|
|
517
|
+
}
|
|
518
|
+
else if (robots.address_count >= 3 && robots.blanket_disallow) {
|
|
519
|
+
notes.push(`Names ${robots.address_count} bots but pairs with a global blanket disallow`);
|
|
520
|
+
}
|
|
521
|
+
else if (robots.address_count > 0) {
|
|
522
|
+
notes.push(`Names ${robots.address_count} bot(s) — under threshold (need 3+) for granular-control credit`);
|
|
507
523
|
}
|
|
508
524
|
return { pts: Math.min(pts, max), max, status: statusFor(pts, max), notes };
|
|
509
525
|
}
|
|
@@ -512,9 +528,12 @@ function scoreAgentCapabilities(signals) {
|
|
|
512
528
|
let pts = 0;
|
|
513
529
|
const notes = [];
|
|
514
530
|
const surfaces = signals.signals.surfaces;
|
|
515
|
-
if (surfaces['well_known_mcp']?.ok) {
|
|
531
|
+
if (surfaces['well_known_mcp']?.ok || surfaces['well_known_mcp_json']?.ok) {
|
|
516
532
|
pts += 15;
|
|
517
|
-
|
|
533
|
+
const variant = surfaces['well_known_mcp_json']?.ok
|
|
534
|
+
? '/.well-known/mcp-server-card.json'
|
|
535
|
+
: '/.well-known/mcp-server-card';
|
|
536
|
+
notes.push(`MCP Server Card published at ${variant}`);
|
|
518
537
|
}
|
|
519
538
|
else {
|
|
520
539
|
notes.push('No MCP Server Card');
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@capitalthought/agentsfirst-mcp",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "MCP server that scores websites and codebases against the Agents First framework. Use it to check how agent-ready any product is. https://agentsfirst.dev",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Joshua Baer <josh@capitalfactory.com>",
|