Unify MCP tool handlers around one result type

This commit is contained in:
Ian Gulliver
2026-10-23 17:38:34 -07:00
parent 6c51457a06
commit 758aa7f893
7 changed files with 28 additions and 48 deletions
+16 -36
View File
@@ -13,35 +13,26 @@ type Tool struct {
Name string
Description string
InputSchema json.RawMessage
Handler func(ctx context.Context, args json.RawMessage) (string, error)
Rich func(ctx context.Context, args json.RawMessage) Result
Handler func(ctx context.Context, args json.RawMessage) Result
}
func decode[A any](raw json.RawMessage) (A, error) {
args := *new(A)
err := json.Unmarshal(raw, &args)
if err != nil {
return args, fmt.Errorf("malformed call: %w", err)
}
return args, nil
}
func Typed[A any](run func(ctx context.Context, args A) (string, error)) func(ctx context.Context, raw json.RawMessage) (string, error) {
return func(ctx context.Context, raw json.RawMessage) (string, error) {
args, err := decode[A](raw)
if err != nil {
return "", err
}
return run(ctx, args)
}
}
func TypedRich[A any](run func(ctx context.Context, args A) Result) func(ctx context.Context, raw json.RawMessage) Result {
return func(ctx context.Context, raw json.RawMessage) Result {
args, err := decode[A](raw)
func Typed[A any](run func(ctx context.Context, args A) (string, error)) func(ctx context.Context, raw json.RawMessage) Result {
return TypedResult(func(ctx context.Context, args A) Result {
text, err := run(ctx, args)
if err != nil {
return TextResult(err.Error(), true)
}
return TextResult(text, false)
})
}
func TypedResult[A any](run func(ctx context.Context, args A) Result) func(ctx context.Context, raw json.RawMessage) Result {
return func(ctx context.Context, raw json.RawMessage) Result {
var args A
err := json.Unmarshal(raw, &args)
if err != nil {
return TextResult(fmt.Sprintf("malformed call: %s", err), true)
}
return run(ctx, args)
}
}
@@ -120,7 +111,7 @@ func (t Tool) Call(ctx context.Context, args json.RawMessage) Result {
defer cancel()
done := make(chan Result, 1)
go func() {
done <- t.run(cctx, args)
done <- t.Handler(cctx, args)
}()
late := time.NewTimer(timeout + Grace)
defer late.Stop()
@@ -134,17 +125,6 @@ func (t Tool) Call(ctx context.Context, args json.RawMessage) Result {
}
}
func (t Tool) run(ctx context.Context, args json.RawMessage) Result {
if t.Rich != nil {
return t.Rich(ctx, args)
}
text, err := t.Handler(ctx, args)
if err != nil {
return TextResult(err.Error(), true)
}
return TextResult(text, false)
}
type Server struct {
Name string
Version string