Skip to content

Commit 5390807

Browse files
committed
adding error message for invalid toolsets
1 parent 5dfeaca commit 5390807

File tree

3 files changed

+74
-11
lines changed

3 files changed

+74
-11
lines changed

internal/ghmcp/server.go

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,12 @@ func NewMCPServer(cfg MCPServerConfig) (*server.MCPServer, error) {
106106
},
107107
}
108108

109-
enabledToolsets := cleanToolsets(cfg.EnabledToolsets, cfg.DynamicToolsets)
109+
enabledToolsets, invalidToolsets := cleanToolsets(cfg.EnabledToolsets, cfg.DynamicToolsets)
110+
111+
// Log warning about invalid toolsets
112+
if len(invalidToolsets) > 0 {
113+
slog.Warn("invalid toolsets ignored", "toolsets", strings.Join(invalidToolsets, ", "))
114+
}
110115

111116
// Generate instructions based on enabled toolsets
112117
instructions := github.GenerateInstructions(enabledToolsets)
@@ -465,20 +470,32 @@ func (t *bearerAuthTransport) RoundTrip(req *http.Request) (*http.Response, erro
465470
// cleanToolsets handles special toolset keywords in the enabled toolsets list:
466471
// - Duplicates are removed from the result.
467472
// - Removes whitespaces
473+
// - Validates toolset names and returns invalid ones separately
468474
// - "all": Returns ["all"] immediately, ignoring all other toolsets (unless dynamicToolsets is true)
469475
// - "default": Replaces with the actual default toolset IDs from GetDefaultToolsetIDs()
470476
// When dynamicToolsets is true, filters out "all" from the enabled toolsets.
471-
func cleanToolsets(enabledToolsets []string, dynamicToolsets bool) []string {
477+
// Returns: (validToolsets, invalidToolsets)
478+
func cleanToolsets(enabledToolsets []string, dynamicToolsets bool) ([]string, []string) {
472479
seen := make(map[string]bool)
473480
result := make([]string, 0, len(enabledToolsets))
481+
invalid := make([]string, 0)
482+
validIDs := github.GetValidToolsetIDs()
474483

475484
// Add non-default toolsets, removing duplicates and trimming whitespace
476485
for _, toolset := range enabledToolsets {
477486
trimmed := strings.TrimSpace(toolset)
487+
if trimmed == "" {
488+
continue
489+
}
478490
if !seen[trimmed] {
479491
seen[trimmed] = true
480492
if trimmed != github.ToolsetMetadataDefault.ID && trimmed != github.ToolsetMetadataAll.ID {
481-
result = append(result, trimmed)
493+
// Validate the toolset name
494+
if validIDs[trimmed] {
495+
result = append(result, trimmed)
496+
} else {
497+
invalid = append(invalid, trimmed)
498+
}
482499
}
483500
}
484501
}
@@ -488,7 +505,7 @@ func cleanToolsets(enabledToolsets []string, dynamicToolsets bool) []string {
488505

489506
// Handle "all" keyword - return early if not in dynamic mode
490507
if hasAll && !dynamicToolsets {
491-
return []string{github.ToolsetMetadataAll.ID}
508+
return []string{github.ToolsetMetadataAll.ID}, invalid
492509
}
493510

494511
// Expand "default" keyword to actual default toolsets
@@ -501,5 +518,5 @@ func cleanToolsets(enabledToolsets []string, dynamicToolsets bool) []string {
501518
}
502519
}
503520

504-
return result
521+
return result, invalid
505522
}

internal/ghmcp/server_test.go

Lines changed: 40 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ func TestCleanToolsets(t *testing.T) {
1313
input []string
1414
dynamicToolsets bool
1515
expected []string
16+
expectedInvalid []string
1617
}{
1718
{
1819
name: "empty slice",
@@ -211,16 +212,41 @@ func TestCleanToolsets(t *testing.T) {
211212
dynamicToolsets: false,
212213
expected: []string{"all"},
213214
},
215+
// Invalid toolset test cases
216+
{
217+
name: "mix of valid and invalid toolsets",
218+
input: []string{"actions", "invalid_toolset", "gists", "typo_repo"},
219+
dynamicToolsets: false,
220+
expected: []string{"actions", "gists"},
221+
expectedInvalid: []string{"invalid_toolset", "typo_repo"},
222+
},
223+
{
224+
name: "invalid with whitespace",
225+
input: []string{" invalid_tool ", " actions ", " typo_gist "},
226+
dynamicToolsets: false,
227+
expected: []string{"actions"},
228+
expectedInvalid: []string{"invalid_tool", "typo_gist"},
229+
},
230+
{
231+
name: "empty string in toolsets",
232+
input: []string{"", "actions", " ", "gists"},
233+
dynamicToolsets: false,
234+
expected: []string{"actions", "gists"},
235+
expectedInvalid: []string{},
236+
},
214237
}
215238

216239
for _, tt := range tests {
217240
t.Run(tt.name, func(t *testing.T) {
218-
result := cleanToolsets(tt.input, tt.dynamicToolsets)
241+
result, invalid := cleanToolsets(tt.input, tt.dynamicToolsets)
219242

220-
// Check that the result has the correct length
221243
require.Len(t, result, len(tt.expected), "result length should match expected length")
222244

223-
// Create a map for easier comparison since order might vary
245+
if tt.expectedInvalid == nil {
246+
tt.expectedInvalid = []string{}
247+
}
248+
require.Len(t, invalid, len(tt.expectedInvalid), "invalid length should match expected invalid length")
249+
224250
resultMap := make(map[string]bool)
225251
for _, toolset := range result {
226252
resultMap[toolset] = true
@@ -231,13 +257,21 @@ func TestCleanToolsets(t *testing.T) {
231257
expectedMap[toolset] = true
232258
}
233259

234-
// Check that both maps contain the same toolsets
260+
invalidMap := make(map[string]bool)
261+
for _, toolset := range invalid {
262+
invalidMap[toolset] = true
263+
}
264+
265+
expectedInvalidMap := make(map[string]bool)
266+
for _, toolset := range tt.expectedInvalid {
267+
expectedInvalidMap[toolset] = true
268+
}
269+
235270
assert.Equal(t, expectedMap, resultMap, "result should contain all expected toolsets without duplicates")
271+
assert.Equal(t, expectedInvalidMap, invalidMap, "invalid should contain all expected invalid toolsets")
236272

237-
// Verify no duplicates in result
238273
assert.Len(t, resultMap, len(result), "result should not contain duplicates")
239274

240-
// Verify "default" is not in the result
241275
assert.False(t, resultMap["default"], "result should not contain 'default'")
242276
})
243277
}

pkg/github/tools.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,18 @@ func AvailableTools() []ToolsetMetadata {
133133
}
134134
}
135135

136+
// GetValidToolsetIDs returns a map of all valid toolset IDs for quick lookup
137+
func GetValidToolsetIDs() map[string]bool {
138+
validIDs := make(map[string]bool)
139+
for _, tool := range AvailableTools() {
140+
validIDs[tool.ID] = true
141+
}
142+
// Add special keywords
143+
validIDs[ToolsetMetadataAll.ID] = true
144+
validIDs[ToolsetMetadataDefault.ID] = true
145+
return validIDs
146+
}
147+
136148
func GetDefaultToolsetIDs() []string {
137149
return []string{
138150
ToolsetMetadataContext.ID,

0 commit comments

Comments
 (0)