github.getAuthoredPRs
Fetch and analyze pull requests authored by a GitHub user within specified repositories and time periods to assess code contributions, track activity trends, and gather performance metrics.
Instructions
Fetch all pull requests authored by a given user within a time range. Returns PRs with metadata including state (OPEN/MERGED/CLOSED), creation/merge dates, code statistics (files changed, additions, deletions), and repository information. Optionally filter by specific repositories. Automatically filters out auto-generated PRs (e.g., backmerge PRs). Use this tool to analyze a user's code contribution activity.
Example use cases:
Assess developer productivity by counting PRs authored in a time period
Analyze code contribution trends over time
Get detailed metrics for performance reviews
Track PR merge rates and code change statistics
Returns: Array of PR objects with id, repo, title, createdAt, mergedAt, state, filesChanged, additions, deletions
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| username | Yes | GitHub username (case-insensitive, @ prefix optional). Examples: "octocat", "@octocat", "JohnDoe" | |
| repos | Yes | Array of repositories in owner/repo format (required, at least one). Example: ["owner/repo1", "owner/repo2"] | |
| from | No | Optional: Start timestamp in ISO 8601 format. Must be before "to" parameter if provided. If omitted, uses last 3 months. Example: "2024-01-01T00:00:00Z" | |
| to | No | Optional: End timestamp in ISO 8601 format. Must be after "from" parameter if provided. If omitted, uses last 3 months. Example: "2024-12-31T23:59:59Z" |
Implementation Reference
- src/mcp/tools.ts:312-432 (handler)Core handler implementation for the github.getAuthoredPRs tool. Validates inputs, performs GitHub GraphQL search for PR IDs, fetches detailed PR data in batches, applies filters (time range, repository, auto-generated PRs), maps to AuthoredPR format, and returns the results.async getAuthoredPRs( username: string, repos: string[], from?: string, to?: string ): Promise<{ prs: AuthoredPR[] }> { // Validate inputs const { normalizedUsername, normalizedRepos, from: validatedFrom, to: validatedTo } = this.validateCommonParameters(username, repos, from, to); // Format dates for GitHub search (YYYY-MM-DD format) const fromDate = new Date(validatedFrom).toISOString().split('T')[0]; const toDate = new Date(validatedTo).toISOString().split('T')[0]; // Build search query // GitHub search syntax: is:pr created:YYYY-MM-DD..YYYY-MM-DD author:username // Note: GitHub search uses inclusive date ranges // GitHub search supports multiple repo: filters const repoFilters = normalizedRepos.map(repo => `repo:${repo}`).join(' '); let searchQuery = `is:pr created:${fromDate}..${toDate} author:${normalizedUsername} ${repoFilters}`; // Two-step approach: get PR IDs from search, then fetch full details by ID // This avoids issues with null nodes in search results for private org repos // Step 1: Collect all PR IDs from search const prIds: string[] = []; await fetchAllPages( async (cursor: string | null) => { const response = await this.client.query(QUERIES.AUTHoredPRsSearch, { searchQuery: searchQuery, after: cursor, }); return response.data; }, (data: any) => { const searchData = data.search || {}; const nodes = searchData.nodes || []; // Extract PR IDs (filter out null nodes) for (const node of nodes) { if (node && node.id && node.__typename === 'PullRequest') { prIds.push(node.id); } } return []; // Return empty array since we're collecting IDs in closure }, (data: any) => { const searchData = data.search || {}; return extractPageInfo(searchData.pageInfo || {}); } ); if (prIds.length === 0) { return { prs: [] }; } // Step 2: Fetch full PR details by ID (batch in groups of 100, GitHub's limit) const batchSize = 100; const allPRs: any[] = []; for (let i = 0; i < prIds.length; i += batchSize) { const batch = prIds.slice(i, i + batchSize); const response = await this.client.query(QUERIES.AUTHoredPRsDetails, { prIds: batch, }); const nodes = response.data.nodes || []; // Filter out null nodes and collect PRs for (const node of nodes) { if (node && node.id) { allPRs.push(node); } } } // Step 3: Filter and map PRs (apply time range filter and repository filter) const fromTime = new Date(validatedFrom).getTime(); const toTime = new Date(validatedTo).getTime(); const validPRs = allPRs .filter((node: any) => { // All nodes from Step 2 should already be PRs with full data // Just apply time range and repository filters if (!node.id || !node.repository) { return false; } // Apply time range filter (createdAt should already be in range from search, but double-check) const createdAt = new Date(node.createdAt).getTime(); if (createdAt < fromTime || createdAt > toTime) { return false; } // Apply repository filter const repoName = node.repository.nameWithOwner.toLowerCase(); if (!normalizedRepos.some(repo => repo === repoName)) { return false; } // Filter out auto-created PRs (e.g., backmerge PRs) if (this.isAutoCreatedPR(node.title)) { return false; } return true; }) .map((node: any) => { try { return mapAuthoredPR(node); } catch (error: any) { console.error(`[Error] Failed to map PR node:`, error.message); return null; } }) .filter((pr: any) => pr !== null) as AuthoredPR[]; return { prs: validPRs }; }
- src/mcp/server.ts:61-76 (registration)MCP server request handler registration for github.getAuthoredPRs. Dispatches tool calls to the GitHubTools.getAuthoredPRs method and formats the response as MCP content.case 'github.getAuthoredPRs': { const result = await tools.getAuthoredPRs( args.username as string, args.repos as string[], args.from as string | undefined, args.to as string | undefined ); return { content: [ { type: 'text', text: JSON.stringify(result, null, 2), }, ], }; }
- src/mcp/tools.ts:1132-1170 (schema)Tool schema definition including name, description, inputSchema with properties (username, repos, from, to), required fields, and examples for github.getAuthoredPRs.{ name: 'github.getAuthoredPRs', description: `Fetch all pull requests authored by a given user within a time range. Returns PRs with metadata including state (OPEN/MERGED/CLOSED), creation/merge dates, code statistics (files changed, additions, deletions), and repository information. Optionally filter by specific repositories. Automatically filters out auto-generated PRs (e.g., backmerge PRs). Use this tool to analyze a user's code contribution activity. Example use cases: - Assess developer productivity by counting PRs authored in a time period - Analyze code contribution trends over time - Get detailed metrics for performance reviews - Track PR merge rates and code change statistics Returns: Array of PR objects with id, repo, title, createdAt, mergedAt, state, filesChanged, additions, deletions`, inputSchema: { type: 'object', properties: { username: { type: 'string', description: 'GitHub username (case-insensitive, @ prefix optional). Examples: "octocat", "@octocat", "JohnDoe"', examples: ['octocat', '@octocat'], }, repos: { type: 'array', items: { type: 'string' }, description: 'Array of repositories in owner/repo format (required, at least one). Example: ["owner/repo1", "owner/repo2"]', examples: [['owner/repo'], ['owner/repo1', 'owner/repo2']], }, from: { type: 'string', description: 'Optional: Start timestamp in ISO 8601 format. Must be before "to" parameter if provided. If omitted, uses last 3 months. Example: "2024-01-01T00:00:00Z"', examples: ['2024-01-01T00:00:00Z', '2024-06-01T00:00:00Z'], }, to: { type: 'string', description: 'Optional: End timestamp in ISO 8601 format. Must be after "from" parameter if provided. If omitted, uses last 3 months. Example: "2024-12-31T23:59:59Z"', examples: ['2024-12-31T23:59:59Z', '2024-06-30T23:59:59Z'], }, }, required: ['username', 'repos'], }, },
- src/mcp/tools.ts:165-181 (helper)Shared validation helper used by getAuthoredPRs and other tools for common parameters (username, repos, time range).private validateCommonParameters( username: string, repos: string[], from?: string, to?: string ): { normalizedUsername: string; normalizedRepos: string[]; from: string; to: string } { const normalizedUsername = this.validateUsernameParameter(username); const normalizedRepos = this.validateReposParameter(repos); const timeRange = this.validateTimeRangeParameters(from, to); return { normalizedUsername, normalizedRepos, from: timeRange.from, to: timeRange.to }; }
- src/mcp/tools.ts:208-212 (helper)Helper function to filter out auto-created PRs (e.g., backmerge PRs) used in getAuthoredPRs filtering logic.private isAutoCreatedPR(prTitle: string | null | undefined): boolean { if (!prTitle) return false; const title = prTitle.trim(); return title.toLowerCase().startsWith('backmerge:'); }