A hand-built GitHub MCP (Model Context Protocol) server exposing repositories, pull requests, and code search as tools for AI assistants like Claude.
Note: GitHub publishes an official MCP server with broad API coverage. This project is intentionally minimal — built from scratch to understand how MCP servers are structured, how tools are defined, and how the protocol works end-to-end. It is a learning and exploration project, not a replacement.
Author: Gift Mphuthi
| Tool | Description |
|---|---|
list_repos |
List repos for the authenticated user or a username |
get_repo |
Get details of a specific repository |
create_repo |
Create a new repository |
list_pull_requests |
List pull requests for a repository |
get_pull_request |
Get details and diff stats for a specific PR |
search_repos |
Search GitHub repositories |
search_code |
Search for code across GitHub |
src/
├── index.ts # Entry point (stdio transport — for Claude)
├── http.ts # HTTP server (for local testing with Postman)
├── server.ts # MCP server setup
├── config.ts # Env vars and constants
├── logger.ts # Pino logger singleton
├── types/
│ └── index.ts # Shared TypeScript interfaces
├── github/
│ └── client.ts # Octokit singleton
├── services/ # GitHub API calls
│ ├── repos.service.ts
│ ├── pullRequests.service.ts
│ └── search.service.ts
└── tools/ # MCP tool definitions
├── index.ts
├── repos.ts
├── pullRequests.ts
└── search.ts
npm installGo to GitHub Settings → Developer settings → Personal access tokens and create a token with the repo scope.
Add it to .mcp.json (already gitignored):
{
"mcpServers": {
"github-mcp-explorer": {
"command": "node",
"args": ["dist/index.js"],
"env": {
"GITHUB_TOKEN": "your_token_here"
}
}
}
}npm run buildAdd .mcp.json to the project root (see Setup above). Claude Code picks it up automatically on restart.
npm run start:http
# → GitHub MCP server listening on http://localhost:3000/mcp1. Initialize a session
POST http://localhost:3000/mcp
{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2024-11-05",
"clientInfo": { "name": "postman", "version": "1.0" },
"capabilities": {}
}
}Copy the mcp-session-id from the response header and include it in all subsequent requests.
2. List available tools
{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/list",
"params": {}
}3. Call a tool
{
"jsonrpc": "2.0",
"id": 3,
"method": "tools/call",
"params": {
"name": "search_repos",
"arguments": { "query": "language:typescript stars:>1000" }
}
}| Script | Description |
|---|---|
npm run build |
Compile TypeScript |
npm run start |
Start stdio server (for Claude) |
npm run start:http |
Start HTTP server (for Postman) |
npm run dev |
Watch mode |
npm run lint |
Run ESLint |
npm run lint:check |
ESLint with zero warnings (CI) |
npm run lint:fix |
Auto-fix lint issues |
npm run format |
Prettier write |
npm run format:check |
Prettier check (CI) |
npm run audit |
npm audit |
| Variable | Required | Description |
|---|---|---|
GITHUB_TOKEN |
Yes | GitHub personal access token (repo scope) |
PORT |
No | HTTP server port (default: 3000) |
LOG_LEVEL |
No | Pino log level (default: info) |
NODE_ENV |
No | Set to production for JSON logs |