Skip to content

Commit 06440fd

Browse files
Copilotomgitsads
andcommitted
Migrate Dependabot toolset to modelcontextprotocol/go-sdk
Co-authored-by: omgitsads <[email protected]>
1 parent a6896be commit 06440fd

File tree

2 files changed

+92
-90
lines changed

2 files changed

+92
-90
lines changed

pkg/github/dependabot.go

Lines changed: 90 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
//go:build ignore
2-
31
package github
42

53
import (
@@ -11,49 +9,56 @@ import (
119

1210
ghErrors "github.com/github/github-mcp-server/pkg/errors"
1311
"github.com/github/github-mcp-server/pkg/translations"
12+
"github.com/github/github-mcp-server/pkg/utils"
1413
"github.com/google/go-github/v77/github"
15-
"github.com/mark3labs/mcp-go/mcp"
16-
"github.com/mark3labs/mcp-go/server"
14+
"github.com/google/jsonschema-go/jsonschema"
15+
"github.com/modelcontextprotocol/go-sdk/mcp"
1716
)
1817

19-
func GetDependabotAlert(getClient GetClientFn, t translations.TranslationHelperFunc) (tool mcp.Tool, handler server.ToolHandlerFunc) {
20-
return mcp.NewTool(
21-
"get_dependabot_alert",
22-
mcp.WithDescription(t("TOOL_GET_DEPENDABOT_ALERT_DESCRIPTION", "Get details of a specific dependabot alert in a GitHub repository.")),
23-
mcp.WithToolAnnotation(mcp.ToolAnnotation{
18+
func GetDependabotAlert(getClient GetClientFn, t translations.TranslationHelperFunc) (tool mcp.Tool, handler mcp.ToolHandlerFor[map[string]any, any]) {
19+
return mcp.Tool{
20+
Name: "get_dependabot_alert",
21+
Description: t("TOOL_GET_DEPENDABOT_ALERT_DESCRIPTION", "Get details of a specific dependabot alert in a GitHub repository."),
22+
Annotations: &mcp.ToolAnnotations{
2423
Title: t("TOOL_GET_DEPENDABOT_ALERT_USER_TITLE", "Get dependabot alert"),
25-
ReadOnlyHint: ToBoolPtr(true),
26-
}),
27-
mcp.WithString("owner",
28-
mcp.Required(),
29-
mcp.Description("The owner of the repository."),
30-
),
31-
mcp.WithString("repo",
32-
mcp.Required(),
33-
mcp.Description("The name of the repository."),
34-
),
35-
mcp.WithNumber("alertNumber",
36-
mcp.Required(),
37-
mcp.Description("The number of the alert."),
38-
),
39-
),
40-
func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
41-
owner, err := RequiredParam[string](request, "owner")
24+
ReadOnlyHint: true,
25+
},
26+
InputSchema: &jsonschema.Schema{
27+
Type: "object",
28+
Properties: map[string]*jsonschema.Schema{
29+
"owner": {
30+
Type: "string",
31+
Description: "The owner of the repository.",
32+
},
33+
"repo": {
34+
Type: "string",
35+
Description: "The name of the repository.",
36+
},
37+
"alertNumber": {
38+
Type: "number",
39+
Description: "The number of the alert.",
40+
},
41+
},
42+
Required: []string{"owner", "repo", "alertNumber"},
43+
},
44+
},
45+
func(ctx context.Context, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) {
46+
owner, err := RequiredParam[string](args, "owner")
4247
if err != nil {
43-
return mcp.NewToolResultError(err.Error()), nil
48+
return utils.NewToolResultError(err.Error()), nil, nil
4449
}
45-
repo, err := RequiredParam[string](request, "repo")
50+
repo, err := RequiredParam[string](args, "repo")
4651
if err != nil {
47-
return mcp.NewToolResultError(err.Error()), nil
52+
return utils.NewToolResultError(err.Error()), nil, nil
4853
}
49-
alertNumber, err := RequiredInt(request, "alertNumber")
54+
alertNumber, err := RequiredInt(args, "alertNumber")
5055
if err != nil {
51-
return mcp.NewToolResultError(err.Error()), nil
56+
return utils.NewToolResultError(err.Error()), nil, nil
5257
}
5358

5459
client, err := getClient(ctx)
5560
if err != nil {
56-
return nil, fmt.Errorf("failed to get GitHub client: %w", err)
61+
return utils.NewToolResultErrorFromErr("failed to get GitHub client", err), nil, err
5762
}
5863

5964
alert, resp, err := client.Dependabot.GetRepoAlert(ctx, owner, repo, alertNumber)
@@ -62,74 +67,82 @@ func GetDependabotAlert(getClient GetClientFn, t translations.TranslationHelperF
6267
fmt.Sprintf("failed to get alert with number '%d'", alertNumber),
6368
resp,
6469
err,
65-
), nil
70+
), nil, nil
6671
}
6772
defer func() { _ = resp.Body.Close() }()
6873

6974
if resp.StatusCode != http.StatusOK {
7075
body, err := io.ReadAll(resp.Body)
7176
if err != nil {
72-
return nil, fmt.Errorf("failed to read response body: %w", err)
77+
return utils.NewToolResultErrorFromErr("failed to read response body", err), nil, err
7378
}
74-
return mcp.NewToolResultError(fmt.Sprintf("failed to get alert: %s", string(body))), nil
79+
return utils.NewToolResultError(fmt.Sprintf("failed to get alert: %s", string(body))), nil, nil
7580
}
7681

7782
r, err := json.Marshal(alert)
7883
if err != nil {
79-
return nil, fmt.Errorf("failed to marshal alert: %w", err)
84+
return utils.NewToolResultErrorFromErr("failed to marshal alert", err), nil, err
8085
}
8186

82-
return mcp.NewToolResultText(string(r)), nil
87+
return utils.NewToolResultText(string(r)), nil, nil
8388
}
8489
}
8590

