MCP Discovery via Well-Known URI

StatusDraft
Version2026-01-24
AuthorColin Knapp
Sourcemcp-discovery.md

Abstract

This document defines a well-known URI, /.well-known/mcp.json, that allows a website origin to publish Model Context Protocol (MCP) connection metadata for servers and tools associated with that origin. This enables automatic discovery by compatible clients including AI agents, integrated development environments, browser extensions, and automation platforms.

Status of This Memo

This is a non-standard draft specification intended for documentation and implementation guidance. Implementations MAY vary until a formal standard is established. This document is structured in the style of an IETF Internet-Draft for potential future standardization.

1. Introduction

1.1 Motivation

Modern web applications increasingly integrate with external services, AI assistants, and automation tools. These integrations typically require manual configuration: exchanging API keys, hardcoding endpoints, and maintaining service-specific integration code.

The .well-known directory (RFC 8615) provides a standardized location for site-wide metadata. This specification extends that pattern to Model Context Protocol (MCP) discovery, enabling:

1.2 Terminology

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 (RFC 2119, RFC 8174).

1.3 Notational Conventions

Examples in this document use JSON (RFC 8259). All JSON field names are case-sensitive. Optional fields MAY be omitted entirely rather than set to null.

2. Well-Known URI

2.1 URI Path

The discovery document MUST be served at the following path relative to the origin:

/.well-known/mcp.json

For example, for the origin https://example.com, the full URI would be:

https://example.com/.well-known/mcp.json

2.2 HTTP Methods

2.3 Content Type

2.4 Caching

Servers SHOULD include caching headers to enable efficient polling:

Clients SHOULD:

3. Document Schema

3.1 Root Object

The response body MUST be a JSON object containing an mcp object at the top level:

{
  "mcp": {
    "spec_version": "2026-01-24",
    "status": "draft",
    "servers": [],
    "tools": []
  }
}

The root object MAY contain additional fields for future extensibility. Clients MUST ignore unknown fields at the root level.

3.2 The mcp Object

The mcp object MUST contain the following fields:

FieldTypeRequiredDescription
spec_versionstringREQUIREDDate-based version (YYYY-MM-DD format)
statusstringREQUIRED"draft" or "stable"
serversarrayOPTIONALArray of MCP server definitions
toolsarrayOPTIONALArray of tool/service definitions

The mcp object MAY contain additional fields:

FieldTypeDescription
spec_urlstringURL to the specification document
notesstringHuman-readable notes
contactstringContact email or URL

3.3 The spec_version Field

Clients SHOULD check spec_version and MAY warn users if encountering an unknown future version. Clients MUST NOT reject documents solely based on unrecognized spec_version values.

3.4 The status Field

ValueMeaning
draftExperimental; schema or endpoints may change
stableProduction-ready; breaking changes will increment spec_version

3.5 The servers[] Array

An array of MCP server definitions. Each entry is an object with the following fields:

FieldTypeRequiredDescription
namestringREQUIREDUnique identifier (lowercase, alphanumeric, hyphens)
descriptionstringOPTIONALHuman-readable description
urlstringREQUIREDAbsolute URL for connecting
transportstringOPTIONALTransport protocol
authobjectOPTIONALAuthentication configuration
capabilitiesarrayOPTIONALArray of capability strings

Transport Values

ValueDescription
http+sseHTTP with Server-Sent Events (default)
wsWebSocket
wssWebSocket Secure
stdioStandard I/O (for local servers)

Auth Object

FieldTypeDescription
typestring"none", "api-key", "oauth2", "bearer"
token_endpointstringOAuth2 token endpoint
scopesarrayRequired OAuth2 scopes
headerstringHeader name for API key (default: Authorization)

3.6 The tools[] Array

An array of tool or service definitions that are not full MCP servers but can be invoked or integrated:

FieldTypeRequiredDescription
namestringREQUIREDUnique identifier
descriptionstringOPTIONALHuman-readable description
urlstringREQUIREDAbsolute URL of the service
capabilitiesarrayOPTIONALArray of capability strings
authobjectOPTIONALAuthentication configuration
methodsarrayOPTIONALSupported HTTP methods
content_typesarrayOPTIONALAccepted content types

3.7 Extension Mechanism

4. Processing Model

4.1 Discovery Flow

┌─────────┐ GET /.well-known/mcp.json ┌─────────┐ │ │ ─────────────────────────────────► │ │ │ Client │ │ Server │ │ │ ◄───────────────────────────────── │ │ └─────────┘ 200 OK + JSON document └─────────┘ │ ▼ ┌─────────────────────────────────────────────────────────┐ │ 1. Validate JSON structure │ │ 2. Check spec_version compatibility │ │ 3. Enumerate servers[] and tools[] │ │ 4. Filter by capabilities (if searching for specific) │ │ 5. Check auth requirements │ │ 6. Connect to selected server(s) or invoke tool(s) │ └─────────────────────────────────────────────────────────┘

4.2 Client Conformance

A conforming client:

  1. MUST fetch the discovery document using HTTPS (HTTP MAY be used only for localhost)
  2. MUST parse the response as JSON
  3. MUST ignore unknown fields at any level
  4. MUST NOT require any OPTIONAL fields to be present
  5. SHOULD validate URLs before connecting to servers
  6. SHOULD respect the status field when making stability assumptions

