From 255ba0884e4adeb14769fb9888f83799e7f46a4c Mon Sep 17 00:00:00 2001 From: William Martin Date: Fri, 4 Apr 2025 17:24:06 +0200 Subject: [PATCH] Add optional string array param --- pkg/github/issues.go | 10 +++--- pkg/github/issues_test.go | 10 +++--- pkg/github/server.go | 30 ++++++++++++++++- pkg/github/server_test.go | 68 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 107 insertions(+), 11 deletions(-) diff --git a/pkg/github/issues.go b/pkg/github/issues.go index 0e3376373..df2f6f584 100644 --- a/pkg/github/issues.go +++ b/pkg/github/issues.go @@ -286,13 +286,13 @@ func createIssue(client *github.Client, t translations.TranslationHelperFunc) (t } // Get assignees - assignees, err := optionalParam[[]string](request, "assignees") + assignees, err := optionalStringArrayParam(request, "assignees") if err != nil { return mcp.NewToolResultError(err.Error()), nil } // Get labels - labels, err := optionalParam[[]string](request, "labels") + labels, err := optionalStringArrayParam(request, "labels") if err != nil { return mcp.NewToolResultError(err.Error()), nil } @@ -401,7 +401,7 @@ func listIssues(client *github.Client, t translations.TranslationHelperFunc) (to } // Get labels - opts.Labels, err = optionalParam[[]string](request, "labels") + opts.Labels, err = optionalStringArrayParam(request, "labels") if err != nil { return mcp.NewToolResultError(err.Error()), nil } @@ -548,7 +548,7 @@ func updateIssue(client *github.Client, t translations.TranslationHelperFunc) (t } // Get labels - labels, err := optionalParam[[]string](request, "labels") + labels, err := optionalStringArrayParam(request, "labels") if err != nil { return mcp.NewToolResultError(err.Error()), nil } @@ -557,7 +557,7 @@ func updateIssue(client *github.Client, t translations.TranslationHelperFunc) (t } // Get assignees - assignees, err := optionalParam[[]string](request, "assignees") + assignees, err := optionalStringArrayParam(request, "assignees") if err != nil { return mcp.NewToolResultError(err.Error()), nil } diff --git a/pkg/github/issues_test.go b/pkg/github/issues_test.go index f29e2b04d..5dab16312 100644 --- a/pkg/github/issues_test.go +++ b/pkg/github/issues_test.go @@ -436,8 +436,8 @@ func Test_CreateIssue(t *testing.T) { "repo": "repo", "title": "Test Issue", "body": "This is a test issue", - "assignees": []string{"user1", "user2"}, - "labels": []string{"bug", "help wanted"}, + "assignees": []any{"user1", "user2"}, + "labels": []any{"bug", "help wanted"}, "milestone": float64(5), }, expectError: false, @@ -636,7 +636,7 @@ func Test_ListIssues(t *testing.T) { "owner": "owner", "repo": "repo", "state": "open", - "labels": []string{"bug", "enhancement"}, + "labels": []any{"bug", "enhancement"}, "sort": "created", "direction": "desc", "since": "2023-01-01T00:00:00Z", @@ -790,8 +790,8 @@ func Test_UpdateIssue(t *testing.T) { "title": "Updated Issue Title", "body": "Updated issue description", "state": "closed", - "labels": []string{"bug", "priority"}, - "assignees": []string{"assignee1", "assignee2"}, + "labels": []any{"bug", "priority"}, + "assignees": []any{"assignee1", "assignee2"}, "milestone": float64(5), }, expectError: false, diff --git a/pkg/github/server.go b/pkg/github/server.go index f93ca37f5..66dbfd1ca 100644 --- a/pkg/github/server.go +++ b/pkg/github/server.go @@ -171,7 +171,7 @@ func optionalParam[T any](r mcp.CallToolRequest, p string) (T, error) { // Check if the parameter is of the expected type if _, ok := r.Params.Arguments[p].(T); !ok { - return zero, fmt.Errorf("parameter %s is not of type %T", p, zero) + return zero, fmt.Errorf("parameter %s is not of type %T, is %T", p, zero, r.Params.Arguments[p]) } return r.Params.Arguments[p].(T), nil @@ -201,3 +201,31 @@ func optionalIntParamWithDefault(r mcp.CallToolRequest, p string, d int) (int, e } return v, nil } + +// optionalStringArrayParam is a helper function that can be used to fetch a requested parameter from the request. +// It does the following checks: +// 1. Checks if the parameter is present in the request, if not, it returns its zero-value +// 2. If it is present, iterates the elements and checks each is a string +func optionalStringArrayParam(r mcp.CallToolRequest, p string) ([]string, error) { + // Check if the parameter is present in the request + if _, ok := r.Params.Arguments[p]; !ok { + return []string{}, nil + } + + switch v := r.Params.Arguments[p].(type) { + case []string: + return v, nil + case []any: + strSlice := make([]string, len(v)) + for i, v := range v { + s, ok := v.(string) + if !ok { + return []string{}, fmt.Errorf("parameter %s is not of type string, is %T", p, v) + } + strSlice[i] = s + } + return strSlice, nil + default: + return []string{}, fmt.Errorf("parameter %s could not be coerced to []string, is %T", p, r.Params.Arguments[p]) + } +} diff --git a/pkg/github/server_test.go b/pkg/github/server_test.go index ffaa4dd8d..beb6ecbb2 100644 --- a/pkg/github/server_test.go +++ b/pkg/github/server_test.go @@ -483,3 +483,71 @@ func Test_OptionalBooleanParam(t *testing.T) { }) } } + +func TestOptionalStringArrayParam(t *testing.T) { + tests := []struct { + name string + params map[string]interface{} + paramName string + expected []string + expectError bool + }{ + { + name: "parameter not in request", + params: map[string]any{}, + paramName: "flag", + expected: []string{}, + expectError: false, + }, + { + name: "valid any array parameter", + params: map[string]any{ + "flag": []any{"v1", "v2"}, + }, + paramName: "flag", + expected: []string{"v1", "v2"}, + expectError: false, + }, + { + name: "valid string array parameter", + params: map[string]any{ + "flag": []string{"v1", "v2"}, + }, + paramName: "flag", + expected: []string{"v1", "v2"}, + expectError: false, + }, + { + name: "wrong type parameter", + params: map[string]any{ + "flag": 1, + }, + paramName: "flag", + expected: []string{}, + expectError: true, + }, + { + name: "wrong slice type parameter", + params: map[string]any{ + "flag": []any{"foo", 2}, + }, + paramName: "flag", + expected: []string{}, + expectError: true, + }, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + request := createMCPRequest(tc.params) + result, err := optionalStringArrayParam(request, tc.paramName) + + if tc.expectError { + assert.Error(t, err) + } else { + assert.NoError(t, err) + assert.Equal(t, tc.expected, result) + } + }) + } +} pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy