GitHub MCP Server
by decuma02
README.md
# Kage — GitHub MCP Server
> **Kage** (影, *shadow*) acts as the invisible layer between an LLM and GitHub — an AI agent can command it without ever touching a UI.
[](https://python.org)
[](https://github.com/modelcontextprotocol/python-sdk)
[](LICENSE)
---
## What is this?
**Kage** is a custom [Model Context Protocol (MCP)](https://modelcontextprotocol.io) server that exposes GitHub repository operations as structured, schema-validated tools that any MCP-compatible LLM agent (Claude Desktop, Claude Code, etc.) can call autonomously.
Instead of writing hardcoded scripts that chain GitHub API calls, an agent connected to Kage can **think, plan, and act** — searching for issues, reading their context, and creating new ones — all in one natural language conversation.
### Why MCP instead of a plain REST API?
A REST API requires a human (or hardcoded client) to know *exactly* what endpoints to call. MCP is different: the server **advertises its capabilities at runtime** via JSON-RPC. An LLM can query the server for what tools exist, read their schemas, and decide autonomously how to use them. No hardcoding, no predefined flows.
---
## Architecture
```
┌─────────────────────────┐ JSON-RPC 2.0 over stdio
│ LLM Agent │◄────────────────────────────────►│ Kage MCP Server (Python) │
│ (Claude Desktop / Code) │ │ │
└─────────────────────────┘ │ FastMCP Framework │
│ ↓ │
│ Pydantic Validation │
│ ↓ │
│ PyGithub Client │
│ ↓ │
│ GitHub REST API │
└──────────────────────────┘
```
```mermaid
sequenceDiagram
participant Agent as LLM Agent (Claude)
participant Kage as Kage MCP Server
participant GH as GitHub API
Agent->>Kage: tools/list → "What can you do?"
Kage-->>Agent: Returns tool names + JSON Schemas
Agent->>Kage: tools/call → search_issues(repo, query)
Note over Kage: Pydantic validates inputs
Kage->>GH: Authenticated search request
GH-->>Kage: Raw issue data
Note over Kage: Formats + limits to top 10 results
Kage-->>Agent: Structured JSON result
Agent->>Kage: tools/call → create_issue(repo, title, body)
Note over Kage: Validates min_length constraints
Kage->>GH: POST /repos/{owner}/{repo}/issues
GH-->>Kage: Created issue data
Kage-->>Agent: { "html_url": "..." }
```
---
## Available Tools
| Tool | Description | Type |
|:---|:---|:---|
| `test_connection` | Verifies the server is alive and reachable | Read |
| `search_issues` | Search for issues/PRs in a repo using GitHub search syntax | Read |
| `get_issue_details` | Fetch title, body, author, state, and last 5 comments of an issue | Read |
| `create_issue` | Create a new issue with a validated title and body | Write |
### Tool Schemas
#### `search_issues`
```json
{
"repo": "owner/repo",
"query": "is:issue is:open label:bug"
}
```
#### `get_issue_details`
```json
{
"repo": "owner/repo",
"issue_number": 42
}
```
#### `create_issue`
```json
{
"repo": "owner/repo",
"title": "Min 5 characters required",
"body": "Min 10 characters required"
}
```
---
## Security Design
- **Least-Privilege Tokens:** Uses GitHub Fine-Grained Personal Access Tokens (PAT) scoped to a *single* repository with *only* Issues read/write permission. A compromised token cannot touch any other repo or perform any other action.
- **Pydantic Input Validation:** Every tool input is validated against a strict schema *before* any API call is made. If an LLM hallucinates a bad payload (e.g., an empty issue title), the server rejects it locally with a clear error — no wasted API call, no garbage data in your repo.
- **Additive-Only Writes:** The only write tool (`create_issue`) is additive. Destructive operations (delete, close, edit) are deliberately not exposed — preventing an LLM hallucination from causing irreversible damage.
- **Secret Management:** The GitHub token is loaded from a `.env` file (never hardcoded) and the `.env` is in `.gitignore`.
---
## Project Structure
```
Kage-The-MCP/
├── server.py # MCP server: all tool definitions and GitHub integration
├── requirements.txt # Python dependencies
├── .env.example # Template for environment variables (copy to .env)
├── .gitignore # Ensures .env and venv are never committed
├── start_inspector.bat # One-click script to launch MCP Inspector for local testing
└── LICENSE # MIT License
```
---
## Setup & Local Testing
### Prerequisites
- Python 3.10+
- Node.js (for MCP Inspector)
- A GitHub account and a test repository
### 1. Clone & Install
```powershell
git clone https://github.com/YourUsername/Kage-The-MCP.git
cd Kage-The-MCP
python -m venv venv
.\venv\Scripts\activate
pip install -r requirements.txt
```
### 2. Configure Your Token
Create a GitHub Fine-Grained PAT with:
- **Repository access:** Your test repo only
- **Permissions:** Issues → Read and write, Metadata → Read-only
Then create a `.env` file:
```env
GITHUB_TOKEN=github_pat_your_token_here
```
### 3. Run the MCP Inspector
```powershell
.\start_inspector.bat
```
Open the URL shown in your terminal (e.g., `http://localhost:6274`), set Command to `python` and Arguments to `server.py`, then click **Connect**.
---
## Stack
`Python` · `FastMCP (MCP SDK 1.28)` · `PyGithub` · `Pydantic v2` · `python-dotenv` · `MCP Inspector`
This server cannot be deployed
Maintenance
ActivityStale
ResponsivenessNo issues