diff --git a/docs/specification/draft/basic/authentication.md b/docs/specification/draft/basic/authentication.md new file mode 100644 index 0000000..45b108f --- /dev/null +++ b/docs/specification/draft/basic/authentication.md @@ -0,0 +1,417 @@ +--- +title: Authentication +type: docs +weight: 15 +--- + +{{< callout type="info" >}} **Protocol Revision**: draft {{< /callout >}} + +## 1. Introduction + +### 1.1 Purpose and Scope + +The Model Context Protocol provides authentication capabilities at the transport level, +enabling MCP clients to make requests to restricted resources on behalf of resource +owners. This specification defines the authentication flow for HTTP+SSE transport. + +### 1.2 Protocol Requirements + +MCP clients and servers supporting HTTP+SSE transport **SHOULD** implement this +specification, though they **MAY** support additional authentication mechanisms. +Implementations using alternative transports **MAY** implement authentication according +to the best practices for their specific transport. + +For deployments supporting third-party clients or servers via HTTP+SSE, implementations +**SHOULD** expect authentication as defined in this document. However, controlled +environment deployments like corporate networks **MAY** implement alternative methods +such as certificate-based authentication. + +### 1.3 Standards Compliance + +This authentication mechanism implements following specifications but recommends a +specific subsets: + +- [OAuth 2.1 IETF DRAFT](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-12) +- OAuth 2.0 Authentication Server Metadata + ([RFC8414](https://datatracker.ietf.org/doc/html/rfc8414)) +- OAuth 2.0 Dynamic Client Registration Protocol + ([RFC7591](https://datatracker.ietf.org/doc/html/rfc7591)) + +## 2. Authentication Flow + +### 2.1 Overview + +MCP is designed to support interactive, user-facing developer tools that connect to +arbitrary servers. This leads to two key design decisions: + +1. All MCP clients **MUST** be treated as public OAuth 2.1 clients, as they cannot + securely store client secrets when distributed to end users + +2. PKCE **MUST** be implemented by all clients to prevent authorization code interception + attacks, which is especially important for locally-running tools + +3. All MCP implementations **MUST** support the OAuth 2.0 Dynamic Client Registration + Protocol ([RFC7591](https://datatracker.ietf.org/doc/html/rfc7591)), with the + exception of servers that only listen on loopback interfaces (e.g. localhost for + native application authentication). + +4. All MCP implementations **SHOULD** implement OAuth 2.0 Authentication Server Metadata + ([RFC8414](https://datatracker.ietf.org/doc/html/rfc8414)). Servers that do not + support Authentication Server Metadata **MUST** follow the default URI schema. + +### 2.2 Basic OAuth 2.1 Authentication + +When authentication is required, servers **MUST** respond with HTTP 401 Unauthorized. The +basic +[OAuth 2.1 IETF DRAFT](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-12) +authentication flow with PKCE comprises the following sequence: + +```mermaid +sequenceDiagram + participant B as User-Agent (Browser) + participant C as Client + participant M as MCP Server + + C->>M: MCP Request + M->>C: HTTP 401 Unauthorized + Note over C: Generate code_verifier and code_challenge + C->>B: Open browser with authorization URL + code_challenge + B->>M: GET /authorize + Note over M: User logs in and authorizes + M->>B: Redirect to callback URL with auth code + B->>C: Callback with authorization code + C->>M: Token Request with code + code_verifier + M->>C: Access Token + Refresh Token + C->>M: MCP Request with Access Token + Note over C,M: Begin standard MCP message exchange +``` + +### 2.3 Server Metadata Discovery + +Since MCP clients need to connect to previously unknown servers, automated server +capability discovery is essential. The metadata discovery mechanism allows clients to: + +- Locate the OAuth endpoints without manual configuration +- Determine supported authentication features +- Adapt to server-specific requirements +- Enable zero-configuration connections to new servers + +The discovery flow is illustrated below: + +```mermaid +sequenceDiagram + participant C as Client + participant S as Server + + C->>S: GET /.well-known/oauth-authorization-server + alt Discovery Success + S->>C: 200 OK + Metadata Document + Note over C: Use endpoints from metadata + else Discovery Failed + S->>C: 404 Not Found + Note over C: Fall back to default endpoints + end + Note over C: Continue with authentication flow +``` + +#### 2.3.1 Discovery Document Location + +MCP servers **SHOULD** implement OAuth 2.0 Authentication Server Metadata +[RFC8414](https://datatracker.ietf.org/doc/html/rfc8414) by exposing a discovery document +at: + +``` +/.well-known/oauth-authorization-server +``` + +#### 2.3.2 Required Fields + +The discovery document **MUST** include the following fields: + +| Field | Description | +| -------------------------------- | ---------------------------------- | +| authorization_endpoint | Authorization request endpoint URL | +| token_endpoint | Token exchange endpoint URL | +| registration_endpoint | Client registration endpoint URL | +| code_challenge_methods_supported | Supported PKCE methods | +| response_types_supported | Supported OAuth response types | +| grant_types_supported | Supported OAuth grant types | + +Example discovery document: + +```json +{ + "issuer": "https://mcp.example.com", + "authorization_endpoint": "https://mcp.example.com/authorize", + "token_endpoint": "https://mcp.example.com/token", + "registration_endpoint": "https://mcp.example.com/register", + "code_challenge_methods_supported": ["S256"], + "response_types_supported": ["code"], + "grant_types_supported": ["authorization_code", "refresh_token"], + "scopes_supported": ["mcp"] +} +``` + +#### 2.3.3 Fallback for Servers without Server Metadata Discovery + +For servers that do not implement OAuth 2.0 Authentication Server Metadata, clients +**MUST** use the following default endpoint paths relative to the server's base URL: + +| Endpoint | Default Path | Description | +| ---------------------- | ------------ | ------------------------------------ | +| Authorization Endpoint | /authorize | Used for authorization requests | +| Token Endpoint | /token | Used for token exchange & refresh | +| Registration Endpoint | /register | Used for dynamic client registration | + +These default paths **MUST** be used when: + +1. The /.well-known/oauth-authorization-server endpoint returns a 404 status code +2. The metadata document cannot be retrieved or parsed +3. Required endpoints are missing from the metadata document + +Clients **SHOULD** first attempt to discover endpoints via the metadata document before +falling back to default paths. When using default paths, all other protocol requirements +remain unchanged. + +Example default endpoints for https://mcp.example.com: + +``` +https://mcp.example.com/authorize +https://mcp.example.com/token +https://mcp.example.com/register +``` + +### 2.3 Client Registration Requirements + +MCP defines two distinct registration scenarios based on the redirect URI: + +#### 2.3.1 Localhost Redirect URIs + +When using localhost redirect URIs (http://localhost:{port} or http://127.0.0.1:{port}), +clients: + +- Do **NOT** require dynamic registration +- **MUST** use PKCE +- **MAY** proceed directly to authorization +- **MUST NOT** require client secrets + +This exception for localhost is explicitly supported by OAuth 2.1 for public clients and +provides a secure flow through the combination of PKCE and localhost-only redirects. + +#### 2.3.2 Non-Localhost Redirect URIs + +For all other redirect URIs, dynamic client registration is **REQUIRED**. This provides a +standardized way for clients to automatically register with new servers, which is crucial +for MCP because: + +- Clients cannot know all possible servers in advance +- Manual registration would create friction for users +- It enables seamless connection to new servers +- Servers can implement their own registration policies + +#### 2.3.3 Registration Process + +For non-localhost scenarios, clients register with the server by making a POST request to +the registration endpoint with their client metadata: + +``` +POST /register HTTP/1.1 +Content-Type: application/json + +{ + "client_name": "Example MCP Client", + "redirect_uris": ["https://example.com/callback"], + "token_endpoint_auth_method": "none", + "grant_types": ["authorization_code", "refresh_token"], + "response_types": ["code"], + "scope": "mcp" +} +``` + +#### 2.3.4 Server Response + +The server responds with client credentials: + +```json +{ + "client_id": "s6BhdRkqt3", + "client_secret": null, + "registration_access_token": "reg-23410913-abewfq", + "registration_client_uri": "https://mcp.example.com/register/s6BhdRkqt3", + "client_id_issued_at": 2893256800 +} +``` + +### 2.4 Authentication Flow Steps + +The complete authentication flow proceeds as follows: + +1. Client discovers server metadata (if supported) +2. For non-localhost redirect URIs, client **MUST** register dynamically with server +3. Client generates PKCE code_verifier and code_challenge +4. Client requests authorization with code_challenge +5. User authenticates and authorizes the client +6. Server returns authorization code +7. Client exchanges code and code_verifier for tokens +8. Client uses access token for API requests + +**NOTE**: Dynamic registration (step 2) is only required when using non-localhost +redirect URIs. Clients using localhost redirect URIs may skip this step. + +Flow diagram: + +```mermaid +sequenceDiagram + participant B as User-Agent (Browser) + participant C as Client + participant M as MCP Server + + C->>M: GET /.well-known/oauth-authorization-server + alt Server Supports Discovery + M->>C: Authorization Server Metadata + else No Discovery + M->>C: 404 (Use default endpoints) + end + + alt Non-Localhost Redirect URI + C->>M: POST /register + M->>C: Client Credentials + end + + Note over C: Generate PKCE Parameters + C->>B: Open browser with authorization URL + code_challenge + B->>M: Authorization Request + Note over M: User authenticates/authorizes + M->>B: Redirect to callback with authorization code + B->>C: Authorization code callback + C->>M: Token Request + code_verifier + M->>C: Access Token + Refresh Token + C->>M: API Requests with Access Token +``` + +### 2.5 Access Token Usage + +#### 2.5.1 Token Requirements + +Access token handling **MUST** conform to +[OAuth 2.1 Section 5](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-12#section-5) +requirements for resource requests. Specifically: + +1. Access tokens **MUST** be included using one of the two methods defined in + [Section 5.1](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-12#section-5.1) + +2. The preferred method is using the Authorization header with Bearer scheme per + [Section 5.1.1](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-12#section-5.1.1): + +``` +Authorization: Bearer +``` + +3. Form-encoded body parameters per + [Section 5.1.2](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-12#section-5.1.2) + **MAY** be supported as a fallback + +4. Access tokens **MUST NOT** be included in the URI query string + +Example request: + +```http +GET /v1/contexts HTTP/1.1 +Host: mcp.example.com +Authorization: Bearer eyJhbGciOiJIUzI1NiIs... +``` + +#### 2.5.2 Token Handling + +Resource servers **MUST** validate access tokens as described in +[Section 5.2](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-12#section-5.2). +If validation fails, servers **MUST** respond according to +[Section 5.3](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-12#section-5.3) +error handling requirements. Invalid or expired tokens **MUST** receive a HTTP 401 +response with a WWW-Authenticate header indicating the error. + +### 2.6 Security Considerations + +The following security requirements **MUST** be implemented: + +1. Clients **MUST** securely store tokens following OAuth 2.0 best practices +2. Servers **SHOULD** enforce token expiration and rotation +3. All authorization endpoints **MUST** be served over HTTPS +4. Servers **MUST** validate redirect URIs to prevent open redirect vulnerabilities +5. Redirect URIs **MUST** be either localhost URLs or HTTPS URLs + +### 2.7 Error Handling + +Servers **MUST** return appropriate HTTP status codes for authentication errors: + +| Status Code | Description | Usage | +| ----------- | ------------ | ------------------------------------------ | +| 401 | Unauthorized | Authentication required or token invalid | +| 403 | Forbidden | Invalid scopes or insufficient permissions | +| 400 | Bad Request | Malformed authentication request | + +### 2.8 Implementation Requirements + +1. Implementations **MUST** follow OAuth 2.1 security best practices +2. PKCE is **REQUIRED** for all clients +3. Refresh token rotation **SHOULD** be implemented for enhanced security +4. Token lifetimes **SHOULD** be limited based on security requirements + +### 2.9 Third-Party Authentication Flow + +#### 2.9.1 Overview + +MCP servers **MAY** support delegated authentication through third-party authorization servers. In this flow, the MCP server acts as both an OAuth client (to the third-party auth server) and an OAuth authorization server (to the MCP client). + +#### 2.9.2 Flow Description + +The third-party authentication flow comprises these steps: + +1. MCP client initiates standard OAuth flow with MCP server +2. MCP server redirects user to third-party authorization server +3. User authenticates with third-party server +4. Third-party server redirects back to MCP server with authorization code +5. MCP server exchanges code for third-party access token +6. MCP server generates its own access token bound to the third-party session +7. MCP server completes original OAuth flow with MCP client + +```mermaid +sequenceDiagram + participant B as User-Agent (Browser) + participant C as MCP Client + participant M as MCP Server + participant T as Third-Party Auth Server + + C->>M: Initial OAuth Request + M->>B: Redirect to Third-Party /authorize + B->>T: Authorization Request + Note over T: User authenticates + T->>B: Redirect to MCP Server callback + B->>M: Authorization code + M->>T: Exchange code for token + T->>M: Third-party access token + Note over M: Generate bound MCP token + M->>B: Redirect to MCP Client callback + B->>C: MCP authorization code + C->>M: Exchange code for token + M->>C: MCP access token +``` + +#### 2.9.3 Session Binding Requirements + +MCP servers implementing third-party authentication **MUST**: + +1. Maintain secure mapping between third-party tokens and issued MCP tokens +2. Validate third-party token status before honoring MCP tokens +3. Implement appropriate token lifecycle management +4. Handle third-party token expiration and renewal + +#### 2.9.4 Security Considerations + +When implementing third-party authentication, servers **MUST**: + +1. Validate all redirect URIs +2. Securely store third-party credentials +3. Implement appropriate session timeout handling +4. Consider security implications of token chaining +5. Implement proper error handling for third-party auth failures diff --git a/docs/specification/draft/basic/lifecycle.md b/docs/specification/draft/basic/lifecycle.md index ad16f14..a861224 100644 --- a/docs/specification/draft/basic/lifecycle.md +++ b/docs/specification/draft/basic/lifecycle.md @@ -46,6 +46,8 @@ During this phase, the client and server: - Exchange and negotiate capabilities - Share implementation details +#### Initial Request + The client **MUST** initiate this phase by sending an `initialize` request containing: - Protocol version supported @@ -73,6 +75,8 @@ The client **MUST** initiate this phase by sending an `initialize` request conta } ``` +#### Server Response + The server **MUST** respond with its own capabilities and information: ```json @@ -102,6 +106,40 @@ The server **MUST** respond with its own capabilities and information: } ``` +#### Upgrading Transports + +The server **MAY** request a transport change by including an `upgrade` field in the +initialize response: + +```json +{ + "jsonrpc": "2.0", + "id": 1, + "result": { + "protocolVersion": "2024-11-05", + "upgrade": { + "endpoint": "http://localhost:8080", + "transport": "http+sse" + }, + "serverInfo": { + "name": "ExampleServer", + "version": "1.0.0" + } + } +} +``` + +When receiving an upgrade response, the client **MUST**: + +1. Close the current transport connection +2. Connect to the specified endpoint using the new transport +3. Perform initialization again on the new transport + +Clients **MUST** track transport history and **MUST NOT** accept upgrades to previously +used transports to prevent upgrade loops. + +#### Initialization Complete + After successful initialization, the client **MUST** send an `initialized` notification to indicate it is ready to begin normal operations: diff --git a/docs/specification/draft/basic/transports/_index.md b/docs/specification/draft/basic/transports/_index.md new file mode 100644 index 0000000..df5cf21 --- /dev/null +++ b/docs/specification/draft/basic/transports/_index.md @@ -0,0 +1,89 @@ +--- +title: Transports +type: docs +weight: 10 +--- + +{{< callout type="info" >}} **Protocol Revision**: draft {{< /callout >}} + +MCP currently defines two standard transport mechanisms for client-server communication: + +1. [stdio](#stdio), communication over standard in and standard out +2. [HTTP with Server-Sent Events](#http-with-sse) (SSE) + +Clients **SHOULD** support stdio whenever possible. + +It is also possible for clients and servers to implement +[custom transports](#custom-transports) in a pluggable fashion. + +## stdio + +In the **stdio** transport: + +- The client launches the MCP server as a subprocess. +- The server receives JSON-RPC messages on its standard input (`stdin`) and writes + responses to its standard output (`stdout`). +- Messages are delimited by newlines, and **MUST NOT** contain embedded newlines. +- The server **MAY** write UTF-8 strings to its standard error (`stderr`) for logging + purposes. Clients **MAY** capture, forward, or ignore this logging. +- The server **MUST NOT** write anything to its `stdout` that is not a valid MCP message. +- The client **MUST NOT** write anything to the server's `stdin` that is not a valid MCP + message. + +```mermaid +sequenceDiagram + participant Client + participant Server Process + + Client->>+Server Process: Launch subprocess + loop Message Exchange + Client->>Server Process: Write to stdin + Server Process->>Client: Write to stdout + Server Process--)Client: Optional logs on stderr + end + Client->>Server Process: Close stdin, terminate subprocess + deactivate Server Process +``` + +## HTTP with SSE + +In the **SSE** transport, the server operates as an independent process that can handle +multiple client connections. + +The server **MUST** provide two endpoints: + +1. An SSE endpoint, for clients to establish a connection and receive messages from the + server +2. A regular HTTP POST endpoint for clients to send messages to the server + +When a client connects, the server **MUST** send an `endpoint` event containing a URI for +the client to use for sending messages. All subsequent client messages **MUST** be sent +as HTTP POST requests to this endpoint. + +Server messages are sent as SSE `message` events, with the message content encoded as +JSON in the event data. + +```mermaid +sequenceDiagram + participant Client + participant Server + + Client->>Server: Open SSE connection + Server->>Client: endpoint event + loop Message Exchange + Client->>Server: HTTP POST messages + Server->>Client: SSE message events + end + Client->>Server: Close SSE connection +``` + +## Custom Transports + +Clients and servers **MAY** implement additional custom transport mechanisms to suit +their specific needs. The protocol is transport-agnostic and can be implemented over any +communication channel that supports bidirectional message exchange. + +Implementers who choose to support custom transports **MUST** ensure they preserve the +JSON-RPC message format and lifecycle requirements defined by MCP. Custom transports +**SHOULD** document their specific connection establishment and message exchange patterns +to aid interoperability. diff --git a/docs/specification/draft/basic/transports/upgrade.md b/docs/specification/draft/basic/transports/upgrade.md new file mode 100644 index 0000000..3163f94 --- /dev/null +++ b/docs/specification/draft/basic/transports/upgrade.md @@ -0,0 +1,91 @@ +# Transport Protocol Upgrade Mechanism + +## 1. Introduction + +This specification defines a protocol upgrade mechanism that enables MCP servers to +transition clients from one transport protocol to another during session initialization. +The primary use case is upgrading from transports with limited capabilities (like STDIO) +to more feature-rich transports that support additional functionality like +authentication. + +## 2. Upgrade Process + +### 2.1 Available Transports + +The `transport` field **MUST** specify one of the following standardized values: + +- `stdio` - Standard input/output transport +- `http+sse` - HTTP with Server-Sent Events transport + +Servers **SHOULD NOT** request upgrades from HTTP+SSE to STDIO as this would reduce +protocol capabilities. While the transport field supports custom values for +extensibility, any custom transport **MUST** provide at least the same capabilities as +the transport being upgraded from. + +Example custom transport upgrade: + +```json +{ + "upgrade": { + "endpoint": "grpc://new-server.example.com:50051", + "transport": "grpc" // Custom transport implementation + } +} +``` + +### 2.2 Initialization + +When a client connects using a transport that lacks required capabilities, the server +**MUST** include an `upgrade` field in its initialize response to indicate that a +transport upgrade is necessary. + +### 2.3 Upgrade Fields + +The `upgrade` object contains the following required fields: + +| Field | Type | Description | +| --------- | ------ | ----------------------------------- | +| endpoint | string | The URL of the new server endpoint | +| transport | string | The protocol identifier for the new | +| | | transport | + +### 2.4 Example Upgrade Flow + +During initialization with STDIO transport: + +```json +{ + "jsonrpc": "2.0", + "id": 1, + "result": { + "protocolVersion": "2024-11-05", + "upgrade": { + "endpoint": "http://new-server.example.com:8080", + "transport": "http+sse" + }, + "serverInfo": { + "name": "ExampleServer", + "version": "1.0.0" + } + } +} +``` + +### 2.5 Client Requirements + +Upon receiving an upgrade response, clients **MUST**: + +1. Terminate the existing connection +2. Establish a new connection using the specified transport protocol +3. Reinitialize the session with the new endpoint + +### 2.6 Authentication Flow + +The most common upgrade scenario is transitioning from STDIO to HTTP+SSE transport to +support authentication: + +1. Client connects via STDIO +2. Server requires authentication +3. Server responds with upgrade to HTTP+SSE +4. Client reconnects using HTTP+SSE +5. Authentication proceeds on new transport