Skip to content

Commit 9b8ebc0

Browse files
committed
Create 'list sub-issues' tool
1 parent 080e498 commit 9b8ebc0

File tree

3 files changed

+385
-0
lines changed

3 files changed

+385
-0
lines changed

pkg/github/issues.go

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,104 @@ func AddSubIssue(getClient GetClientFn, t translations.TranslationHelperFunc) (t
266266
}
267267
}
268268

269+
// ListSubIssues creates a tool to list sub-issues for a GitHub issue.
270+
func ListSubIssues(getClient GetClientFn, t translations.TranslationHelperFunc) (tool mcp.Tool, handler server.ToolHandlerFunc) {
271+
return mcp.NewTool("list_sub_issues",
272+
mcp.WithDescription(t("TOOL_LIST_SUB_ISSUES_DESCRIPTION", "List sub-issues for a specific issue in a GitHub repository.")),
273+
mcp.WithToolAnnotation(mcp.ToolAnnotation{
274+
Title: t("TOOL_LIST_SUB_ISSUES_USER_TITLE", "List sub-issues"),
275+
ReadOnlyHint: toBoolPtr(true),
276+
}),
277+
mcp.WithString("owner",
278+
mcp.Required(),
279+
mcp.Description("Repository owner"),
280+
),
281+
mcp.WithString("repo",
282+
mcp.Required(),
283+
mcp.Description("Repository name"),
284+
),
285+
mcp.WithNumber("issue_number",
286+
mcp.Required(),
287+
mcp.Description("Issue number"),
288+
),
289+
mcp.WithNumber("page",
290+
mcp.Description("Page number for pagination (default: 1)"),
291+
),
292+
mcp.WithNumber("per_page",
293+
mcp.Description("Number of results per page (max 100, default: 30)"),
294+
),
295+
),
296+
func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
297+
owner, err := requiredParam[string](request, "owner")
298+
if err != nil {
299+
return mcp.NewToolResultError(err.Error()), nil
300+
}
301+
repo, err := requiredParam[string](request, "repo")
302+
if err != nil {
303+
return mcp.NewToolResultError(err.Error()), nil
304+
}
305+
issueNumber, err := RequiredInt(request, "issue_number")
306+
if err != nil {
307+
return mcp.NewToolResultError(err.Error()), nil
308+
}
309+
page, err := OptionalIntParamWithDefault(request, "page", 1)
310+
if err != nil {
311+
return mcp.NewToolResultError(err.Error()), nil
312+
}
313+
perPage, err := OptionalIntParamWithDefault(request, "per_page", 30)
314+
if err != nil {
315+
return mcp.NewToolResultError(err.Error()), nil
316+
}
317+
318+
client, err := getClient(ctx)
319+
if err != nil {
320+
return nil, fmt.Errorf("failed to get GitHub client: %w", err)
321+
}
322+
323+
// Since the go-github library might not have sub-issues support yet,
324+
// we'll make a direct HTTP request using the client's HTTP client
325+
url := fmt.Sprintf("%srepos/%s/%s/issues/%d/sub_issues?page=%d&per_page=%d",
326+
client.BaseURL.String(), owner, repo, issueNumber, page, perPage)
327+
req, err := http.NewRequestWithContext(ctx, "GET", url, nil)
328+
if err != nil {
329+
return nil, fmt.Errorf("failed to create request: %w", err)
330+
}
331+
332+
req.Header.Set("Accept", "application/vnd.github+json")
333+
req.Header.Set("X-GitHub-Api-Version", "2022-11-28")
334+
335+
// Use the same authentication as the GitHub client
336+
httpClient := client.Client()
337+
resp, err := httpClient.Do(req)
338+
if err != nil {
339+
return nil, fmt.Errorf("failed to list sub-issues: %w", err)
340+
}
341+
defer func() { _ = resp.Body.Close() }()
342+
343+
body, err := io.ReadAll(resp.Body)
344+
if err != nil {
345+
return nil, fmt.Errorf("failed to read response body: %w", err)
346+
}
347+
348+
if resp.StatusCode != http.StatusOK {
349+
return mcp.NewToolResultError(fmt.Sprintf("failed to list sub-issues: %s", string(body))), nil
350+
}
351+
352+
// Parse and re-marshal to ensure consistent formatting
353+
var result interface{}
354+
if err := json.Unmarshal(body, &result); err != nil {
355+
return nil, fmt.Errorf("failed to unmarshal response: %w", err)
356+
}
357+
358+
r, err := json.Marshal(result)
359+
if err != nil {
360+
return nil, fmt.Errorf("failed to marshal response: %w", err)
361+
}
362+
363+
return mcp.NewToolResultText(string(r)), nil
364+
}
365+
}
366+
269367
// SearchIssues creates a tool to search for issues and pull requests.
270368
func SearchIssues(getClient GetClientFn, t translations.TranslationHelperFunc) (tool mcp.Tool, handler server.ToolHandlerFunc) {
271369
return mcp.NewTool("search_issues",

0 commit comments

Comments
 (0)