Add experimental Server Cards support (SEP-2127)

SA
3mo ago
+2024-0

Closes https://github.com/modelcontextprotocol/experimental-ext-server-card/issues/16

Summary

Experimental SDK support for MCP Server Cards (SEP-2127) and AI Catalog discovery, opt-in under mcp.{shared,server,client}.experimental. As an experimental extension, these APIs may change without notice.

Takes over #2696 (thanks @dsp-ant — the original two commits are preserved with authorship), rebased cleanly onto current main. #2696 was stacked on the Tasks (SEP-1686) work, since removed from main (#2714).

Opening as a draft for maintainer review — per the extension repo's contribution rules, AI-assisted changes are not self-merged.

What it does

A server builds a Server Card from its own identity, serves it from a Starlette app, and advertises it through an AI Catalog. A client discovers a host's catalog, then fetches and validates the cards it references. Cards describe identity and remote (HTTP) transport only — locally-runnable package metadata stays in the MCP Registry's server.json.

Conformance to the current schemas

  • $schema is pinned to https://static.modelcontextprotocol.io/schemas/v1/server-card.schema.json; a card pointing at the registry's server.schema.json is rejected. A document that omits $schema is defaulted to the v1 URL rather than rejected.
  • AI Catalog entries use the serialized type field, require specVersion, and accept optional displayName. server_card_entry() emits the minimal MCP shape (identifier, type, and url) so human-readable fields cannot drift from the referenced card.
  • Media type — serving and catalog entries use application/mcp-server-card+json; the client recognizes only this type and skips catalog entries declaring anything else.
  • Catalog identifiers are urn:air:{publisher}:mcp:{name} — the card name's reverse-DNS namespace turned back into the publisher's forward-DNS domain (com.example/weather → urn:air:example.com:mcp:weather).
  • Discovery uses the AI Catalog at /.well-known/ai-catalog.json. Discovery responses carry the CORS headers the spec requires (MUST), Cache-Control (SHOULD), strong SHA-256 ETags, and If-None-Match handling for conditional requests.
  • version accepts exact versions only; ranges and wildcards (^1.2.3, ~1.2.3, >=1.2.3, 1.x, 1 || 2, 1 - 2) are rejected.
  • Unsettled AI Catalog metadata remains available but is documented as unstable pending the outcome of Agent-Card/ai-catalog#77.

Verification

  • ./scripts/test — full coverage suite and strict-no-cover
  • pre-commit run --all-files — formatting, lint, pyright, markdownlint, lock consistency, and README snippets
  • Focused Server Card and AI Catalog tests cover URL and inline discovery, entry filtering, relative URLs, CORS on both 200 and 304, ETags, validation, and client/server helpers

🤖 The implementation and cleanup were AI-assisted and human-directed.