@@ -182,6 +182,95 @@ func ListGlobalSecurityAdvisories(getClient GetClientFn, t translations.Translat
182182 }
183183}
184184
185+ func ListRepositorySecurityAdvisories (getClient GetClientFn , t translations.TranslationHelperFunc ) (tool mcp.Tool , handler server.ToolHandlerFunc ) {
186+ return mcp .NewTool ("list_repository_security_advisories" ,
187+ mcp .WithDescription (t ("TOOL_LIST_REPOSITORY_SECURITY_ADVISORIES_DESCRIPTION" , "List repository security advisories for a GitHub repository." )),
188+ mcp .WithToolAnnotation (mcp.ToolAnnotation {
189+ Title : t ("TOOL_LIST_REPOSITORY_SECURITY_ADVISORIES_USER_TITLE" , "List repository security advisories" ),
190+ ReadOnlyHint : ToBoolPtr (true ),
191+ }),
192+ mcp .WithString ("owner" ,
193+ mcp .Required (),
194+ mcp .Description ("The owner of the repository." ),
195+ ),
196+ mcp .WithString ("repo" ,
197+ mcp .Required (),
198+ mcp .Description ("The name of the repository." ),
199+ ),
200+ mcp .WithString ("direction" ,
201+ mcp .Description ("Sort direction." ),
202+ mcp .Enum ("asc" , "desc" ),
203+ ),
204+ mcp .WithString ("sort" ,
205+ mcp .Description ("Sort field." ),
206+ mcp .Enum ("created" , "updated" , "published" ),
207+ ),
208+ mcp .WithString ("state" ,
209+ mcp .Description ("Filter by advisory state." ),
210+ mcp .Enum ("triage" , "draft" , "published" , "closed" ),
211+ ),
212+ ), func (ctx context.Context , request mcp.CallToolRequest ) (* mcp.CallToolResult , error ) {
213+ owner , err := RequiredParam [string ](request , "owner" )
214+ if err != nil {
215+ return mcp .NewToolResultError (err .Error ()), nil
216+ }
217+ repo , err := RequiredParam [string ](request , "repo" )
218+ if err != nil {
219+ return mcp .NewToolResultError (err .Error ()), nil
220+ }
221+
222+ direction , err := OptionalParam [string ](request , "direction" )
223+ if err != nil {
224+ return mcp .NewToolResultError (err .Error ()), nil
225+ }
226+ sortField , err := OptionalParam [string ](request , "sort" )
227+ if err != nil {
228+ return mcp .NewToolResultError (err .Error ()), nil
229+ }
230+ state , err := OptionalParam [string ](request , "state" )
231+ if err != nil {
232+ return mcp .NewToolResultError (err .Error ()), nil
233+ }
234+
235+ client , err := getClient (ctx )
236+ if err != nil {
237+ return nil , fmt .Errorf ("failed to get GitHub client: %w" , err )
238+ }
239+
240+ opts := & github.ListRepositorySecurityAdvisoriesOptions {}
241+ if direction != "" {
242+ opts .Direction = direction
243+ }
244+ if sortField != "" {
245+ opts .Sort = sortField
246+ }
247+ if state != "" {
248+ opts .State = state
249+ }
250+
251+ advisories , resp , err := client .SecurityAdvisories .ListRepositorySecurityAdvisories (ctx , owner , repo , opts )
252+ if err != nil {
253+ return nil , fmt .Errorf ("failed to list repository security advisories: %w" , err )
254+ }
255+ defer func () { _ = resp .Body .Close () }()
256+
257+ if resp .StatusCode != http .StatusOK {
258+ body , err := io .ReadAll (resp .Body )
259+ if err != nil {
260+ return nil , fmt .Errorf ("failed to read response body: %w" , err )
261+ }
262+ return mcp .NewToolResultError (fmt .Sprintf ("failed to list repository advisories: %s" , string (body ))), nil
263+ }
264+
265+ r , err := json .Marshal (advisories )
266+ if err != nil {
267+ return nil , fmt .Errorf ("failed to marshal advisories: %w" , err )
268+ }
269+
270+ return mcp .NewToolResultText (string (r )), nil
271+ }
272+ }
273+
185274func GetGlobalSecurityAdvisory (getClient GetClientFn , t translations.TranslationHelperFunc ) (tool mcp.Tool , handler server.ToolHandlerFunc ) {
186275 return mcp .NewTool ("get_global_security_advisory" ,
187276 mcp .WithDescription (t ("TOOL_GET_GLOBAL_SECURITY_ADVISORY_DESCRIPTION" , "Get a global security advisory" )),
@@ -226,3 +315,83 @@ func GetGlobalSecurityAdvisory(getClient GetClientFn, t translations.Translation
226315 return mcp .NewToolResultText (string (r )), nil
227316 }
228317}
318+
319+ func ListOrgRepositorySecurityAdvisories (getClient GetClientFn , t translations.TranslationHelperFunc ) (tool mcp.Tool , handler server.ToolHandlerFunc ) {
320+ return mcp .NewTool ("list_org_repository_security_advisories" ,
321+ mcp .WithDescription (t ("TOOL_LIST_ORG_REPOSITORY_SECURITY_ADVISORIES_DESCRIPTION" , "List repository security advisories for a GitHub organization." )),
322+ mcp .WithToolAnnotation (mcp.ToolAnnotation {
323+ Title : t ("TOOL_LIST_ORG_REPOSITORY_SECURITY_ADVISORIES_USER_TITLE" , "List org repository security advisories" ),
324+ ReadOnlyHint : ToBoolPtr (true ),
325+ }),
326+ mcp .WithString ("org" ,
327+ mcp .Required (),
328+ mcp .Description ("The organization login." ),
329+ ),
330+ mcp .WithString ("direction" ,
331+ mcp .Description ("Sort direction." ),
332+ mcp .Enum ("asc" , "desc" ),
333+ ),
334+ mcp .WithString ("sort" ,
335+ mcp .Description ("Sort field." ),
336+ mcp .Enum ("created" , "updated" , "published" ),
337+ ),
338+ mcp .WithString ("state" ,
339+ mcp .Description ("Filter by advisory state." ),
340+ mcp .Enum ("triage" , "draft" , "published" , "closed" ),
341+ ),
342+ ), func (ctx context.Context , request mcp.CallToolRequest ) (* mcp.CallToolResult , error ) {
343+ org , err := RequiredParam [string ](request , "org" )
344+ if err != nil {
345+ return mcp .NewToolResultError (err .Error ()), nil
346+ }
347+ direction , err := OptionalParam [string ](request , "direction" )
348+ if err != nil {
349+ return mcp .NewToolResultError (err .Error ()), nil
350+ }
351+ sortField , err := OptionalParam [string ](request , "sort" )
352+ if err != nil {
353+ return mcp .NewToolResultError (err .Error ()), nil
354+ }
355+ state , err := OptionalParam [string ](request , "state" )
356+ if err != nil {
357+ return mcp .NewToolResultError (err .Error ()), nil
358+ }
359+
360+ client , err := getClient (ctx )
361+ if err != nil {
362+ return nil , fmt .Errorf ("failed to get GitHub client: %w" , err )
363+ }
364+
365+ opts := & github.ListRepositorySecurityAdvisoriesOptions {}
366+ if direction != "" {
367+ opts .Direction = direction
368+ }
369+ if sortField != "" {
370+ opts .Sort = sortField
371+ }
372+ if state != "" {
373+ opts .State = state
374+ }
375+
376+ advisories , resp , err := client .SecurityAdvisories .ListRepositorySecurityAdvisoriesForOrg (ctx , org , opts )
377+ if err != nil {
378+ return nil , fmt .Errorf ("failed to list organization repository security advisories: %w" , err )
379+ }
380+ defer func () { _ = resp .Body .Close () }()
381+
382+ if resp .StatusCode != http .StatusOK {
383+ body , err := io .ReadAll (resp .Body )
384+ if err != nil {
385+ return nil , fmt .Errorf ("failed to read response body: %w" , err )
386+ }
387+ return mcp .NewToolResultError (fmt .Sprintf ("failed to list organization repository advisories: %s" , string (body ))), nil
388+ }
389+
390+ r , err := json .Marshal (advisories )
391+ if err != nil {
392+ return nil , fmt .Errorf ("failed to marshal advisories: %w" , err )
393+ }
394+
395+ return mcp .NewToolResultText (string (r )), nil
396+ }
397+ }
0 commit comments