|
2 | 2 |
|
3 | 3 | This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. |
4 | 4 |
|
5 | | -## Overview |
| 5 | +## Project Overview |
6 | 6 |
|
7 | | -GitHub MCP Server is a Model Context Protocol (MCP) server that provides access to GitHub documentation via the GitHub API. It's built with FastMCP and runs as a stdio-based MCP server, designed to be integrated with Claude Desktop or other MCP clients. |
| 7 | +GitHub MCP Server - A Model Context Protocol (MCP) server that provides GitHub API access for fetching and searching documentation in `/doc` folders across GitHub organizations. Built with FastMCP. |
8 | 8 |
|
9 | 9 | ## Development Commands |
10 | 10 |
|
11 | | -### Environment Setup |
12 | | - |
13 | 11 | ```bash |
14 | | -# Create and activate virtual environment |
| 12 | +# Setup |
15 | 13 | python3 -m venv .venv |
16 | | -source .venv/bin/activate # On Windows: .venv\Scripts\activate |
17 | | - |
18 | | -# Install dependencies |
| 14 | +source .venv/bin/activate |
19 | 15 | pip install -r requirements.txt |
| 16 | +cp .env.example .env # Add GITHUB_TOKEN |
20 | 17 |
|
21 | | -# Configure environment |
22 | | -cp .env.example .env |
23 | | -# Edit .env and add your GITHUB_TOKEN |
24 | | -``` |
25 | | - |
26 | | -### Running the Server |
27 | | - |
28 | | -```bash |
29 | | -# Run directly with Python (stdio mode for MCP) |
| 18 | +# Run locally (stdio transport for Claude Desktop) |
30 | 19 | python main.py |
31 | 20 |
|
32 | | -# Run with Docker |
33 | | -docker build -t github-mcp-server:local . |
34 | | -docker run -i --rm -e GITHUB_TOKEN='your_token' github-mcp-server:local |
35 | | - |
36 | | -# Run with docker-compose |
37 | | -docker-compose build |
38 | | -docker-compose up |
| 21 | +# Run with HTTP transport (for Hugging Face Spaces) |
| 22 | +# Set MCP_HTTP_TRANSPORT=true or modify main.py to use mcp.run(transport="http") |
39 | 23 | ``` |
40 | 24 |
|
41 | | -### Docker Build Performance |
42 | | - |
43 | | -The Dockerfile is optimized for fast rebuilds (10-20x faster): |
44 | | -- Uses BuildKit for layer caching |
45 | | -- Separates dependency installation from code copying |
46 | | -- Enable BuildKit: `export DOCKER_BUILDKIT=1` |
47 | | - |
48 | 25 | ## Architecture |
49 | 26 |
|
50 | | -### Single-File Architecture |
51 | | - |
52 | | -The entire server is implemented in `main.py` (~650 lines) with a clear functional organization: |
| 27 | +**Single-file MCP server** (`main.py`) using FastMCP framework: |
53 | 28 |
|
54 | | -1. **Configuration & Setup** (lines 1-37): Environment loading, logging, MCP initialization |
55 | | -2. **Helper Functions** (lines 39-114): GitHub API headers, /doc folder detection, content type determination |
56 | | -3. **Business Logic Functions** (lines 116-442): Core async functions that implement GitHub API interactions |
57 | | -4. **MCP Tools Registration** (lines 444-569): Decorated wrappers that expose business logic as MCP tools |
58 | | -5. **MCP Resources** (lines 571-638): URI-based resource handlers for documentation access |
59 | | -6. **Main Entry Point** (lines 640-652): Server startup |
| 29 | +1. **MCP Tools** (decorated with `@mcp.tool()`): |
| 30 | + - `get_org_repos_tool` - List repos with `/doc` folder detection (uses Search API first, falls back to listing all) |
| 31 | + - `get_repo_docs_tool` - Get documentation files from repo's `/doc` folder |
| 32 | + - `get_file_content_tool` - Fetch and decode file content (handles base64) |
| 33 | + - `search_documentation_tool` - Search docs across org using GitHub Code Search API |
60 | 34 |
|
61 | | -### Key Design Patterns |
| 35 | +2. **MCP Resources** (decorated with `@mcp.resource()`): |
| 36 | + - `documentation://{org}/{repo}` - List docs |
| 37 | + - `content://{org}/{repo}/{path}` - Get file content |
62 | 38 |
|
63 | | -**Separation of Concerns**: Business logic functions (e.g., `get_org_repos()`) are separate from MCP tool decorators (e.g., `get_org_repos_tool()`). This allows the core logic to be testable independently of MCP. |
| 39 | +3. **Business Logic Functions** (async, testable): |
| 40 | + - `get_org_repos()`, `get_repo_docs()`, `get_file_content()`, `search_documentation()` |
| 41 | + - Each tool is a thin wrapper calling these functions |
64 | 42 |
|
65 | | -**Async/Await Throughout**: All GitHub API interactions use `aiohttp` for async HTTP requests. Functions reuse `ClientSession` objects for connection pooling. |
| 43 | +## Key Implementation Details |
66 | 44 |
|
67 | | -**Two-Strategy Approach**: `get_org_repos()` tries GitHub Search API first (efficient, one request), then falls back to listing all repos individually if search fails. |
| 45 | +- **GitHub API strategy**: Search API first for efficiency, fallback to paginated list + check each repo |
| 46 | +- **Supported doc types**: `.md`, `.mmd`, `.mermaid`, `.svg`, `.yml`, `.yaml`, `.json` |
| 47 | +- **Content decoding**: Base64 content from GitHub API is automatically decoded |
| 48 | +- **Health check**: `/health` endpoint available via `@mcp.custom_route()` |
68 | 49 |
|
69 | | -**Base64 Decoding**: GitHub API returns file content as base64-encoded strings. The `get_file_content()` function automatically decodes this to UTF-8 text. |
| 50 | +## Environment Variables |
70 | 51 |
|
71 | | -## MCP Integration |
72 | | - |
73 | | -### Tools (4 total) |
74 | | - |
75 | | -- `get_org_repos_tool(org)` - Lists repositories with /doc folder detection |
76 | | -- `get_repo_docs_tool(org, repo)` - Lists documentation files in a repo's /doc folder |
77 | | -- `get_file_content_tool(org, repo, path)` - Fetches and decodes file content |
78 | | -- `search_documentation_tool(org, query)` - Searches docs across repos using GitHub Code Search API |
79 | | - |
80 | | -### Resources (2 patterns) |
81 | | - |
82 | | -- `documentation://{org}/{repo}` - Lists documentation files in formatted text |
83 | | -- `content://{org}/{repo}/{path}` - Returns raw file content |
84 | | - |
85 | | -### Environment Variables |
86 | | - |
87 | | -Required: |
88 | | -- `GITHUB_TOKEN` - GitHub personal access token (scopes: `repo`, `read:org`, `read:user`) |
89 | | - |
90 | | -Optional: |
| 52 | +- `GITHUB_TOKEN` - Required for API access (scopes: `repo`, `read:org`, `read:user`) |
91 | 53 | - `GITHUB_API_BASE_URL` - Default: `https://api.github.com` |
92 | 54 | - `LOG_LEVEL` - Default: `INFO` |
93 | | -- `MCP_SERVER_PORT` - Default: `8000` (note: not used in stdio mode) |
94 | | - |
95 | | -## Supported File Types |
96 | | - |
97 | | -The server filters for specific documentation file types in /doc folders: |
98 | | -- Markdown: `.md` |
99 | | -- Mermaid diagrams: `.mmd`, `.mermaid` |
100 | | -- SVG images: `.svg` |
101 | | -- OpenAPI specs: `.yml`, `.yaml`, `.json` |
102 | | -- Postman collections: `.json` (filename must start with "postman") |
103 | | - |
104 | | -## Error Handling |
105 | | - |
106 | | -- 404 responses return empty lists or specific error messages |
107 | | -- Rate limiting (403 from Search API) returns user-facing error message |
108 | | -- All GitHub API errors include status code and response text |
109 | | -- Missing GITHUB_TOKEN triggers warning but allows unauthenticated requests (with rate limits) |
110 | | - |
111 | | -## Claude Desktop Configuration |
112 | | - |
113 | | -Add to `claude_desktop_config.json`: |
114 | | - |
115 | | -**Docker deployment:** |
116 | | -```json |
117 | | -{ |
118 | | - "mcpServers": { |
119 | | - "github-docs": { |
120 | | - "command": "docker", |
121 | | - "args": ["run", "-i", "--rm", "-e", "GITHUB_TOKEN", "ghcr.io/sperekrestova/github-mcp-server:latest"], |
122 | | - "env": {"GITHUB_TOKEN": "ghp_your_token_here"} |
123 | | - } |
124 | | - } |
125 | | -} |
126 | | -``` |
127 | | - |
128 | | -**Python deployment:** |
129 | | -```json |
130 | | -{ |
131 | | - "mcpServers": { |
132 | | - "github-docs": { |
133 | | - "command": "python3", |
134 | | - "args": ["/absolute/path/to/main.py"], |
135 | | - "env": {"GITHUB_TOKEN": "ghp_your_token_here"} |
136 | | - } |
137 | | - } |
138 | | -} |
139 | | -``` |
140 | 55 |
|
141 | | -## Testing Approach |
| 56 | +## CI/CD |
142 | 57 |
|
143 | | -Currently no test suite exists. When adding tests: |
144 | | -- Test business logic functions separately from MCP tool wrappers |
145 | | -- Mock `aiohttp.ClientSession` for GitHub API interactions |
146 | | -- Test base64 decoding edge cases in `get_file_content()` |
147 | | -- Test /doc folder detection logic |
148 | | -- Test file type filtering against supported extensions |
| 58 | +Docker image published to `ghcr.io/sperekrestova/github-mcp-server` on push to main or version tags. Multi-platform build (amd64/arm64). |
0 commit comments