list_issues
Retrieve GitHub issues with filters for status, assignee, labels, milestone, and sorting options to manage project tasks effectively.
Instructions
List GitHub issues
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| status | Yes | ||
| milestone | No | ||
| labels | No | ||
| assignee | No | ||
| sort | No | ||
| direction | No | ||
| limit | No |
Input Schema (JSON Schema)
{
"properties": {
"assignee": {
"type": "string"
},
"direction": {
"type": "string"
},
"labels": {
"items": {
"type": "string"
},
"type": "array"
},
"limit": {
"type": "string"
},
"milestone": {
"type": "string"
},
"sort": {
"type": "string"
},
"status": {
"type": "string"
}
},
"required": [
"status"
],
"type": "object"
}
Implementation Reference
- Primary handler function implementing list_issues tool logic: fetches issues (by milestone or all), filters by status/labels/assignee, sorts, limits.async listIssues(options: { status?: string; milestone?: string; labels?: string[]; assignee?: string; sort?: string; direction?: string; limit?: number; } = {}): Promise<Issue[]> { try { // Set default values const { status = 'open', milestone, labels = [], assignee, sort = 'created', direction = 'desc', limit = 30 } = options; let issues: Issue[]; if (milestone) { // If milestone is specified, get issues for that milestone issues = await this.issueRepo.findByMilestone(milestone); } else { // Otherwise get all issues issues = await this.issueRepo.findAll(); } // Filter by status if (status !== 'all') { const resourceStatus = status === 'open' ? ResourceStatus.ACTIVE : ResourceStatus.CLOSED; issues = issues.filter(issue => issue.status === resourceStatus); } // Filter by labels if provided if (labels.length > 0) { issues = issues.filter(issue => labels.every(label => issue.labels.includes(label)) ); } // Filter by assignee if provided if (assignee) { issues = issues.filter(issue => issue.assignees.includes(assignee) ); } // Sort the issues issues.sort((a, b) => { let valueA, valueB; switch(sort) { case 'updated': valueA = a.updatedAt; valueB = b.updatedAt; break; case 'comments': // Since we don't have comment count in our model, default to created case 'created': default: valueA = a.createdAt; valueB = b.createdAt; } const comparison = valueA.localeCompare(valueB); return direction === 'desc' ? -comparison : comparison; }); // Apply limit return issues.slice(0, limit); } catch (error) { throw this.mapErrorToMCPError(error); } }
- Zod schema definition for list_issues tool input validation and TypeScript type inference.// Schema for list_issues tool export const listIssuesSchema = z.object({ status: z.enum(["open", "closed", "all"]).default("open"), milestone: z.string().optional(), labels: z.array(z.string()).optional(), assignee: z.string().optional(), sort: z.enum(["created", "updated", "comments"]).default("created").optional(), direction: z.enum(["asc", "desc"]).default("desc").optional(), limit: z.number().int().positive().default(30).optional(), }); export type ListIssuesArgs = z.infer<typeof listIssuesSchema>;
- src/infrastructure/tools/ToolRegistry.ts:156-156 (registration)Registers the listIssuesTool in the central ToolRegistry singleton.this.registerTool(listIssuesTool);
- src/index.ts:278-279 (handler)MCP tool dispatch handler that routes list_issues calls to ProjectManagementService.listIssues.case "list_issues": return await this.service.listIssues(args);
- Repository helper: Fetches all issues via GraphQL and maps to domain Issue model (used by listIssues).async findAll(): Promise<Issue[]> { const query = ` query($owner: String!, $repo: String!) { repository(owner: $owner, name: $repo) { issues(first: 100) { nodes { id number title body state createdAt updatedAt assignees(first: 100) { nodes { login } } labels(first: 100) { nodes { name } } milestone { id } } } } } `; const response = await this.graphql<ListIssuesResponse>(query, { owner: this.owner, repo: this.repo, }); return response.repository.issues.nodes.map(issue => this.mapGitHubIssueToIssue(issue) ); }