Skip to content

Commit 5f2f192

Browse files
Add tests for dynamic toolset management tools
Tests cover: - list_available_toolsets: verifies toolsets are listed with enabled status - get_toolset_tools: verifies tools can be retrieved for a toolset - enable_toolset: verifies toolset can be enabled and marked as enabled - enable_toolset invalid: verifies proper error for non-existent toolset - toolsets enum: verifies tools have proper enum values in schema
1 parent 315122e commit 5f2f192

File tree

1 file changed

+231
-0
lines changed

1 file changed

+231
-0
lines changed

pkg/github/dynamic_tools_test.go

Lines changed: 231 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,231 @@
1+
package github
2+
3+
import (
4+
"context"
5+
"encoding/json"
6+
"testing"
7+
8+
"github.com/github/github-mcp-server/pkg/registry"
9+
"github.com/github/github-mcp-server/pkg/translations"
10+
"github.com/google/jsonschema-go/jsonschema"
11+
"github.com/modelcontextprotocol/go-sdk/mcp"
12+
"github.com/stretchr/testify/assert"
13+
"github.com/stretchr/testify/require"
14+
)
15+
16+
// createDynamicRequest creates an MCP request with the given arguments for dynamic tools.
17+
func createDynamicRequest(args map[string]any) *mcp.CallToolRequest {
18+
argsJSON, _ := json.Marshal(args)
19+
return &mcp.CallToolRequest{
20+
Params: &mcp.CallToolParamsRaw{
21+
Arguments: json.RawMessage(argsJSON),
22+
},
23+
}
24+
}
25+
26+
func TestDynamicTools_ListAvailableToolsets(t *testing.T) {
27+
// Build a registry with no toolsets enabled (dynamic mode)
28+
reg := NewRegistry(translations.NullTranslationHelper).
29+
WithToolsets([]string{}).
30+
Build()
31+
32+
// Create a mock server
33+
server := mcp.NewServer(&mcp.Implementation{Name: "test"}, nil)
34+
35+
// Create dynamic tool dependencies
36+
deps := DynamicToolDependencies{
37+
Server: server,
38+
Registry: reg,
39+
ToolDeps: nil,
40+
T: translations.NullTranslationHelper,
41+
}
42+
43+
// Get the list_available_toolsets tool
44+
tool := ListAvailableToolsets()
45+
handler := tool.Handler(deps)
46+
47+
// Call the handler
48+
result, err := handler(context.Background(), createDynamicRequest(map[string]any{}))
49+
require.NoError(t, err)
50+
require.NotNil(t, result)
51+
require.Len(t, result.Content, 1)
52+
53+
// Parse the result
54+
var toolsets []map[string]string
55+
textContent := result.Content[0].(*mcp.TextContent)
56+
err = json.Unmarshal([]byte(textContent.Text), &toolsets)
57+
require.NoError(t, err)
58+
59+
// Verify we got toolsets
60+
assert.NotEmpty(t, toolsets, "should have available toolsets")
61+
62+
// Find the repos toolset and verify it's not enabled
63+
var reposToolset map[string]string
64+
for _, ts := range toolsets {
65+
if ts["name"] == "repos" {
66+
reposToolset = ts
67+
break
68+
}
69+
}
70+
require.NotNil(t, reposToolset, "repos toolset should exist")
71+
assert.Equal(t, "false", reposToolset["currently_enabled"], "repos should not be enabled initially")
72+
}
73+
74+
func TestDynamicTools_GetToolsetTools(t *testing.T) {
75+
// Build a registry with no toolsets enabled (dynamic mode)
76+
reg := NewRegistry(translations.NullTranslationHelper).
77+
WithToolsets([]string{}).
78+
Build()
79+
80+
// Create a mock server
81+
server := mcp.NewServer(&mcp.Implementation{Name: "test"}, nil)
82+
83+
// Create dynamic tool dependencies
84+
deps := DynamicToolDependencies{
85+
Server: server,
86+
Registry: reg,
87+
ToolDeps: nil,
88+
T: translations.NullTranslationHelper,
89+
}
90+
91+
// Get the get_toolset_tools tool
92+
tool := GetToolsetsTools(reg)
93+
handler := tool.Handler(deps)
94+
95+
// Call the handler for repos toolset
96+
result, err := handler(context.Background(), createDynamicRequest(map[string]any{
97+
"toolset": "repos",
98+
}))
99+
require.NoError(t, err)
100+
require.NotNil(t, result)
101+
require.Len(t, result.Content, 1)
102+
103+
// Parse the result
104+
var tools []map[string]string
105+
textContent := result.Content[0].(*mcp.TextContent)
106+
err = json.Unmarshal([]byte(textContent.Text), &tools)
107+
require.NoError(t, err)
108+
109+
// Verify we got tools for the repos toolset
110+
assert.NotEmpty(t, tools, "repos toolset should have tools")
111+
112+
// Verify at least get_commit is there (a repos toolset tool)
113+
var foundGetCommit bool
114+
for _, tool := range tools {
115+
if tool["name"] == "get_commit" {
116+
foundGetCommit = true
117+
break
118+
}
119+
}
120+
assert.True(t, foundGetCommit, "get_commit should be in repos toolset")
121+
}
122+
123+
func TestDynamicTools_EnableToolset(t *testing.T) {
124+
// Build a registry with no toolsets enabled (dynamic mode)
125+
reg := NewRegistry(translations.NullTranslationHelper).
126+
WithToolsets([]string{}).
127+
Build()
128+
129+
// Create a mock server
130+
server := mcp.NewServer(&mcp.Implementation{Name: "test"}, nil)
131+
132+
// Create dynamic tool dependencies
133+
deps := DynamicToolDependencies{
134+
Server: server,
135+
Registry: reg,
136+
ToolDeps: NewBaseDeps(nil, nil, nil, nil, translations.NullTranslationHelper, FeatureFlags{}, 0),
137+
T: translations.NullTranslationHelper,
138+
}
139+
140+
// Verify repos is not enabled initially
141+
assert.False(t, reg.IsToolsetEnabled(registry.ToolsetID("repos")))
142+
143+
// Get the enable_toolset tool
144+
tool := EnableToolset(reg)
145+
handler := tool.Handler(deps)
146+
147+
// Enable the repos toolset
148+
result, err := handler(context.Background(), createDynamicRequest(map[string]any{
149+
"toolset": "repos",
150+
}))
151+
require.NoError(t, err)
152+
require.NotNil(t, result)
153+
require.Len(t, result.Content, 1)
154+
155+
// Verify the toolset is now enabled
156+
assert.True(t, reg.IsToolsetEnabled(registry.ToolsetID("repos")), "repos should be enabled after enable_toolset")
157+
158+
// Verify the success message
159+
textContent := result.Content[0].(*mcp.TextContent)
160+
assert.Contains(t, textContent.Text, "enabled")
161+
162+
// Try enabling again - should say already enabled
163+
result2, err := handler(context.Background(), createDynamicRequest(map[string]any{
164+
"toolset": "repos",
165+
}))
166+
require.NoError(t, err)
167+
textContent2 := result2.Content[0].(*mcp.TextContent)
168+
assert.Contains(t, textContent2.Text, "already enabled")
169+
}
170+
171+
func TestDynamicTools_EnableToolset_InvalidToolset(t *testing.T) {
172+
// Build a registry with no toolsets enabled (dynamic mode)
173+
reg := NewRegistry(translations.NullTranslationHelper).
174+
WithToolsets([]string{}).
175+
Build()
176+
177+
// Create a mock server
178+
server := mcp.NewServer(&mcp.Implementation{Name: "test"}, nil)
179+
180+
// Create dynamic tool dependencies
181+
deps := DynamicToolDependencies{
182+
Server: server,
183+
Registry: reg,
184+
ToolDeps: nil,
185+
T: translations.NullTranslationHelper,
186+
}
187+
188+
// Get the enable_toolset tool
189+
tool := EnableToolset(reg)
190+
handler := tool.Handler(deps)
191+
192+
// Try to enable a non-existent toolset
193+
result, err := handler(context.Background(), createDynamicRequest(map[string]any{
194+
"toolset": "nonexistent",
195+
}))
196+
require.NoError(t, err)
197+
require.NotNil(t, result)
198+
199+
// Should be an error result
200+
textContent := result.Content[0].(*mcp.TextContent)
201+
assert.Contains(t, textContent.Text, "not found")
202+
}
203+
204+
func TestDynamicTools_ToolsetsEnum(t *testing.T) {
205+
// Build a registry
206+
reg := NewRegistry(translations.NullTranslationHelper).Build()
207+
208+
// Get tools to verify they have proper enum values
209+
tools := DynamicTools(reg)
210+
211+
// Find enable_toolset and get_toolset_tools
212+
for _, tool := range tools {
213+
if tool.Tool.Name == "enable_toolset" || tool.Tool.Name == "get_toolset_tools" {
214+
// Verify the toolset property has an enum
215+
schema := tool.Tool.InputSchema.(*jsonschema.Schema)
216+
toolsetProp := schema.Properties["toolset"]
217+
require.NotNil(t, toolsetProp, "toolset property should exist")
218+
assert.NotEmpty(t, toolsetProp.Enum, "toolset property should have enum values")
219+
220+
// Verify repos is in the enum
221+
var foundRepos bool
222+
for _, v := range toolsetProp.Enum {
223+
if v == registry.ToolsetID("repos") {
224+
foundRepos = true
225+
break
226+
}
227+
}
228+
assert.True(t, foundRepos, "repos should be in toolset enum for %s", tool.Tool.Name)
229+
}
230+
}
231+
}

0 commit comments

Comments
 (0)