mcp/server: expose InitializeParams to ServerSession (#336)
This CL enables the server session to see what capabilities the client has by introducing the InitializeParams() function. This CL also adds a test to ensure ClientCapabilities is accurate. Fixes #141
This commit is contained in:
parent
62d815922f
commit
48abccbf6b
3 changed files with 57 additions and 7 deletions
|
|
@ -105,6 +105,15 @@ func (e unsupportedProtocolVersionError) Error() string {
|
||||||
// ClientSessionOptions is reserved for future use.
|
// ClientSessionOptions is reserved for future use.
|
||||||
type ClientSessionOptions struct{}
|
type ClientSessionOptions struct{}
|
||||||
|
|
||||||
|
func (c *Client) capabilities() *ClientCapabilities {
|
||||||
|
caps := &ClientCapabilities{}
|
||||||
|
caps.Roots.ListChanged = true
|
||||||
|
if c.opts.CreateMessageHandler != nil {
|
||||||
|
caps.Sampling = &SamplingCapabilities{}
|
||||||
|
}
|
||||||
|
return caps
|
||||||
|
}
|
||||||
|
|
||||||
// Connect begins an MCP session by connecting to a server over the given
|
// Connect begins an MCP session by connecting to a server over the given
|
||||||
// transport, and initializing the session.
|
// transport, and initializing the session.
|
||||||
//
|
//
|
||||||
|
|
@ -118,16 +127,10 @@ func (c *Client) Connect(ctx context.Context, t Transport, _ *ClientSessionOptio
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
caps := &ClientCapabilities{}
|
|
||||||
caps.Roots.ListChanged = true
|
|
||||||
if c.opts.CreateMessageHandler != nil {
|
|
||||||
caps.Sampling = &SamplingCapabilities{}
|
|
||||||
}
|
|
||||||
|
|
||||||
params := &InitializeParams{
|
params := &InitializeParams{
|
||||||
ProtocolVersion: latestProtocolVersion,
|
ProtocolVersion: latestProtocolVersion,
|
||||||
ClientInfo: c.impl,
|
ClientInfo: c.impl,
|
||||||
Capabilities: caps,
|
Capabilities: c.capabilities(),
|
||||||
}
|
}
|
||||||
req := &ClientRequest[*InitializeParams]{Session: cs, Params: params}
|
req := &ClientRequest[*InitializeParams]{Session: cs, Params: params}
|
||||||
res, err := handleSend[*InitializeResult](ctx, methodInitialize, req)
|
res, err := handleSend[*InitializeResult](ctx, methodInitialize, req)
|
||||||
|
|
|
||||||
|
|
@ -190,3 +190,48 @@ func TestClientPaginateVariousPageSizes(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestClientCapabilities(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
configureClient func(s *Client)
|
||||||
|
clientOpts ClientOptions
|
||||||
|
wantCapabilities *ClientCapabilities
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "With initial capabilities",
|
||||||
|
configureClient: func(s *Client) {},
|
||||||
|
wantCapabilities: &ClientCapabilities{
|
||||||
|
Roots: struct {
|
||||||
|
ListChanged bool "json:\"listChanged,omitempty\""
|
||||||
|
}{ListChanged: true},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "With sampling",
|
||||||
|
configureClient: func(s *Client) {},
|
||||||
|
clientOpts: ClientOptions{
|
||||||
|
CreateMessageHandler: func(context.Context, *ClientRequest[*CreateMessageParams]) (*CreateMessageResult, error) {
|
||||||
|
return nil, nil
|
||||||
|
},
|
||||||
|
},
|
||||||
|
wantCapabilities: &ClientCapabilities{
|
||||||
|
Roots: struct {
|
||||||
|
ListChanged bool "json:\"listChanged,omitempty\""
|
||||||
|
}{ListChanged: true},
|
||||||
|
Sampling: &SamplingCapabilities{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
client := NewClient(testImpl, &tc.clientOpts)
|
||||||
|
tc.configureClient(client)
|
||||||
|
gotCapabilities := client.capabilities()
|
||||||
|
if diff := cmp.Diff(tc.wantCapabilities, gotCapabilities); diff != "" {
|
||||||
|
t.Errorf("capabilities() mismatch (-want +got):\n%s", diff)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -849,6 +849,8 @@ func (ss *ServerSession) handle(ctx context.Context, req *jsonrpc.Request) (any,
|
||||||
return handleReceive(ctx, ss, req)
|
return handleReceive(ctx, ss, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ss *ServerSession) InitializeParams() *InitializeParams { return ss.state.InitializeParams }
|
||||||
|
|
||||||
func (ss *ServerSession) initialize(ctx context.Context, params *InitializeParams) (*InitializeResult, error) {
|
func (ss *ServerSession) initialize(ctx context.Context, params *InitializeParams) (*InitializeResult, error) {
|
||||||
if params == nil {
|
if params == nil {
|
||||||
return nil, fmt.Errorf("%w: \"params\" must be be provided", jsonrpc2.ErrInvalidParams)
|
return nil, fmt.Errorf("%w: \"params\" must be be provided", jsonrpc2.ErrInvalidParams)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue