Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ protocol.
1. [Logging](server.md#logging)
1. [Pagination](server.md#pagination)

## Experimental Extensions

1. [Server Cards](server_cards.md)

# TroubleShooting

See [troubleshooting.md](troubleshooting.md) for a troubleshooting guide.
Expand Down
219 changes: 219 additions & 0 deletions docs/server_cards.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,219 @@
<!-- Autogenerated by weave; DO NOT EDIT -->
# MCP Server Cards

1. [Discovery](#discovery)
1. [Card fields](#card-fields)
1. [Build a card](#build-a-card)
1. [Serve a card](#serve-a-card)
1. [Host static JSON](#host-static-json)
1. [AI Catalog context](#ai-catalog-context)
1. [Security and operations](#security-and-operations)

!!! warning "Experimental API"

Server Cards and the Go APIs in
[`mcp/experimental/servercard`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/mcp/experimental/servercard)
are experimental. They may change or be removed without deprecation as
[SEP-2127](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2127)
evolves. Pin the SDK version if you depend on them in a deployed system.

An MCP Server Card is a static JSON document that describes a remote server's
identity and connection details before a client connects. The format is being
developed in the
[experimental Server Card extension](https://github.com/modelcontextprotocol/experimental-ext-server-card).

A Server Card describes connectivity, not capability. It does not list tools,
resources, or prompts. Its claims are advisory: after connecting, clients must
use the MCP initialization result and the live runtime APIs as the authoritative
source for server metadata, capabilities, and access.

## Discovery

A typical discovery flow is:

1. A client obtains a Server Card URL from trusted configuration or an AI
Catalog.
2. The client fetches the URL with an `Accept:
application/mcp-server-card+json` header.
3. The client validates the card and selects one of its advertised remote
endpoints.
4. The client connects and performs normal MCP initialization and capability
discovery.

A card may be served from any unreserved URI. For a Streamable HTTP endpoint,
the recommended location is `<streamable-http-url>/server-card`. For example,
an endpoint at `https://dice.example.com/mcp` would normally publish its card
at `https://dice.example.com/mcp/server-card`.

The Go SDK currently builds, validates, and serves Server Cards. It does not
provide an AI Catalog client or automatically discover card URLs.

## Card fields

| JSON field | Required | Description |
| --- | --- | --- |
| `$schema` | Yes | The Server Card schema URL. [`BuildServerCard`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/mcp/experimental/servercard#BuildServerCard) uses the canonical v1 schema. |
| `name` | Yes | A stable reverse-DNS namespace/name identifier, such as `com.example/dice-roller`. |
| `description` | Yes | A user-facing description of at most 100 characters. |
| `version` | Yes | The exact server version. Ranges and wildcards are invalid. |
| `title` | No | A human-readable display name. |
| `websiteUrl` | No | The server's website. |
| `icons` | No | Icons suitable for display in a client. |
| `repository` | No | Source repository metadata. |
| `remotes` | No | Streamable HTTP or legacy SSE connection endpoints. |
| `_meta` | No | Namespaced extension metadata. |

The canonical v1 schema identifier currently returns `404` while the extension
is pre-release. Until it is published, use the extension repository's generated
[`schema.json`](https://github.com/modelcontextprotocol/experimental-ext-server-card/blob/3b2d974dbbc1bcf899e0ed2ef49a91758853c9a6/schema.json)
as the validation payload. Its
[`schema.ts`](https://github.com/modelcontextprotocol/experimental-ext-server-card/blob/3b2d974dbbc1bcf899e0ed2ef49a91758853c9a6/schema.ts)
source is authoritative.

`BuildServerCard` copies `title`, `version`, `websiteUrl`, and `icons` from
[`mcp.Implementation`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/mcp#Implementation).
The API accepts the card's name separately because `Implementation.Name` is
free-form, but a Server Card-enabled server should use the same stable
reverse-DNS identifier for both values so its pre-connection and runtime
identities do not contradict each other.

## Build a card

Use `BuildServerCard` with an exact implementation version, a reverse-DNS card
name, and a short description. Add remotes, repository information, and
namespaced metadata as needed.

```go
func ExampleBuildServerCard() {
impl := &mcp.Implementation{
Name: "com.example/dice-roller",
Title: "Dice Roller",
Version: "1.0.0",
WebsiteURL: "https://dice.example.com",
}
card, err := servercard.BuildServerCard(impl,
servercard.WithName("com.example/dice-roller"),
servercard.WithDescription("Rolls dice for tabletop games."),
servercard.WithRemotes(servercard.Remote{
Type: servercard.RemoteTypeStreamableHTTP,
URL: "https://dice.example.com/mcp",
}),
servercard.WithRepository(servercard.Repository{
URL: "https://github.com/example/dice-roller",
Source: "github",
}),
)
if err != nil {
log.Fatal(err)
}

fmt.Println(card.Name, card.Version)
fmt.Println(card.Remotes[0].URL)
// Output:
// com.example/dice-roller 1.0.0
// https://dice.example.com/mcp
}
```

`BuildServerCard` validates the result before returning it. Call
[`ServerCard.Validate`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/mcp/experimental/servercard#ServerCard.Validate)
again after modifying a card directly.

## Serve a card

Serve the card on a public route that does not require MCP authentication.
`Mount` registers the handler on an `http.ServeMux`:

```go
mux := http.NewServeMux()
servercard.Mount(mux, "/mcp/server-card", card)
```

When the MCP transport endpoint is `/mcp`, pass `/mcp/server-card` explicitly.
Calling `Mount` with an empty path uses `servercard.DefaultPath`
(`/server-card`) on the mux; it does not infer the transport endpoint.

The handler:

- accepts `GET` and `HEAD`;
- returns `application/mcp-server-card+json`;
- enables cross-origin reads with `Access-Control-Allow-Origin: *`;
- sends `Cache-Control: public, max-age=3600`;
- sends a strong content-derived `ETag`; and
- returns `304 Not Modified` when `If-None-Match` matches.

ETag handling is additional Go handler behavior. The current extension does
not require `ETag` or `If-None-Match`.

## Host static JSON

Server Cards are static metadata, so they can also be generated during a build
and hosted by a web server, object store, or CDN:

```go
func Example_staticFile() {
card, err := servercard.BuildServerCard(
&mcp.Implementation{Name: "com.example/dice-roller", Version: "1.0.0"},
servercard.WithName("com.example/dice-roller"),
servercard.WithDescription("Rolls dice for tabletop games."),
)
if err != nil {
log.Fatal(err)
}

data, err := json.MarshalIndent(card, "", " ")
if err != nil {
log.Fatal(err)
}
data = append(data, '\n')
if err := os.WriteFile("server-card.json", data, 0o644); err != nil {
log.Fatal(err)
}
}
```

The example uses a card returned by `BuildServerCard`, so it is already
validated. Configure the hosting layer to return `servercard.MediaType`, allow
cross-origin `GET` requests, and use appropriate cache validators.

## AI Catalog context

The extension's intended discovery direction is
[draft PR #42](https://github.com/modelcontextprotocol/experimental-ext-server-card/pull/42),
which delegates catalog discovery to the
[AI Catalog specification](https://github.com/Agent-Card/ai-catalog/blob/28825483143ce9f3b344ed01dc2771d4adf02d01/specification/ai-catalog.md).
AI Catalog documents use `application/ai-catalog+json`, contain `specVersion`
and `entries`, and may be published at any URL. A domain may advertise one at
`/.well-known/ai-catalog.json`.

An MCP entry uses `type: "application/mcp-server-card+json"` and contains
exactly one of:

- `url`, which the client fetches with `Accept:
application/mcp-server-card+json`; or
- `data`, which contains the inline Server Card.

Use the JSON member `type`, not the obsolete `mediaType`. Avoid duplicating the
card's display name, description, version, or repository data in the catalog
entry, where those values could drift. AI Catalog defines `urn:air:` entry
identifiers and uses the `mcp` namespace for MCP entries.

Do not publish an MCP-specific catalog at
`/.well-known/mcp/catalog.json`; that format is removed by the intended
discovery direction. The Go SDK does not currently define AI Catalog models or
derive `urn:air:` identifiers.

## Security and operations

Server Cards and public catalogs are normally available before authentication.
Do not include credentials, populated secret inputs, internal hostnames, or
private network topology in them.

Treat card and AI Catalog URLs as untrusted input. A client that fetches a
discovered URL should enforce its normal outbound network policy, including
HTTPS requirements in production and protections against server-side request
forgery. Deployments should also apply reasonable rate limits, caching, and
polling intervals.

Finally, do not use card claims as authoritative security or access-control
data. The connected MCP server's live protocol responses take precedence.
4 changes: 4 additions & 0 deletions internal/docs/README.src.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ protocol.
1. [Logging](server.md#logging)
1. [Pagination](server.md#pagination)

## Experimental Extensions

1. [Server Cards](server_cards.md)

# TroubleShooting

See [troubleshooting.md](troubleshooting.md) for a troubleshooting guide.
Expand Down
1 change: 1 addition & 0 deletions internal/docs/doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
//go:generate weave -o ../../docs/protocol.md ./protocol.src.md
//go:generate weave -o ../../docs/client.md ./client.src.md
//go:generate weave -o ../../docs/server.md ./server.src.md
//go:generate weave -o ../../docs/server_cards.md ./server_cards.src.md
//go:generate weave -o ../../docs/troubleshooting.md ./troubleshooting.src.md
//go:generate weave -o ../../docs/rough_edges.md ./rough_edges.src.md
//go:generate weave -o ../../docs/mcpgodebug.md ./mcpgodebug.src.md
Expand Down
Loading
Loading