Skip to content

Commit c17ebfe

Browse files
chore: separate toolset creation from init and use typed error (#487)
1 parent 9dd6fc5 commit c17ebfe

File tree

4 files changed

+68
-20
lines changed

4 files changed

+68
-20
lines changed

internal/ghmcp/server.go

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -113,26 +113,22 @@ func NewMCPServer(cfg MCPServerConfig) (*server.MCPServer, error) {
113113
}
114114

115115
// Create default toolsets
116-
toolsets, err := github.InitToolsets(
117-
enabledToolsets,
118-
cfg.ReadOnly,
119-
getClient,
120-
getGQLClient,
121-
cfg.Translator,
122-
)
116+
tsg := github.DefaultToolsetGroup(cfg.ReadOnly, getClient, getGQLClient, cfg.Translator)
117+
err = tsg.EnableToolsets(enabledToolsets)
118+
123119
if err != nil {
124-
return nil, fmt.Errorf("failed to initialize toolsets: %w", err)
120+
return nil, fmt.Errorf("failed to enable toolsets: %w", err)
125121
}
126122

127123
context := github.InitContextToolset(getClient, cfg.Translator)
128124
github.RegisterResources(ghServer, getClient, cfg.Translator)
129125

130126
// Register the tools with the server
131-
toolsets.RegisterTools(ghServer)
127+
tsg.RegisterTools(ghServer)
132128
context.RegisterTools(ghServer)
133129

134130
if cfg.DynamicToolsets {
135-
dynamic := github.InitDynamicToolset(ghServer, toolsets, cfg.Translator)
131+
dynamic := github.InitDynamicToolset(ghServer, tsg, cfg.Translator)
136132
dynamic.RegisterTools(ghServer)
137133
}
138134

pkg/github/tools.go

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,7 @@ type GetGQLClientFn func(context.Context) (*githubv4.Client, error)
1515

1616
var DefaultTools = []string{"all"}
1717

18-
func InitToolsets(passedToolsets []string, readOnly bool, getClient GetClientFn, getGQLClient GetGQLClientFn, t translations.TranslationHelperFunc) (*toolsets.ToolsetGroup, error) {
19-
// Create a new toolset group
18+
func DefaultToolsetGroup(readOnly bool, getClient GetClientFn, getGQLClient GetGQLClientFn, t translations.TranslationHelperFunc) *toolsets.ToolsetGroup {
2019
tsg := toolsets.NewToolsetGroup(readOnly)
2120

2221
// Define all available features with their default state (disabled)
@@ -116,13 +115,8 @@ func InitToolsets(passedToolsets []string, readOnly bool, getClient GetClientFn,
116115
tsg.AddToolset(secretProtection)
117116
tsg.AddToolset(notifications)
118117
tsg.AddToolset(experiments)
119-
// Enable the requested features
120118

121-
if err := tsg.EnableToolsets(passedToolsets); err != nil {
122-
return nil, err
123-
}
124-
125-
return tsg, nil
119+
return tsg
126120
}
127121

128122
func InitContextToolset(getClient GetClientFn, t translations.TranslationHelperFunc) *toolsets.Toolset {

pkg/toolsets/toolsets.go

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,28 @@ import (
77
"github.com/mark3labs/mcp-go/server"
88
)
99

10+
type ToolsetDoesNotExistError struct {
11+
Name string
12+
}
13+
14+
func (e *ToolsetDoesNotExistError) Error() string {
15+
return fmt.Sprintf("toolset %s does not exist", e.Name)
16+
}
17+
18+
func (e *ToolsetDoesNotExistError) Is(target error) bool {
19+
if target == nil {
20+
return false
21+
}
22+
if _, ok := target.(*ToolsetDoesNotExistError); ok {
23+
return true
24+
}
25+
return false
26+
}
27+
28+
func NewToolsetDoesNotExistError(name string) *ToolsetDoesNotExistError {
29+
return &ToolsetDoesNotExistError{Name: name}
30+
}
31+
1032
func NewServerTool(tool mcp.Tool, handler server.ToolHandlerFunc) server.ServerTool {
1133
return server.ServerTool{Tool: tool, Handler: handler}
1234
}
@@ -150,7 +172,7 @@ func (tg *ToolsetGroup) EnableToolsets(names []string) error {
150172
func (tg *ToolsetGroup) EnableToolset(name string) error {
151173
toolset, exists := tg.Toolsets[name]
152174
if !exists {
153-
return fmt.Errorf("toolset %s does not exist", name)
175+
return NewToolsetDoesNotExistError(name)
154176
}
155177
toolset.Enabled = true
156178
tg.Toolsets[name] = toolset
@@ -162,3 +184,11 @@ func (tg *ToolsetGroup) RegisterTools(s *server.MCPServer) {
162184
toolset.RegisterTools(s)
163185
}
164186
}
187+
188+
func (tg *ToolsetGroup) GetToolset(name string) (*Toolset, error) {
189+
toolset, exists := tg.Toolsets[name]
190+
if !exists {
191+
return nil, NewToolsetDoesNotExistError(name)
192+
}
193+
return toolset, nil
194+
}

pkg/toolsets/toolsets_test.go

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package toolsets
22

33
import (
4+
"errors"
45
"testing"
56
)
67

@@ -151,6 +152,9 @@ func TestEnableToolsets(t *testing.T) {
151152
if err == nil {
152153
t.Error("Expected error when enabling list with non-existent toolset")
153154
}
155+
if !errors.Is(err, NewToolsetDoesNotExistError("non-existent")) {
156+
t.Errorf("Expected ToolsetDoesNotExistError when enabling non-existent toolset, got: %v", err)
157+
}
154158

155159
// Test with empty list
156160
err = tsg.EnableToolsets([]string{})
@@ -207,7 +211,7 @@ func TestEnableEverything(t *testing.T) {
207211
func TestIsEnabledWithEverythingOn(t *testing.T) {
208212
tsg := NewToolsetGroup(false)
209213

210-
// Enable "everything"
214+
// Enable "all"
211215
err := tsg.EnableToolsets([]string{"all"})
212216
if err != nil {
213217
t.Errorf("Expected no error when enabling 'all', got: %v", err)
@@ -222,3 +226,27 @@ func TestIsEnabledWithEverythingOn(t *testing.T) {
222226
t.Error("Expected IsEnabled to return true for any toolset when everythingOn is true")
223227
}
224228
}
229+
230+
func TestToolsetGroup_GetToolset(t *testing.T) {
231+
tsg := NewToolsetGroup(false)
232+
toolset := NewToolset("my-toolset", "desc")
233+
tsg.AddToolset(toolset)
234+
235+
// Should find the toolset
236+
got, err := tsg.GetToolset("my-toolset")
237+
if err != nil {
238+
t.Fatalf("expected no error, got %v", err)
239+
}
240+
if got != toolset {
241+
t.Errorf("expected to get the same toolset instance")
242+
}
243+
244+
// Should not find a non-existent toolset
245+
_, err = tsg.GetToolset("does-not-exist")
246+
if err == nil {
247+
t.Error("expected error for missing toolset, got nil")
248+
}
249+
if !errors.Is(err, NewToolsetDoesNotExistError("does-not-exist")) {
250+
t.Errorf("expected error to be ToolsetDoesNotExistError, got %v", err)
251+
}
252+
}

0 commit comments

Comments
 (0)