4.3 Server Conformance

A conforming server:

  1. MUST serve a valid JSON document at /.well-known/mcp.json
  2. MUST include the required fields: spec_version and status
  3. MUST serve the document without requiring authentication
  4. MUST use HTTPS in production
  5. SHOULD include appropriate caching headers
  6. SHOULD include CORS headers if cross-origin access is intended
  7. MUST NOT include secrets, credentials, or private keys

4.4 Error Handling

ScenarioRecommended Behavior
Network timeoutRetry with exponential backoff (max 3 attempts)
Invalid JSONTreat as unsupported, log error
Missing required fieldsTreat as unsupported, log error
Unknown spec_versionProcess document, warn user
Server unreachableCache previous valid response if available

5. Cross-Origin and Delegation

5.1 Same-Origin Preference

Clients SHOULD prefer same-origin servers when multiple options exist. Same-origin servers inherit the trust relationship the user has with the website.

5.2 External Service Trust Model

When a discovery document references servers or tools on different origins:

  1. Clients MUST clearly indicate to users that external services will be contacted
  2. Clients SHOULD require explicit user consent before connecting to external origins
  3. Clients MAY maintain allowlists/blocklists of trusted external origins
  4. Servers SHOULD minimize external references where same-origin alternatives exist

5.3 CORS Configuration

For cross-origin discovery (e.g., browser-based clients):

Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, HEAD, OPTIONS
Access-Control-Allow-Headers: Accept, Content-Type
Access-Control-Max-Age: 86400

Servers MAY restrict Access-Control-Allow-Origin to specific client origins if cross-origin access should be limited.

6. Security Considerations

6.1 No Secrets in Discovery Documents

The discovery document MUST NOT contain:

Authentication details in the auth object describe HOW to authenticate, not the credentials themselves.

6.2 HTTPS Requirement

6.3 CORS Guidance

6.4 Content Validation

Clients SHOULD:

7. IANA Considerations

This document does not require IANA registration unless adopted as an official standard. If standardized:

8. References

8.1 Normative References

8.2 Informative References

Appendix A: Complete Example

A complete discovery document for a website with both MCP servers and tools:

{
  "mcp": {
    "spec_version": "2026-01-24",
    "spec_url": "https://colinknapp.com/specs/mcp-discovery.html",
    "status": "draft",
    "notes": "Example MCP discovery document demonstrating all features.",
    "contact": "https://colinknapp.com",
    "servers": [
      {
        "name": "hastebin",
        "description": "Text paste and sharing service for code snippets and logs",
        "url": "https://haste.nixc.us/mcp",
        "transport": "http+sse",
        "auth": {
          "type": "none"
        },
        "capabilities": ["create-paste", "retrieve-paste", "list-recent"]
      },
      {
        "name": "markdown-renderer",
        "description": "Markdown to HTML conversion with live preview",
        "url": "https://md.colinknapp.com/mcp",
        "transport": "http+sse",
        "auth": {
          "type": "none"
        },
        "capabilities": ["render-markdown", "preview", "export-pdf"]
      }
    ],
    "tools": [
      {
        "name": "repair-tracker",
        "description": "Hardware repair ticket lookup and status tracking",
        "url": "https://tracker.motherboardrepair.ca/",
        "capabilities": ["ticket-lookup", "status-view"],
        "auth": {
          "type": "none"
        }
      }
    ]
  }
}

Appendix B: JSON Schema

JSON Schema (Draft 2020-12) for validating discovery documents:

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://colinknapp.com/specs/mcp-discovery.schema.json",
  "title": "MCP Discovery Document",
  "description": "Schema for /.well-known/mcp.json discovery documents",
  "type": "object",
  "required": ["mcp"],
  "properties": {
    "mcp": {
      "type": "object",
      "required": ["spec_version", "status"],
      "properties": {
        "spec_version": {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
        },
        "status": {
          "type": "string",
          "enum": ["draft", "stable"]
        },
        "servers": {
          "type": "array",
          "items": { "$ref": "#/$defs/server" }
        },
        "tools": {
          "type": "array",
          "items": { "$ref": "#/$defs/tool" }
        }
      }
    }
  },
  "$defs": {
    "server": {
      "type": "object",
      "required": ["name", "url"],
      "properties": {
        "name": { "type": "string", "pattern": "^[a-z0-9-]+$" },
        "description": { "type": "string" },
        "url": { "type": "string", "format": "uri" },
        "transport": { "type": "string", "enum": ["http+sse", "ws", "wss", "stdio"] },
        "auth": { "$ref": "#/$defs/auth" },
        "capabilities": { "type": "array", "items": { "type": "string" } }
      }
    },
    "tool": {
      "type": "object",
      "required": ["name", "url"],
      "properties": {
        "name": { "type": "string" },
        "description": { "type": "string" },
        "url": { "type": "string", "format": "uri" },
        "capabilities": { "type": "array", "items": { "type": "string" } },
        "auth": { "$ref": "#/$defs/auth" }
      }
    },
    "auth": {
      "type": "object",
      "required": ["type"],
      "properties": {
        "type": { "type": "string", "enum": ["none", "api-key", "oauth2", "bearer"] },
        "token_endpoint": { "type": "string", "format": "uri" },
        "scopes": { "type": "array", "items": { "type": "string" } },
        "header": { "type": "string" }
      }
    }
  }
}