Skip to content

Commit b3442e1

Browse files
Copilotomgitsads
andcommitted
Migrate dependabot toolset to Go SDK
Co-authored-by: omgitsads <[email protected]>
1 parent 8e36d65 commit b3442e1

File tree

5 files changed

+488
-38
lines changed

5 files changed

+488
-38
lines changed
Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,30 @@
11
{
22
"annotations": {
3-
"title": "Get dependabot alert",
4-
"readOnlyHint": true
3+
"readOnlyHint": true,
4+
"title": "Get dependabot alert"
55
},
66
"description": "Get details of a specific dependabot alert in a GitHub repository.",
77
"inputSchema": {
8+
"type": "object",
9+
"required": [
10+
"owner",
11+
"repo",
12+
"alertNumber"
13+
],
814
"properties": {
915
"alertNumber": {
10-
"description": "The number of the alert.",
11-
"type": "number"
16+
"type": "number",
17+
"description": "The number of the alert."
1218
},
1319
"owner": {
14-
"description": "The owner of the repository.",
15-
"type": "string"
20+
"type": "string",
21+
"description": "The owner of the repository."
1622
},
1723
"repo": {
18-
"description": "The name of the repository.",
19-
"type": "string"
24+
"type": "string",
25+
"description": "The name of the repository."
2026
}
21-
},
22-
"required": [
23-
"owner",
24-
"repo",
25-
"alertNumber"
26-
],
27-
"type": "object"
27+
}
2828
},
2929
"name": "get_dependabot_alert"
3030
}
Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,46 @@
11
{
22
"annotations": {
3-
"title": "List dependabot alerts",
4-
"readOnlyHint": true
3+
"readOnlyHint": true,
4+
"title": "List dependabot alerts"
55
},
66
"description": "List dependabot alerts in a GitHub repository.",
77
"inputSchema": {
8+
"type": "object",
9+
"required": [
10+
"owner",
11+
"repo"
12+
],
813
"properties": {
914
"owner": {
10-
"description": "The owner of the repository.",
11-
"type": "string"
15+
"type": "string",
16+
"description": "The owner of the repository."
1217
},
1318
"repo": {
14-
"description": "The name of the repository.",
15-
"type": "string"
19+
"type": "string",
20+
"description": "The name of the repository."
1621
},
1722
"severity": {
23+
"type": "string",
1824
"description": "Filter dependabot alerts by severity",
1925
"enum": [
2026
"low",
2127
"medium",
2228
"high",
2329
"critical"
24-
],
25-
"type": "string"
30+
]
2631
},
2732
"state": {
28-
"default": "open",
33+
"type": "string",
2934
"description": "Filter dependabot alerts by state. Defaults to open",
35+
"default": "open",
3036
"enum": [
3137
"open",
3238
"fixed",
3339
"dismissed",
3440
"auto_dismissed"
35-
],
36-
"type": "string"
41+
]
3742
}
38-
},
39-
"required": [
40-
"owner",
41-
"repo"
42-
],
43-
"type": "object"
43+
}
4444
},
4545
"name": "list_dependabot_alerts"
4646
}

