Skip to content

Commit a04f1e5

Browse files
committed
Merge branch 'main' into fgrosse/479-connection-closing-callback
2 parents f3b5d93 + 28753c9 commit a04f1e5

22 files changed

+640
-160
lines changed

.github/workflows/docs-check.yml

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
name: Docs Check
2+
on:
3+
workflow_dispatch:
4+
pull_request:
5+
paths:
6+
- 'internal/readme/**'
7+
- 'README.md'
8+
- 'internal/docs/**'
9+
- 'docs/**'
10+
11+
permissions:
12+
contents: read
13+
14+
jobs:
15+
docs-check:
16+
runs-on: ubuntu-latest
17+
steps:
18+
- name: Set up Go
19+
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5
20+
- name: Check out code
21+
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4
22+
- name: Check docs are up-to-date
23+
run: |
24+
go generate ./...
25+
if [ -n "$(git status --porcelain)" ]; then
26+
echo "ERROR: docs are not up-to-date!"
27+
echo ""
28+
echo "The docs differ from what would be generated by `go generate ./...`."
29+
echo "Please update internal/**/*.src.md instead of directly editing README.md or docs/ files,"
30+
echo "then run `go generate ./...` to regenerate docs."
31+
echo ""
32+
echo "Changes:"
33+
git status --porcelain
34+
echo ""
35+
echo "Diff:"
36+
git diff
37+
exit 1
38+
fi
39+
echo "Docs are up-to-date."

.github/workflows/readme-check.yml

Lines changed: 0 additions & 39 deletions
This file was deleted.

.github/workflows/test.yml

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@ jobs:
1414
runs-on: ubuntu-latest
1515
steps:
1616
- name: Check out code
17-
uses: actions/checkout@v4
17+
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4
1818
- name: Set up Go
19-
uses: actions/setup-go@v5
19+
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5
2020
with:
2121
go-version: "^1.23"
2222
- name: Check formatting
@@ -31,7 +31,7 @@ jobs:
3131
- name: Run Go vet
3232
run: go vet ./...
3333
- name: Run staticcheck
34-
uses: dominikh/staticcheck-action@v1
34+
uses: dominikh/staticcheck-action@024238d2898c874f26d723e7d0ff4308c35589a2 # v1
3535
with:
3636
version: "latest"
3737

@@ -42,9 +42,9 @@ jobs:
4242
go: ["1.23", "1.24", "1.25"]
4343
steps:
4444
- name: Check out code
45-
uses: actions/checkout@v4
45+
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4
4646
- name: Set up Go
47-
uses: actions/setup-go@v5
47+
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5
4848
with:
4949
go-version: ${{ matrix.go }}
5050
- name: Test
@@ -54,9 +54,9 @@ jobs:
5454
runs-on: ubuntu-latest
5555
steps:
5656
- name: Check out code
57-
uses: actions/checkout@v4
57+
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4
5858
- name: Set up Go
59-
uses: actions/setup-go@v5
59+
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5
6060
with:
6161
go-version: "1.24"
6262
- name: Test with -race

docs/client.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ The SDK supports this as follows:
1313

