-
Notifications
You must be signed in to change notification settings - Fork 1.7k
SEP-2127: MCP Server Cards - HTTP Server Discovery via .well-known #2127
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
dsp-ant
wants to merge
33
commits into
main
Choose a base branch
from
sep/mcp-server-cards
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+397
−0
Open
Changes from all commits
Commits
Show all changes
33 commits
Select commit
Hold shift + click to select a range
3bb8831
SEP-2127: MCP Server Cards - HTTP Server Discovery via .well-known
dsp-ant e105d30
Community feedback iteration (rev 1) on SEP-1649 (MCP Server Cards) (…
tadasant 2195161
Rev on server.json
tadasant ed7258c
Fix brace
tadasant e052ea1
Fix indent
tadasant 759ca5e
Header formatting
tadasant 3a61af5
Prettier
tadasant e285eb7
Add extended-server-card
tadasant 2e2b40a
Rename Extended
tadasant 308c652
sep: remove primitives from server cards
SamMorrowDrums b988e49
sep: add rationale on dynamic server disadvantage
SamMorrowDrums a35f7e2
sep: strengthen rationale — deployment atomicity, cache coherence
SamMorrowDrums b407c04
sep: discovery should not be blocked on primitives debate
SamMorrowDrums f2ac257
sep: condense primitives rationale to a short paragraph
SamMorrowDrums 9a65e6c
style: remove em-dashes from added lines
SamMorrowDrums b6417ef
docs(sep): apply review suggestions from tadasant
SamMorrowDrums bfbb7e9
add sponsor
dsp-ant cfe7de2
Align Server Card with server.json and simplify endpoints
tadasant 97c6286
sep: use flat mcp-server-card well-known suffix
dsp-ant 6bb3fb9
docs: regenerate SEP docs for SEP-2127
dsp-ant 389a07d
Remove authentication, capabilities, and requires to limit scope
tadasant ce0d2da
Tweak language
tadasant 85b895a
docs: regenerate SEP docs for SEP-2127
tadasant aa59517
Merge pull request #2525 from tadasant/tadasant/scope-down-additive-f…
dsp-ant 4590aa4
SEP-2127: refactor to Extensions Track charter
e99ebf6
SEP-2127: update authors — swap Nick Cooper for Sam Morrow
28c7ab5
SEP-2127: don't presume .well-known in generic delegation references
8940b02
SEP-2127: don't state primitive exclusion as fact in the spec pointer
7749ed0
SEP-2127: reconcile charter with open extension-repo issues
229e5cd
SEP-2127: drop temporal Open Items / status notes from charter
a02dba0
SEP-2127: 'MCP / AI Catalog' in Discovery bullet (review suggestion)
e196ecb
Remove temporary MCP catalog reference from this SEP
tadasant e5d3187
Merge pull request #2893 from modelcontextprotocol/sep-2127-extension…
dsp-ant File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,199 @@ | ||
| --- | ||
| title: "SEP-2127: MCP Server Cards - HTTP Server Discovery via .well-known" | ||
| sidebarTitle: "SEP-2127: MCP Server Cards - HTTP Server Discover…" | ||
| description: "MCP Server Cards - HTTP Server Discovery via .well-known" | ||
| --- | ||
|
|
||
| <div className="flex items-center gap-2 mb-4"> | ||
| <Badge color="gray" shape="pill"> | ||
| Draft | ||
| </Badge> | ||
| <Badge color="gray" shape="pill"> | ||
| Extensions Track | ||
| </Badge> | ||
| </div> | ||
|
|
||
| | Field | Value | | ||
| | ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | ||
| | **SEP** | 2127 | | ||
| | **Title** | MCP Server Cards - HTTP Server Discovery via .well-known | | ||
| | **Status** | Draft | | ||
| | **Type** | Extensions Track | | ||
| | **Created** | 2026-01-21 | | ||
| | **Author(s)** | David Soria Parra ([@dsp-ant](https://github.com/dsp-ant)), Sam Morrow ([@SamMorrowDrums](https://github.com/SamMorrowDrums)), Tadas Antanavicius ([@tadasant](https://github.com/tadasant)); on behalf of the Server Card Working Group | | ||
| | **Sponsor** | David Soria Parra ([@dsp-ant](https://github.com/dsp-ant)) | | ||
| | **PR** | [#2127](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2127) | | ||
|
|
||
| --- | ||
|
|
||
| ## Abstract | ||
|
|
||
| This SEP proposes adding a standardized, self-contained format to describe MCP servers, e.g. for discovery using a `.well-known` endpoint. This enables clients to automatically discover available transports, protocol versions, and connection guidance before establishing a connection. | ||
|
|
||
| As an Extensions Track SEP (per [SEP-2133](./2133-extensions.md)), this document charters the **Server Card** extension and names its Working Group and maintainers. The detailed, normative wire format — the Server Card and `server.json` schemas, field definitions, the discovery mechanics, and the full security analysis — is maintained in the [experimental-ext-server-card](https://github.com/modelcontextprotocol/experimental-ext-server-card) repository rather than inline here, following the precedent set by [SEP-1865 (MCP Apps)](./1865-mcp-apps-interactive-user-interfaces-for-mcp.md). | ||
|
|
||
| ## Motivation | ||
|
|
||
| MCP clients currently lack efficient mechanisms to discover information about MCP servers before establishing a full connection. To obtain even basic metadata like server name and version, clients must complete an entire initialization handshake. This creates friction for discovery, integration, and optimization scenarios. | ||
|
|
||
| ### Current Pain Points | ||
|
|
||
| - **Manual Endpoint Configuration**: Users must manually configure transport URLs for each server, with no standardized discovery mechanism. | ||
| - **No Domain-Level Discovery**: Clients cannot automatically discover available MCP servers on a domain. This prevents automated integration scenarios, such as registry crawling or service auto-detection. | ||
| - **Expensive Initialization**: Every capability query requires a full initialization sequence. This round-trip is costly, difficult to cache efficiently, and creates unnecessary latency for simple metadata retrieval. | ||
|
|
||
| ### Proposed Solution | ||
|
|
||
| This SEP introduces **MCP Server Cards** – structured metadata documents that servers expose through standardized mechanisms. The primary mechanism is a `.well-known` endpoint and similar mechanism appropriate for the transport. These provide static server information without requiring connection establishment. In addition the same information is served via a well known MCP resource. | ||
|
|
||
| ### Enabled Use Cases | ||
|
|
||
| - **Autoconfiguration**: IDE extensions can automatically configure themselves when pointed at a domain, eliminating manual setup. | ||
| - **Automated Discovery**: Clients and registries can crawl domains to discover available MCP servers, enabling ecosystem-wide server indexes. | ||
| - **Reduced Latency:** Display server information and metadata without waiting for full initialization sequences. | ||
|
|
||
| ### Design Philosophy | ||
|
|
||
| The discovery mechanism complements rather than replaces initialization. Discovery answers where to connect and what transports and protocol versions are available, while initialization handles the communication handshake. | ||
|
|
||
| ### Discovery | ||
|
|
||
| #### Relationship to AI Card | ||
|
|
||
| The [AI Card](https://github.com/Agent-Card/ai-card) standard is paving a path to providing decentralized, protocol-agnostic mechanisms for identifying agent entrypoints. For example, a `.well-known` path and file format for discovering services (`.well-known/ai-catalog.json`). | ||
|
|
||
| #### MCP Connection Details | ||
|
|
||
| MCP Server Cards provide a richer, MCP-specific definition that can be used by MCP clients to actually connect and start performing MCP operations. The canonical discovery path and the relationship to the broader [AI Catalog](https://github.com/Agent-Card/ai-catalog) are specified in the extension repository's [`docs/discovery.md`](https://github.com/modelcontextprotocol/experimental-ext-server-card/blob/main/docs/discovery.md). | ||
|
|
||
| Example: | ||
|
|
||
| - "Restaurant A" works with platform "Restaurant Reservations SaaS" to provide MCP-powered bookings for their restaurant | ||
| - Restaurant A also works with platform "Jobs SaaS" to provide MCP-powered job listings to prospective job seekers | ||
| - Restaurant A would advertise the two relevant AI Cards at `restaurant-a.com/.well-known/ai-catalog.json` | ||
| - Restaurant Reservations SaaS would expose a Server Card per restaurant it hosts (one for Restaurant A, one for Restaurant B, etc.) | ||
| - Jobs SaaS would expose a Server Card per entity it hosts (one for Restaurant A, one for Coffee Shop B, etc.) | ||
|
|
||
| We can develop and iterate on MCP Server Cards largely independently from the broader effort to integrate with AI Cards, as long as we maintain some integration point so it is possible to understand when an entry in an AI Card references an MCP Server Card that is hosted and maintained elsewhere. | ||
|
|
||
| ### Relationship to `server.json` | ||
|
|
||
| The focus of MCP Server Cards is on expressing _remote_ MCP servers; however the card is designed to be compatible with the previously established `server.json` standard that includes consideration for locally-run MCP servers (e.g. where to download executable packages, how to run them). | ||
|
|
||
| This alignment is useful for the following reasons: | ||
|
|
||
| 1. **Cross-cutting concerns**. The two use cases share many cross-cutting concerns, such as identity, documentation, and more. By keeping one as a strict subset of the other, we ensure that efforts to improve the shape move in concert and avoid re-inventing the wheel. | ||
|
|
||
| 2. **Shared tooling**. Only one set of tooling or frameworks needs to exist to parse and generate/modify Server Card files. | ||
|
|
||
| 3. **Sprawl and adoption friction**. Server maintainers don't have _yet another_ shape to maintain. For example, a single server may already have a `package.json`, `Dockerfile`, `manifest.json`, and more. By consolidating to a single `server-card.json` shape, we limit further maintenance sprawl and adoption friction. | ||
|
|
||
| We chose not to include these local considerations in the core MCP Server Card specification because: | ||
|
|
||
| 1. **Compliance with .well-known guidance**. Given our intent to use MCP Server Cards in concert with `.well-known` standardization, [RFC 5785](https://www.ietf.org/rfc/rfc5785.txt) says, _"in keeping with the Architecture of the World-Wide Web, well-known URIs are not intended for general information retrieval or establishment of large URI namespaces on the Web. Rather, they are designed to facilitate discovery of information on a site when it isn't practical to use other mechanisms; for example, when discovering policy that needs to be evaluated before a resource is accessed, or when using multiple round-trips is judged detrimental to performance."_. Local servers cannot, by definition, be hosted on a website, and so do not belong in file hosted at a `.well-known` URI. | ||
|
|
||
| 2. **Exposure of additional security vectors**. If we include local servers (and how to run them) in this shape, we would effectively be saying that clients that receive that metadata must absolutely do proper input sanitization as you just gave a one-click shortcut for someone to install something/trigger execution on a local machine. The threat model went from "We can point to resources to connect to" to "Here is an executable blob that might run on a target machine right away if the client didn't check it." You could also argue that this is something we do with the registry today, and the discovery mechanism might just be a variation of it - however, the registry has some degree of moderation. This would be a wide-open mechanism for anyone to advertise their server, however good or bad it is. | ||
|
|
||
| ## Specification | ||
|
|
||
| The full specification is maintained in the | ||
| [experimental-ext-server-card](https://github.com/modelcontextprotocol/experimental-ext-server-card) | ||
| repository. The TypeScript file [`schema.ts`](https://github.com/modelcontextprotocol/experimental-ext-server-card/blob/main/schema.ts) | ||
| is the single source of truth; the generated [`schema.json`](https://github.com/modelcontextprotocol/experimental-ext-server-card/blob/main/schema.json) | ||
| and the discovery mechanics in [`docs/discovery.md`](https://github.com/modelcontextprotocol/experimental-ext-server-card/blob/main/docs/discovery.md) | ||
| are derived from it. | ||
|
|
||
| At a high level, the Server Card extension introduces: | ||
|
|
||
| - **Server Card document**: A static metadata document describing a _remote_ MCP server — its identity (`name`, `version`, `description`, optional `title` / `icons` / `repository` / `websiteUrl`), its remote transport endpoints (URLs, headers, variable templates, supported protocol versions), and optional `_meta` extension metadata. The precise field set is defined in the extension repository's [`schema.ts`](https://github.com/modelcontextprotocol/experimental-ext-server-card/blob/main/schema.ts). | ||
| - **`server.json` (the `Server` shape)**: A strict superset of the Server Card that additionally describes locally-runnable `packages`. This is the shape used by the MCP Registry's `server.json`. Keeping it a superset of the Server Card means a single parser and toolchain serves both use cases. | ||
| - **Discovery**: A predictable HTTP location (and an AI Catalog that indexes multiple cards) from which clients can retrieve cards before connecting, with CORS and caching guidance for browser-based discovery. The canonical path, media type, and catalog format are specified in [`docs/discovery.md`](https://github.com/modelcontextprotocol/experimental-ext-server-card/blob/main/docs/discovery.md). | ||
|
|
||
| As an extension, MCP Server Cards are **optional** and additive: servers that do not publish a card continue to work normally through standard initialization (see [Backward Compatibility](#backward-compatibility)). | ||
|
|
||
| ## Rationale | ||
|
|
||
| ### Why .well-known? | ||
|
|
||
| The `.well-known` URI pattern is an established IETF standard (RFC 8615) used by many protocols for service discovery, including OAuth 2.0 Authorization Server Metadata (RFC 8414). This approach: | ||
|
|
||
| - Provides a predictable, standardized location for discovery | ||
| - Requires no prior knowledge of server configuration | ||
| - Works with standard HTTP infrastructure (caches, CDNs, load balancers) | ||
| - Is already familiar to developers working with web services | ||
|
|
||
| ### Why Adopt `server.json`'s shape? | ||
|
|
||
| MCP Server Cards aim to provide a static representation of server metadata and capabilities so that clients can discover and connect to them without prior knowledge of their existence. | ||
|
|
||
| The MCP Registry and its corresponding `server.json` share the same goal but for different consumers. Consequently, keeping both as closely aligned as possible ensures that we don't have to re-invent and diverge, and that developers have to only rely on one parser. | ||
|
|
||
| ### Why Exclude Primitives? | ||
|
|
||
| This specification intentionally omits primitive definitions (tools, resources, and prompts) from server cards. MCP servers are inherently dynamic: the primitives a server exposes can vary by authenticated user, session, configuration, feature flags, deployment state, and more. A static document cannot reliably represent this surface, and there is currently no viable substitute for runtime listing via the protocol's standard operations (`tools/list`, `resources/list`, `prompts/list`) with the logged-in user's identity. Including primitives prematurely risks disadvantaging dynamic servers and encouraging clients to rely on information that may be incorrect. A follow-on SEP should address the prerequisites, such as variant enumeration and clear consumer contracts, before primitive advertisement is added. | ||
|
|
||
| ### Why Not Wait for Primitives? | ||
|
|
||
| The debate around primitives should not delay server card adoption. Discovery (knowing that a server exists, where to connect, and what transports and protocol versions it supports) is enormously valuable on its own. It is the information an end user or IDE needs to install and configure a server, and it is the information a registry needs to index one. None of this depends on knowing the server's tool list in advance. | ||
|
|
||
| Server cards without primitives already enable the core use cases that motivate this SEP: autoconfiguration, domain-level discovery, reduced-latency metadata retrieval, and registry integration. Primitives can be added in a future revision once the ecosystem has the right mechanisms to advertise them safely. Shipping discovery now, and shipping it correctly, is more important than shipping a larger surface that risks being wrong. | ||
|
|
||
| ### Other Considered Discovery Mechanisms | ||
|
|
||
| **DNS-based discovery**: We considered using DNS TXT records for discovery, similar to DKIM or SPF. However, this approach would be limited to domain-level discovery and wouldn't work for path-based or port-based MCP servers, making it too restrictive. | ||
|
|
||
| **Header-based discovery**: We considered using HTTP headers (similar to Link headers) to advertise server card locations. While this could work, it requires an HTTP request to the main endpoint first, eliminating many of the benefits of pre-connection discovery. | ||
|
|
||
| ## Backward Compatibility | ||
|
|
||
| This SEP is fully backward compatible with existing MCP implementations: | ||
|
|
||
| - Server cards are **optional**. Servers that don't implement them continue to work normally through standard initialization. | ||
| - Clients that don't support server cards can ignore them and use the initialization handshake as before. | ||
| - The server card schema is designed to mirror the initialization response structure, minimizing implementation complexity for servers that want to support both. | ||
| - No changes to the core MCP protocol messages or initialization flow are required. | ||
|
|
||
| ### Migration Path | ||
|
|
||
| 1. **Phase 1** (Optional): Servers can begin exposing server cards without requiring client support | ||
| 2. **Phase 2** (Recommended): Clients can implement server card fetching for enhanced discovery and pre-connection validation | ||
| 3. **Phase 3** (Future): The ecosystem can develop tooling around server cards for registries, security scanning, and automated discovery | ||
|
|
||
| ## Security Implications | ||
|
|
||
| Server Cards are publicly accessible, read-only metadata documents served over HTTP, and the extension's security posture follows from that: | ||
|
|
||
| - **Information disclosure**: Cards are public by design; servers MUST NOT include credentials, internal network topology, proprietary logic, or user/session-specific data. | ||
| - **Primitive exclusion as a safety property**: Cards deliberately exclude primitive definitions (tools, resources, prompts) so clients cannot trust a static manifest for access-control or safety decisions; primitives are always validated at runtime via standard list operations. | ||
| - **CORS**: Wide-open CORS (`Access-Control-Allow-Origin: *`) is acceptable because cards carry only public, read-only metadata. | ||
| - **Transport security and MITM**: Cards SHOULD be served over HTTPS with certificate validation; because cards are advisory (the real connection still requires initialization and authentication), a compromised card primarily affects discoverability rather than security. | ||
| - **Denial of service**: Servers SHOULD rate-limit discovery endpoints and clients SHOULD respect cache headers. | ||
|
|
||
| The full threat model and the normative CORS/caching/transport requirements are maintained in the extension repository's [`docs/discovery.md`](https://github.com/modelcontextprotocol/experimental-ext-server-card/blob/main/docs/discovery.md). | ||
|
|
||
| ## Reference Implementation | ||
|
|
||
| The Server Card extension is incubated in the | ||
| [experimental-ext-server-card](https://github.com/modelcontextprotocol/experimental-ext-server-card) | ||
| repository, which holds the TypeScript schema source of truth, the generated JSON Schema, | ||
| discovery documentation, and valid/invalid example documents exercised by a validation script. | ||
|
|
||
| [python-sdk#2696](https://github.com/modelcontextprotocol/python-sdk/pull/2696) is an experimental | ||
| Server Cards implementation for the Python SDK by @dsp-ant: server-side card construction and | ||
| serving, client-side fetch and validation, and Pydantic models for the `ServerCard` / `Server` | ||
| shapes, with tests that round-trip the conformance examples. | ||
|
|
||
| ## Working Group and Maintainers | ||
|
|
||
| - **Working Group**: Server Card Working Group (see the [Server Card WG discussion #2563](https://github.com/modelcontextprotocol/modelcontextprotocol/discussions/2563)). | ||
| - **Extension Maintainers**: David Soria Parra (@dsp-ant), Sam Morrow (@SamMorrowDrums), Tadas Antanavicius (@tadasant). | ||
| - **Extension repository**: [modelcontextprotocol/experimental-ext-server-card](https://github.com/modelcontextprotocol/experimental-ext-server-card) (graduating to `ext-server-card` on acceptance). | ||
|
|
||
| ## References | ||
|
|
||
| - [SEP-1865: MCP Apps (Extensions Track precedent)](./1865-mcp-apps-interactive-user-interfaces-for-mcp.md) | ||
| - [SEP-2133: Extensions](./2133-extensions.md) | ||
| - [RFC 8414: OAuth 2.0 Authorization Server Metadata](https://datatracker.ietf.org/doc/html/rfc8414) | ||
| - [RFC 8615: Well-Known URIs](https://datatracker.ietf.org/doc/html/rfc8615) | ||
| - [MCP Protocol Specification](https://modelcontextprotocol.io/specification) | ||
| - [Original GitHub Issue #1649](https://github.com/modelcontextprotocol/modelcontextprotocol/issues/1649) | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should add go-sdk and also Goose client demo tadasant/goose#1