Skip to content

Commit 1270a88

Browse files
chore: separate toolset creation from init and use typed error
1 parent 9dd6fc5 commit 1270a88

File tree

10 files changed

+59
-19
lines changed

10 files changed

+59
-19
lines changed

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ module github.com/github/github-mcp-server
33
go 1.23.7
44

55
require (
6+
github.com/go-errors/errors v1.5.1
67
github.com/google/go-github/v72 v72.0.0
78
github.com/josephburnett/jd v1.9.2
89
github.com/mark3labs/mcp-go v0.31.0

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHk
88
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
99
github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M=
1010
github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
11+
github.com/go-errors/errors v1.5.1 h1:ZwEMSLRCapFLflTpT7NKaAc7ukJ8ZPEjzlxt8rPN8bk=
12+
github.com/go-errors/errors v1.5.1/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og=
1113
github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY=
1214
github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
1315
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=

internal/ghmcp/server.go

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515
"github.com/github/github-mcp-server/pkg/github"
1616
mcplog "github.com/github/github-mcp-server/pkg/log"
1717
"github.com/github/github-mcp-server/pkg/translations"
18+
"github.com/go-errors/errors"
1819
gogithub "github.com/google/go-github/v72/github"
1920
"github.com/mark3labs/mcp-go/mcp"
2021
"github.com/mark3labs/mcp-go/server"
@@ -113,26 +114,22 @@ func NewMCPServer(cfg MCPServerConfig) (*server.MCPServer, error) {
113114
}
114115

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

127124
context := github.InitContextToolset(getClient, cfg.Translator)
128125
github.RegisterResources(ghServer, getClient, cfg.Translator)
129126

130127
// Register the tools with the server
131-
toolsets.RegisterTools(ghServer)
128+
tsg.RegisterTools(ghServer)
132129
context.RegisterTools(ghServer)
133130

134131
if cfg.DynamicToolsets {
135-
dynamic := github.InitDynamicToolset(ghServer, toolsets, cfg.Translator)
132+
dynamic := github.InitDynamicToolset(ghServer, tsg, cfg.Translator)
136133
dynamic.RegisterTools(ghServer)
137134
}
138135

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: 33 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,13 @@ 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+
toolset.Enabled = true
194+
tg.Toolsets[name] = toolset
195+
return toolset, nil
196+
}

pkg/toolsets/toolsets_test.go

Lines changed: 4 additions & 0 deletions
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{})

third-party-licenses.darwin.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ Some packages may only be included on certain architectures or operating systems
99

1010
- [github.com/fsnotify/fsnotify](https://pkg.go.dev/github.com/fsnotify/fsnotify) ([BSD-3-Clause](https://github.com/fsnotify/fsnotify/blob/v1.8.0/LICENSE))
1111
- [github.com/github/github-mcp-server](https://pkg.go.dev/github.com/github/github-mcp-server) ([MIT](https://github.com/github/github-mcp-server/blob/HEAD/LICENSE))
12+
- [github.com/go-errors/errors](https://pkg.go.dev/github.com/go-errors/errors) ([MIT](https://github.com/go-errors/errors/blob/v1.5.1/LICENSE.MIT))
1213
- [github.com/go-openapi/jsonpointer](https://pkg.go.dev/github.com/go-openapi/jsonpointer) ([Apache-2.0](https://github.com/go-openapi/jsonpointer/blob/v0.19.5/LICENSE))
1314
- [github.com/go-openapi/swag](https://pkg.go.dev/github.com/go-openapi/swag) ([Apache-2.0](https://github.com/go-openapi/swag/blob/v0.21.1/LICENSE))
1415
- [github.com/go-viper/mapstructure/v2](https://pkg.go.dev/github.com/go-viper/mapstructure/v2) ([MIT](https://github.com/go-viper/mapstructure/blob/v2.2.1/LICENSE))

third-party-licenses.linux.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ Some packages may only be included on certain architectures or operating systems
99

1010
- [github.com/fsnotify/fsnotify](https://pkg.go.dev/github.com/fsnotify/fsnotify) ([BSD-3-Clause](https://github.com/fsnotify/fsnotify/blob/v1.8.0/LICENSE))
1111
- [github.com/github/github-mcp-server](https://pkg.go.dev/github.com/github/github-mcp-server) ([MIT](https://github.com/github/github-mcp-server/blob/HEAD/LICENSE))
12+
- [github.com/go-errors/errors](https://pkg.go.dev/github.com/go-errors/errors) ([MIT](https://github.com/go-errors/errors/blob/v1.5.1/LICENSE.MIT))
1213
- [github.com/go-openapi/jsonpointer](https://pkg.go.dev/github.com/go-openapi/jsonpointer) ([Apache-2.0](https://github.com/go-openapi/jsonpointer/blob/v0.19.5/LICENSE))
1314
- [github.com/go-openapi/swag](https://pkg.go.dev/github.com/go-openapi/swag) ([Apache-2.0](https://github.com/go-openapi/swag/blob/v0.21.1/LICENSE))
1415
- [github.com/go-viper/mapstructure/v2](https://pkg.go.dev/github.com/go-viper/mapstructure/v2) ([MIT](https://github.com/go-viper/mapstructure/blob/v2.2.1/LICENSE))

third-party-licenses.windows.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ Some packages may only be included on certain architectures or operating systems
99

1010
- [github.com/fsnotify/fsnotify](https://pkg.go.dev/github.com/fsnotify/fsnotify) ([BSD-3-Clause](https://github.com/fsnotify/fsnotify/blob/v1.8.0/LICENSE))
1111
- [github.com/github/github-mcp-server](https://pkg.go.dev/github.com/github/github-mcp-server) ([MIT](https://github.com/github/github-mcp-server/blob/HEAD/LICENSE))
12+
- [github.com/go-errors/errors](https://pkg.go.dev/github.com/go-errors/errors) ([MIT](https://github.com/go-errors/errors/blob/v1.5.1/LICENSE.MIT))
1213
- [github.com/go-openapi/jsonpointer](https://pkg.go.dev/github.com/go-openapi/jsonpointer) ([Apache-2.0](https://github.com/go-openapi/jsonpointer/blob/v0.19.5/LICENSE))
1314
- [github.com/go-openapi/swag](https://pkg.go.dev/github.com/go-openapi/swag) ([Apache-2.0](https://github.com/go-openapi/swag/blob/v0.21.1/LICENSE))
1415
- [github.com/go-viper/mapstructure/v2](https://pkg.go.dev/github.com/go-viper/mapstructure/v2) ([MIT](https://github.com/go-viper/mapstructure/blob/v2.2.1/LICENSE))
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
Copyright (c) 2015 Conrad Irwin <[email protected]>
2+
3+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4+
5+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6+
7+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

0 commit comments

Comments
 (0)