> ## Documentation Index
> Fetch the complete documentation index at: https://docs.37audits.com/llms.txt
> Use this file to discover all available pages before exploring further.

# MCP Server Card Auditor

> Validates the MCP Server Card that advertises a remote MCP server for AI clients

<Info>
  **AI Readiness Auditor** — validates the MCP Server Card that advertises a remote MCP server for AI clients.
</Info>

<CardGroup cols={2}>
  <Card title="AI Readiness" icon="bot">
    Makes the site's MCP server discoverable and connectable by AI clients.
  </Card>

  <Card title="Security" icon="shield">
    HTTPS-only hosting and browser-safe CORS on the card endpoint.
  </Card>
</CardGroup>

An MCP Server Card is a static JSON document that describes a remote [Model Context Protocol](https://modelcontextprotocol.io/) server — its identity, transport endpoints, and protocol versions — so AI clients can discover and connect to it before any protocol exchange. This auditor finds the site's Server Card, validates the document against the Server Card v1 schema rules, and checks how it is hosted.

## How it works

The auditor discovers Server Cards from the audited URL's origin and then validates every card it finds:

1. **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.
2. **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.
3. **Document validation** — each card is checked against the Server Card v1 schema rules: `$schema`, `name`, `version`, `description`, and `remotes`.
4. **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.
5. **Specification pin** — every run emits `37A-McpServerCardAuditor-100` (`INFORMATION`) naming MCP Server Card [v1](https://static.modelcontextprotocol.io/schemas/v1/server-card.schema.json) (27 Jun 2026) and [schema.json](https://github.com/modelcontextprotocol/ext-server-card/blob/92999cb3f5d82e648385cb92ce41ed9aa1386eda/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`.

## What it audits

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                                                                                                                                                                                                |
| --------------------------------------------------------------------- | ------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| <a id="37A-McpServerCardAuditor-100" />`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. |
| <a id="37A-McpServerCardAuditor-400" />`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`.                                                |
| <a id="37A-McpServerCardAuditor-401" />`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}`.                                                                                                                                                                      |
| <a id="37A-McpServerCardAuditor-402" />`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}`.                                                                                                |
| <a id="37A-McpServerCardAuditor-403" />`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.                                                                                                                                                 |
| <a id="37A-McpServerCardAuditor-404" />`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}`.                                                                                                                         |
| <a id="37A-McpServerCardAuditor-405" />`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`.                                                                                                                                                |
| <a id="37A-McpServerCardAuditor-406" />`37A-McpServerCardAuditor-406` | `FAIL`        | The card has no `version` field.                                                                                                                                      | Set version on `{nameOrUrl}` (e.g. 1.0.0); do not use ranges.                                                                                                                                                 |
| <a id="37A-McpServerCardAuditor-407" />`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.                                                                                                                                     |
| <a id="37A-McpServerCardAuditor-408" />`37A-McpServerCardAuditor-408` | `FAIL`        | The card has no `description` field (or it is blank).                                                                                                                 | Add a 1-100 character description to `{nameOrUrl}`.                                                                                                                                                           |
| <a id="37A-McpServerCardAuditor-409" />`37A-McpServerCardAuditor-409` | `FAIL`        | `description` is longer than 100 characters.                                                                                                                          | Shorten the description of `{nameOrUrl}` from `{length}` to at most 100 characters.                                                                                                                           |
| <a id="37A-McpServerCardAuditor-410" />`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}`.                                                                                                               |
| <a id="37A-McpServerCardAuditor-411" />`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.                                                                                                         |
| <a id="37A-McpServerCardAuditor-412" />`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}`.                                                                                                                                                          |
| <a id="37A-McpServerCardAuditor-413" />`37A-McpServerCardAuditor-413` | `FAIL`        | The card URL uses the `http` scheme in production (localhost is exempt).                                                                                              | Serve `{cardUrl}` over https instead of http.                                                                                                                                                                 |
| <a id="37A-McpServerCardAuditor-300" />`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}`.                                                                                                               |
| <a id="37A-McpServerCardAuditor-200" />`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.` | —                                                                                                                                                                                                             |

## Output documentation

| 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.                                 |

## Risks and considerations

### AI discoverability

* 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.

### Client interoperability

* 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.

### Security and trust

* 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.

### Operational drift

* 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.
