You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
[Server] Add CORS, DNS rebinding and protocol version middleware
Introduce three PSR-15 middleware for `StreamableHttpTransport` exposed
through a public `StreamableHttpTransport::defaultMiddleware()` factory
composed automatically when no middleware is passed.
- `CorsMiddleware`: secure-by-default (no `Access-Control-Allow-Origin`),
configurable allowlist, reflects matching origin with `Vary: Origin`
to protect shared caches.
- `DnsRebindingProtectionMiddleware`: validates `Origin`/`Host` against
a hostname allowlist (localhost-only by default).
- `ProtocolVersionMiddleware`: rejects requests carrying an unsupported
`Mcp-Protocol-Version` header with `400 Bad Request`.
The transport no longer applies CORS via an `instanceof + array_unshift`
post-hook; the middleware parameter is nullable — `null` installs the
secure defaults, `[]` disables them, and users compose by spreading
`StreamableHttpTransport::defaultMiddleware()`. `SESSION_HEADER` and
`PROTOCOL_VERSION_HEADER` are promoted to public constants so middleware
can reuse them.
BC breaks:
- The `corsHeaders` constructor parameter is removed; the `middleware`
parameter shifts one position. Positional callers passing the old
`corsHeaders` argument must switch to named arguments or drop it.
- Default `Access-Control-Allow-Origin` is no longer `*`.
Addresses #260 (DNS rebinding), #277 (CORS extraction) and #306
(protocol version validation).
Copy file name to clipboardExpand all lines: CHANGELOG.md
+2Lines changed: 2 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -6,6 +6,8 @@ All notable changes to `mcp/sdk` will be documented in this file.
6
6
-----
7
7
8
8
* Allow overriding the default name pattern for Discovery
9
+
* Add `CorsMiddleware`, `DnsRebindingProtectionMiddleware`, and `ProtocolVersionMiddleware` for `StreamableHttpTransport`, composed automatically as the default stack via `StreamableHttpTransport::defaultMiddleware()`
10
+
***[BC BREAK]**`StreamableHttpTransport` constructor: `$corsHeaders` parameter removed; CORS is now configured via `CorsMiddleware`. The `$middleware` parameter is nullable — `null` (or omitted) installs the default stack; `[]` disables all defaults. Default `Access-Control-Allow-Origin` is no longer set (was `*`).
@@ -110,8 +110,8 @@ $transport = new StreamableHttpTransport(
110
110
-**`request`** (required): `ServerRequestInterface` - The incoming PSR-7 HTTP request
111
111
-**`responseFactory`** (optional): `ResponseFactoryInterface` - PSR-17 factory for creating HTTP responses. Auto-discovered if not provided.
112
112
-**`streamFactory`** (optional): `StreamFactoryInterface` - PSR-17 factory for creating response body streams. Auto-discovered if not provided.
113
-
-**`corsHeaders`** (optional): `array` - Custom CORS headers to override defaults. Merges with secure defaults. Defaults to `[]`.
114
113
-**`logger`** (optional): `LoggerInterface` - PSR-3 logger for debugging. Defaults to `NullLogger`.
114
+
-**`middleware`** (optional): `iterable<MiddlewareInterface>|null` - PSR-15 middleware chain. `null` (omitted) installs the [default stack](#default-middleware). `[]` disables all defaults — useful when the surrounding application already handles CORS, host validation, etc.
115
115
116
116
### PSR-17 Auto-Discovery
117
117
@@ -137,56 +137,109 @@ $psr17Factory = new Psr17Factory();
137
137
$transport = new StreamableHttpTransport($request, $psr17Factory, $psr17Factory);
138
138
```
139
139
140
-
### CORS Configuration
140
+
### Default Middleware
141
+
142
+
When the `middleware` argument is omitted (or set to `null`), the transport installs a secure default stack:
141
143
142
-
The transport sets secure CORS defaults that can be customized or disabled:
144
+
| Order | Middleware | Purpose |
145
+
|-------|------------|---------|
146
+
| 1 |`CorsMiddleware`| Applies CORS headers to every response. By default does **not** set `Access-Control-Allow-Origin` (cross-origin requests are blocked). |
147
+
| 2 |`DnsRebindingProtectionMiddleware`| Validates `Origin`/`Host` against an allowlist. Defaults to localhost variants only. |
148
+
| 3 |`ProtocolVersionMiddleware`| Rejects requests carrying an unsupported `MCP-Protocol-Version` header with `400 Bad Request`. |
143
149
144
150
```php
145
-
// Default CORS headers (backward compatible)
146
-
$transport = new StreamableHttpTransport($request, $responseFactory, $streamFactory);
151
+
// Zero-config, secure-by-default — local servers get full protection automatically.
152
+
$transport = new StreamableHttpTransport($request);
0 commit comments