mcp-scorecard 0.2.0 → 0.4.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 CHANGED
@@ -1,5 +1,25 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.4.0
4
+
5
+ - **Compare** (`mcp-scorecard compare a b c`): audit several targets, print a ranked side-by-side table.
6
+ - **Baseline/regression** (`--baseline old.json`): diff a run against a previous `--json` report (CI guardrail).
7
+ - **Scoring profiles** (`--profile security|quality|agent-ready`): score only one category, rescaled.
8
+ - **HTML report** (`--html`): a self-contained, shareable scorecard.
9
+ - **Checks explainer page** (`/checks.html` on the site, generated from the single-source catalog): every check, its category, and why it matters.
10
+
11
+
12
+
13
+ ## 0.3.0
14
+
15
+ - **Run AS an MCP server** (`mcp-scorecard serve`): exposes an `audit` tool so agents can score any MCP server mid-task — an MCP that scores MCPs. Add to a client: `{"command":"npx","args":["-y","mcp-scorecard","serve"]}`.
16
+ - **Letter grade (A–F) + `--badge`**: `npx mcp-scorecard <t> --badge` emits a shields.io markdown badge for your README.
17
+ - **Top fixes**: the markdown report now leads with the 3 changes that gain the most points.
18
+ - **Deeper web security checks** (web mode, now 12 checks): exposed `/.git` and `/.env` detection (content-verified, no SPA false positives) and CORS posture (flags wildcard/reflected origin + credentials).
19
+ - GitHub Action (`action.yml`) to gate CI on a minimum score.
20
+
21
+
22
+
3
23
  ## 0.2.0
4
24
 
5
25
  - **Web mode**: audit hosted/remote MCP servers + sites by URL (`npx -y mcp-scorecard https://your-server`). Adds 10 security + agent-readiness checks: HTTPS/TLS, security headers, auth posture, OAuth discovery, llms.txt, MCP Server Card (SEP-1649), Agent Skills index, API catalog (RFC 9727), robots + AI/Content-Signal, structured metadata (JSON-LD / OG / Markdown-for-Agents). The stdio path (10 protocol-quality checks) is unchanged.
package/README.md CHANGED
@@ -229,3 +229,27 @@ production agent.
229
229
  ## License
230
230
 
231
231
  MIT - see [LICENSE](LICENSE).
232
+
233
+ ---
234
+
235
+ ## New in v0.3.0 — differentiators
236
+
237
+ - **Run it AS an MCP server** so agents can call it mid-task:
238
+ ```json
239
+ { "mcpServers": { "mcp-scorecard": { "command": "npx", "args": ["-y", "mcp-scorecard", "serve"] } } }
240
+ ```
241
+ Then your agent can `audit("some-mcp-server")` before installing it. *An MCP that scores MCPs.*
242
+ - **Audit hosted/remote servers** by URL (12 security + agent-readiness checks): `npx -y mcp-scorecard https://your-server`
243
+ - **Badge for your README:** `npx -y mcp-scorecard my-mcp --badge` → a shields.io markdown badge.
244
+ - **GitHub Action:**
245
+ ```yaml
246
+ - uses: davidmosiah/mcp-scorecard@v0.3.0
247
+ with:
248
+ target: dist/index.js
249
+ min-score: 80
250
+ ```
251
+
252
+ ### v0.4.0
253
+ - `mcp-scorecard compare a b c` — side-by-side ranking.
254
+ - `--profile security|quality|agent-ready` — score one category. `--baseline old.json` — regression diff. `--html` — shareable scorecard.
255
+ - Checks explainer: https://mcp-scorecard.vercel.app/checks.html
@@ -6,6 +6,7 @@
6
6
  * with a synthetic detail entry rather than crashing the audit.
7
7
  */
8
8
  import { SERVER_VERSION } from '../constants.js';
9
+ import { toGrade } from '../types.js';
9
10
  import { checkAgentManifest } from './checks/agent-manifest.js';
10
11
  import { checkAnnotations } from './checks/annotations.js';
11
12
  import { checkManifestDiscoverability } from './checks/manifest-discoverability.js';
@@ -61,6 +62,7 @@ export async function runAudit(target) {
61
62
  safeRun('annotations', () => checkAnnotations(snapshot)),
62
63
  safeRun('manifest_discoverability', () => checkManifestDiscoverability(snapshot))
63
64
  ];
65
+ const totalScore = aggregateScore(checks);
64
66
  return {
65
67
  target: {
66
68
  displayName: target.displayName,
@@ -68,7 +70,9 @@ export async function runAudit(target) {
68
70
  serverName: snapshot.serverInfo.name,
69
71
  serverVersion: snapshot.serverInfo.version
70
72
  },
71
- totalScore: aggregateScore(checks),
73
+ totalScore,
74
+ grade: toGrade(totalScore),
75
+ mode: 'stdio',
72
76
  checks,
73
77
  generatedAt: new Date().toISOString(),
74
78
  scorecardVersion: SERVER_VERSION
@@ -1 +1 @@
1
- {"version":3,"file":"runner.js","sourceRoot":"","sources":["../../src/audit/runner.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"runner.js","sourceRoot":"","sources":["../../src/audit/runner.ts"],"names":[],"mappings":"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"}
@@ -11,7 +11,7 @@ export function aggregateScore(checks) {
11
11
  // Use the expected denominator (10 checks * 10 each = 100); if a check
12
12
  // failed to even run, we still divide by 10 so the score reflects gaps.
13
13
  const sum = checks.reduce((acc, c) => acc + Math.max(0, Math.min(10, c.score)), 0);
14
- const denom = EXPECTED_CHECK_COUNT * 10;
14
+ const denom = checks.length * 10; // supports stdio (10) + web (12) modes
15
15
  return Math.round((sum / denom) * 100);
16
16
  }
17
17
  //# sourceMappingURL=scorer.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"scorer.js","sourceRoot":"","sources":["../../src/audit/scorer.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,MAAM,oBAAoB,GAAG,EAAE,CAAC;AAEhC,MAAM,UAAU,cAAc,CAAC,MAAqB;IAClD,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,CAAC,CAAC;IAClC,uEAAuE;IACvE,wEAAwE;IACxE,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACnF,MAAM,KAAK,GAAG,oBAAoB,GAAG,EAAE,CAAC;IACxC,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,GAAG,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC;AACzC,CAAC"}
1
+ {"version":3,"file":"scorer.js","sourceRoot":"","sources":["../../src/audit/scorer.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,MAAM,oBAAoB,GAAG,EAAE,CAAC;AAEhC,MAAM,UAAU,cAAc,CAAC,MAAqB;IAClD,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,CAAC,CAAC;IAClC,uEAAuE;IACvE,wEAAwE;IACxE,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACnF,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC,uCAAuC;IACzE,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,GAAG,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC;AACzC,CAAC"}
@@ -23,7 +23,13 @@ export function scoreWeb(p) {
23
23
  mk('web_agent_skills', 'Agent Skills index', p.agentSkills ? 10 : 0, p.agentSkills ? '/.well-known/agent-skills/index.json present' : 'Agent Skills discovery index missing', p.agentSkills ? [] : ['Publish /.well-known/agent-skills/index.json (Agent Skills Discovery RFC) listing your skills.']),
24
24
  mk('web_api_catalog', 'API catalog (RFC 9727)', p.apiCatalog ? 10 : 0, p.apiCatalog ? '/.well-known/api-catalog present' : 'API catalog missing', p.apiCatalog ? [] : ['Publish /.well-known/api-catalog (application/linkset+json) pointing to your OpenAPI / docs / status.']),
25
25
  mk('web_robots_signals', 'robots + AI signals', (p.robotsTxt ? 4 : 0) + (p.aiBotRules ? 2 : 0) + (p.contentSignal ? 2 : 0) + (p.sitemap ? 2 : 0), `robots:${p.robotsTxt ? 'y' : 'n'} ai-bots:${p.aiBotRules ? 'y' : 'n'} content-signal:${p.contentSignal ? 'y' : 'n'} sitemap:${p.sitemap ? 'y' : 'n'}`, (p.robotsTxt && p.aiBotRules && p.contentSignal && p.sitemap) ? [] : ['robots.txt with explicit AI-bot rules + a Content-Signal directive + a Sitemap line.']),
26
- mk('web_structured_data', 'Structured metadata', (p.jsonLd ? 4 : 0) + (p.ogTags ? 3 : 0) + (p.markdownNegotiation ? 3 : 0), `json-ld:${p.jsonLd ? 'y' : 'n'} og:${p.ogTags ? 'y' : 'n'} markdown-for-agents:${p.markdownNegotiation ? 'y' : 'n'}`, (p.jsonLd && p.ogTags && p.markdownNegotiation) ? [] : ['Add JSON-LD (schema.org), OpenGraph tags, and Markdown-for-Agents (Accept: text/markdown).'])
26
+ mk('web_structured_data', 'Structured metadata', (p.jsonLd ? 4 : 0) + (p.ogTags ? 3 : 0) + (p.markdownNegotiation ? 3 : 0), `json-ld:${p.jsonLd ? 'y' : 'n'} og:${p.ogTags ? 'y' : 'n'} markdown-for-agents:${p.markdownNegotiation ? 'y' : 'n'}`, (p.jsonLd && p.ogTags && p.markdownNegotiation) ? [] : ['Add JSON-LD (schema.org), OpenGraph tags, and Markdown-for-Agents (Accept: text/markdown).']),
27
+ mk('web_exposed_paths', 'No exposed secrets', (p.gitExposed || p.envExposed) ? 0 : 10, (p.gitExposed || p.envExposed)
28
+ ? `CRITICAL: ${[p.gitExposed && '/.git/config', p.envExposed && '/.env'].filter(Boolean).join(' + ')} is publicly readable`
29
+ : 'no /.git or /.env exposed' + (p.securityTxt ? ' (+ security.txt present)' : ''), (p.gitExposed || p.envExposed) ? ['URGENT: block public access to /.git and /.env — they leak source history and credentials.'] : []),
30
+ mk('web_cors_posture', 'CORS posture', (p.corsAllowCredentials && (p.corsAllowOrigin === '*' || /mcp-scorecard\.test/.test(p.corsAllowOrigin || ''))) ? 2 : 10, (p.corsAllowCredentials && (p.corsAllowOrigin === '*' || /mcp-scorecard\.test/.test(p.corsAllowOrigin || '')))
31
+ ? 'DANGEROUS: credentials allowed with wildcard/reflected origin'
32
+ : `safe (allow-origin: ${p.corsAllowOrigin ?? 'none'}, credentials: ${p.corsAllowCredentials})`, (p.corsAllowCredentials && (p.corsAllowOrigin === '*' || /mcp-scorecard\.test/.test(p.corsAllowOrigin || ''))) ? ['Never combine Access-Control-Allow-Credentials:true with a wildcard or reflected Access-Control-Allow-Origin.'] : [])
27
33
  ];
28
34
  }
29
35
  //# sourceMappingURL=web-checks.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"web-checks.js","sourceRoot":"","sources":["../../../src/audit/web/web-checks.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"web-checks.js","sourceRoot":"","sources":["../../../src/audit/web/web-checks.ts"],"names":[],"mappings":"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"}
@@ -3,10 +3,13 @@ async function get(url, opts = {}) {
3
3
  const ctrl = new AbortController();
4
4
  const t = setTimeout(() => ctrl.abort(), opts.timeoutMs ?? 8000);
5
5
  try {
6
+ const headersIn = { 'user-agent': UA, accept: opts.accept ?? '*/*' };
7
+ if (opts.origin)
8
+ headersIn['origin'] = opts.origin;
6
9
  const res = await fetch(url, {
7
10
  signal: ctrl.signal,
8
11
  redirect: 'follow',
9
- headers: { 'user-agent': UA, accept: opts.accept ?? '*/*' }
12
+ headers: headersIn
10
13
  });
11
14
  const headers = {};
12
15
  res.headers.forEach((v, k) => { headers[k.toLowerCase()] = v; });
@@ -29,7 +32,7 @@ export async function fetchWebProbe(rawUrl) {
29
32
  const base = rawUrl.replace(/\/+$/, '');
30
33
  const u = new URL(base);
31
34
  const at = (p) => `${u.origin}${p}`;
32
- const [root, llms, robots, card, skills, apiCat, sitemap, oauthPR, oauthAS, authMd, mdNeg] = await Promise.all([
35
+ const [root, llms, robots, card, skills, apiCat, sitemap, oauthPR, oauthAS, authMd, mdNeg, gitCfg, envFile, secTxt, corsProbe] = await Promise.all([
33
36
  get(base + '/'),
34
37
  get(at('/llms.txt')),
35
38
  get(at('/robots.txt')),
@@ -40,8 +43,18 @@ export async function fetchWebProbe(rawUrl) {
40
43
  get(at('/.well-known/oauth-protected-resource')),
41
44
  get(at('/.well-known/oauth-authorization-server')),
42
45
  get(at('/auth.md')),
43
- get(base + '/', { accept: 'text/markdown' })
46
+ get(base + '/', { accept: 'text/markdown' }),
47
+ get(at('/.git/config')),
48
+ get(at('/.env')),
49
+ get(at('/.well-known/security.txt')),
50
+ get(base + '/', { origin: 'https://mcp-scorecard.test' })
44
51
  ]);
52
+ // Verify CONTENT (not just 200) — SPAs/CDNs return 200 + index.html for any path.
53
+ const gitExposed = ok(gitCfg) && /\[core\]|repositoryformatversion/i.test(gitCfg.text) && !/<html/i.test(gitCfg.text);
54
+ const envExposed = ok(envFile) && /^[A-Z0-9_]+=/m.test(envFile.text) && !/<html/i.test(envFile.text);
55
+ const securityTxt = ok(secTxt) && /contact:/i.test(secTxt.text);
56
+ const corsAllowOrigin = corsProbe?.headers['access-control-allow-origin'] ?? null;
57
+ const corsAllowCredentials = (corsProbe?.headers['access-control-allow-credentials'] ?? '').toLowerCase() === 'true';
45
58
  const robotsText = ok(robots) ? robots.text.toLowerCase() : '';
46
59
  const rootHtml = ok(root) ? root.text : '';
47
60
  let serverCardValid = false;
@@ -72,7 +85,12 @@ export async function fetchWebProbe(rawUrl) {
72
85
  authMd: ok(authMd) && /auth\.md/i.test(authMd.text),
73
86
  jsonLd: /application\/ld\+json/i.test(rootHtml),
74
87
  ogTags: /property=["']og:/i.test(rootHtml),
75
- markdownNegotiation: !!mdNeg && (mdNeg.headers['content-type'] || '').includes('text/markdown')
88
+ markdownNegotiation: !!mdNeg && (mdNeg.headers['content-type'] || '').includes('text/markdown'),
89
+ gitExposed,
90
+ envExposed,
91
+ securityTxt,
92
+ corsAllowOrigin,
93
+ corsAllowCredentials
76
94
  };
77
95
  }
78
96
  //# sourceMappingURL=web-probe.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"web-probe.js","sourceRoot":"","sources":["../../../src/audit/web/web-probe.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"web-probe.js","sourceRoot":"","sources":["../../../src/audit/web/web-probe.ts"],"names":[],"mappings":"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"}
@@ -3,18 +3,19 @@
3
3
  * pure web checks, aggregate into the same AuditReport shape as the stdio path.
4
4
  */
5
5
  import { SERVER_VERSION } from '../../constants.js';
6
+ import { toGrade } from '../../types.js';
6
7
  import { aggregateScore } from '../scorer.js';
7
8
  import { fetchWebProbe } from './web-probe.js';
8
9
  import { scoreWeb } from './web-checks.js';
9
10
  export async function runWebAudit(url) {
10
11
  const probe = await fetchWebProbe(url);
11
12
  const checks = scoreWeb(probe);
13
+ const totalScore = aggregateScore(checks);
12
14
  return {
13
- target: {
14
- displayName: probe.url,
15
- serverName: probe.url
16
- },
17
- totalScore: aggregateScore(checks),
15
+ target: { displayName: probe.url, serverName: probe.url },
16
+ totalScore,
17
+ grade: toGrade(totalScore),
18
+ mode: 'web',
18
19
  checks,
19
20
  generatedAt: new Date().toISOString(),
20
21
  scorecardVersion: SERVER_VERSION
@@ -1 +1 @@
1
- {"version":3,"file":"web-runner.js","sourceRoot":"","sources":["../../../src/audit/web/web-runner.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAEpD,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAE3C,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,GAAW;IAC3C,MAAM,KAAK,GAAG,MAAM,aAAa,CAAC,GAAG,CAAC,CAAC;IACvC,MAAM,MAAM,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC/B,OAAO;QACL,MAAM,EAAE;YACN,WAAW,EAAE,KAAK,CAAC,GAAG;YACtB,UAAU,EAAE,KAAK,CAAC,GAAG;SACtB;QACD,UAAU,EAAE,cAAc,CAAC,MAAM,CAAC;QAClC,MAAM;QACN,WAAW,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACrC,gBAAgB,EAAE,cAAc;KACjC,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"web-runner.js","sourceRoot":"","sources":["../../../src/audit/web/web-runner.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAEpD,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AACzC,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAE3C,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,GAAW;IAC3C,MAAM,KAAK,GAAG,MAAM,aAAa,CAAC,GAAG,CAAC,CAAC;IACvC,MAAM,MAAM,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC/B,MAAM,UAAU,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;IAC1C,OAAO;QACL,MAAM,EAAE,EAAE,WAAW,EAAE,KAAK,CAAC,GAAG,EAAE,UAAU,EAAE,KAAK,CAAC,GAAG,EAAE;QACzD,UAAU;QACV,KAAK,EAAE,OAAO,CAAC,UAAU,CAAC;QAC1B,IAAI,EAAE,KAAK;QACX,MAAM;QACN,WAAW,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACrC,gBAAgB,EAAE,cAAc;KACjC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Single source of truth for every check: category + why it matters.
3
+ * Powers `--profile` (filter by category) and the site's /checks explainer page.
4
+ */
5
+ import type { CheckId } from './types.js';
6
+ export type Category = 'quality' | 'security' | 'agent-ready';
7
+ export interface CheckMeta {
8
+ label: string;
9
+ category: Category;
10
+ why: string;
11
+ }
12
+ export declare const CHECK_META: Record<CheckId, CheckMeta>;
13
+ export declare const PROFILES: Record<string, {
14
+ label: string;
15
+ categories: Category[];
16
+ }>;
@@ -0,0 +1,33 @@
1
+ export const CHECK_META = {
2
+ // --- stdio: protocol quality ---
3
+ schema_validity: { label: 'Schema validity', category: 'quality', why: 'Agents reject or mis-call tools whose input schemas are invalid or missing.' },
4
+ tool_naming: { label: 'Tool naming', category: 'quality', why: 'Consistent snake_case verb_noun names make tools predictable for models to select.' },
5
+ tool_descriptions: { label: 'Tool descriptions', category: 'quality', why: 'Rich descriptions are the only thing a model has to decide when/how to call a tool.' },
6
+ annotations: { label: 'Annotations', category: 'quality', why: 'readOnly/destructive hints let agents reason about safety before calling.' },
7
+ resources: { label: 'Resources advertised', category: 'quality', why: 'Exposing resources lets agents pull context without bespoke tool calls.' },
8
+ smoke_test: { label: 'Smoke test', category: 'quality', why: 'A smoke script proves the server actually boots — the baseline of trust.' },
9
+ mutation_gating: { label: 'Mutation gating', category: 'security', why: 'State-changing tools must document/guard side effects so agents do not mutate blindly.' },
10
+ privacy_modes: { label: 'Privacy modes', category: 'security', why: 'A privacy_mode parameter lets agents request non-sensitive responses.' },
11
+ agent_manifest: { label: 'Agent manifest', category: 'agent-ready', why: 'recommended_first_calls tells an agent how to start — the onboarding contract.' },
12
+ manifest_discoverability: { label: 'Manifest discoverability', category: 'agent-ready', why: 'Standard discovery tools (capabilities, inventory) let agents self-orient.' },
13
+ // --- web: hosted/remote ---
14
+ web_https: { label: 'HTTPS / TLS', category: 'security', why: 'Plaintext HTTP exposes tokens and tool traffic to interception.' },
15
+ web_security_headers: { label: 'Security headers', category: 'security', why: 'HSTS/CSP/X-Content-Type-Options harden the server against common web attacks.' },
16
+ web_auth_posture: { label: 'Auth posture declared', category: 'security', why: 'Agents cannot connect safely if they cannot tell whether/how to authenticate.' },
17
+ web_oauth_discovery: { label: 'OAuth discovery', category: 'security', why: 'Standard OAuth metadata lets agents programmatically obtain access.' },
18
+ web_exposed_paths: { label: 'No exposed secrets', category: 'security', why: 'A public /.git or /.env leaks source history and live credentials — critical.' },
19
+ web_cors_posture: { label: 'CORS posture', category: 'security', why: 'Wildcard + credentials CORS is a classic data-exfiltration misconfiguration.' },
20
+ web_llms_txt: { label: 'llms.txt', category: 'agent-ready', why: 'A concise machine summary tells LLMs what the server is and how to use it.' },
21
+ web_mcp_server_card: { label: 'MCP Server Card', category: 'agent-ready', why: 'The /.well-known card is how agents discover the server, transport and tools.' },
22
+ web_agent_skills: { label: 'Agent Skills index', category: 'agent-ready', why: 'The skills discovery index lets agents find and verify your capabilities.' },
23
+ web_api_catalog: { label: 'API catalog (RFC 9727)', category: 'agent-ready', why: 'A standard catalog points agents to your OpenAPI, docs and status.' },
24
+ web_robots_signals: { label: 'robots + AI signals', category: 'agent-ready', why: 'Explicit AI-bot rules + Content-Signal declare how agents may use your content.' },
25
+ web_structured_data: { label: 'Structured metadata', category: 'agent-ready', why: 'JSON-LD, OpenGraph and Markdown-for-Agents make the page machine-legible.' }
26
+ };
27
+ export const PROFILES = {
28
+ all: { label: 'All checks', categories: ['quality', 'security', 'agent-ready'] },
29
+ security: { label: 'Security', categories: ['security'] },
30
+ quality: { label: 'Protocol quality', categories: ['quality'] },
31
+ 'agent-ready': { label: 'Agent-readiness', categories: ['agent-ready'] }
32
+ };
33
+ //# sourceMappingURL=checks-catalog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"checks-catalog.js","sourceRoot":"","sources":["../src/checks-catalog.ts"],"names":[],"mappings":"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"}
@@ -19,19 +19,28 @@ import { runWebAudit } from '../audit/web/web-runner.js';
19
19
  function isWebTarget(subject) {
20
20
  return /^https?:\/\//.test(subject) && !/github\.com/.test(subject);
21
21
  }
22
- import { renderJson, renderMarkdown } from './output.js';
22
+ import { readFileSync } from 'node:fs';
23
+ import { applyProfile, isProfile } from '../profiles.js';
24
+ import { renderBadge, renderBaseline, renderCompare, renderHtml, renderJson, renderMarkdown } from './output.js';
23
25
  const USAGE = `mcp-scorecard v${SERVER_VERSION}
24
26
 
25
27
  Usage:
26
- mcp-scorecard <subject> [--json] [--min-score N]
28
+ mcp-scorecard <subject> [--json|--badge|--html] [--profile P] [--baseline f.json] [--min-score N]
29
+ mcp-scorecard serve run AS an MCP server (agents can call the 'audit' tool)
30
+ mcp-scorecard compare a b c audit several subjects, print a side-by-side table
27
31
 
28
32
  Subjects:
29
33
  npm-package e.g. whoop-mcp-unofficial[@version]
30
34
  github-url e.g. https://github.com/davidmosiah/whoop-mcp
35
+ https://host a HOSTED/remote MCP server or site (web security + agent-readiness audit)
31
36
  /abs/path/dist/index.js built MCP server entry
32
37
 
33
38
  Flags:
34
39
  --json emit structured JSON to stdout
40
+ --badge emit a markdown shields.io badge (paste into your README)
41
+ --html emit a self-contained HTML scorecard
42
+ --profile P score only one category: all | security | quality | agent-ready
43
+ --baseline f diff against a previous --json report (regression view)
35
44
  --min-score N exit non-zero if total score < N (default 0)
36
45
  --version print version
37
46
  --help, -h print this message
@@ -40,7 +49,7 @@ Privacy: the probe sets MCP_PROBE=1 so MCP authors can detect an audit and
40
49
  skip auth-only side effects. Probe responses are NEVER persisted; only
41
50
  counts and field names are recorded. See the README for the security model.`;
42
51
  function parseArgs(argv) {
43
- const out = { json: false, minScore: 0, help: false, showVersion: false };
52
+ const out = { json: false, badge: false, html: false, minScore: 0, help: false, showVersion: false };
44
53
  for (let i = 0; i < argv.length; i++) {
45
54
  const arg = argv[i];
46
55
  if (arg === '--help' || arg === '-h')
@@ -49,6 +58,20 @@ function parseArgs(argv) {
49
58
  out.showVersion = true;
50
59
  else if (arg === '--json')
51
60
  out.json = true;
61
+ else if (arg === '--badge')
62
+ out.badge = true;
63
+ else if (arg === '--html')
64
+ out.html = true;
65
+ else if (arg === '--baseline') {
66
+ out.baseline = argv[++i];
67
+ if (!out.baseline)
68
+ throw new Error('--baseline expects a path to a previous --json report');
69
+ }
70
+ else if (arg === '--profile') {
71
+ out.profile = argv[++i];
72
+ if (!out.profile || !isProfile(out.profile))
73
+ throw new Error(`--profile expects one of: all, security, quality, agent-ready`);
74
+ }
52
75
  else if (arg === '--min-score') {
53
76
  const v = argv[++i];
54
77
  const n = Number.parseInt(v, 10);
@@ -80,7 +103,43 @@ async function resolveSubject(subject) {
80
103
  return resolveLocal(subject);
81
104
  return resolveNpmPackage(subject);
82
105
  }
106
+ /** Audit one subject — web mode for hosted URLs, stdio mode otherwise. */
107
+ async function auditSubject(subject) {
108
+ if (isWebTarget(subject))
109
+ return runWebAudit(subject);
110
+ return runAudit(await resolveSubject(subject));
111
+ }
83
112
  export async function run(argv) {
113
+ // `serve` → run mcp-scorecard itself AS an MCP server (agents call the audit tool).
114
+ if (argv[0] === 'serve') {
115
+ const { serve } = await import('../mcp-server.js');
116
+ await serve();
117
+ // Keep the process alive for the stdio transport (the CLI entry would
118
+ // otherwise process.exit() as soon as run() resolves).
119
+ await new Promise(() => { });
120
+ return 0;
121
+ }
122
+ // `compare a b c` → audit each and print a side-by-side table.
123
+ if (argv[0] === 'compare') {
124
+ const subjects = argv.slice(1).filter((a) => !a.startsWith('--'));
125
+ if (subjects.length < 2) {
126
+ process.stderr.write(`compare needs at least 2 subjects.\n\n${USAGE}\n`);
127
+ return 2;
128
+ }
129
+ const reports = [];
130
+ for (const s of subjects) {
131
+ try {
132
+ reports.push(await auditSubject(s));
133
+ }
134
+ catch (err) {
135
+ process.stderr.write(`skip ${s}: ${err instanceof Error ? err.message : String(err)}\n`);
136
+ }
137
+ }
138
+ if (reports.length === 0)
139
+ return 1;
140
+ process.stdout.write(`${renderCompare(reports)}\n`);
141
+ return 0;
142
+ }
84
143
  let parsed;
85
144
  try {
86
145
  parsed = parseArgs(argv);
@@ -102,35 +161,31 @@ export async function run(argv) {
102
161
  return 2;
103
162
  }
104
163
  let report;
105
- if (isWebTarget(parsed.subject)) {
106
- // Hosted/remote MCP server or site → web security + agent-readiness audit.
107
- try {
108
- report = await runWebAudit(parsed.subject);
109
- }
110
- catch (err) {
111
- process.stderr.write(`Web audit error: ${err instanceof Error ? err.message : String(err)}\n`);
112
- return 1;
113
- }
164
+ try {
165
+ report = await auditSubject(parsed.subject);
114
166
  }
115
- else {
116
- let target;
117
- try {
118
- target = await resolveSubject(parsed.subject);
119
- }
120
- catch (err) {
121
- process.stderr.write(`Resolver error: ${err instanceof Error ? err.message : String(err)}\n`);
122
- return 1;
123
- }
167
+ catch (err) {
168
+ process.stderr.write(`Audit error: ${err instanceof Error ? err.message : String(err)}\n`);
169
+ return 1;
170
+ }
171
+ if (parsed.profile)
172
+ report = applyProfile(report, parsed.profile);
173
+ let baseline;
174
+ if (parsed.baseline) {
124
175
  try {
125
- report = await runAudit(target);
176
+ baseline = JSON.parse(readFileSync(parsed.baseline, 'utf8'));
126
177
  }
127
178
  catch (err) {
128
- process.stderr.write(`Audit error: ${err instanceof Error ? err.message : String(err)}\n`);
179
+ process.stderr.write(`--baseline read error: ${err instanceof Error ? err.message : String(err)}\n`);
129
180
  return 1;
130
181
  }
131
182
  }
132
- process.stdout.write(parsed.json ? renderJson(report) : renderMarkdown(report));
133
- process.stdout.write('\n');
183
+ const out = parsed.badge ? renderBadge(report)
184
+ : parsed.json ? renderJson(report)
185
+ : parsed.html ? renderHtml(report)
186
+ : baseline ? renderBaseline(report, baseline)
187
+ : renderMarkdown(report);
188
+ process.stdout.write(`${out}\n`);
134
189
  if (report.totalScore < parsed.minScore) {
135
190
  process.stderr.write(`\nScore ${report.totalScore} < --min-score ${parsed.minScore}\n`);
136
191
  return 1;
@@ -1 +1 @@
1
- {"version":3,"file":"commands.js","sourceRoot":"","sources":["../../src/cli/commands.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"commands.js","sourceRoot":"","sources":["../../src/cli/commands.ts"],"names":[],"mappings":"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"}
@@ -10,4 +10,12 @@
10
10
  import type { AuditReport } from '../types.js';
11
11
  /** Markdown table-ish output suitable for terminals and PR comments. */
12
12
  export declare function renderMarkdown(report: AuditReport): string;
13
+ /** A shields.io badge (markdown) maintainers can paste into their README. */
14
+ export declare function renderBadge(report: AuditReport): string;
15
+ /** Side-by-side comparison table for multiple audited targets. */
16
+ export declare function renderCompare(reports: AuditReport[]): string;
17
+ /** Current report + delta against a previous run (regression view). */
18
+ export declare function renderBaseline(report: AuditReport, baseline: AuditReport): string;
19
+ /** Self-contained HTML scorecard for sharing / embedding in docs or a PR. */
20
+ export declare function renderHtml(report: AuditReport): string;
13
21
  export declare function renderJson(report: AuditReport): string;
@@ -26,11 +26,23 @@ export function renderMarkdown(report) {
26
26
  const versionTag = report.target.version ? ` @${report.target.version}` : '';
27
27
  lines.push(`# mcp-scorecard - ${report.target.displayName}${versionTag}`);
28
28
  lines.push('');
29
- lines.push(`**Agent-readiness score:** ${report.totalScore}/100`);
29
+ lines.push(`**Score: ${report.totalScore}/100 — grade ${report.grade}** · mode: \`${report.mode}\``);
30
30
  lines.push('');
31
31
  for (const c of report.checks) {
32
32
  lines.push(`- ${STATUS_ICON[c.status]} ${c.label.padEnd(28)} (${redact(c.summary)})`);
33
33
  }
34
+ // Top fixes: the lowest-scoring checks that have a remediation — biggest points first.
35
+ const top = report.checks
36
+ .filter((c) => c.fixes.length > 0 && c.score < 10)
37
+ .sort((a, b) => a.score - b.score)
38
+ .slice(0, 3);
39
+ if (top.length > 0) {
40
+ lines.push('');
41
+ lines.push('## Top fixes (most points to gain)');
42
+ for (const c of top) {
43
+ lines.push(`- **+${10 - c.score} pts · ${c.label}** — ${redact(c.fixes[0])}`);
44
+ }
45
+ }
34
46
  const detailLines = [];
35
47
  for (const c of report.checks) {
36
48
  if (c.details.length > 0) {
@@ -62,6 +74,56 @@ export function renderMarkdown(report) {
62
74
  lines.push(`_Generated by mcp-scorecard v${report.scorecardVersion} at ${report.generatedAt}_`);
63
75
  return lines.join('\n');
64
76
  }
77
+ /** A shields.io badge (markdown) maintainers can paste into their README. */
78
+ export function renderBadge(report) {
79
+ const color = report.grade === 'A' ? 'brightgreen' : report.grade === 'B' ? 'green'
80
+ : report.grade === 'C' ? 'yellow' : report.grade === 'D' ? 'orange' : 'red';
81
+ const msg = encodeURIComponent(`${report.totalScore}/100 (${report.grade})`);
82
+ const url = `https://img.shields.io/badge/mcp--scorecard-${msg}-${color}`;
83
+ return `[![mcp-scorecard: ${report.grade}](${url})](https://mcp-scorecard.vercel.app)`;
84
+ }
85
+ /** Side-by-side comparison table for multiple audited targets. */
86
+ export function renderCompare(reports) {
87
+ const sorted = [...reports].sort((a, b) => b.totalScore - a.totalScore);
88
+ const lines = ['# mcp-scorecard — comparison', '', '| # | target | score | grade |', '|---|--------|-------|-------|'];
89
+ sorted.forEach((r, i) => {
90
+ lines.push(`| ${i + 1} | ${redact(r.target.displayName)} | ${r.totalScore}/100 | ${r.grade} |`);
91
+ });
92
+ lines.push('', `_Generated by mcp-scorecard v${sorted[0]?.scorecardVersion ?? ''}_`);
93
+ return lines.join('\n');
94
+ }
95
+ /** Current report + delta against a previous run (regression view). */
96
+ export function renderBaseline(report, baseline) {
97
+ const delta = report.totalScore - baseline.totalScore;
98
+ const arrow = delta > 0 ? `▲ +${delta}` : delta < 0 ? `▼ ${delta}` : '= 0';
99
+ const prevById = new Map(baseline.checks.map((c) => [c.id, c.score]));
100
+ const lines = [renderMarkdown(report), '', '## vs baseline', `**Total: ${report.totalScore}/100 (${arrow} from ${baseline.totalScore})**`, ''];
101
+ for (const c of report.checks) {
102
+ const prev = prevById.get(c.id);
103
+ if (prev !== undefined && prev !== c.score) {
104
+ const d = c.score - prev;
105
+ lines.push(`- ${c.label}: ${prev} → ${c.score} (${d > 0 ? '+' : ''}${d})`);
106
+ }
107
+ }
108
+ return lines.join('\n');
109
+ }
110
+ /** Self-contained HTML scorecard for sharing / embedding in docs or a PR. */
111
+ export function renderHtml(report) {
112
+ const color = report.grade === 'A' ? '#10b981' : report.grade === 'B' ? '#34d399' : report.grade === 'C' ? '#f59e0b' : report.grade === 'D' ? '#fb923c' : '#f43f5e';
113
+ const esc = (t) => t.replace(/[&<>]/g, (m) => ({ '&': '&amp;', '<': '&lt;', '>': '&gt;' }[m]));
114
+ const rows = report.checks.map((c) => {
115
+ const cc = c.status === 'pass' ? '#10b981' : c.status === 'warn' ? '#f59e0b' : '#f43f5e';
116
+ return `<tr><td>${esc(c.label)}</td><td style="text-align:right;color:${cc};font-weight:700">${c.score}/10</td><td style="color:#9aa6c2">${esc(redact(c.summary))}</td></tr>`;
117
+ }).join('');
118
+ return `<!doctype html><meta charset="utf-8"><title>mcp-scorecard — ${esc(report.target.displayName)}</title>
119
+ <div style="font-family:ui-monospace,monospace;background:#0b1120;color:#e8eefc;max-width:760px;margin:30px auto;padding:28px;border-radius:14px">
120
+ <div style="font-size:13px;color:#7c8aa6;letter-spacing:.1em">MCP-SCORECARD · ${report.mode.toUpperCase()} MODE</div>
121
+ <h1 style="margin:6px 0 2px">${esc(report.target.displayName)}</h1>
122
+ <div style="font-size:48px;font-weight:800;color:${color}">${report.totalScore}<span style="font-size:20px;color:#7c8aa6">/100</span> &nbsp;<span style="border:2px solid ${color};border-radius:8px;padding:2px 12px;font-size:24px">${report.grade}</span></div>
123
+ <table style="width:100%;border-collapse:collapse;margin-top:18px;font-size:13.5px">${rows}</table>
124
+ <p style="color:#7c8aa6;font-size:12px;margin-top:18px">Generated by <a style="color:#10b981" href="https://mcp-scorecard.vercel.app">mcp-scorecard</a> v${report.scorecardVersion} · ${report.generatedAt}</p>
125
+ </div>`;
126
+ }
65
127
  export function renderJson(report) {
66
128
  // JSON output is also redacted at the string level so consumers don't
67
129
  // accidentally persist secrets from probed servers.
@@ -1 +1 @@
1
- {"version":3,"file":"output.js","sourceRoot":"","sources":["../../src/cli/output.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"output.js","sourceRoot":"","sources":["../../src/cli/output.ts"],"names":[],"mappings":"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"}
@@ -3,7 +3,7 @@
3
3
  * same string. Bumping this without updating package.json is intentional during
4
4
  * dev (keep src as source of truth); a release script can sync them.
5
5
  */
6
- export declare const SERVER_VERSION = "0.1.3";
6
+ export declare const SERVER_VERSION = "0.4.0";
7
7
  /** Identifier used when the probe connects to a target MCP server. */
8
8
  export declare const PROBE_CLIENT_NAME = "mcp-scorecard";
9
9
  /** Env var set on the spawned target so MCP authors can detect we are probing
package/dist/constants.js CHANGED
@@ -3,7 +3,7 @@
3
3
  * same string. Bumping this without updating package.json is intentional during
4
4
  * dev (keep src as source of truth); a release script can sync them.
5
5
  */
6
- export const SERVER_VERSION = '0.1.3';
6
+ export const SERVER_VERSION = '0.4.0';
7
7
  /** Identifier used when the probe connects to a target MCP server. */
8
8
  export const PROBE_CLIENT_NAME = 'mcp-scorecard';
9
9
  /** Env var set on the spawned target so MCP authors can detect we are probing
@@ -0,0 +1 @@
1
+ export declare function serve(): Promise<void>;
@@ -0,0 +1,79 @@
1
+ /**
2
+ * MCP server mode — exposes mcp-scorecard itself as an MCP server so an agent
3
+ * can call the `audit` tool mid-task (e.g. to vet a server before installing it).
4
+ * An MCP that scores MCPs. Run with: `mcp-scorecard serve`.
5
+ *
6
+ * Uses the low-level Server + setRequestHandler API with a plain JSON-Schema
7
+ * tool definition (no zod shape) to stay decoupled from the SDK's zod version.
8
+ */
9
+ import { existsSync } from 'node:fs';
10
+ import { isAbsolute } from 'node:path';
11
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
12
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
13
+ import { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js';
14
+ import { SERVER_VERSION } from './constants.js';
15
+ import { runAudit } from './audit/runner.js';
16
+ import { runWebAudit } from './audit/web/web-runner.js';
17
+ import { resolveGithubRepo } from './resolvers/github-resolver.js';
18
+ import { resolveLocal } from './resolvers/local-resolver.js';
19
+ import { resolveNpmPackage } from './resolvers/npm-resolver.js';
20
+ async function auditTarget(target) {
21
+ if (/^https?:\/\//.test(target) && !/github\.com/.test(target)) {
22
+ return runWebAudit(target);
23
+ }
24
+ let resolved;
25
+ if (/^https?:\/\/github\.com\//.test(target) || target.startsWith('github:')) {
26
+ resolved = await resolveGithubRepo(target);
27
+ }
28
+ else if (isAbsolute(target) && existsSync(target)) {
29
+ resolved = await resolveLocal(target);
30
+ }
31
+ else {
32
+ resolved = await resolveNpmPackage(target);
33
+ }
34
+ return runAudit(resolved);
35
+ }
36
+ export async function serve() {
37
+ const server = new Server({ name: 'mcp-scorecard', version: SERVER_VERSION }, { capabilities: { tools: {} } });
38
+ server.setRequestHandler(ListToolsRequestSchema, async () => ({
39
+ tools: [
40
+ {
41
+ name: 'audit',
42
+ description: "Grade an MCP server's agent-readiness and security. Accepts an npm package name, a GitHub repo URL, a local dist path (→ stdio protocol-quality checks), or a hosted https:// URL (→ web security + agent-readiness checks). Returns a 0–100 score, an A–F grade, itemized checks, and actionable fixes.",
43
+ inputSchema: {
44
+ type: 'object',
45
+ properties: {
46
+ target: {
47
+ type: 'string',
48
+ description: 'npm package, GitHub URL, local dist path, or https:// hosted MCP server'
49
+ }
50
+ },
51
+ required: ['target']
52
+ }
53
+ }
54
+ ]
55
+ }));
56
+ server.setRequestHandler(CallToolRequestSchema, async (req) => {
57
+ if (req.params.name !== 'audit') {
58
+ return { content: [{ type: 'text', text: `unknown tool: ${req.params.name}` }], isError: true };
59
+ }
60
+ const target = String(req.params.arguments?.target ?? '').trim();
61
+ if (!target) {
62
+ return { content: [{ type: 'text', text: 'missing required argument: target' }], isError: true };
63
+ }
64
+ try {
65
+ const report = await auditTarget(target);
66
+ const summary = `${report.target.displayName}: ${report.totalScore}/100 (grade ${report.grade}, ${report.mode} mode)`;
67
+ return { content: [{ type: 'text', text: `${summary}\n\n${JSON.stringify(report, null, 2)}` }] };
68
+ }
69
+ catch (err) {
70
+ return {
71
+ content: [{ type: 'text', text: `audit failed for "${target}": ${err instanceof Error ? err.message : String(err)}` }],
72
+ isError: true
73
+ };
74
+ }
75
+ });
76
+ await server.connect(new StdioServerTransport());
77
+ console.error(`mcp-scorecard MCP server v${SERVER_VERSION} running (stdio) — tool: audit`);
78
+ }
79
+ //# sourceMappingURL=mcp-server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-server.js","sourceRoot":"","sources":["../src/mcp-server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { AuditReport } from './types.js';
2
+ export declare function isProfile(name: string): boolean;
3
+ export declare function applyProfile(report: AuditReport, profileName: string): AuditReport;
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Scoring profiles — narrow a report to the checks in a category (security /
3
+ * quality / agent-ready) and rescore over just those. Pure; returns a new report.
4
+ */
5
+ import { CHECK_META, PROFILES } from './checks-catalog.js';
6
+ import { toGrade } from './types.js';
7
+ export function isProfile(name) {
8
+ return name in PROFILES;
9
+ }
10
+ export function applyProfile(report, profileName) {
11
+ const profile = PROFILES[profileName];
12
+ if (!profile || profileName === 'all')
13
+ return report;
14
+ const cats = profile.categories;
15
+ const filtered = report.checks.filter((c) => {
16
+ const meta = CHECK_META[c.id];
17
+ return meta && cats.includes(meta.category);
18
+ });
19
+ if (filtered.length === 0)
20
+ return report; // nothing in this profile for this mode
21
+ const sum = filtered.reduce((acc, c) => acc + Math.max(0, Math.min(10, c.score)), 0);
22
+ const totalScore = Math.round((sum / (filtered.length * 10)) * 100);
23
+ return { ...report, checks: filtered, totalScore, grade: toGrade(totalScore) };
24
+ }
25
+ //# sourceMappingURL=profiles.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"profiles.js","sourceRoot":"","sources":["../src/profiles.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAE3D,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAErC,MAAM,UAAU,SAAS,CAAC,IAAY;IACpC,OAAO,IAAI,IAAI,QAAQ,CAAC;AAC1B,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,MAAmB,EAAE,WAAmB;IACnE,MAAM,OAAO,GAAG,QAAQ,CAAC,WAAW,CAAC,CAAC;IACtC,IAAI,CAAC,OAAO,IAAI,WAAW,KAAK,KAAK;QAAE,OAAO,MAAM,CAAC;IACrD,MAAM,IAAI,GAAG,OAAO,CAAC,UAAU,CAAC;IAChC,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE;QAC1C,MAAM,IAAI,GAAG,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAC9B,OAAO,IAAI,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC9C,CAAC,CAAC,CAAC;IACH,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,MAAM,CAAC,CAAC,wCAAwC;IAClF,MAAM,GAAG,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACrF,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,GAAG,CAAC,QAAQ,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC;IACpE,OAAO,EAAE,GAAG,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,KAAK,EAAE,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC;AACjF,CAAC"}
package/dist/types.d.ts CHANGED
@@ -57,7 +57,7 @@ export interface ResolvedTarget {
57
57
  /** package.json contents, if any. */
58
58
  packageJson?: Record<string, unknown>;
59
59
  }
60
- export type CheckId = 'schema_validity' | 'tool_naming' | 'privacy_modes' | 'mutation_gating' | 'agent_manifest' | 'smoke_test' | 'resources' | 'tool_descriptions' | 'annotations' | 'manifest_discoverability' | 'web_https' | 'web_security_headers' | 'web_auth_posture' | 'web_oauth_discovery' | 'web_llms_txt' | 'web_mcp_server_card' | 'web_agent_skills' | 'web_api_catalog' | 'web_robots_signals' | 'web_structured_data';
60
+ export type CheckId = 'schema_validity' | 'tool_naming' | 'privacy_modes' | 'mutation_gating' | 'agent_manifest' | 'smoke_test' | 'resources' | 'tool_descriptions' | 'annotations' | 'manifest_discoverability' | 'web_https' | 'web_security_headers' | 'web_auth_posture' | 'web_oauth_discovery' | 'web_llms_txt' | 'web_mcp_server_card' | 'web_agent_skills' | 'web_api_catalog' | 'web_robots_signals' | 'web_structured_data' | 'web_exposed_paths' | 'web_cors_posture';
61
61
  /**
62
62
  * Snapshot captured from a hosted/remote target over HTTP — the parallel of
63
63
  * ProbeSnapshot for the web/security audit path. Pure scorers read this.
@@ -82,6 +82,11 @@ export interface WebProbe {
82
82
  jsonLd: boolean;
83
83
  ogTags: boolean;
84
84
  markdownNegotiation: boolean;
85
+ gitExposed: boolean;
86
+ envExposed: boolean;
87
+ securityTxt: boolean;
88
+ corsAllowOrigin: string | null;
89
+ corsAllowCredentials: boolean;
85
90
  }
86
91
  export interface CheckResult {
87
92
  id: CheckId;
@@ -103,7 +108,10 @@ export interface AuditReport {
103
108
  serverVersion?: string;
104
109
  };
105
110
  totalScore: number;
111
+ grade: 'A' | 'B' | 'C' | 'D' | 'F';
112
+ mode: 'stdio' | 'web';
106
113
  checks: CheckResult[];
107
114
  generatedAt: string;
108
115
  scorecardVersion: string;
109
116
  }
117
+ export declare function toGrade(score: number): 'A' | 'B' | 'C' | 'D' | 'F';
package/dist/types.js CHANGED
@@ -2,5 +2,7 @@
2
2
  * Shared types: the snapshot the probe captures and the shape of a check.
3
3
  * Kept deliberately minimal so the audit pipeline stays portable.
4
4
  */
5
- export {};
5
+ export function toGrade(score) {
6
+ return score >= 90 ? 'A' : score >= 80 ? 'B' : score >= 70 ? 'C' : score >= 60 ? 'D' : 'F';
7
+ }
6
8
  //# sourceMappingURL=types.js.map
package/dist/types.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;GAGG"}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAkJH,MAAM,UAAU,OAAO,CAAC,KAAa;IACnC,OAAO,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;AAC7F,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mcp-scorecard",
3
- "version": "0.2.0",
3
+ "version": "0.4.0",
4
4
  "mcpName": "io.github.davidmosiah/mcp-scorecard",
5
5
  "description": "Grade any MCP server's agent-readiness in one command \u2014 stdio (10 protocol checks) AND hosted/remote servers (10 security + web agent-readiness checks). Open source, local-first, no credentials.",
6
6
  "type": "module",
@@ -22,9 +22,11 @@
22
22
  "dev": "tsx src/index.ts",
23
23
  "test:checks": "node scripts/test-checks.mjs",
24
24
  "test:self": "node scripts/smoke-self.mjs",
25
- "test": "npm run typecheck && npm run build && npm run test:checks && npm run test:self && npm run test:web",
25
+ "test": "npm run typecheck && npm run build && npm run test:checks && npm run test:self && npm run test:web && npm run test:features",
26
26
  "prepublishOnly": "npm test",
27
- "test:web": "node scripts/test-web.mjs"
27
+ "test:web": "node scripts/test-web.mjs",
28
+ "test:features": "node scripts/test-features.mjs",
29
+ "gen:checks": "node scripts/gen-checks-page.mjs"
28
30
  },
29
31
  "keywords": [
30
32
  "mcp",