86-
func ListDependabotAlerts(getClient GetClientFn, t translations.TranslationHelperFunc) (tool mcp.Tool, handler server.ToolHandlerFunc) {
87-
return mcp.NewTool(
88-
"list_dependabot_alerts",
89-
mcp.WithDescription(t("TOOL_LIST_DEPENDABOT_ALERTS_DESCRIPTION", "List dependabot alerts in a GitHub repository.")),
90-
mcp.WithToolAnnotation(mcp.ToolAnnotation{
91+
func ListDependabotAlerts(getClient GetClientFn, t translations.TranslationHelperFunc) (tool mcp.Tool, handler mcp.ToolHandlerFor[map[string]any, any]) {
92+
return mcp.Tool{
93+
Name: "list_dependabot_alerts",
94+
Description: t("TOOL_LIST_DEPENDABOT_ALERTS_DESCRIPTION", "List dependabot alerts in a GitHub repository."),
95+
Annotations: &mcp.ToolAnnotations{
9196
Title: t("TOOL_LIST_DEPENDABOT_ALERTS_USER_TITLE", "List dependabot alerts"),
92-
ReadOnlyHint: ToBoolPtr(true),
93-
}),
94-
mcp.WithString("owner",
95-
mcp.Required(),
96-
mcp.Description("The owner of the repository."),
97-
),
98-
mcp.WithString("repo",
99-
mcp.Required(),
100-
mcp.Description("The name of the repository."),
101-
),
102-
mcp.WithString("state",
103-
mcp.Description("Filter dependabot alerts by state. Defaults to open"),
104-
mcp.DefaultString("open"),
105-
mcp.Enum("open", "fixed", "dismissed", "auto_dismissed"),
106-
),
107-
mcp.WithString("severity",
108-
mcp.Description("Filter dependabot alerts by severity"),
109-
mcp.Enum("low", "medium", "high", "critical"),
110-
),
111-
),
112-
func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
113-
owner, err := RequiredParam[string](request, "owner")
97+
ReadOnlyHint: true,
98+
},
99+
InputSchema: &jsonschema.Schema{
100+
Type: "object",
101+
Properties: map[string]*jsonschema.Schema{
102+
"owner": {
103+
Type: "string",
104+
Description: "The owner of the repository.",
105+
},
106+
"repo": {
107+
Type: "string",
108+
Description: "The name of the repository.",
109+
},
110+
"state": {
111+
Type: "string",
112+
Description: "Filter dependabot alerts by state. Defaults to open",
113+
Enum: []any{"open", "fixed", "dismissed", "auto_dismissed"},
114+
Default: json.RawMessage(`"open"`),
115+
},
116+
"severity": {
117+
Type: "string",
118+
Description: "Filter dependabot alerts by severity",
119+
Enum: []any{"low", "medium", "high", "critical"},
120+
},
121+
},
122+
Required: []string{"owner", "repo"},
123+
},
124+
},
125+
func(ctx context.Context, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) {
126+
owner, err := RequiredParam[string](args, "owner")
114127
if err != nil {
115-
return mcp.NewToolResultError(err.Error()), nil
128+
return utils.NewToolResultError(err.Error()), nil, nil
116129
}
117-
repo, err := RequiredParam[string](request, "repo")
130+
repo, err := RequiredParam[string](args, "repo")
118131
if err != nil {
119-
return mcp.NewToolResultError(err.Error()), nil
132+
return utils.NewToolResultError(err.Error()), nil, nil
120133
}
121-
state, err := OptionalParam[string](request, "state")
134+
state, err := OptionalParam[string](args, "state")
122135
if err != nil {
123-
return mcp.NewToolResultError(err.Error()), nil
136+
return utils.NewToolResultError(err.Error()), nil, nil
124137
}
125-
severity, err := OptionalParam[string](request, "severity")
138+
severity, err := OptionalParam[string](args, "severity")
126139
if err != nil {
127-
return mcp.NewToolResultError(err.Error()), nil
140+
return utils.NewToolResultError(err.Error()), nil, nil
128141
}
129142

130143
client, err := getClient(ctx)
131144
if err != nil {
132-
return nil, fmt.Errorf("failed to get GitHub client: %w", err)
145+
return utils.NewToolResultErrorFromErr("failed to get GitHub client", err), nil, err
133146
}
134147

135148
alerts, resp, err := client.Dependabot.ListRepoAlerts(ctx, owner, repo, &github.ListAlertsOptions{
@@ -141,23 +154,23 @@ func ListDependabotAlerts(getClient GetClientFn, t translations.TranslationHelpe
141154
fmt.Sprintf("failed to list alerts for repository '%s/%s'", owner, repo),
142155
resp,
143156
err,
144-
), nil
157+
), nil, nil
145158
}
146159
defer func() { _ = resp.Body.Close() }()
147160

148161
if resp.StatusCode != http.StatusOK {
149162
body, err := io.ReadAll(resp.Body)
150163
if err != nil {
151-
return nil, fmt.Errorf("failed to read response body: %w", err)
164+
return utils.NewToolResultErrorFromErr("failed to read response body", err), nil, err
152165
}
153-
return mcp.NewToolResultError(fmt.Sprintf("failed to list alerts: %s", string(body))), nil
166+
return utils.NewToolResultError(fmt.Sprintf("failed to list alerts: %s", string(body))), nil, nil
154167
}
155168

156169
r, err := json.Marshal(alerts)
157170
if err != nil {
158-
return nil, fmt.Errorf("failed to marshal alerts: %w", err)
171+
return utils.NewToolResultErrorFromErr("failed to marshal alerts", err), nil, err
159172
}
160173

161-
return mcp.NewToolResultText(string(r)), nil
174+
return utils.NewToolResultText(string(r)), nil, nil
162175
}
163176
}

pkg/github/dependabot_test.go

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
//go:build ignore
2-
31
package github
42

53
import (
@@ -25,10 +23,6 @@ func Test_GetDependabotAlert(t *testing.T) {
2523
// Validate tool schema
2624
assert.Equal(t, "get_dependabot_alert", tool.Name)
2725
assert.NotEmpty(t, tool.Description)
28-
assert.Contains(t, tool.InputSchema.Properties, "owner")
29-
assert.Contains(t, tool.InputSchema.Properties, "repo")
30-
assert.Contains(t, tool.InputSchema.Properties, "alertNumber")
31-
assert.ElementsMatch(t, tool.InputSchema.Required, []string{"owner", "repo", "alertNumber"})
3226

3327
// Setup mock alert for success case
3428
mockAlert := &github.DependabotAlert{
@@ -92,7 +86,7 @@ func Test_GetDependabotAlert(t *testing.T) {
9286
request := createMCPRequest(tc.requestArgs)
9387

9488
// Call handler
95-
result, err := handler(context.Background(), request)
89+
result, _, err := handler(context.Background(), &request, tc.requestArgs)
9690

9791
// Verify results
9892
if tc.expectError {
@@ -128,11 +122,6 @@ func Test_ListDependabotAlerts(t *testing.T) {
128122

129123
assert.Equal(t, "list_dependabot_alerts", tool.Name)
130124
assert.NotEmpty(t, tool.Description)
131-
assert.Contains(t, tool.InputSchema.Properties, "owner")
132-
assert.Contains(t, tool.InputSchema.Properties, "repo")
133-
assert.Contains(t, tool.InputSchema.Properties, "state")
134-
assert.Contains(t, tool.InputSchema.Properties, "severity")
135-
assert.ElementsMatch(t, tool.InputSchema.Required, []string{"owner", "repo"})
136125

137126
// Setup mock alerts for success case
138127
criticalAlert := github.DependabotAlert{
@@ -244,7 +233,7 @@ func Test_ListDependabotAlerts(t *testing.T) {
244233

245234
request := createMCPRequest(tc.requestArgs)
246235

247-
result, err := handler(context.Background(), request)
236+
result, _, err := handler(context.Background(), &request, tc.requestArgs)
248237

249238
if tc.expectError {
250239
require.NoError(t, err)

0 commit comments

Comments
 (0)