# GitHub Fetcher MCP

[![npm version](https://badge.fury.io/js/github-fetcher-mcp.svg)](https://www.npmjs.com/package/github-fetcher-mcp)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![Node.js Version](https://img.shields.io/badge/node-%3E%3D18.0.0-brightgreen)](https://nodejs.org/)
[![TypeScript](https://img.shields.io/badge/TypeScript-5.3-blue)](https://www.typescriptlang.org/)
[![Tests](https://img.shields.io/badge/tests-79%20passed-success)](https://github.com/choesumin/github-fetcher-mcp)

MCP (Model Context Protocol) server for fetching GitHub repository files and directory trees.

## Features

- **fetch-file**: Fetch raw file content from GitHub repositories
- **fetch-subdir-tree**: Fetch directory tree structure in unix tree format
- **fetch-sub-tree** ⭐ NEW: Enhanced directory tree with file sizes, depth limits, statistics, and filtering
- Flexible configuration via CLI arguments or per-request parameters
- Built with TypeScript for type safety
- Comprehensive test coverage (79 tests)

## Installation

### NPM

```bash
npm install -g github-fetcher-mcp
```

### Smithery

To install GitHub Fetcher MCP Server for any client automatically via [Smithery](https://smithery.ai):

```bash
npx -y @smithery/cli@latest install github-fetcher-mcp --client <CLIENT_NAME>
```

Available clients: `cursor`, `claude`, `vscode`, `windsurf`, `cline`, `zed`, etc.

**Example for Cursor:**

```bash
npx -y @smithery/cli@latest install github-fetcher-mcp --client cursor
```

This will automatically configure the MCP server in your chosen client.

## MCP Client Integration

GitHub Fetcher MCP can be integrated with various AI coding assistants and IDEs that support the Model Context Protocol (MCP).

### Requirements

- Node.js >= v18.0.0
- An MCP-compatible client (Cursor, Claude Code, VS Code, Windsurf, etc.)

<details>
<summary><b>Install in Cursor</b></summary>

Go to: `Settings` -> `Cursor Settings` -> `MCP` -> `Add new global MCP server`

Add the following configuration to your `~/.cursor/mcp.json` file:

```json
{
  "mcpServers": {
    "github-fetcher": {
      "command": "npx",
      "args": ["-y", "github-fetcher-mcp", "--repoIdentifier", "facebook/react/main"]
    }
  }
}
```

**Without repoIdentifier** (specify repository per request):

```json
{
  "mcpServers": {
    "github-fetcher": {
      "command": "npx",
      "args": ["-y", "github-fetcher-mcp"]
    }
  }
}
```

</details>

<details>
<summary><b>Install in Claude Code</b></summary>

Run this command:

```sh
claude mcp add github-fetcher -- npx -y github-fetcher-mcp --repoIdentifier facebook/react/main
```

Or without repoIdentifier:

```sh
claude mcp add github-fetcher -- npx -y github-fetcher-mcp
```

</details>

<details>
<summary><b>Install in VS Code</b></summary>

Add this to your VS Code MCP config file. See [VS Code MCP docs](https://code.visualstudio.com/docs/copilot/chat/mcp-servers) for more info.

```json
"mcp": {
  "servers": {
    "github-fetcher": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "github-fetcher-mcp", "--repoIdentifier", "facebook/react/main"]
    }
  }
}
```

</details>

<details>
<summary><b>Install in Windsurf</b></summary>

Add this to your Windsurf MCP config file:

```json
{
  "mcpServers": {
    "github-fetcher": {
      "command": "npx",
      "args": ["-y", "github-fetcher-mcp", "--repoIdentifier", "facebook/react/main"]
    }
  }
}
```

</details>

<details>
<summary><b>Install in Cline</b></summary>

1. Open **Cline**
2. Click the hamburger menu icon (☰) to enter the **MCP Servers** section
3. Choose **Remote Servers** tab
4. Click the **Edit Configuration** button
5. Add github-fetcher to `mcpServers`:

```json
{
  "mcpServers": {
    "github-fetcher": {
      "command": "npx",
      "args": ["-y", "github-fetcher-mcp", "--repoIdentifier", "facebook/react/main"]
    }
  }
}
```

</details>

<details>
<summary><b>Install in Claude Desktop</b></summary>

Open Claude Desktop developer settings and edit your `claude_desktop_config.json` file:

```json
{
  "mcpServers": {
    "github-fetcher": {
      "command": "npx",
      "args": ["-y", "github-fetcher-mcp", "--repoIdentifier", "facebook/react/main"]
    }
  }
}
```

</details>

<details>
<summary><b>Install in Zed</b></summary>

Add this to your Zed `settings.json`:

```json
{
  "context_servers": {
    "github-fetcher": {
      "source": "custom",
      "command": "npx",
      "args": ["-y", "github-fetcher-mcp", "--repoIdentifier", "facebook/react/main"]
    }
  }
}
```

</details>

<details>
<summary><b>Install in Roo Code</b></summary>

Add this to your Roo Code MCP configuration file:

```json
{
  "mcpServers": {
    "github-fetcher": {
      "command": "npx",
      "args": ["-y", "github-fetcher-mcp", "--repoIdentifier", "facebook/react/main"]
    }
  }
}
```

</details>

<details>
<summary><b>Using with Bun</b></summary>

```json
{
  "mcpServers": {
    "github-fetcher": {
      "command": "bunx",
      "args": ["-y", "github-fetcher-mcp", "--repoIdentifier", "facebook/react/main"]
    }
  }
}
```

</details>

<details>
<summary><b>Using with Docker</b></summary>

**Build the Docker Image:**

Create a `Dockerfile`:

```dockerfile
FROM node:18-alpine

WORKDIR /app

# Install the package globally
RUN npm install -g github-fetcher-mcp

# Expose the server port
EXPOSE 3000

# Default command to run the server
CMD ["github-fetcher-mcp"]
```

Build the image:

```bash
docker build -t github-fetcher-mcp .
```

**Configure Your MCP Client:**

```json
{
  "mcpServers": {
    "github-fetcher": {
      "command": "docker",
      "args": ["run", "-i", "--rm", "-p", "3000:3000", "github-fetcher-mcp", "--repoIdentifier", "facebook/react/main"]
    }
  }
}
```

</details>

## Usage

### With Repository Identifier (CLI Argument)

When you provide a `--repoIdentifier` argument, all tools will use that repository by default:

```bash
github-fetcher-mcp --repoIdentifier facebook/react/main
```

**Tools available:**
- `fetch-file`: Requires only `filePath`
- `fetch-subdir-tree`: Requires only `dirPath`
- `fetch-sub-tree`: Requires only `dirPath` (+ optional: `showSize`, `maxDepth`, `showStats`, `fileExtFilter`)

### Without Repository Identifier

When no repository identifier is provided, you can specify the repository for each request:

```bash
github-fetcher-mcp
```

**Tools available:**
- `fetch-file`: Requires `ownerName`, `repoName`, `branchName` (optional, default: 'main'), and `filePath`
- `fetch-subdir-tree`: Requires `ownerName`, `repoName`, `branchName` (optional, default: 'main'), and `dirPath`
- `fetch-sub-tree`: Requires `ownerName`, `repoName`, `branchName` (optional, default: 'main'), `dirPath` (+ optional: `showSize`, `maxDepth`, `showStats`, `fileExtFilter`)

## Available Tools

GitHub Fetcher MCP provides the following tools that can be used by LLMs:

- **fetch-file**: Fetches the raw content of a file from a GitHub repository
  - Required parameters vary based on whether `--repoIdentifier` is provided
  - Returns the complete file content as text

- **fetch-subdir-tree**: Fetches directory tree structure in unix tree format
  - Required parameters vary based on whether `--repoIdentifier` is provided
  - Returns formatted directory tree showing files and subdirectories

- **fetch-sub-tree** ⭐ NEW: Enhanced version with advanced options
  - Required parameters vary based on whether `--repoIdentifier` is provided
  - Optional parameters:
    - `showSize` (boolean): Show file and directory sizes
    - `maxDepth` (number): Limit tree depth (e.g., 1 for immediate children only)
    - `showStats` (boolean): Show statistics summary (default: true)
    - `fileExtFilter` (string[]): Filter files by extensions (e.g., [".ts", ".js"])
  - Returns enhanced directory tree with optional file sizes and statistics

## Usage Examples

### Example 1: Fetch a specific file

**In Cursor/Claude Code:**
```
Fetch the package.json file from the facebook/react repository on the main branch
```

**In any MCP client (with repoIdentifier configured):**
```
Show me the contents of src/index.ts
```

### Example 2: Browse directory structure

**In Cursor/Claude Code:**
```
Show me the directory structure of the src folder in microsoft/vscode on the main branch
```

**In any MCP client (with repoIdentifier configured):**
```
What files are in the components directory?
```

### Example 3: Analyze code structure

**In Cursor/Claude Code:**
```
I want to understand the structure of the Next.js repository.
Show me the directory tree of the packages folder from vercel/next.js on the canary branch.
Then fetch the package.json file to see the dependencies.
```

## Tool Reference

### fetch-file

Fetches the raw content of a file from a GitHub repository.

**With repoIdentifier:**
```json
{
  "filePath": "src/index.ts"
}
```

**Without repoIdentifier:**
```json
{
  "ownerName": "facebook",
  "repoName": "react",
  "branchName": "main",
  "filePath": "src/index.ts"
}
```

### fetch-subdir-tree

Fetches directory tree structure in unix tree format.

**With repoIdentifier:**
```json
{
  "dirPath": "src"
}
```

**Without repoIdentifier:**
```json
{
  "ownerName": "microsoft",
  "repoName": "vscode",
  "branchName": "main",
  "dirPath": "src"
}
```

### fetch-sub-tree ⭐ NEW

Enhanced directory tree with file sizes, depth limits, and filtering options.

**With repoIdentifier - Basic usage:**
```json
{
  "dirPath": "src"
}
```

**With repoIdentifier - Show file sizes:**
```json
{
  "dirPath": "src",
  "showSize": true
}
```

**With repoIdentifier - Limit depth:**
```json
{
  "dirPath": "src",
  "maxDepth": 2
}
```

**With repoIdentifier - Filter by file extensions:**
```json
{
  "dirPath": "src",
  "fileExtFilter": [".ts", ".tsx"]
}
```

**With repoIdentifier - All options:**
```json
{
  "dirPath": "src",
  "showSize": true,
  "maxDepth": 3,
  "showStats": true,
  "fileExtFilter": [".ts", ".js"]
}
```

**Example Output (with showSize and showStats):**
```
src/
├── components/ (2 files, 15.3KB)
│   ├── Button.tsx (8.2KB)
│   └── Input.tsx (7.1KB)
└── utils/ (3 files, 5.8KB)
    ├── helpers.ts (2.1KB)
    ├── format.ts (1.9KB)
    └── validate.ts (1.8KB)

📊 Summary: 2 directories, 5 files, 21.1KB total
```

**Without repoIdentifier:**
```json
{
  "ownerName": "microsoft",
  "repoName": "vscode",
  "branchName": "main",
  "dirPath": "src",
  "showSize": true,
  "maxDepth": 2
}
```

## Docker Usage

### Build Docker Image

```bash
docker build -t github-fetcher-mcp .
```

### Run with Docker

**With repoIdentifier:**

```bash
docker run -d -p 3000:3000 \
  --name github-fetcher \
  github-fetcher-mcp \
  node dist/server.js --repoIdentifier facebook/react/main
```

**Without repoIdentifier:**

```bash
docker run -d -p 3000:3000 \
  --name github-fetcher \
  github-fetcher-mcp
```

### Docker Compose Example

Create a `docker-compose.yml`:

```yaml
version: '3.8'

services:
  github-fetcher-mcp:
    build: .
    ports:
      - "3000:3000"
    environment:
      - PORT=3000
      - NODE_ENV=production
    command: ["node", "dist/server.js", "--repoIdentifier", "facebook/react/main"]
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "node", "-e", "require('http').get('http://localhost:3000/mcp', (r) => {process.exit(r.statusCode === 200 ? 0 : 1)})"]
      interval: 30s
      timeout: 3s
      retries: 3
      start_period: 5s
```

Run with Docker Compose:

```bash
docker-compose up -d
```

### Use Docker Image in MCP Clients

Configure your MCP client to use the Docker container:

```json
{
  "mcpServers": {
    "github-fetcher": {
      "command": "docker",
      "args": [
        "run",
        "-i",
        "--rm",
        "github-fetcher-mcp",
        "node",
        "dist/server.js",
        "--repoIdentifier",
        "facebook/react/main"
      ]
    }
  }
}
```

## Development

```bash
# Install dependencies
npm install

# Run in development mode
npm run dev

# Run tests
npm test

# Build
npm run build

# Type check
npm run typecheck

# Lint
npm run lint
```

## Architecture

The project follows a modular architecture:

- **config/**: CLI argument parsing
- **services/**: GitHub API integration and tree formatting
- **tools/**: MCP tool implementations
- **types/**: TypeScript type definitions
- **utils/**: Utility functions

## Testing

The project has comprehensive test coverage:
- Unit tests for all services, tools, and utilities
- Integration tests for tool creation
- 79 total tests, all passing

```bash
# Run all tests
npm test

# Run tests in watch mode
npm run test:watch

# Generate coverage report
npm run test:coverage
```

## License

MIT

## Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

## Author

choesumin