1414
**Client-side**: The SDK client always has the `roots.listChanged` capability.
1515
To add roots to a client, use the
16-
[`Client.AddRoots`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/mcp#AddRoots)
16+
[`Client.AddRoots`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/mcp#Client.AddRoots)
1717
and
1818
[`Client.RemoveRoots`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/mcp#Client.RemoveRoots)
1919
methods. If any servers are already [connected](protocol.md#lifecycle) to the

docs/protocol.md

Lines changed: 87 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,12 @@
88
1. [Custom transports](#custom-transports)
99
1. [Concurrency](#concurrency)
1010
1. [Authorization](#authorization)
11+
1. [Server](#server)
12+
1. [Client](#client)
1113
1. [Security](#security)
14+
1. [Confused Deputy](#confused-deputy)
15+
1. [Token Passthrough](#token-passthrough)
16+
1. [Session Hijacking](#session-hijacking)
1217
1. [Utilities](#utilities)
1318
1. [Cancellation](#cancellation)
1419
1. [Ping](#ping)
@@ -182,15 +187,35 @@ the server using the streamable transport protocol.
182187

183188
#### Stateless Mode
184189

185-
<!-- TODO -->
190+
The streamable server supports a _stateless mode_ by setting
191+
[`StreamableHTTPOptions.Stateless`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/mcp#StreamableHTTPOptions.Stateless),
192+
which is where the server does not perform any validation of the session id,
193+
and uses a temporary session to handle requests. In this mode, it is impossible
194+
for the server to make client requests, as there is no way for the client's
195+
response to reach the session.
186196

187-
#### Sessionless mode
197+
However, it is still possible for the server to access the `ServerSession.ID`
198+
to see the logical session
188199

189-
<!-- TODO -->
200+
> [!WARNING]
201+
> Stateless mode is not directly discussed in the spec, and is still being
202+
> defined. See modelcontextprotocol/modelcontextprotocol#1364,
203+
> modelcontextprotocol/modelcontextprotocol#1372, or
204+
> modelcontextprotocol/modelcontextprotocol#11442 for potential refinements.
205+
206+
_See [examples/server/distributed](../examples/server/distributed/main.go) for
207+
an example using statless mode to implement a server distributed across
208+
multiple processes._
190209

191210
### Custom transports
192211

193-
<!-- TODO -->
212+
The SDK supports [custom
213+
transports](https://modelcontextprotocol.io/specification/2025-06-18/basic/transports#custom-transports)
214+
by implementing the
215+
[`Transport`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/mcp#Transport)
216+
interface: a logical bidirectional stream of JSON-RPC messages.
217+
218+
_Full example: [examples/server/custom-transport](../examples/server/custom-transport/main.go)._
194219

195220
### Concurrency
196221

@@ -212,11 +237,67 @@ for more background.
212237

213238
## Authorization
214239

215-
<!-- TODO -->
240+
### Server
241+
242+
To write an MCP server that performs authorization,
243+
use [`RequireBearerToken`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/auth#RequireBearerToken).
244+
This function is middleware that wraps an HTTP handler, such as the one returned
245+
by [`NewStreamableHTTPHandler`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/mcp#NewStreamableHTTPHandler), to provide support for verifying bearer tokens.
246+
The middleware function checks every request for an Authorization header with a bearer token,
247+
and invokes the
248+
[`TokenVerifier`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/auth#TokenVerifier)
249+
passed to `RequireBearerToken` to parse the token and perform validation.
250+
The middleware function checks expiration and scopes (if they are provided in
251+
[`RequireBearerTokenOptions.Scopes`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/auth#RequireBearerTokenOptions.Scopes)), so the
252+
`TokenVerifer` doesn't have to.
253+
If [`RequireBearerTokenOptions.ResourceMetadataURL`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/auth#RequireBearerTokenOptions.ResourceMetadataURL) is set and verification fails,
254+
the middleware function sets the WWW-Authenticate header as required by the [Protected Resource
255+
Metadata spec](https://datatracker.ietf.org/doc/html/rfc9728).
256+
257+
The [_auth middleware example_](https://github.com/modelcontextprotocol/go-sdk/tree/main/examples/server/auth-middleware) shows how to implement authorization for both JWT tokens and API keys.
258+
259+
### Client
260+
261+
Client-side OAuth is implemented by setting
262+
[`StreamableClientTransport.HTTPClient`](https://pkg.go.dev/github.com/modelcontextprotocol/[email protected]/mcp#StreamableClientTransport.HTTPClient) to a custom [`http.Client`](https://pkg.go.dev/net/http#Client)
263+
Additional support is forthcoming; see #493.
216264

217265
## Security
218266

219-
<!-- TODO -->
267+
Here we discuss the mitigations described under
268+
the MCP spec's [Security Best Practices](https://modelcontextprotocol.io/specification/2025-06-18/basic/security_best_practices) section, and how we handle them.
269+
270+
### Confused Deputy
271+
272+
The [mitigation](https://modelcontextprotocol.io/specification/2025-06-18/basic/security_best_practices#mitigation), obtaining user consent for dynamically registered clients,
273+
happens on the MCP client. At present we don't provide client-side OAuth support.
274+
275+
276+
### Token Passthrough
277+
278+
The [mitigation](https://modelcontextprotocol.io/specification/2025-06-18/basic/security_best_practices#mitigation-2), accepting only tokens that were issued for the server, depends on the structure
279+
of tokens and is the responsibility of the
280+
[`TokenVerifier`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/auth#TokenVerifier)
281+
provided to
282+
[`RequireBearerToken`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/auth#RequireBearerToken).
283+
284+
### Session Hijacking
285+
286+
The [mitigations](https://modelcontextprotocol.io/specification/2025-06-18/basic/security_best_practices#mitigation-3) are as follows:
287+
288+
- _Verify all inbound requests_. The [`RequireBearerToken`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/auth#RequireBearerToken)
289+
middleware function will verify all HTTP requests that it receives. It is the
290+
user's responsibility to wrap that function around all handlers in their server.
291+
292+
- _Secure session IDs_. This SDK generates cryptographically secure session IDs by default.
293+
If you create your own with
294+
[`ServerOptions.GetSessionID`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/mcp#ServerOptions.GetSessionID), it is your responsibility to ensure they are secure.
295+
If you are using Go 1.24 or above,
296+
we recommend using [`crypto/rand.Text`](https://pkg.go.dev/crypto/rand#Text)
297+
298+
- _Binding session IDs to user information_. This is an application requirement, out of scope
299+
for the SDK. You can create your own session IDs by setting
300+
[`ServerOptions.GetSessionID`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/mcp#ServerOptions.GetSessionID).
220301

221302
## Utilities
222303

0 commit comments

Comments
 (0)