Skip to content

Commit 47040f4

Browse files
authored
Add Global Security Advisories Toolset (#919)
1 parent b189531 commit 47040f4

File tree

5 files changed

+505
-3
lines changed

5 files changed

+505
-3
lines changed

README.md

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ Alternatively, to manually configure VS Code, choose the appropriate JSON block
3636
<tr><th align=left colspan=2>VS Code (version 1.101 or greater)</th></tr>
3737
<tr valign=top>
3838
<td>
39-
39+
4040
```json
4141
{
4242
"servers": {
@@ -130,7 +130,7 @@ To keep your GitHub PAT secure and reusable across different MCP hosts:
130130
```bash
131131
# CLI usage
132132
claude mcp update github -e GITHUB_PERSONAL_ACCESS_TOKEN=$GITHUB_PAT
133-
133+
134134
# In config files (where supported)
135135
"env": {
136136
"GITHUB_PERSONAL_ACCESS_TOKEN": "$GITHUB_PAT"
@@ -241,7 +241,7 @@ For other MCP host applications, please refer to our installation guides:
241241

242242
- **[GitHub Copilot in other IDEs](/docs/installation-guides/install-other-copilot-ides.md)** - Installation for JetBrains, Visual Studio, Eclipse, and Xcode with GitHub Copilot
243243
- **[Claude Code & Claude Desktop](docs/installation-guides/install-claude.md)** - Installation guide for Claude Code and Claude Desktop
244-
- **[Cursor](docs/installation-guides/install-cursor.md)** - Installation guide for Cursor IDE
244+
- **[Cursor](docs/installation-guides/install-cursor.md)** - Installation guide for Cursor IDE
245245
- **[Windsurf](docs/installation-guides/install-windsurf.md)** - Installation guide for Windsurf IDE
246246

247247
For a complete overview of all installation options, see our **[Installation Guides Index](docs/installation-guides)**.
@@ -295,6 +295,7 @@ The following sets of tools are available (all are on by default):
295295
| `pull_requests` | GitHub Pull Request related tools |
296296
| `repos` | GitHub Repository related tools |
297297
| `secret_protection` | Secret protection related tools, such as GitHub Secret Scanning |
298+
| `security_advisories` | Security advisories related tools |
298299
| `users` | GitHub User related tools |
299300
<!-- END AUTOMATED TOOLSETS -->
300301

@@ -923,6 +924,28 @@ The following sets of tools are available (all are on by default):
923924

924925
<details>
925926

927+
<summary>Security Advisories</summary>
928+
929+
- **get_global_security_advisory** - Get a global security advisory
930+
- `ghsaId`: GitHub Security Advisory ID (format: GHSA-xxxx-xxxx-xxxx). (string, required)
931+
932+
- **list_global_security_advisories** - List global security advisories
933+
- `affects`: Filter advisories by affected package or version (e.g. "package1,package2@1.0.0"). (string, optional)
934+
- `cveId`: Filter by CVE ID. (string, optional)
935+
- `cwes`: Filter by Common Weakness Enumeration IDs (e.g. ["79", "284", "22"]). (string[], optional)
936+
- `ecosystem`: Filter by package ecosystem. (string, optional)
937+
- `ghsaId`: Filter by GitHub Security Advisory ID (format: GHSA-xxxx-xxxx-xxxx). (string, optional)
938+
- `isWithdrawn`: Whether to only return withdrawn advisories. (boolean, optional)
939+
- `modified`: Filter by publish or update date or date range (ISO 8601 date or range). (string, optional)
940+
- `published`: Filter by publish date or date range (ISO 8601 date or range). (string, optional)
941+
- `severity`: Filter by severity. (string, optional)
942+
- `type`: Advisory type. (string, optional)
943+
- `updated`: Filter by update date or date range (ISO 8601 date or range). (string, optional)
944+
945+
</details>
946+
947+
<details>
948+
926949
<summary>Users</summary>
927950

928951
- **search_users** - Search users

docs/remote-server.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ Below is a table of available toolsets for the remote GitHub MCP Server. Each to
3232
| Pull Requests | GitHub Pull Request related tools | https://api.githubcopilot.com/mcp/x/pull_requests | [Install](https://insiders.vscode.dev/redirect/mcp/install?name=gh-pull_requests&config=%7B%22type%22%3A%20%22http%22%2C%22url%22%3A%20%22https%3A%2F%2Fapi.githubcopilot.com%2Fmcp%2Fx%2Fpull_requests%22%7D) | [read-only](https://api.githubcopilot.com/mcp/x/pull_requests/readonly) | [Install read-only](https://insiders.vscode.dev/redirect/mcp/install?name=gh-pull_requests&config=%7B%22type%22%3A%20%22http%22%2C%22url%22%3A%20%22https%3A%2F%2Fapi.githubcopilot.com%2Fmcp%2Fx%2Fpull_requests%2Freadonly%22%7D) |
3333
| Repositories | GitHub Repository related tools | https://api.githubcopilot.com/mcp/x/repos | [Install](https://insiders.vscode.dev/redirect/mcp/install?name=gh-repos&config=%7B%22type%22%3A%20%22http%22%2C%22url%22%3A%20%22https%3A%2F%2Fapi.githubcopilot.com%2Fmcp%2Fx%2Frepos%22%7D) | [read-only](https://api.githubcopilot.com/mcp/x/repos/readonly) | [Install read-only](https://insiders.vscode.dev/redirect/mcp/install?name=gh-repos&config=%7B%22type%22%3A%20%22http%22%2C%22url%22%3A%20%22https%3A%2F%2Fapi.githubcopilot.com%2Fmcp%2Fx%2Frepos%2Freadonly%22%7D) |
3434
| Secret Protection | Secret protection related tools, such as GitHub Secret Scanning | https://api.githubcopilot.com/mcp/x/secret_protection | [Install](https://insiders.vscode.dev/redirect/mcp/install?name=gh-secret_protection&config=%7B%22type%22%3A%20%22http%22%2C%22url%22%3A%20%22https%3A%2F%2Fapi.githubcopilot.com%2Fmcp%2Fx%2Fsecret_protection%22%7D) | [read-only](https://api.githubcopilot.com/mcp/x/secret_protection/readonly) | [Install read-only](https://insiders.vscode.dev/redirect/mcp/install?name=gh-secret_protection&config=%7B%22type%22%3A%20%22http%22%2C%22url%22%3A%20%22https%3A%2F%2Fapi.githubcopilot.com%2Fmcp%2Fx%2Fsecret_protection%2Freadonly%22%7D) |
35+
| Security Advisories | Security advisories related tools | https://api.githubcopilot.com/mcp/x/security_advisories | [Install](https://insiders.vscode.dev/redirect/mcp/install?name=gh-security_advisories&config=%7B%22type%22%3A%20%22http%22%2C%22url%22%3A%20%22https%3A%2F%2Fapi.githubcopilot.com%2Fmcp%2Fx%2Fsecurity_advisories%22%7D) | [read-only](https://api.githubcopilot.com/mcp/x/security_advisories/readonly) | [Install read-only](https://insiders.vscode.dev/redirect/mcp/install?name=gh-security_advisories&config=%7B%22type%22%3A%20%22http%22%2C%22url%22%3A%20%22https%3A%2F%2Fapi.githubcopilot.com%2Fmcp%2Fx%2Fsecurity_advisories%2Freadonly%22%7D) |
3536
| Users | GitHub User related tools | https://api.githubcopilot.com/mcp/x/users | [Install](https://insiders.vscode.dev/redirect/mcp/install?name=gh-users&config=%7B%22type%22%3A%20%22http%22%2C%22url%22%3A%20%22https%3A%2F%2Fapi.githubcopilot.com%2Fmcp%2Fx%2Fusers%22%7D) | [read-only](https://api.githubcopilot.com/mcp/x/users/readonly) | [Install read-only](https://insiders.vscode.dev/redirect/mcp/install?name=gh-users&config=%7B%22type%22%3A%20%22http%22%2C%22url%22%3A%20%22https%3A%2F%2Fapi.githubcopilot.com%2Fmcp%2Fx%2Fusers%2Freadonly%22%7D) |
3637

3738
<!-- END AUTOMATED TOOLSETS -->

pkg/github/security_advisories.go

Lines changed: 228 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,228 @@
1+
package github
2+
3+
import (
4+
"context"
5+
"encoding/json"
6+
"fmt"
7+
"io"
8+
"net/http"
9+
10+
"github.com/github/github-mcp-server/pkg/translations"
11+
"github.com/google/go-github/v74/github"
12+
"github.com/mark3labs/mcp-go/mcp"
13+
"github.com/mark3labs/mcp-go/server"
14+
)
15+
16+
func ListGlobalSecurityAdvisories(getClient GetClientFn, t translations.TranslationHelperFunc) (tool mcp.Tool, handler server.ToolHandlerFunc) {
17+
return mcp.NewTool("list_global_security_advisories",
18+
mcp.WithDescription(t("TOOL_LIST_GLOBAL_SECURITY_ADVISORIES_DESCRIPTION", "List global security advisories from GitHub.")),
19+
mcp.WithToolAnnotation(mcp.ToolAnnotation{
20+
Title: t("TOOL_LIST_GLOBAL_SECURITY_ADVISORIES_USER_TITLE", "List global security advisories"),
21+
ReadOnlyHint: ToBoolPtr(true),
22+
}),
23+
mcp.WithString("ghsaId",
24+
mcp.Description("Filter by GitHub Security Advisory ID (format: GHSA-xxxx-xxxx-xxxx)."),
25+
),
26+
mcp.WithString("type",
27+
mcp.Description("Advisory type."),
28+
mcp.Enum("reviewed", "malware", "unreviewed"),
29+
mcp.DefaultString("reviewed"),
30+
),
31+
mcp.WithString("cveId",
32+
mcp.Description("Filter by CVE ID."),
33+
),
34+
mcp.WithString("ecosystem",
35+
mcp.Description("Filter by package ecosystem."),
36+
mcp.Enum("actions", "composer", "erlang", "go", "maven", "npm", "nuget", "other", "pip", "pub", "rubygems", "rust"),
37+
),
38+
mcp.WithString("severity",
39+
mcp.Description("Filter by severity."),
40+
mcp.Enum("unknown", "low", "medium", "high", "critical"),
41+
),
42+
mcp.WithArray("cwes",
43+
mcp.Description("Filter by Common Weakness Enumeration IDs (e.g. [\"79\", \"284\", \"22\"])."),
44+
mcp.Items(map[string]any{
45+
"type": "string",
46+
}),
47+
),
48+
mcp.WithBoolean("isWithdrawn",
49+
mcp.Description("Whether to only return withdrawn advisories."),
50+
),
51+
mcp.WithString("affects",
52+
mcp.Description("Filter advisories by affected package or version (e.g. \"package1,package2@1.0.0\")."),
53+
),
54+
mcp.WithString("published",
55+
mcp.Description("Filter by publish date or date range (ISO 8601 date or range)."),
56+
),
57+
mcp.WithString("updated",
58+
mcp.Description("Filter by update date or date range (ISO 8601 date or range)."),
59+
),
60+
mcp.WithString("modified",
61+
mcp.Description("Filter by publish or update date or date range (ISO 8601 date or range)."),
62+
),
63+
), func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
64+
client, err := getClient(ctx)
65+
if err != nil {
66+
return nil, fmt.Errorf("failed to get GitHub client: %w", err)
67+
}
68+
69+
ghsaID, err := OptionalParam[string](request, "ghsaId")
70+
if err != nil {
71+
return mcp.NewToolResultError(fmt.Sprintf("invalid ghsaId: %v", err)), nil
72+
}
73+
74+
typ, err := OptionalParam[string](request, "type")
75+
if err != nil {
76+
return mcp.NewToolResultError(fmt.Sprintf("invalid type: %v", err)), nil
77+
}
78+
79+
cveID, err := OptionalParam[string](request, "cveId")
80+
if err != nil {
81+
return mcp.NewToolResultError(fmt.Sprintf("invalid cveId: %v", err)), nil
82+
}
83+
84+
eco, err := OptionalParam[string](request, "ecosystem")
85+
if err != nil {
86+
return mcp.NewToolResultError(fmt.Sprintf("invalid ecosystem: %v", err)), nil
87+
}
88+
89+
sev, err := OptionalParam[string](request, "severity")
90+
if err != nil {
91+
return mcp.NewToolResultError(fmt.Sprintf("invalid severity: %v", err)), nil
92+
}
93+
94+
cwes, err := OptionalParam[[]string](request, "cwes")
95+
if err != nil {
96+
return mcp.NewToolResultError(fmt.Sprintf("invalid cwes: %v", err)), nil
97+
}
98+
99+
isWithdrawn, err := OptionalParam[bool](request, "isWithdrawn")
100+
if err != nil {
101+
return mcp.NewToolResultError(fmt.Sprintf("invalid isWithdrawn: %v", err)), nil
102+
}
103+
104+
affects, err := OptionalParam[string](request, "affects")
105+
if err != nil {
106+
return mcp.NewToolResultError(fmt.Sprintf("invalid affects: %v", err)), nil
107+
}
108+
109+
published, err := OptionalParam[string](request, "published")
110+
if err != nil {
111+
return mcp.NewToolResultError(fmt.Sprintf("invalid published: %v", err)), nil
112+
}
113+
114+
updated, err := OptionalParam[string](request, "updated")
115+
if err != nil {
116+
return mcp.NewToolResultError(fmt.Sprintf("invalid updated: %v", err)), nil
117+
}
118+
119+
modified, err := OptionalParam[string](request, "modified")
120+
if err != nil {
121+
return mcp.NewToolResultError(fmt.Sprintf("invalid modified: %v", err)), nil
122+
}
123+
124+
opts := &github.ListGlobalSecurityAdvisoriesOptions{}
125+
126+
if ghsaID != "" {
127+
opts.GHSAID = &ghsaID
128+
}
129+
if typ != "" {
130+
opts.Type = &typ
131+
}
132+
if cveID != "" {
133+
opts.CVEID = &cveID
134+
}
135+
if eco != "" {
136+
opts.Ecosystem = &eco
137+
}
138+
if sev != "" {
139+
opts.Severity = &sev
140+
}
141+
if len(cwes) > 0 {
142+
opts.CWEs = cwes
143+
}
144+
145+
if isWithdrawn {
146+
opts.IsWithdrawn = &isWithdrawn
147+
}
148+
149+
if affects != "" {
150+
opts.Affects = &affects
151+
}
152+
if published != "" {
153+
opts.Published = &published
154+
}
155+
if updated != "" {
156+
opts.Updated = &updated
157+
}
158+
if modified != "" {
159+
opts.Modified = &modified
160+
}
161+
162+
advisories, resp, err := client.SecurityAdvisories.ListGlobalSecurityAdvisories(ctx, opts)
163+
if err != nil {
164+
return nil, fmt.Errorf("failed to list global security advisories: %w", err)
165+
}
166+
defer func() { _ = resp.Body.Close() }()
167+
168+
if resp.StatusCode != http.StatusOK {
169+
body, err := io.ReadAll(resp.Body)
170+
if err != nil {
171+
return nil, fmt.Errorf("failed to read response body: %w", err)
172+
}
173+
return mcp.NewToolResultError(fmt.Sprintf("failed to list advisories: %s", string(body))), nil
174+
}
175+
176+
r, err := json.Marshal(advisories)
177+
if err != nil {
178+
return nil, fmt.Errorf("failed to marshal advisories: %w", err)
179+
}
180+
181+
return mcp.NewToolResultText(string(r)), nil
182+
}
183+
}
184+
185+
func GetGlobalSecurityAdvisory(getClient GetClientFn, t translations.TranslationHelperFunc) (tool mcp.Tool, handler server.ToolHandlerFunc) {
186+
return mcp.NewTool("get_global_security_advisory",
187+
mcp.WithDescription(t("TOOL_GET_GLOBAL_SECURITY_ADVISORY_DESCRIPTION", "Get a global security advisory")),
188+
mcp.WithToolAnnotation(mcp.ToolAnnotation{
189+
Title: t("TOOL_GET_GLOBAL_SECURITY_ADVISORY_USER_TITLE", "Get a global security advisory"),
190+
ReadOnlyHint: ToBoolPtr(true),
191+
}),
192+
mcp.WithString("ghsaId",
193+
mcp.Description("GitHub Security Advisory ID (format: GHSA-xxxx-xxxx-xxxx)."),
194+
mcp.Required(),
195+
),
196+
), func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
197+
client, err := getClient(ctx)
198+
if err != nil {
199+
return nil, fmt.Errorf("failed to get GitHub client: %w", err)
200+
}
201+
202+
ghsaID, err := RequiredParam[string](request, "ghsaId")
203+
if err != nil {
204+
return mcp.NewToolResultError(fmt.Sprintf("invalid ghsaId: %v", err)), nil
205+
}
206+
207+
advisory, resp, err := client.SecurityAdvisories.GetGlobalSecurityAdvisories(ctx, ghsaID)
208+
if err != nil {
209+
return nil, fmt.Errorf("failed to get advisory: %w", err)
210+
}
211+
defer func() { _ = resp.Body.Close() }()
212+
213+
if resp.StatusCode != http.StatusOK {
214+
body, err := io.ReadAll(resp.Body)
215+
if err != nil {
216+
return nil, fmt.Errorf("failed to read response body: %w", err)
217+
}
218+
return mcp.NewToolResultError(fmt.Sprintf("failed to get advisory: %s", string(body))), nil
219+
}
220+
221+
r, err := json.Marshal(advisory)
222+
if err != nil {
223+
return nil, fmt.Errorf("failed to marshal advisory: %w", err)
224+
}
225+
226+
return mcp.NewToolResultText(string(r)), nil
227+
}
228+
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy