Skip to content
Closed
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
feat: Add get_dependencies method to issue_read tool
- Add 'get_dependencies' enum value to IssueRead tool method parameter
- Implement GetIssueDependencies function to fetch dependency relationships
- Support both 'depends_on' (blocked by) and 'blocking' relationships
- Use GitHub REST API /repos/{owner}/{repo}/issues/{number}/dependencies endpoint

Addresses #950 (read functionality)
  • Loading branch information
drtootsie committed Feb 3, 2026
commit 4873ab1e45057cc6fffd657bd875a7f507d0fe33
66 changes: 65 additions & 1 deletion pkg/github/issues.go
Original file line number Diff line number Diff line change
Expand Up @@ -244,8 +244,9 @@ Options are:
2. get_comments - Get issue comments.
3. get_sub_issues - Get sub-issues of the issue.
4. get_labels - Get labels assigned to the issue.
5. get_dependencies - Get issue dependencies (blocked by/blocking relationships).
`,
Enum: []any{"get", "get_comments", "get_sub_issues", "get_labels"},
Enum: []any{"get", "get_comments", "get_sub_issues", "get_labels", "get_dependencies"},
},
"owner": {
Type: "string",
Expand Down Expand Up @@ -323,6 +324,9 @@ Options are:
case "get_labels":
result, err := GetIssueLabels(ctx, gqlClient, owner, repo, issueNumber)
return result, nil, err
case "get_dependencies":
result, err := GetIssueDependencies(ctx, client, deps.GetRepoAccessCache(), owner, repo, issueNumber)
return result, nil, err
default:
return utils.NewToolResultError(fmt.Sprintf("unknown method: %s", method)), nil, nil
}
Expand Down Expand Up @@ -2112,3 +2116,63 @@ func GetGraphQLFeatures(ctx context.Context) []string {
}
return nil
}

// IssueDependency represents a dependency relationship between issues
type IssueDependency struct {
ID int64 `json:"id"`
NodeID string `json:"node_id"`
Number int `json:"number"`
Title string `json:"title"`
State string `json:"state"`
Repository struct {
Name string `json:"name"`
FullName string `json:"full_name"`
Owner struct {
Login string `json:"login"`
} `json:"owner"`
} `json:"repository"`
HTMLURL string `json:"html_url"`
}

// IssueDependencies represents the complete dependency information for an issue
type IssueDependencies struct {
DependsOn []IssueDependency `json:"depends_on"` // Issues this issue depends on (blocked by)
Blocking []IssueDependency `json:"blocking"` // Issues that depend on this issue
}

// GetIssueDependencies retrieves dependency information for an issue.
// Returns both "depends_on" (issues blocking this issue) and "blocking" (issues blocked by this issue).
func GetIssueDependencies(ctx context.Context, client *github.Client, cache *lockdown.RepoAccessCache, owner string, repo string, issueNumber int) (*mcp.CallToolResult, error) {
url := fmt.Sprintf("repos/%s/%s/issues/%d/dependencies", owner, repo, issueNumber)
req, err := client.NewRequest("GET", url, nil)
if err != nil {
return nil, fmt.Errorf("failed to create request: %w", err)
}

var dependencies IssueDependencies
resp, err := client.Do(ctx, req, &dependencies)
if err != nil {
return ghErrors.NewGitHubAPIErrorResponse(ctx,
"failed to get issue dependencies",
resp,
err,
), nil
}

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 ghErrors.NewGitHubAPIStatusErrorResponse(ctx, "failed to get issue dependencies", resp, body), nil
}

r, err := json.Marshal(dependencies)
if err != nil {
return nil, fmt.Errorf("failed to marshal response: %w", err)
}

return utils.NewToolResultText(string(r)), nil
}