Skip to main content
Glama
README.md•17.1 kB
# GitHub MCP Server A production-ready MCP (Model Context Protocol) server that exposes employee-centric GitHub activity APIs for AI agents and agent orchestration systems. This server abstracts GitHub REST & GraphQL APIs and provides semantic endpoints for analyzing developer contributions, code reviews, and impact over time ranges. ## 🎯 For AI Agents & Agent Orchestration **Quick Start for Agents**: See [AGENT_GUIDE.md](./AGENT_GUIDE.md) for comprehensive agent-focused documentation, use cases, and examples. **Recommended Tool for Quick Overview**: Use `github.getUserRepoStats` to get comprehensive metrics in a single call (PRs, comments, reviews, code changes). **Tool Discovery**: All tools include detailed descriptions, examples, and use cases in their schemas for easy agent discovery. ## Features - **Pull Request Analysis**: Fetch PRs authored by employees with detailed metadata - **Review Tracking**: Get PR reviews with states (APPROVED, CHANGES_REQUESTED, COMMENTED) - **Comment Analysis**: Extract inline and general review comments with file/line context - **User Comments**: Fetch all comments (review and issue) by a user for a repository within a time range - **Repository Statistics**: Get comprehensive stats (PRs, comments, reviews, code changes) for a user in a repository - **Impact Assessment**: Analyze whether review comments led to code changes - **Code Statistics**: Get detailed diff metadata and code stats for PRs ## Architecture ``` /src /mcp server.ts # MCP server registration tools.ts # Tool definitions and handlers /github client.ts # GraphQL client with auth queries.ts # GraphQL query definitions mapper.ts # Normalize GitHub → MCP DTOs /utils pagination.ts # Cursor-based pagination time.ts # ISO 8601 timestamp handling rateLimit.ts # Rate limit management ``` ## Prerequisites - Node.js 20+ - GitHub Personal Access Token with appropriate permissions: - `repo` (REQUIRED for private repos) - `read:org` (REQUIRED for organization repositories) - `read:user` (for user data) ### For Private Organization Repositories If you're querying private organization repositories (e.g., `radireddy/AiApps`), ensure: 1. **Token has both scopes**: `repo` AND `read:org` 2. **Account membership**: Your account must be a member of the organization 3. **Organization settings**: Organization must allow third-party access (if using OAuth) 4. **Repository access**: You must have at least read access to the repository To verify your token has access, run: ```bash npm run check-token radireddy/AiApps ``` ## Installation ```bash npm install npm run build ``` ## Configuration ### Option 1: Using .env file (Recommended) 1. Copy the example file: ```bash cp .env.example .env ``` 2. Edit `.env` and add your GitHub token: ```bash GITHUB_TOKEN=ghp_your_token_here ``` The `.env` file is automatically loaded and is excluded from git (already in `.gitignore`). ### Option 2: Environment Variable ```bash export GITHUB_TOKEN=ghp_your_token_here ``` **Note:** The `.env` file approach is recommended as it keeps your token local and secure. ## Usage ### MCP Configuration Add to your MCP client configuration (`mcp.json`): ```json { "mcpServers": { "github": { "command": "node", "args": ["dist/mcp/server.js"], "env": { "GITHUB_TOKEN": "${GITHUB_TOKEN}" } } } } ``` ### Running the Server ```bash npm start ``` The server communicates via stdio, so it should be launched by your MCP client. ## MCP Tools ### 1. `github.getAuthoredPRs` Fetch all PRs authored by a user in a time range. **Input:** ```json { "username": "octocat", "repos": ["owner/repo1", "owner/repo2"], "from": "2024-01-01T00:00:00Z", "to": "2024-12-31T23:59:59Z" } ``` **Note:** `from` and `to` are optional. If omitted, defaults to last 3 months. `repos` is required (at least one repository). **Output:** ```json { "prs": [ { "id": "PR_kwDO...", "repo": "owner/repo", "title": "Fix bug in authentication", "createdAt": "2024-06-15T10:30:00Z", "mergedAt": "2024-06-16T14:20:00Z", "state": "MERGED", "filesChanged": 5, "additions": 120, "deletions": 45 } ] } ``` ### 2. `github.getPRReviews` Fetch PR reviews submitted by the employee. Filters by repository. **Input:** ```json { "username": "octocat", "repos": ["owner/repo"], "from": "2024-01-01T00:00:00Z", "to": "2024-12-31T23:59:59Z" } ``` **Note:** `from` and `to` are optional. If omitted, defaults to last 3 months. `repos` is required (at least one repository). **Output:** ```json { "reviews": [ { "id": "PRR_kwDO...", "state": "APPROVED", "prId": "PR_kwDO...", "prNumber": 123, "prTitle": "Add feature X", "prRepo": "owner/repo", "submittedAt": "2024-06-20T09:15:00Z" } ] } ``` ### 3. `github.getReviewComments` Fetch inline and general review comments. Returns structured JSON with PR-level grouping, totals, and date range. Filters by repository. **Input:** ```json { "username": "octocat", "repos": ["owner/repo"], "from": "2024-01-01T00:00:00Z", "to": "2024-12-31T23:59:59Z" } ``` **Note:** `from` and `to` are optional. If omitted, defaults to last 3 months. `repos` is required (at least one repository). **Note:** The `repos` parameter is required (at least one repository). Only comments on PRs in the specified repositories will be included. `from` and `to` are optional (defaults to last 3 months if omitted). **Output:** ```json { "userId": "octocat", "dateRange": { "from": "2024-01-01T00:00:00Z", "to": "2024-12-31T23:59:59Z" }, "totalPRsReviewed": 5, "totalComments": 12, "prs": [ { "prId": "PR_kwDO...", "prNumber": 123, "prTitle": "Add feature X", "prRepo": "owner/repo", "prUrl": "https://github.com/owner/repo/pull/123", "prCreatedAt": "2024-06-15T10:30:00Z", "comments": [ "Consider using a constant here", "This looks good!" ], "totalComments": 2 }, { "prId": "PR_kwDO...", "prNumber": 124, "prTitle": "Fix bug Y", "prRepo": "owner/repo", "prUrl": "https://github.com/owner/repo/pull/124", "prCreatedAt": "2024-06-20T14:20:00Z", "comments": [ "Maybe we should add error handling here" ], "totalComments": 1 } ] } ``` **Note:** All comment bodies are properly JSON-escaped to handle newlines (`\n`), quotes, and other special characters. The response is 100% valid JSON format. ### 4. `github.getCommentImpact` Analyze whether review comments resulted in code changes. Filters by repository. **Input:** ```json { "username": "octocat", "repos": ["owner/repo"], "from": "2024-01-01T00:00:00Z", "to": "2024-12-31T23:59:59Z" } ``` **Note:** `from` and `to` are optional. If omitted, defaults to last 3 months. `repos` is required (at least one repository). **Output:** ```json { "impacts": [ { "commentId": "PRRC_kwDO...", "prId": "PR_kwDO...", "hadImpact": true, "confidence": 0.7, "evidence": [ "Commit abc1234 modified files after comment (3 files)" ] } ], "stats": { "totalComments": 25, "totalPRsReviewed": 10, "totalImpacts": 8 } } ``` **Note:** - Only comments with actual impact (commits found after comment) are included in the `impacts` array - The `stats` object is only included if data is available (i.e., if comments were analyzed) - Statistics are calculated from existing data without additional API calls ### 5. `github.getUserComments` Fetch all comments (review comments and issue comments) added by a user for a given repository within a time duration. This tool combines PR review comments and PR issue comments, filters by `comment.createdAt` and author, normalizes the results, and deduplicates them. **Input:** ```json { "username": "octocat", "repos": ["owner/repo"], "from": "2024-01-01T00:00:00Z", "to": "2024-12-31T23:59:59Z" } ``` **Note:** `from` and `to` are optional. If omitted, defaults to last 3 months. `repos` is required (at least one repository). **Output:** ```json { "comments": [ { "id": "PRRC_kwDO...", "body": "Consider using a constant here", "createdAt": "2024-06-20T09:15:00Z", "author": "octocat", "prId": "PR_kwDO...", "prNumber": 123, "prTitle": "Add feature X", "prRepo": "owner/repo", "commentType": "review", "filePath": "src/utils/helper.ts", "lineNumber": 42, "reviewId": "PRR_kwDO..." }, { "id": "IC_kwDO...", "body": "Great work! This looks good to me.", "createdAt": "2024-06-21T14:30:00Z", "author": "octocat", "prId": "PR_kwDO...", "prNumber": 123, "prTitle": "Add feature X", "prRepo": "owner/repo", "commentType": "issue", "filePath": null, "lineNumber": null, "reviewId": null } ] } ``` **Note:** This tool uses GitHub GraphQL APIs directly and filters by `comment.createdAt` client-side for accurate time-based filtering. It combines both review comments (inline comments from PR reviews) and issue comments (general comments on PRs), normalizes them into a unified format, and deduplicates by comment ID. ### 6. `github.getUserRepoStats` Get comprehensive repository statistics for a user within a time frame. Aggregates all activity metrics including PRs, comments, reviews, and code changes. **Input:** ```json { "username": "octocat", "repos": ["owner/repo"], "from": "2024-01-01T00:00:00Z", "to": "2024-12-31T23:59:59Z" } ``` **Note:** `from` and `to` are optional. If omitted, defaults to last 3 months. `repos` is required (at least one repository). **Output:** ```json { "stats": { "username": "octocat", "repo": "owner/repo", "timeRange": { "from": "2024-01-01T00:00:00Z", "to": "2024-12-31T23:59:59Z" }, "prs": { "count": 15, "merged": 12, "open": 2, "closed": 1 }, "comments": { "total": 45, "review": 30, "issue": 15 }, "reviews": { "total": 20, "totalPRsReviewed": 15, "approved": 12, "changesRequested": 5, "commented": 3 }, "codeChanges": { "filesChanged": 120, "additions": 3500, "deletions": 800, "netChange": 2700 } } } ``` **Note:** This tool combines data from multiple sources (`getAuthoredPRs`, `getUserComments`, `getPRReviews`) to provide a complete overview of user activity in a repository. All statistics are filtered by the specified time range and repository. **Important:** When comparing with `github.getReviewComments`: - `getUserRepoStats.comments.total` includes both review comments AND issue comments, while `getReviewComments.totalComments` includes only review comments - `getUserRepoStats.comments.review` should match `getReviewComments.totalComments` when both are filtered by the same repository - `getUserRepoStats.reviews.totalPRsReviewed` counts unique PRs reviewed, while `getUserRepoStats.reviews.total` counts total review submissions (a user can review the same PR multiple times) ## Agent Orchestration This MCP server is designed for use by AI agents and agent orchestration systems. All tools include: - **Detailed descriptions** with use cases and examples - **Parameter examples** in tool schemas - **Consistent response formats** for easy parsing - **Automatic filtering** of auto-generated content - **Error handling** with clear error messages ### Quick Reference for Agents | Tool | Best For | Returns | |------|----------|---------| | `github.getUserRepoStats` | **Quick overview** - Single call for all metrics | Complete stats (PRs, comments, reviews, code changes) | | `github.getAuthoredPRs` | PR analysis | Array of PRs with metadata | | `github.getPRReviews` | Review participation | Array of reviews with states | | `github.getReviewComments` | Comment analysis | Grouped comments by PR | | `github.getCommentImpact` | Review effectiveness | Impact assessments with confidence scores | | `github.getUserComments` | All comments | Combined review + issue comments | **See [AGENT_GUIDE.md](./AGENT_GUIDE.md) for comprehensive agent documentation, workflows, and best practices.** **See [agent-examples.json](./agent-examples.json) for real-world agent usage examples and workflows.** ## Example Agent Call Here's an example of how an AI agent might use this MCP server: ```typescript // Agent workflow for collecting data for employee performance analysis // 1. Get all PRs authored by employee in Q1 2024 const prs = await mcp.callTool('github.getAuthoredPRs', { username: 'johndoe', repos: ['company/main-repo'], from: '2024-01-01T00:00:00Z', to: '2024-03-31T23:59:59Z' }); // 2. Get PR reviews to assess code review participation const reviews = await mcp.callTool('github.getPRReviews', { username: 'johndoe', repos: ['company/main-repo'], from: '2024-01-01T00:00:00Z', to: '2024-03-31T23:59:59Z' }); // 3. Analyze review comment impact const impacts = await mcp.callTool('github.getCommentImpact', { username: 'johndoe', repos: ['company/main-repo'], from: '2024-01-01T00:00:00Z', to: '2024-03-31T23:59:59Z' }); // 4. Get all comments by employee for a specific repository const comments = await mcp.callTool('github.getUserComments', { username: 'johndoe', repos: ['company/important-repo'], from: '2024-01-01T00:00:00Z', to: '2024-03-31T23:59:59Z' }); // 6. Get comprehensive repository statistics const repoStats = await mcp.callTool('github.getUserRepoStats', { username: 'johndoe', repos: ['company/important-repo'], from: '2024-01-01T00:00:00Z', to: '2024-03-31T23:59:59Z' }); // Returns aggregated stats: PRs, comments, reviews, code changes ``` ## Design Decisions ### GraphQL over REST - More efficient for nested data (reviews, comments, files) - Single request for complex queries - Better type safety ### Cursor-based Pagination - Handles large datasets efficiently - No duplicate results - Predictable performance ### Normalized DTOs - Consistent data structure for agents - Hides GitHub API complexity - Easy to extend ### Rate Limit Handling - Automatic detection and waiting - Request ID logging for debugging - Graceful error messages ### Case-Insensitive Usernames - User-friendly (handles @ prefix, case variations) - Normalizes to lowercase for consistency ## Error Handling The server handles: - **Authentication errors**: Clear messages about GITHUB_TOKEN - **Rate limits**: Automatic waiting and informative errors - **Invalid timestamps**: Validation with helpful error messages - **Missing data**: Graceful defaults (null, empty arrays) ## Extensibility The architecture supports easy extension: 1. **New Tools**: Add to `tools.ts` and register in `server.ts` 2. **New Queries**: Add GraphQL queries to `queries.ts` 3. **New Mappers**: Extend `mapper.ts` with new DTOs 4. **Caching**: Add caching layer in `client.ts` (extension point) ## Development ```bash # Build npm run build # Watch mode npm run dev # Run npm start ``` ## Agent Integration Examples ### Example 1: Performance Review Data Collection ```typescript // Get comprehensive stats in one call (from/to optional, defaults to last 3 months) const stats = await mcp.callTool('github.getUserRepoStats', { username: 'johndoe', repos: ['company/main-repo'], from: '2024-01-01T00:00:00Z', to: '2024-12-31T23:59:59Z' }); // Returns: Complete metrics that can be used for performance reviews ``` ### Example 2: Code Review Quality Assessment ```typescript // Step 1: Get review activity const reviews = await mcp.callTool('github.getPRReviews', { username: 'reviewer-name', repos: ['company/main-repo'], from: '2024-01-01T00:00:00Z', to: '2024-12-31T23:59:59Z' }); // Step 2: Measure review impact const impact = await mcp.callTool('github.getCommentImpact', { username: 'reviewer-name', repos: ['company/main-repo'], from: '2024-01-01T00:00:00Z', to: '2024-12-31T23:59:59Z' }); // Calculate effectiveness: impact.stats.totalImpacts / impact.stats.totalComments ``` ### Example 3: Multi-Repository Analysis ```typescript // Option 1: Get stats for multiple repos separately const repos = ['company/repo1', 'company/repo2']; const results = await Promise.all( repos.map(repo => mcp.callTool('github.getUserRepoStats', { username: 'developer-name', repos: [repo], from: '2024-01-01T00:00:00Z', to: '2024-12-31T23:59:59Z' }) ) ); // Option 2: Get stats for multiple repos in one call (aggregated) const aggregatedStats = await mcp.callTool('github.getUserRepoStats', { username: 'developer-name', repos: ['company/repo1', 'company/repo2'], from: '2024-01-01T00:00:00Z', to: '2024-12-31T23:59:59Z' }); ``` **For more examples and workflows, see [AGENT_GUIDE.md](./AGENT_GUIDE.md).** ## License MIT

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/radireddy/github-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server