Skip to content
Open
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
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ A prior attempt to land these types directly in the core spec ([modelcontextprot
A **Server Card** is a JSON document — hosted at any unreserved URI, with `GET <streamable-http-url>/server-card` reserved as the recommended location (see [discovery.md](docs/discovery.md)) — describing:

- The server's identity (`name`, `version`, `description`, optional `title` / `icons` / `repository` / `websiteUrl`)
- Its remote transport endpoints (URLs, headers, variable templates, supported protocol versions)
- Its remote transport endpoints (URLs, headers, variable templates, supported protocol versions, server-level extension information)
- Optional registry-style extension metadata (`_meta`)

Clients can automatically discover Server Cards through [AI Catalog](https://github.com/Agent-Card/ai-catalog) entries advertised on domains present in agentic sessions.
Expand Down
6 changes: 6 additions & 0 deletions docs/discovery.md
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,12 @@ the transport served at each `remotes[]` endpoint, and descriptive fields (`titl
`description`, `icons`) — SHOULD NOT contradict the equivalent values declared in the Server
Card.

A remote's `extensions` map carries server-level information defined by each extension; it
is not a declaration of extension support. Clients MUST NOT infer from the presence or
absence of an entry whether the server supports that extension — support is negotiated via
`capabilities.extensions` in `server/discover`, which may vary per user and need not match
the Server Card.

As with the deliberately omitted primitives (tools, resources, prompts), a static manifest
can drift from runtime, so even the fields a Server Card does declare are advisory rather
than binding. Accordingly:
Expand Down
15 changes: 15 additions & 0 deletions examples/ServerCard/invalid/non-object-extension-info.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"$schema": "https://static.modelcontextprotocol.io/schemas/v1/server-card.schema.json",
"name": "example-org/bad-extension",
"version": "1.0.0",
"description": "Extension information must be an object, not a boolean.",
"remotes": [
{
"type": "streamable-http",
"url": "https://mcp.example.com/mcp",
"extensions": {
"io.modelcontextprotocol/tasks": true
}
}
]
}
30 changes: 30 additions & 0 deletions examples/ServerCard/valid/remote-extensions.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{
"$schema": "https://static.modelcontextprotocol.io/schemas/v1/server-card.schema.json",
"name": "example-org/with-extensions",
"version": "1.0.0",
"description": "Server Card whose remote publishes extension information.",
"remotes": [
{
"type": "streamable-http",
"url": "https://mcp.example.com/mcp",
"supportedProtocolVersions": ["2025-11-25"],
"extensions": {
"io.modelcontextprotocol/events": {
"webhooks": {
"signingKeys": {
"keys": [
{
"kty": "OKP",
"crv": "Ed25519",
"kid": "2026-10",
"x": "11qYAYKxCrfVS_7TyWQHOg7hcvPapiMlrwIaaPcHURo"
}
]
},
"egressIpRanges": ["203.0.113.0/24", "2001:db8::/32"]
}
}
}
}
]
}
35 changes: 35 additions & 0 deletions schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,34 @@
},
"type": "object"
},
"JSONArray": {
"items": {
"$ref": "#/$defs/JSONValue"
},
"type": "array"
},
"JSONObject": {
"additionalProperties": {
"$ref": "#/$defs/JSONValue"
},
"type": "object"
},
"JSONValue": {
"anyOf": [
{
"$ref": "#/$defs/JSONObject"
},
{
"items": {
"$ref": "#/$defs/JSONValue"
},
"type": "array"
},
{
"type": ["string", "integer", "boolean"]
}
]
},
"KeyValueInput": {
"description": "A named {@link Input} — used for HTTP headers — whose `value` may reference\nvariables for substitution.",
"properties": {
Expand Down Expand Up @@ -133,6 +161,13 @@
"Remote": {
"description": "Metadata for connecting to a remote (HTTP-based) MCP server endpoint.",
"properties": {
"extensions": {
"additionalProperties": {
"$ref": "#/$defs/JSONObject"
},
"description": "Optional server-level information about MCP extensions for this remote\nendpoint. Keys are extension identifiers (e.g.,\n`\"io.modelcontextprotocol/events\"`), and values are objects whose contents\nare defined by the respective extension — typically information a client\nneeds before connecting, such as keys for verifying webhook signatures.\n\nThe presence or absence of an entry does not indicate whether the server\nsupports that extension, and an entry need not match the server's\n`capabilities.extensions`. Extension support is negotiated at runtime via\n`server/discover` and may vary per user.\n\nKeys MUST follow the {@link MetaObject`_meta` key naming rules}, with a\nmandatory prefix.",
"type": "object"
},
"headers": {
"description": "HTTP headers required or accepted when connecting to this remote\nendpoint. Each header is described as a {@link KeyValueInput} so that\nclients can prompt users for required values, mark secrets, surface\ndefaults, and constrain to a list of choices.",
"items": {
Expand Down
38 changes: 38 additions & 0 deletions schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,23 @@ export interface Remote {
* clients to select a compatible protocol version before connecting.
*/
supportedProtocolVersions?: string[];

/**
* Optional server-level information about MCP extensions for this remote
* endpoint. Keys are extension identifiers (e.g.,
* `"io.modelcontextprotocol/events"`), and values are objects whose contents
* are defined by the respective extension — typically information a client
* needs before connecting, such as keys for verifying webhook signatures.
*
* The presence or absence of an entry does not indicate whether the server
* supports that extension, and an entry need not match the server's
* `capabilities.extensions`. Extension support is negotiated at runtime via
* `server/discover` and may vary per user.
*
* Keys MUST follow the {@link MetaObject | `_meta` key naming rules}, with a
* mandatory prefix.
*/
extensions?: { [key: string]: JSONObject };
}

/**
Expand Down Expand Up @@ -279,6 +296,27 @@ export interface KeyValueInput extends Input {

/* ---------- Inlined dependencies from the main MCP spec ---------- */

/**
* @category Common Types
*/
export type JSONValue =
| string
| number
| boolean
| null
| JSONObject
| JSONArray;

/**
* @category Common Types
*/
export type JSONObject = { [key: string]: JSONValue };

/**
* @category Common Types
*/
export type JSONArray = JSONValue[];

/**
* Represents the contents of a `_meta` field, which clients and servers use to attach additional metadata to their interactions.
*
Expand Down
Loading