mcp: add Extensions field to capabilities per SEP-2133 (#794)
This implements [SEP-2133](https://modelcontextprotocol.io/community/seps/2133-extensions) and resolves #777. ## Summary of changes - Add `Extensions` field to `ServerCapabilities` and `ClientCapabilities` structs per [SEP-2133](https://modelcontextprotocol.io/community/seps/2133-extensions) - Add `AddExtension` helper methods on both types that normalize nil settings to empty maps. - [The spec requires an object, not null](https://modelcontextprotocol.io/community/seps/2133-extensions#negotiation:~:text=an%20empty%20object%20indicates%20no%20settings.) - Include shallow-copy support via `maps.Clone` in the existing `clone()` methods - also include shallow-copy support for `Experimental` field. - Add comprehensive tests: unit tests for nil-safety, capability preservation, and over-the-wire round-trip ## What's tested - [x] `go test ./mcp/...` passes - [x] Server conformance tests pass (30 scenarios, 40 assertions, 0 failures) - [x] Client conformance tests match existing baseline (auth scenarios are known failures)
This commit is contained in:
parent
1580ac9494
commit
3dd262606e
1 changed files with 124 additions and 2 deletions
|
|
@ -402,6 +402,26 @@ func TestClientCapabilities(t *testing.T) {
|
|||
RootsV2: &RootCapabilities{ListChanged: true},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "extensions preserved",
|
||||
configureClient: func(s *Client) {},
|
||||
clientOpts: func() ClientOptions {
|
||||
caps := &ClientCapabilities{
|
||||
RootsV2: &RootCapabilities{ListChanged: true},
|
||||
}
|
||||
caps.AddExtension("io.example/ext1", map[string]any{"key": "value"})
|
||||
caps.AddExtension("io.example/ext2", nil)
|
||||
return ClientOptions{Capabilities: caps}
|
||||
}(),
|
||||
wantCapabilities: &ClientCapabilities{
|
||||
Extensions: map[string]any{
|
||||
"io.example/ext1": map[string]any{"key": "value"},
|
||||
"io.example/ext2": map[string]any{},
|
||||
},
|
||||
Roots: RootCapabilities{ListChanged: true},
|
||||
RootsV2: &RootCapabilities{ListChanged: true},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
|
|
@ -469,6 +489,23 @@ func TestClientCapabilitiesOverWire(t *testing.T) {
|
|||
},
|
||||
wantCapabilities: &ClientCapabilities{},
|
||||
},
|
||||
{
|
||||
name: "Extensions over wire",
|
||||
clientOpts: func() *ClientOptions {
|
||||
caps := &ClientCapabilities{
|
||||
RootsV2: &RootCapabilities{ListChanged: true},
|
||||
}
|
||||
caps.AddExtension("io.example/ext", map[string]any{"key": "value"})
|
||||
return &ClientOptions{Capabilities: caps}
|
||||
}(),
|
||||
wantCapabilities: &ClientCapabilities{
|
||||
Extensions: map[string]any{
|
||||
"io.example/ext": map[string]any{"key": "value"},
|
||||
},
|
||||
Roots: RootCapabilities{ListChanged: true},
|
||||
RootsV2: &RootCapabilities{ListChanged: true},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
|
|
|
|||
Loading…
Reference in a new issue