GitHub Insights MCP Server
by AhmetSOGUT
README.md
# š GitHub Insights MCP Server
[](https://github.com/AhmetSOGUT/github-insights-mcp/actions/workflows/ci.yml)
An MCP (Model Context Protocol) server that lets Claude understand any public
GitHub repository ā its purpose, structure, tech stack, and architecture ā
by exposing typed, focused tools instead of requiring manual browsing.
Built to explore the MCP protocol: tool design, structured data contracts,
and the division of labor between a tool-providing server and the LLM
client that consumes it.
## Table of Contents
- [How it Works](#how-it-works)
- [Architecture](#architecture)
- [Tech Stack](#tech-stack)
- [Project Structure](#project-structure)
- [Getting Started](#getting-started)
- [Connecting to Claude Desktop](#connecting-to-claude-desktop)
- [Running Tests](#running-tests)
- [Design Decisions](#design-decisions)
- [Known Limitations](#known-limitations)
- [Roadmap](#roadmap)
## How it Works
Ask Claude Desktop about any public GitHub repo, and it can call one of five tools:
- **`get_repo_overview_tool`** ā metadata (stars, language, last update) + README content
- **`get_repo_structure_tool`** ā depth-limited file/folder tree
- **`get_tech_stack_tool`** ā detected languages and dependency manifest files
- **`generate_architecture_diagram_tool`** ā a Mermaid diagram of the top-level structure
- **`get_file_content_tool`** ā full content of a specific file, for deeper analysis
Claude decides which tools to call and in what order based on the question ā
e.g. reading `get_repo_structure_tool`'s output to identify an entry point
file, then calling `get_file_content_tool` to actually read it.
## Architecture
```
āāāāāāāāāāāāāāāāāāā stdio (MCP/JSON-RPC) āāāāāāāāāāāāāāāāāāāāāāāā
ā Claude Desktop ā āāāāāāāāāāāāāāāāāāāāāāāāāāā¶ ā GitHub Insights MCP ā
ā (MCP client) ā āāāāāāāāāāāāāāāāāāāāāāāāāāā ā Server ā
āāāāāāāāāāāāāāāāāāā āāāāāāāāāāāāā¬āāāāāāāāāāā
ā HTTPS (REST)
ā¼
āāāāāāāāāāāāāāāāāāāā
ā GitHub API ā
āāāāāāāāāāāāāāāāāāāā
```
The server runs locally as a subprocess launched by Claude Desktop, communicating
over stdio using the MCP protocol. It never talks to an LLM itself ā it fetches
and structures data from the GitHub REST API, and lets the calling LLM (Claude)
handle summarization and reasoning. See [Design Decisions](#design-decisions)
for why this split matters.
## Tech Stack
| Layer | Choice | Why |
|---|---|---|
| Protocol | Official `mcp` Python SDK (v2, `MCPServer`) | Standard, actively maintained |
| HTTP Client | `httpx` (async) | Async-native, pairs cleanly with MCP's async tool handlers |
| Data Validation | `pydantic` | Typed tool schemas, response validation |
| Configuration | `pydantic-settings` | Validated config, resolved to an absolute `.env` path (see below) |
| Resilience | `tenacity` | Retries on transient network errors, not on definitive API errors |
| Testing | `pytest`, `pytest-asyncio`, `respx` | Fully mocked HTTP ā no real GitHub calls during test runs |
## Project Structure
```
github-insights-mcp/
āāā server.py # MCP entrypoint - registers tools, starts stdio transport
āāā github_client.py # Sole GitHub REST API access layer (auth, retries, error mapping)
āāā analyzers/
ā āāā overview.py # Repo metadata + README content
ā āāā structure.py # Depth-limited file/folder tree
ā āāā tech_stack.py # Language + manifest file detection
ā āāā diagram.py # Mermaid diagram generation (pure function)
ā āāā file_content.py # Single-file content retrieval
āāā tests/
ā āāā conftest.py # Shared fixtures
ā āāā test_github_client.py # URL parsing, HTTP error mapping (mocked)
ā āāā test_tech_stack.py # Detection logic (mocked)
ā āāā test_diagram.py # Diagram generation (pure, unmocked)
āāā models.py # Pydantic models for every tool's input/output
āāā config.py # Validated settings, absolute .env resolution
āāā logging_config.py # Logging setup (stderr, not stdout ā see below)
āāā exceptions.py # Domain-specific exception types
āāā docs/
ā āāā PRD.md # Product requirements
ā āāā ARCHITECTURE.md # Technical design
āāā requirements.txt
āāā pytest.ini
āāā .env.example
```
## Getting Started
### Prerequisites
- Python 3.11+
- A GitHub Personal Access Token with **`public_repo`** scope only
([create one here](https://github.com/settings/tokens))
- Claude Desktop (free to install; no paid plan required for local MCP servers)
### Setup
```bash
git clone https://github.com/AhmetSOGUT/github-insights-mcp.git
cd github-insights-mcp
conda create -n github-insights-mcp python=3.11 -y
conda activate github-insights-mcp
pip install -r requirements.txt
cp .env.example .env
# edit .env and set GITHUB_TOKEN=your-token-here
```
## Connecting to Claude Desktop
1. Open Claude Desktop ā **Settings ā Developer ā Edit Config**
2. Add this server under `mcpServers` (create the key if it doesn't exist):
```json
{
"mcpServers": {
"github-insights": {
"command": "/absolute/path/to/your/python",
"args": ["/absolute/path/to/github-insights-mcp/server.py"]
}
}
}
```
Use the **absolute path** to the Python interpreter inside your conda
environment (`where python` on Windows / `which python` on macOS/Linux) ā
Claude Desktop does not inherit your shell's activated environment.
3. Restart Claude Desktop completely (quit from the system tray, not just
close the window).
4. Check **Settings ā Connectors** ā `github-insights` should show as connected.
5. Ask Claude something like: *"Summarize what this repo does:
https://github.com/owner/repo"*
## Running Tests
All GitHub API calls are mocked via `respx` ā no token or network access
needed to run the suite:
```bash
pytest -v
```
## Design Decisions
- **Why does the server not summarize anything itself?**
It returns structured, factual data (README text, file contents, metadata)
and leaves synthesis to the calling LLM. Calling a second LLM from inside
the server would mean a second API key, doubled latency, and duplicated
work the client is already positioned to do. This keeps the server a pure
tool provider, in line with what MCP is designed for.
- **Why log to `stderr` instead of `stdout`?**
MCP communicates with its client over `stdout`. Anything else written to
`stdout` ā including log output ā would corrupt the protocol stream and
break the connection. All logging in this project is explicitly routed
to `stderr`.
- **Why resolve `.env` via an absolute path in `config.py`?**
Claude Desktop launches this server from an unpredictable working
directory (not necessarily the project root). A relative `.env` path
works when run manually from the project folder but fails silently
under Claude Desktop, causing confusing startup failures. Resolving the
path via `Path(__file__).parent` makes config loading independent of how
the process was launched.
- **Why a single `GitHubClient` instead of calling `httpx` directly from
each analyzer?**
Authentication, retry behavior, and GitHub-specific error translation
(404 ā `RepoNotFoundError`, rate-limited 403 ā `RateLimitError`) live in
exactly one place. Analyzers stay focused on interpreting data, not on
HTTP or auth concerns.
## Known Limitations
- **README and file content are truncated** (README to ~3,000 characters,
individual files to 50,000 characters) to keep responses fast and
token-efficient. For very large files or sparse READMEs, this can
produce a less complete picture than Claude's own web browsing would,
which has no such caps ā this is a deliberate v1 trade-off, not an
oversight (see `docs/PRD.md`, Section 4).
- **The architecture diagram only reflects top-level folders**, not actual
import relationships between files. A more accurate diagram would
require parsing source files, which is out of scope for v1.
- **Single-user, PAT-based auth only.** Anyone using this server needs
their own GitHub token; there's no OAuth flow for a shared/hosted deployment.
## Roadmap
- [ ] Deeper architecture diagrams based on actual import/dependency parsing
- [ ] OAuth-based auth for a shared, multi-user deployment
- [ ] Commit/PR/issue activity summaries
- [ ] Smarter file selection (auto-detect entry points to read, rather than
requiring the LLM to guess a path)
- [ ] A remote-hosted version of the server
## License
MIT
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues