Validates the MCP Server Card advertised to AI clients
The auditor discovers Server Cards from the audited URL's origin and then validates every card it finds:
AI Catalog as a link source β fetches /.well-known/ai-catalog.json and follows entries whose type is application/mcp-server-card+json, using their url (fetched with Accept: application/mcp-server-card+json) or inline data. The catalog itself is not audited: a missing, unreachable, or malformed catalog produces no findings, and broken entry links are only recorded as attempts.
Reserved-location fallback β when the catalog yields no card, tries /.well-known/mcp/server-card.json and then /mcp/server-card, stopping at the first HTTP 200.
Document validation β each card is checked against the Server Card v1 schema rules: $schema, name, version, description, and remotes.
Hosting validation β cards fetched over HTTP are additionally checked for media type, CORS, and HTTPS. Inline cards embedded in a catalog entry have no HTTP response of their own, so hosting rules are skipped for them.
Specification pin β every run emits 37A-McpServerCardAuditor-100 (INFORMATION) naming MCP Server Card v1 (27 Jun 2026) and schema.json commit 92999cb3f5d82e648385cb92ce41ed9aa1386eda. That check does not change overall status.
Any failing rule makes the audit FAIL; otherwise a wrong media type produces a WARNING; otherwise the audit is a SUCCESS.
Every row maps to one checkRule* method and one CheckCode. Hosting rules (412, 413, 300) are skipped for inline cards embedded in an AI Catalog entry. 37A-McpServerCardAuditor-100 is emitted on every run, including missing-card and invalid-URL failures. CheckCode suffixes use status ranges: 100 information, 200 success, 300β399 warning, 400β499 fail.
| CheckCode | Status | When it fires | Recommendation |
|---|---|---|---|
37A-McpServerCardAuditor-100 | INFORMATION | Every run. Records that this auditor implements MCP Server Card v1 and the pinned server-card.schema.json commit. | This auditor implements MCP Server Card v1; documents must set $schema to https://static.modelcontextprotocol.io/schemas/v1/server-card.schema.json. Schema pin 92999cb3f5d82e648385cb92ce41ed9aa1386eda. |
37A-McpServerCardAuditor-400 | FAIL | No Server Card could be obtained from the AI Catalog entries or from either reserved location. | Publish a Server Card at {origin}/mcp/server-card or {origin}/.well-known/mcp/server-card.json, or list its URL in {origin}/.well-known/ai-catalog.json. |
37A-McpServerCardAuditor-401 | FAIL | The document served at the card URL cannot be parsed as a JSON object. | Serve a JSON Server Card at {cardUrl}. |
37A-McpServerCardAuditor-402 | FAIL | The card has no $schema field. | Set $schema to https://static.modelcontextprotocol.io/schemas/v1/server-card.schema.json on {nameOrUrl}. |
37A-McpServerCardAuditor-403 | FAIL | $schema is present but is not the v1 Server Card schema URL (for example a date-versioned or registry schema URL). | Replace {observed} with the v1 server-card.schema.json URL. |
37A-McpServerCardAuditor-404 | FAIL | The card has no name field. | Set name in reverse-DNS form (e.g. com.example/weather) on the card at {cardUrl}. |
37A-McpServerCardAuditor-405 | FAIL | name does not match the reverse-DNS namespace/name format with exactly one slash. | Change {name} to namespace/name, e.g. com.example/weather. |
37A-McpServerCardAuditor-406 | FAIL | The card has no version field. | Set version on {nameOrUrl} (e.g. 1.0.0); do not use ranges. |
37A-McpServerCardAuditor-407 | FAIL | version expresses a range (^1.2.3, ~1.2.3, >=1.2.3, 1.x, 1.*) instead of a single version. | Replace {version} on {nameOrUrl} with a single version such as 1.0.0. |
37A-McpServerCardAuditor-408 | FAIL | The card has no description field (or it is blank). | Add a 1-100 character description to {nameOrUrl}. |
37A-McpServerCardAuditor-409 | FAIL | description is longer than 100 characters. | Shorten the description of {nameOrUrl} from {length} to at most 100 characters. |
37A-McpServerCardAuditor-410 | FAIL | A remotes[] entry has a type other than streamable-http or sse. | Set remotes[{i}].type on {nameOrUrl} to streamable-http or sse instead of {observed}. |
37A-McpServerCardAuditor-411 | FAIL | A remotes[] entry has a url that does not start with http://, https://, or a {template-variable} placeholder. | Change remotes[{i}].url on {nameOrUrl} from {observed} to an http(s) URL or a {template} URL. |
37A-McpServerCardAuditor-412 | FAIL | The HTTP response serving the card has no Access-Control-Allow-Origin header, blocking browser-based clients. | Add Access-Control-Allow-Origin: * on {cardUrl}. |
37A-McpServerCardAuditor-413 | FAIL | The card URL uses the http scheme in production (localhost is exempt). | Serve {cardUrl} over https instead of http. |
37A-McpServerCardAuditor-300 | WARNING | The HTTP response serving the card has a Content-Type other than application/mcp-server-card+json. | Serve {cardUrl} with Content-Type application/mcp-server-card+json instead of {observed}. |
37A-McpServerCardAuditor-200 | SUCCESS | Every rule above passed for a discovered card; one SUCCESS check is added per valid card with the message Server Card "{name}" {version} at "{cardUrl}" is valid. | β |
| Status | Description | Test logic |
|---|---|---|
| INFORMATION | Provenance only; does not change overall status | Every run includes 37A-McpServerCardAuditor-100 with MCP Server Card v1 and schema commit 92999cb3β¦ in the message and Check.data. |
| SUCCESS | A Server Card was found, matches the v1 schema rules, and is properly hosted | Card discovered via AI Catalog or a reserved location. Valid JSON object with the v1 $schema URL, a reverse-DNS name, a single (non-range) version, a 1-100 character description, and remotes[] entries limited to streamable-http/sse types with http(s) or templated URLs. Fetched cards are served over HTTPS with Access-Control-Allow-Origin and the application/mcp-server-card+json media type. The specification pin check is still present. |
| WARNING | The card is valid but served with the wrong media type | Content-Type differs from application/mcp-server-card+json on an otherwise fully valid card (300). The specification pin check is still present. |
| FAIL | No card was found, the card violates the v1 schema rules, or hosting is unsafe | No card at any discovery location (400); invalid JSON (401); missing or wrong $schema (402, 403); missing or malformed name (404, 405); missing or range version (406, 407); missing or over-long description (408, 409); invalid remotes[] type or URL (410, 411); missing Access-Control-Allow-Origin (412); card served over plain HTTP (413). The specification pin check is still present. |
Without a Server Card at a discoverable location, AI clients cannot find or auto-configure a connection to the site's MCP server, so the server is invisible to agentic sessions.
A card that violates the v1 schema (wrong $schema, malformed name, range version) may be rejected by validating clients even when the MCP server itself works.
Browser-based clients are blocked entirely when the card endpoint lacks Access-Control-Allow-Origin.
Serving the card without the application/mcp-server-card+json media type can break clients that negotiate content via the Accept header.
Invalid remotes[] transport types or endpoint URLs steer clients toward connections that cannot be established.
Server Cards are consumed before the client connects; a card served over plain HTTP can be tampered with in transit and redirect clients to a rogue endpoint.
A stale or inaccurate card (identity, transport, protocol versions) is a confusion or downgrade vector β keep the card consistent with the server's runtime behavior.
The card is a static document: version bumps, endpoint moves, or transport changes on the server must be mirrored in the card, or clients will act on outdated connection details.
Add this auditor to your monitoring setup and start identifying issues on your websites today.