pkg/github/dependabot.go

Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
package github
2+
3+
import (
4+
"context"
5+
"encoding/json"
6+
"fmt"
7+
"io"
8+
"net/http"
9+
10+
ghErrors "github.com/github/github-mcp-server/pkg/errors"
11+
"github.com/github/github-mcp-server/pkg/translations"
12+
"github.com/github/github-mcp-server/pkg/utils"
13+
"github.com/google/go-github/v77/github"
14+
"github.com/google/jsonschema-go/jsonschema"
15+
"github.com/modelcontextprotocol/go-sdk/mcp"
16+
)
17+
18+
func GetDependabotAlert(getClient GetClientFn, t translations.TranslationHelperFunc) (mcp.Tool, mcp.ToolHandlerFor[map[string]any, any]) {
19+
tool := 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{
23+
Title: t("TOOL_GET_DEPENDABOT_ALERT_USER_TITLE", "Get dependabot alert"),
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+
46+
handler := mcp.ToolHandlerFor[map[string]any, any](func(ctx context.Context, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) {
47+
owner, err := RequiredParam[string](args, "owner")
48+
if err != nil {
49+
return utils.NewToolResultError(err.Error()), nil, nil
50+
}
51+
repo, err := RequiredParam[string](args, "repo")
52+
if err != nil {
53+
return utils.NewToolResultError(err.Error()), nil, nil
54+
}
55+
alertNumber, err := RequiredInt(args, "alertNumber")
56+
if err != nil {
57+
return utils.NewToolResultError(err.Error()), nil, nil
58+
}
59+
60+
client, err := getClient(ctx)
61+
if err != nil {
62+
return nil, nil, fmt.Errorf("failed to get GitHub client: %w", err)
63+
}
64+
65+
alert, resp, err := client.Dependabot.GetRepoAlert(ctx, owner, repo, alertNumber)
66+
if err != nil {
67+
return ghErrors.NewGitHubAPIErrorResponse(ctx,
68+
fmt.Sprintf("failed to get alert with number '%d'", alertNumber),
69+
resp,
70+
err,
71+
), nil, nil
72+
}
73+
defer func() { _ = resp.Body.Close() }()
74+
75+
if resp.StatusCode != http.StatusOK {
76+
body, err := io.ReadAll(resp.Body)
77+
if err != nil {
78+
return nil, nil, fmt.Errorf("failed to read response body: %w", err)
79+
}
80+
return utils.NewToolResultError(fmt.Sprintf("failed to get alert: %s", string(body))), nil, nil
81+
}
82+
83+
r, err := json.Marshal(alert)
84+
if err != nil {
85+
return nil, nil, fmt.Errorf("failed to marshal alert: %w", err)
86+
}
87+
88+
return utils.NewToolResultText(string(r)), nil, nil
89+
})
90+
91+
return tool, handler
92+
}
93+
94+
func ListDependabotAlerts(getClient GetClientFn, t translations.TranslationHelperFunc) (mcp.Tool, mcp.ToolHandlerFor[map[string]any, any]) {
95+
tool := mcp.Tool{
96+
Name: "list_dependabot_alerts",
97+
Description: t("TOOL_LIST_DEPENDABOT_ALERTS_DESCRIPTION", "List dependabot alerts in a GitHub repository."),
98+
Annotations: &mcp.ToolAnnotations{
99+
Title: t("TOOL_LIST_DEPENDABOT_ALERTS_USER_TITLE", "List dependabot alerts"),
100+
ReadOnlyHint: true,
101+
},
102+
InputSchema: &jsonschema.Schema{
103+
Type: "object",
104+
Properties: map[string]*jsonschema.Schema{
105+
"owner": {
106+
Type: "string",
107+
Description: "The owner of the repository.",
108+
},
109+
"repo": {
110+
Type: "string",
111+
Description: "The name of the repository.",
112+
},
113+
"state": {
114+
Type: "string",
115+
Description: "Filter dependabot alerts by state. Defaults to open",
116+
Enum: []any{"open", "fixed", "dismissed", "auto_dismissed"},
117+
Default: json.RawMessage(`"open"`),
118+
},
119+
"severity": {
120+
Type: "string",
121+
Description: "Filter dependabot alerts by severity",
122+
Enum: []any{"low", "medium", "high", "critical"},
123+
},
124+
},
125+
Required: []string{"owner", "repo"},
126+
},
127+
}
128+
129+
handler := mcp.ToolHandlerFor[map[string]any, any](func(ctx context.Context, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) {
130+
owner, err := RequiredParam[string](args, "owner")
131+
if err != nil {
132+
return utils.NewToolResultError(err.Error()), nil, nil
133+
}
134+
repo, err := RequiredParam[string](args, "repo")
135+
if err != nil {
136+
return utils.NewToolResultError(err.Error()), nil, nil
137+
}
138+
state, err := OptionalParam[string](args, "state")
139+
if err != nil {
140+
return utils.NewToolResultError(err.Error()), nil, nil
141+
}
142+
severity, err := OptionalParam[string](args, "severity")
143+
if err != nil {
144+
return utils.NewToolResultError(err.Error()), nil, nil
145+
}
146+
147+
client, err := getClient(ctx)
148+
if err != nil {
149+
return nil, nil, fmt.Errorf("failed to get GitHub client: %w", err)
150+
}
151+
152+
alerts, resp, err := client.Dependabot.ListRepoAlerts(ctx, owner, repo, &github.ListAlertsOptions{
153+
State: ToStringPtr(state),
154+
Severity: ToStringPtr(severity),
155+
})
156+
if err != nil {
157+
return ghErrors.NewGitHubAPIErrorResponse(ctx,
158+
fmt.Sprintf("failed to list alerts for repository '%s/%s'", owner, repo),
159+
resp,
160+
err,
161+
), nil, nil
162+
}
163+
defer func() { _ = resp.Body.Close() }()
164+
165+
if resp.StatusCode != http.StatusOK {
166+
body, err := io.ReadAll(resp.Body)
167+
if err != nil {
168+
return nil, nil, fmt.Errorf("failed to read response body: %w", err)
169+
}
170+
return utils.NewToolResultError(fmt.Sprintf("failed to list alerts: %s", string(body))), nil, nil
171+
}
172+
173+
r, err := json.Marshal(alerts)
174+
if err != nil {
175+
return nil, nil, fmt.Errorf("failed to marshal alerts: %w", err)
176+
}
177+
178+
return utils.NewToolResultText(string(r)), nil, nil
179+
})
180+
181+
return tool, handler
182+
}

0 commit comments

Comments
 (0)