Skip to content
Closed
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
52 changes: 27 additions & 25 deletions seps/2127-mcp-server-cards.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,11 +88,7 @@ This section provides the technical specification for MCP Server Cards.
"description": "MCP server for Brave Search API integration",
"title": "Brave Search",
"websiteUrl": "https://anonymous.modelcontextprotocol.io/examples",
"repository": {
"url": "https://github.com/modelcontextprotocol/servers",
"source": "github",
"subfolder": "src/everything"
},
"repository": { ... },
"icons": [ ... ],
"remotes": [ ... ],
"capabilities": { ... },
Expand All @@ -117,7 +113,8 @@ Fleshed out (contrived values) example:
"repository": {
"url": "https://github.com/modelcontextprotocol/servers",
"source": "github",
"subfolder": "src/everything"
"subfolder": "src/everything",
"id": "b94b5f7e-c7c6-d760-2c78-a5e9b8a5b8c9"
},
"icons": [
{
Expand Down Expand Up @@ -257,7 +254,7 @@ Most fields follow the current MCP Registry `server.json` standard: https://gith
3. **description** (string, optional): Clear human-readable explanation of server functionality. Should focus on capabilities, not implementation details.
4. **title** (string, optional): Optional human-readable title or display name for the MCP server.
5. **websiteUrl** (string, optional): Optional URL to the server's homepage, documentation, or project website. This provides a central link for users to learn more about the server. Particularly useful when the server has custom installation instructions or setup requirements.
6. **repository** (object, optional): Repository metadata for the MCP server source code. [See details](https://github.com/modelcontextprotocol/registry/blob/main/docs/reference/server-json/server.schema.json#L371).
6. **repository** (object, optional): Repository metadata for the MCP server source code. [See details](https://github.com/modelcontextprotocol/registry/blob/3f3383bb6199990c853ae8be3715e150af5e8bcb/docs/reference/server-json/server.schema.json#L371).
7. **icons** (array of object, optional): Optional set of sized icons that the client can display in a user interface. Clients that support rendering icons MUST support at least the following MIME types: image/png and image/jpeg (safe, universal compatibility). Clients SHOULD also support: image/svg+xml (scalable but requires security precautions) and image/webp (modern, efficient format). [See details](https://github.com/modelcontextprotocol/registry/blob/3f3383bb6199990c853ae8be3715e150af5e8bcb/docs/reference/server-json/server.schema.json#L18).
8. **remotes** (array of object, optional): Metadata helpful for making HTTP-based connections to this MCP server.
1. **supportedProtocolVersions** (array of string, optional): list of MCP protocol versions actively supported by this Remote.
Expand All @@ -270,31 +267,35 @@ Most fields follow the current MCP Registry `server.json` standard: https://gith
2. **logging** (object, optional): Log message support
3. **completions** (object, optional): Argument autocompletion support
4. **prompts** (object, optional): Prompt template support
1. **listChanged** (boolean, optional): Change notification support
1. **listChanged** (boolean, optional): Server runtime change notification support for the client when its prompts list has changed. Value `true` here implies dynamic prompts that can change at server runtime.
5. **resources** (object, optional): Resource support
1. **subscribe** (boolean, optional): Subscription support
2. **listChanged** (boolean, optional): Change notification support
2. **listChanged** (boolean, optional): Server runtime change notification support for the client when its resources list has changed. Value `true` here implies dynamic resources that can change at server runtime.
6. **tools** (object, optional): Tool support
1. **listChanged** (boolean, optional): Change notification support
1. **listChanged** (boolean, optional): Server runtime change notification support for the client when its tools list has changed. Value `true` here implies dynamic tools that can change at server runtime.
10. **requires** (object, optional): Required client capabilities following `ClientCapabilities`
1. **experimental** (object, optional): Required experimental capabilities
2. **roots** (object, optional): Root access requirement
3. **sampling** (object, optional): LLM sampling requirement
4. **elicitation** (object, optional): User elicitation requirement
11. **resources** (string | array, optional): Resource definitions
1. If "dynamic": Must be discovered via protocol
2. If array: Static list following the `Resource` interface
12. **tools** (string | array, optional): Tool definitions
1. If "dynamic": Must be discovered via protocol
2. If array: Static list following the `Tool` interface
13. **prompts** (string | array, optional): Prompt definitions
1. If "dynamic": Must be discovered via protocol
2. If array: Static list following the `Prompt` interface
11. **resources** (array, optional): array of static Resource definitions exposed by the server, array items following the [`Resource`](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/schema/draft/schema.json#L2947) JSON Schema

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You might want to reference a concrete commit here, since the main branch is a moving target.

Suggested change
11. **resources** (array, optional): array of static Resource definitions exposed by the server, array items following the [`Resource`](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/schema/draft/schema.json#L2947) JSON Schema
11. **resources** (array, optional): array of static Resource definitions exposed by the server, array items following the [`Resource`](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/ff8bd88d1dc1973a699bbdc85d8e52bb4d869edf/schema/draft/schema.json#L2947) JSON Schema

12. **tools** (array, optional): array of static Tool definitions exposed by the server, array items following the [`Tool`](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/schema/draft/schema.json#L3993) JSON Schema

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
12. **tools** (array, optional): array of static Tool definitions exposed by the server, array items following the [`Tool`](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/schema/draft/schema.json#L3993) JSON Schema
12. **tools** (array, optional): array of static Tool definitions exposed by the server, array items following the [`Tool`](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/ff8bd88d1dc1973a699bbdc85d8e52bb4d869edf/schema/draft/schema.json#L3993) JSON Schema

13. **prompts** (array, optional): array of static Prompt definitions exposed by the server, array items following the [`Prompt`](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/schema/draft/schema.json#L2682) JSON Schema

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
13. **prompts** (array, optional): array of static Prompt definitions exposed by the server, array items following the [`Prompt`](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/schema/draft/schema.json#L2682) JSON Schema
13. **prompts** (array, optional): array of static Prompt definitions exposed by the server, array items following the [`Prompt`](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/ff8bd88d1dc1973a699bbdc85d8e52bb4d869edf/schema/draft/schema.json#L2682) JSON Schema

14. **\_meta** (object, optional): Additional metadata following [\_meta definition](https://modelcontextprotocol.io/specification/2025-06-18/basic/index#meta)

### Dynamic Primitives
### Primitives

MCP primitives (tools, resources and prompts) are the most important concepts within MCP.
With the help of the `.well-known` URI a client can discover what primitive capabilities a server can offer.

1. Static Primitives

The server's available primitives, which would normally be listed in the MCP protocol lifecycle initialization phase (`*/list`), will be listed under the root document `$.tools`, `$.resources`, and `$.prompts` properties.

2. Dynamic Primitives

MCP primitives are dynamic in nature and can change. To indicate that a list of primitives is dynamic in nature, authors can provide the reserved string "dynamic" (as an array with a single element) for the resources, tools, or prompts field. This indicates that the full list of primitives must be discovered through the protocol's standard list operations.
To indicate that a list of primitives is dynamic in nature and can change at runtime, authors can set the `$.capabilities.tools.listChanged`, `$.capabilities.resources.listChanged`, or `$.capabilities.prompts.listChanged` boolean to `true`.
This indicates that the server will inform the client at runtime when some of its list of primitives has changed.

### `server.json` Schema

Expand Down Expand Up @@ -491,15 +492,16 @@ Server cards are publicly accessible by design. Servers MUST NOT include sensiti
- Proprietary business logic or algorithms
- User-specific or session-specific data

### Tool Description Security
### Primitive Description Security

Exposing tool descriptions in server cards before connection establishment creates an opportunity for clients to perform security analysis. This is a security _improvement_ as it enables:
Exposing primitive descriptions in server cards before connection establishment creates an opportunity for clients to perform security analysis. This is a security _improvement_ as it enables:

- Offline security scanning of tool capabilities
- Offline security scanning of server primitives (tools, resources, prompts)
- Automated classification before user exposure
- Cached security validations reducing runtime overhead

However, clients MUST still validate that the actual tools provided during initialization match the advertised tools in the server card. Servers MAY omit sensitive tool descriptions from the server card and mark tools as "dynamic" if pre-connection disclosure is undesirable.
However, clients MUST still validate that the actual primitives provided during initialization lifecycle phase match the advertised primitives in the server card.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am personally deeply uncomfortable with requirement that they match completely, as some users for auth reasons cannot use certain tools and omitting them doesn't feel morally dynamic.

As another example, a server that does dynamic tool updates (list changed) but only potentially provides tools that can be statically declared in the server card as the superset of functionality also feels like it could avoid being "dynamic", because it is static in the security sense. It's not capable of providing new functionality that the client doesn't know about.

So the MUST should perhaps be must validate that the advertised primitives are equal to or a subset of the advertised functionality.

Additionally, a remote server might be redeployed and server card updated in a race between checking it and initialization. Maybe resilience should be suggested by re-checking before flagging the issue or failing.

Further to that, opt-in features or functionality may reasonably conflict with the advertised superset (which for GitHub Includes rolling out some changes gradually via feature flag to observer potential performance issues and error rates etc).

I am really worried about this because I think dynamic is handwaving and not very actionable, and we should seek to reduce the amount of functionality that would be considered dynamic to avoid clients breaking production servers for end users by saying that are potentially dangerous/malicious when they are absolutely not, doing totally normal things.

Finally Resources are almost always dynamic. Very few Resources can be reasonably enumerated statically (could depend on logged in user, configuration, access), and if they are could often be replaced by a standard http link to the same content. I had suggested maybe static Resources could provide a Template Resource style syntax in server card, so it's clear what the available space would be.

@tadasant and @dsp I know I've had my chance a couple of times to give a perspective, but I am concerned that the current proposal with dynamic:

  • needlessly restricts dynamic behaviours that are deterministic with a clear outer boundary
  • can be broken as a contract by the simple act of deploying a server
  • may be naively enforced by a bunch of clients in the name of security in cases where it actually isn't security at all
  • would lead to one of the most popular public servers being rejected or warned about by clients that acknowledge the server card

Please can we be very careful about the expectations we set if we go ahead with this.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @SamMorrowDrums
As from my point of view I did not add the MUST statement or the security paragraph, it was there before in the initial proposal from @dsp.

This sentence:
However, clients MUST still validate that the actual primitives provided during initialization lifecycle phase match the advertised primitives in the server card.

I read and understand it like this:
An MCP client can discover an MCP server by a .well-known endpoint and automatically connect to it, however a card is just a card. It does not provide more that the possibility for an automatic client connection.

The card is not replacing the MCP protocol initialization lifecycle phase, where the client and the server exchange and negotiate capabilities. (like. e.g. tools listChange is true)

Or the cards tools, resources, prompts information don't replace the fact that a client needs to do after the MCP protocol initialization phase a tools/list, resources/list or prompts/list request.
And the response to this request may return something else than what is advertised in the card, so far my understanding.

Probably the sentence creates confusion and needs adjustments.

I am happy to directly apply what will be suggested by the owners here.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@maiargu I totally see that, and appreciate you didn't add. The issue for me is more existential. I think there's a moderate to high risk of server cards being used for enforcement in the name of security. Not everywhere but in enough places that it's a real concern.

Servers MAY omit sensitive primitives descriptions from the server card and mark primitives as "dynamic" by boolean flag `$.capabilities.tools.listChanged`, `$.capabilities.resources.listChanged`, or `$.capabilities.prompts.listChanged` set to `true`, if pre-connection disclosure is undesirable.

### CORS Requirements

Expand Down