get_person_schedule
Retrieve a team member's upcoming GitHub work schedule to track tasks and manage team availability.
Instructions
Get the schedule and upcoming work for a specific team member
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| login | Yes | GitHub username of the team member | |
| days | No | Number of days to look ahead (default: 7) |
Implementation Reference
- src/tools/person-schedule.ts:12-56 (handler)Core handler logic: fetches GitHub issues assigned to the person, enriches with due date calculations, sorts by urgency (due date then recency), and constructs PersonSchedule object.async getPersonSchedule(login: string): Promise<PersonSchedule> { try { // Get open issues assigned to this person const issues = await this.githubClient.getIssuesByAssignee(login); // Get avatar URL from first issue const avatarUrl = issues[0]?.assignees.find(a => a.login === login)?.avatar_url || ''; // Build upcoming issues with due date info const upcomingIssues = issues.map(issue => { const dueDate = issue.milestone?.due_on || null; const daysUntilDue = dueDate ? differenceInDays(parseISO(dueDate), new Date()) : null; return { issue, dueDate, daysUntilDue }; }); // Sort by due date (soonest first, then by creation date) upcomingIssues.sort((a, b) => { // Items with due dates come first if (a.daysUntilDue !== null && b.daysUntilDue === null) return -1; if (a.daysUntilDue === null && b.daysUntilDue !== null) return 1; // Both have due dates, sort by days until due if (a.daysUntilDue !== null && b.daysUntilDue !== null) { return a.daysUntilDue - b.daysUntilDue; } // Neither has due date, sort by creation date (newest first) return new Date(b.issue.created_at).getTime() - new Date(a.issue.created_at).getTime(); }); return { login, avatar_url: avatarUrl, upcomingIssues }; } catch (error) { console.error(`Error getting schedule for ${login}:`, error); throw error; } }
- src/tools/person-schedule.ts:58-71 (handler)Tool-specific handler: fetches full schedule and filters upcoming issues to those due within the requested number of days (or no due date).async getPersonScheduleForDateRange(login: string, days: number = 7): Promise<PersonSchedule> { const schedule = await this.getPersonSchedule(login); // Filter to only include issues due within the specified number of days const filteredIssues = schedule.upcomingIssues.filter(item => { if (item.daysUntilDue === null) return true; // Include items without due dates return item.daysUntilDue <= days; // Include items due within the range }); return { ...schedule, upcomingIssues: filteredIssues }; }
- src/index.ts:160-171 (handler)MCP dispatch handler: parses tool arguments, invokes PersonScheduleTool.getPersonScheduleForDateRange, formats output, and returns MCP tool response.case 'get_person_schedule': { const { login, days = 7 } = args as { login: string; days?: number }; const schedule = await this.personScheduleTool.getPersonScheduleForDateRange(login, days); return { content: [ { type: 'text', text: this.formatPersonSchedule(schedule, days), }, ], }; }
- src/index.ts:101-119 (registration)Tool registration in MCP listTools handler: defines name, description, and input schema (login required, days optional).{ name: 'get_person_schedule', description: 'Get the schedule and upcoming work for a specific team member', inputSchema: { type: 'object', properties: { login: { type: 'string', description: 'GitHub username of the team member', }, days: { type: 'number', description: 'Number of days to look ahead (default: 7)', default: 7, }, }, required: ['login'], }, },
- src/index.ts:242-271 (helper)Helper function to format the PersonSchedule into a human-readable markdown string, including issue titles, due status, and links.private formatPersonSchedule(schedule: any, days: number): string { const { login, upcomingIssues } = schedule; let output = `## ${login}'s Schedule (next ${days} days)\n\n`; if (upcomingIssues.length === 0) { output += 'No upcoming issues assigned.\n'; return output; } output += '**Upcoming Work:**\n'; for (const item of upcomingIssues) { const { issue, daysUntilDue } = item; output += `- **${issue.title}**`; if (daysUntilDue !== null) { if (daysUntilDue < 0) { output += ` (overdue by ${Math.abs(daysUntilDue)} days)`; } else if (daysUntilDue === 0) { output += ` (due today)`; } else { output += ` (due in ${daysUntilDue} days)`; } } output += `\n - Issue #${issue.number}: ${issue.html_url}\n`; } return output; }