Files
github--github-mcp-server/pkg/github/code_scanning.go
William Martin 4df2d3d803
Unit Tests / build (macos-latest) (push) Has been cancelled
Unit Tests / build (ubuntu-latest) (push) Has been cancelled
Unit Tests / build (windows-latest) (push) Has been cancelled
License Check / license-check (push) Has been cancelled
CodeQL / Analyze (go) (push) Has been cancelled
CodeQL / Analyze (actions) (push) Has been cancelled
Lint / lint (push) Has been cancelled
WIP: schema generation
2025-04-11 22:20:59 +02:00

158 lines
5.0 KiB
Go

package github
import (
"context"
"encoding/json"
"fmt"
"io"
"net/http"
"github.com/github/github-mcp-server/pkg/translations"
"github.com/google/go-github/v69/github"
"github.com/mark3labs/mcp-go/mcp"
"github.com/mark3labs/mcp-go/server"
)
func GetCodeScanningAlert(t translations.TranslationHelperFunc) Tool {
return Tool{
Definition: mcp.NewTool(
"get_code_scanning_alert",
mcp.WithDescription(t("TOOL_GET_CODE_SCANNING_ALERT_DESCRIPTION", "Get details of a specific code scanning alert in a GitHub repository.")),
mcp.WithString("owner",
mcp.Required(),
mcp.Description("The owner of the repository."),
),
mcp.WithString("repo",
mcp.Required(),
mcp.Description("The name of the repository."),
),
mcp.WithNumber("alertNumber",
mcp.Required(),
mcp.Description("The number of the alert."),
),
),
Handler: func(getClient GetClientFn) server.ToolHandlerFunc {
return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
owner, err := requiredParam[string](request, "owner")
if err != nil {
return mcp.NewToolResultError(err.Error()), nil
}
repo, err := requiredParam[string](request, "repo")
if err != nil {
return mcp.NewToolResultError(err.Error()), nil
}
alertNumber, err := RequiredInt(request, "alertNumber")
if err != nil {
return mcp.NewToolResultError(err.Error()), nil
}
client, err := getClient(ctx)
if err != nil {
return nil, fmt.Errorf("failed to get GitHub client: %w", err)
}
alert, resp, err := client.CodeScanning.GetAlert(ctx, owner, repo, int64(alertNumber))
if err != nil {
return nil, fmt.Errorf("failed to get alert: %w", err)
}
defer func() { _ = resp.Body.Close() }()
if resp.StatusCode != http.StatusOK {
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, fmt.Errorf("failed to read response body: %w", err)
}
return mcp.NewToolResultError(fmt.Sprintf("failed to get alert: %s", string(body))), nil
}
r, err := json.Marshal(alert)
if err != nil {
return nil, fmt.Errorf("failed to marshal alert: %w", err)
}
return mcp.NewToolResultText(string(r)), nil
}
},
Access: ReadOnly,
Category: CategoryCodeScanning,
}
}
func ListCodeScanningAlerts(t translations.TranslationHelperFunc) Tool {
return Tool{
Definition: mcp.NewTool(
"list_code_scanning_alerts",
mcp.WithDescription(t("TOOL_LIST_CODE_SCANNING_ALERTS_DESCRIPTION", "List code scanning alerts in a GitHub repository.")),
mcp.WithString("owner",
mcp.Required(),
mcp.Description("The owner of the repository."),
),
mcp.WithString("repo",
mcp.Required(),
mcp.Description("The name of the repository."),
),
mcp.WithString("ref",
mcp.Description("The Git reference for the results you want to list."),
),
mcp.WithString("state",
mcp.Description("State of the code scanning alerts to list. Set to closed to list only closed code scanning alerts. Default: open"),
mcp.DefaultString("open"),
),
mcp.WithString("severity",
mcp.Description("Only code scanning alerts with this severity will be returned. Possible values are: critical, high, medium, low, warning, note, error."),
),
),
Handler: func(getClient GetClientFn) server.ToolHandlerFunc {
return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
owner, err := requiredParam[string](request, "owner")
if err != nil {
return mcp.NewToolResultError(err.Error()), nil
}
repo, err := requiredParam[string](request, "repo")
if err != nil {
return mcp.NewToolResultError(err.Error()), nil
}
ref, err := OptionalParam[string](request, "ref")
if err != nil {
return mcp.NewToolResultError(err.Error()), nil
}
state, err := OptionalParam[string](request, "state")
if err != nil {
return mcp.NewToolResultError(err.Error()), nil
}
severity, err := OptionalParam[string](request, "severity")
if err != nil {
return mcp.NewToolResultError(err.Error()), nil
}
client, err := getClient(ctx)
if err != nil {
return nil, fmt.Errorf("failed to get GitHub client: %w", err)
}
alerts, resp, err := client.CodeScanning.ListAlertsForRepo(ctx, owner, repo, &github.AlertListOptions{Ref: ref, State: state, Severity: severity})
if err != nil {
return nil, fmt.Errorf("failed to list alerts: %w", err)
}
defer func() { _ = resp.Body.Close() }()
if resp.StatusCode != http.StatusOK {
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, fmt.Errorf("failed to read response body: %w", err)
}
return mcp.NewToolResultError(fmt.Sprintf("failed to list alerts: %s", string(body))), nil
}
r, err := json.Marshal(alerts)
if err != nil {
return nil, fmt.Errorf("failed to marshal alerts: %w", err)
}
return mcp.NewToolResultText(string(r)), nil
}
},
Access: ReadOnly,
Category: CategoryCodeScanning,
}
}