Content
# github-mcp-server
A hand-built MCP server that wraps the GitHub REST API. 52 tools covering
nearly everything you'd do with GitHub day-to-day.
## Tools
**Auth**
- `get_authenticated_user`
**Repositories**
- `list_my_repos`, `get_repo`, `search_repos`, `list_commits`
- `create_repo`, `update_repo`, `delete_repo` *(requires typed confirmation)*
**Branches, Tags, Releases**
- `list_branches`, `get_branch`, `create_branch`
- `list_tags`, `list_releases`, `get_latest_release`, `create_release`
- `compare_commits`
**Stars, Watching, Forks**
- `star_repo`, `unstar_repo`, `list_starred_repos`
- `fork_repo`, `list_forks`
**Issues**
- `list_issues`, `get_issue`, `create_issue`, `comment_on_issue`, `close_issue`
**Labels & Milestones**
- `list_labels`, `create_label`, `add_labels_to_issue`
- `list_milestones`, `create_milestone`
**Collaborators**
- `list_collaborators`, `add_collaborator`
**Pull Requests**
- `list_pull_requests`, `get_pull_request`, `create_pull_request`, `get_pull_request_diff_files`
- `merge_pull_request`, `list_pr_reviews`, `create_pr_review`, `request_pr_reviewers`
**Search**
- `search_code`, `search_issues`, `search_users`
**Gists**
- `list_my_gists`, `create_gist`
**GitHub Actions**
- `list_workflows`, `list_workflow_runs`, `trigger_workflow`
**Files**
- `get_file_contents`, `list_directory_contents`, `create_or_update_file`
## 1. Create a GitHub Personal Access Token
1. Go to https://github.com/settings/tokens?type=beta (fine-grained tokens)
2. Click "Generate new token"
3. Under "Repository access", choose specific repos or "All repositories"
4. Under "Permissions", grant at minimum:
- Contents: Read and write
- Issues: Read and write
- Pull requests: Read and write
- Metadata: Read-only (usually required automatically)
5. Generate and copy the token (starts with `github_pat_` or `ghp_`) —
you won't be able to see it again.
## 2. Configure the server
Create a `.env` file in this folder (never commit this file):
```
GITHUB_TOKEN=github_pat_xxxxxxxxxxxxxxxxxxxxxxxxxxxx
```
## 3. Install dependencies
```powershell
cd github-mcp-server
python -m venv venv
.\venv\Scripts\Activate.ps1
pip install -r requirements.txt
```
## 4. Test it standalone
```powershell
mcp dev server.py
```
In the Inspector, set Command to your venv's python.exe and Arguments to
`server.py` (same fix we used for local-tools). Try `get_authenticated_user`
first with no arguments — it should return your GitHub profile.
## 5. Connect to Claude Desktop
On Windows, if Claude Desktop is the MSIX/Store version, edit the config at:
```
%LOCALAPPDATA%\Packages\Claude_<id>\LocalCache\Roaming\Claude\claude_desktop_config.json
```
(Not the documented `%APPDATA%\Claude\` path -- check both, and use whichever
one Claude Desktop actually reads. See the troubleshooting note below.)
Add to `mcpServers` (merge with whatever else is already in the file):
```json
{
"mcpServers": {
"github-mcp-server": {
"command": "C:\\absolute\\path\\to\\github-mcp-server\\venv\\Scripts\\python.exe",
"args": ["C:\\absolute\\path\\to\\github-mcp-server\\server.py"]
}
}
}
```
Restart Claude Desktop fully (End Task in Task Manager, then reopen), then
check via the "+" button in the chat box -> Connectors.
## Security notes
- `.env` is gitignored -- never commit your token.
- Scope the token to only the repos/permissions you actually need.
- `create_or_update_file` commits directly to the branch you specify --
there's no confirmation step beyond what your MCP client asks before
calling tools, so treat it like any other write-capable tool.
- `delete_repo` is permanent and irreversible. It requires you to type the
exact repo name as `confirm_repo_name` -- this is a safeguard against an
AI client calling it by mistake, not a substitute for being careful about
what you ask it to do.
## Extending it
Every tool here follows the same shape: map arguments to a GitHub REST
endpoint, call `_request()`, return the result. GitHub's API docs
(https://docs.github.com/en/rest) are effectively the tool spec -- to add
a new tool, find the endpoint you want and wrap it the same way, e.g.:
```python
@mcp.tool()
def list_branches(owner: str, repo: str) -> dict:
"""List branches in a repository."""
return _request("GET", f"/repos/{owner}/{repo}/branches")
```