MCP Server Cards Are Final. The Best Decision Was What They Left Out.

SEP-2127 merged on 6 October: a card says who an MCP server is and where to connect, but never what tools it has. Why that's right, and where it's too relaxed.


The MCP discovery stack: an AI Catalog at /.well-known/ai-catalog.json points to Server Cards, which carry identity, endpoints and protocol versions and are advisory; once connected, server/discover and tools/list under the caller's identity are authoritative — and that runtime layer is where gateways enforce

A week ago today, on the same day Sierra and Meta announced the Personal Agent Protocol, the MCP project merged SEP-2127: MCP Server Cards, status Final. API Evangelist summed up the week as two front doors for agents, which is about right.

The Personal Agent Protocol got the headlines. Server Cards will probably touch more of your infrastructure, because every remote MCP server you run is a candidate for one. Here’s what shipped, why its biggest omission is its best decision, and the one place I think it’s too relaxed.

What a card is

A Server Card is a static JSON document that describes a remote MCP server before anything connects to it. It’s an Extensions Track spec with the identifier io.modelcontextprotocol/server-card, and the normative schema lives in the extension repository. A minimal valid card:

{
  "$schema": "https://static.modelcontextprotocol.io/schemas/v1/server-card.schema.json",
  "name": "com.example/incident-context",
  "version": "1.4.0",
  "title": "Incident Context",
  "description": "Read-only incident context: recent alerts, deploys, and service ownership.",
  "websiteUrl": "https://example.com/docs/mcp/incident-context",
  "repository": {
    "url": "https://github.com/example/incident-context-mcp",
    "source": "github"
  },
  "remotes": [
    {
      "type": "streamable-http",
      "url": "https://mcp.example.com/incident-context",
      "supportedProtocolVersions": ["2026-07-28"]
    }
  ]
}

I validated that against the published JSON Schema. A few constraints will catch people out. name is reverse-DNS with exactly one slash. description is capped at 100 characters. version must be an exact version, not a range. $schema must be the v1 URL exactly. Each entry in remotes declares a transport (streamable-http or sse), a URL that can contain {variables}, optional headers, and the protocol versions that endpoint supports — so a client can tell whether it can talk to the server before it tries.

Where it lives — not where earlier drafts put it

The card itself has no well-known path. Earlier drafts of the SEP put it at .well-known/mcp-server-card; the final version doesn’t. The discovery document reserves GET <streamable-http-url>/server-card as the recommended default, so a server at https://host/mcp serves its card at https://host/mcp/server-card. Any other unreserved URI, on any domain, is also valid.

Domain-level discovery moves up a layer, to an AI Catalog at /.well-known/ai-catalog.json — the same catalog format I walked through for Agentic Resource Discovery in July. Catalog entries of type application/mcp-server-card+json either link to a card by url or embed it inline as data.

The reasoning is clean. .well-known is for site-wide metadata, like the catalog or OAuth’s protected-resource metadata. A single server’s card is application-level metadata, and because the catalog always gives the card’s exact URL, nobody ever has to guess where it is. If you built anything against a .well-known card path from an earlier draft, move it.

The best decision: no tools on the card

A Server Card doesn’t list the server’s tools, resources or prompts. It doesn’t advertise capabilities or extension support either. The SEP’s reasoning is that the primitives a server exposes “can vary by authenticated user, session, configuration, feature flags, deployment state, and more,” and a static document can’t represent that.

That’s correct, and from a platform team’s point of view it’s more than correct — it’s protective.

Imagine the alternative. If cards listed tools, the card would become the thing people allowlisted against. Gateways would read the brochure, approve the listed tools, and cache the decision. Then the server would change a tool’s description or add a new one — deliberately or through compromise — and the card would still say what it said last week. Your control would be checking the advertising, not the product.

We already know that failure. Silently changing tool definitions is how MCP supply-chain attacks work, which is why the OWASP Q3 roundup recommends snapshotting tool definitions and re-approving them when they change. A static tool list on a card would have handed everyone a plausible-looking reason to skip that step.

The spec closes the door explicitly: clients MUST NOT treat card contents as authoritative for security or access-control decisions, and SHOULD prefer live values from server/discover where the two disagree. Enforcement stays where it belongs, at runtime: tools/list as your gateway sees it, under the caller’s identity, diffed against what you approved.

A follow-on SEP may add primitives once it can handle per-user variants. If it does, keep enforcing at runtime anyway.

Where I’d push back: consistency isn’t authenticity

The SEP’s security section says that because cards are advisory and clients verify them against live runtime metadata, “a compromised card primarily affects discoverability rather than security.”

That holds for one threat: a tampered card pointing at a legitimate server. The client connects, the live server disagrees with the card, the client trusts the server. Fine.

It holds much less well for a card on a lookalike domain pointing at an attacker’s server. The live server will agree with its own card perfectly. Checking a card against the server it describes proves the two are consistent. It doesn’t prove the server is who you think it is.

Two details in the format make this sharper:

  • Cards can ask for secrets. A remote’s headers can be marked isRequired and isSecret, so the client prompts the user for a value. A card on examp1e.com describing “Example’s incident API” can ask for your real Example API key, and an autoconfiguring client will helpfully show the prompt.
  • Catalogs can delegate across domains. By design, a catalog on acme.org may point to cards hosted on a SaaS provider’s domain. That’s legitimate — it’s how hosted MCP will work. It also means the domain in the catalog doesn’t have to match the domain of the endpoint you end up talking to.

None of this is unique to MCP; it’s the same discovery-phishing problem as any directory. But “discoverability rather than security” undersells it once clients start configuring themselves from what they discover. Discovery is where phishing lives. It’s the same lesson as last week’s OWASP roundup, one layer up: being reachable didn’t make a target authorised, and being discoverable doesn’t make a server trustworthy.

What I’d do now

Publish cards for your internal remote MCP servers. A card generated by the same pipeline that deploys the server is a better source for your internal catalog than a wiki page, because its version and endpoints can’t drift from what’s deployed. The discovery doc recommends ETag revalidation, so clients can cache cheaply.

Don’t let clients autoconfigure from public discovery without a policy. Allowlist the catalog domains your clients will configure from. Require explicit human approval when a card’s endpoint is on a different domain from the catalog that listed it, and before any client prompts a user for a secret header declared by a card.

Keep enforcement at runtime. Gateway allowlists key on live tools/list under the caller’s identity, with definitions snapshotted and diffed. Nothing on a card should change what an agent is allowed to call.

Watch your own cards. The most security-relevant diff a card can have is a change to remotes[].url. Alert on it like you’d alert on a DNS change.

Move off draft paths. If you implemented a .well-known card location from an earlier draft, switch to the catalog plus <endpoint>/server-card.

Server Cards are a small, careful spec, and the care shows most in what they refuse to say. The open question is whether clients will be as careful about what they believe.


Related: You’ve Been Governing the Agents You Run. Here Come the Ones You Don’t. · Agentic Resource Discovery: I Read the Spec, Then Published a Catalog · MCP 2026-07-28 shipped

Frequently asked questions

What is an MCP Server Card?

A static JSON document describing a remote MCP server before a client connects to it: its identity (a reverse-DNS name, version, description, and optional title, icons, repository and website), its remote endpoints (transport type, URL template, headers and variables), and the MCP protocol versions each endpoint supports. It was standardised by SEP-2127, merged with status Final on 6 October 2026 as an Extensions Track extension with the identifier io.modelcontextprotocol/server-card.

Where is a Server Card hosted?

Anywhere. The card itself has no well-known path. MCP reserves GET <streamable-http-url>/server-card as the recommended default, so a server at https://host/mcp would serve its card at https://host/mcp/server-card, but any unreserved URI on any domain is valid. Domain-level discovery happens through an AI Catalog at /.well-known/ai-catalog.json, whose entries either link to a card by URL or embed it inline.

Why don't Server Cards list a server's tools?

Because the tools an MCP server exposes can vary by authenticated user, session, configuration, feature flags and deployment state, and a static document cannot represent that reliably. The spec also excludes capabilities and extension support for the same reason, and requires that clients never treat card contents as authoritative for security or access-control decisions. Tools are still discovered at runtime through tools/list under the caller's identity.

Can a malicious Server Card cause harm?

The spec argues that a compromised card mainly affects discoverability rather than security, because clients verify card claims against the live server. That holds for a tampered card pointing at a legitimate server. It is weaker for a card on a lookalike domain pointing at an attacker's server, because the live server will agree with its own card. A card can also declare that a connection requires secret headers, which makes a lookalike card a way to ask for real credentials. Clients that autoconfigure from discovery need a policy on which catalog domains they trust.

Comments