internal/mcp: generic handling of CallToolParams
Make Tool APIs future-proof by pushing generics into CallToolParams, and using CallToolParams throughout. This has several advantages: - We no longer need the awkward CallToolOptions type, which is almost but not quite like CallToolParams. - NewTool no longer needs to define its own handler type: it accepts a ToolHandler[TArgs]. This also means its signature is future-proof. Additionally, provide a `CallTool` helper (the analog of NewTool) to serve as a more strongly typed variant of `ClientSession.CallTool`. + design, protocol generation Change-Id: I80172a25bc50734dae84a541aa4776ed9161694e Reviewed-on: https://go-review.googlesource.com/c/tools/+/676495 Reviewed-by: Jonathan Amsterdam <jba@google.com> Auto-Submit: Robert Findley <rfindley@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
This commit is contained in:
parent
bb2347385e
commit
04ca8ac03b
1 changed files with 170 additions and 108 deletions
|
|
@ -258,35 +258,30 @@ func (cs *ClientSession) ListTools(ctx context.Context, params *ListToolsParams)
|
|||
|
||||
// CallTool calls the tool with the given name and arguments.
|
||||
// Pass a [CallToolOptions] to provide additional request fields.
|
||||
func (cs *ClientSession) CallTool(ctx context.Context, name string, args map[string]any, opts *CallToolOptions) (_ *CallToolResult, err error) {
|
||||
defer func() {
|
||||
if err != nil {
|
||||
err = fmt.Errorf("calling tool %q: %w", name, err)
|
||||
}
|
||||
}()
|
||||
|
||||
data, err := json.Marshal(args)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("marshaling arguments: %w", err)
|
||||
}
|
||||
params := &CallToolParams{
|
||||
Name: name,
|
||||
Arguments: json.RawMessage(data),
|
||||
}
|
||||
func (cs *ClientSession) CallTool(ctx context.Context, params *CallToolParams[json.RawMessage]) (*CallToolResult, error) {
|
||||
return standardCall[CallToolResult](ctx, cs.conn, methodCallTool, params)
|
||||
}
|
||||
|
||||
// CallTool is a helper to call a tool with any argument type. It returns an
|
||||
// error if params.Arguments fails to marshal to JSON.
|
||||
func CallTool[TArgs any](ctx context.Context, cs *ClientSession, params *CallToolParams[TArgs]) (*CallToolResult, error) {
|
||||
data, err := json.Marshal(params.Arguments)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to marshal arguments: %v", err)
|
||||
}
|
||||
// TODO(rfindley): write a test that guarantees this copying is total.
|
||||
wireParams := &CallToolParams[json.RawMessage]{
|
||||
Meta: params.Meta,
|
||||
Name: params.Name,
|
||||
Arguments: data,
|
||||
}
|
||||
return cs.CallTool(ctx, wireParams)
|
||||
}
|
||||
|
||||
func (cs *ClientSession) SetLevel(ctx context.Context, params *SetLevelParams) error {
|
||||
return call(ctx, cs.conn, methodSetLevel, params, nil)
|
||||
}
|
||||
|
||||
// NOTE: the following struct should consist of all fields of callToolParams except name and arguments.
|
||||
|
||||
// CallToolOptions contains options to [ClientSession.CallTool].
|
||||
type CallToolOptions struct {
|
||||
ProgressToken any // string or int
|
||||
}
|
||||
|
||||
// ListResources lists the resources that are currently available on the server.
|
||||
func (cs *ClientSession) ListResources(ctx context.Context, params *ListResourcesParams) (*ListResourcesResult, error) {
|
||||
return standardCall[ListResourcesResult](ctx, cs.conn, methodListResources, params)
|
||||
|
|
|
|||
Loading…
Reference in a new issue