Skip to main content
Glama
tongax12

github-mcp-server

by tongax12
README.md
# GitHub MCP Server

Servidor MCP desarrollado con Node.js y TypeScript que permite a un host compatible, como Antigravity o VS Code, ejecutar operaciones sobre GitHub mediante lenguaje natural.

El servidor expone cinco tools para administrar repositorios, issues y archivos. Usa el transporte `stdio`, valida las entradas con Zod, autentica las solicitudes mediante Octokit y transforma los errores técnicos en mensajes comprensibles.

## Por qué es útil

Este servidor permite que un agente de IA ejecute tareas habituales de GitHub sin que el usuario tenga que escribir manualmente cada llamada a la API.

Casos de uso:

- Crear un repositorio para iniciar un proyecto.
- Registrar errores o tareas como issues.
- Consultar los repositorios de la cuenta autenticada.
- Revisar los issues abiertos de un repositorio.
- Crear o actualizar archivos y generar commits desde una instrucción en lenguaje natural.
- Integrar operaciones de GitHub en flujos de trabajo asistidos por IA.

Las operaciones que escriben en GitHub deben ejecutarse con cuidado. Se recomienda trabajar primero con repositorios de prueba y revisar los parámetros antes de confirmar cambios.

## Arquitectura

```mermaid
flowchart LR
    U[Usuario] --> H[Antigravity o VS Code]
    H --> C[Cliente MCP]
    C --> S[Servidor MCP\ntransporte stdio]
    S --> T[Handlers de tools]
    T --> O[Operaciones GitHub]
    O --> R[Octokit]
    R --> G[GitHub API]
```

Flujo interno:

```text
Prompt del usuario
  -> Host MCP
  -> tool registrada
  -> schema Zod
  -> operación GitHub
  -> Octokit
  -> GitHub API
  -> respuesta MCP
```

Las operaciones recuperables usan `withRetry`, con hasta tres intentos y backoff exponencial para rate limits, errores 5xx y errores de red recuperables. Los logs se escriben en `stderr` para no interferir con el protocolo MCP en `stdout`.

## Requisitos del sistema

- Node.js 18 o superior.
- npm 9 o superior recomendado.
- Una cuenta de GitHub.
- Un GitHub Personal Access Token (PAT).
- Un host MCP compatible: Antigravity, VS Code u otro cliente que soporte servidores `stdio`.
- Windows, macOS o Linux.

Verifica las versiones instaladas:

```bash
node --version
npm --version
```

## Instalación

Clona el repositorio y entra en la carpeta del proyecto:

```bash
git clone <URL_DEL_REPOSITORIO>
cd ProyectoM5_GastonStratta
```

Instala las dependencias:

```bash
npm install
```

Compila TypeScript en la carpeta `dist/`:

```bash
npm run build
```

Inicia el servidor compilado:

```bash
npm start
```

Para desarrollo, ejecuta TypeScript directamente:

```bash
npm run dev
```

El servidor usa `stdio`, por lo que normalmente debe ser iniciado por un host MCP y no como un servidor HTTP visible en el navegador.

## Configuración de GitHub

### 1. Obtener un Personal Access Token

1. Inicia sesión en GitHub.
2. Abre **Settings**.
3. Entra en **Developer settings**.
4. Selecciona **Personal access tokens**.
5. Elige **Tokens (classic)** y pulsa **Generate new token**.
6. Define un nombre, una fecha de expiración y el propietario del recurso.
7. Selecciona los permisos necesarios.
8. Genera el token y cópialo inmediatamente. GitHub no vuelve a mostrarlo completo.

También se puede usar un token clásico, pero los tokens fine-grained son preferibles porque permiten aplicar el principio de mínimo privilegio.

### 2. Permisos necesarios

Para un token fine-grained, concede como mínimo acceso al repositorio o a la cuenta donde se ejecutarán las operaciones:

| Operación | Permiso recomendado |
| --- | --- |
| Listar repositorios | `Metadata: Read` |
| Crear issues | `Issues: Write` |
| Listar issues | `Issues: Read` |
| Crear o actualizar archivos y commits | `Contents: Write` |
| Crear repositorios del usuario | Permiso de administración/repositorios que GitHub solicite para esa cuenta |

El permiso `Metadata: Read` suele ser obligatorio y se concede automáticamente en muchos tokens fine-grained. Si la organización aplica políticas adicionales, puede ser necesario que un administrador apruebe el token.

Para un token clásico, el scope `repo` cubre las operaciones sobre repositorios privados y sus contenidos. No agregues scopes administrativos si no son necesarios.

El endpoint de autenticación utilizado por el servidor también verifica el usuario autenticado. Si GitHub solicita un permiso adicional para esa cuenta, concédelo solo si la política de seguridad lo permite.

### 3. Configurar `.env`

Crea un archivo `.env` en la raíz del proyecto:

```env
GITHUB_TOKEN=tu_token_de_github
```

El cliente carga la variable mediante `dotenv`. No incluyas el token en el código, README, tests, logs ni commits.

Comprueba que `.env` esté excluido por `.gitignore`. Si el token se expone accidentalmente, revócalo desde GitHub y genera uno nuevo.

### 4. Configurar el servidor MCP en Antigravity o VS Code

El proyecto incluye [.vscode/mcp.json](.vscode/mcp.json):

```json
{
  "servers": {
    "github-mcp-server": {
      "type": "stdio",
      "command": "node",
      "args": ["${workspaceFolder}/dist/server.js"],
      "env": {
        "GITHUB_TOKEN": "${env:GITHUB_TOKEN}"
      }
    }
  }
}
```

Antes de iniciar el host MCP:

```bash
npm run build
```

Configura `GITHUB_TOKEN` en el entorno del sistema o en el entorno que utilice VS Code/Antigravity. El archivo MCP no contiene el secreto: solo referencia `${env:GITHUB_TOKEN}`.

En Antigravity, agrega un servidor MCP de tipo `stdio` con estos valores:

- **Command:** `node`
- **Arguments:** `${workspaceFolder}/dist/server.js`
- **Environment:** `GITHUB_TOKEN=${env:GITHUB_TOKEN}`

Cuando el host se conecte correctamente, debería descubrir estas cinco tools:

```text
create_repository
create_issue
list_repositories
create_commit
list_issues
```

## Tools disponibles

### `create_repository`

Crea un repositorio nuevo en la cuenta autenticada.

**Parámetros:**

| Nombre | Tipo | Obligatorio | Descripción |
| --- | --- | --- | --- |
| `name` | `string` | Sí | Nombre del repositorio. Debe ser un identificador válido de GitHub. |
| `description` | `string` | Sí | Descripción del repositorio. |

**Prompt de ejemplo:**

> Crea un repositorio privado llamado `mcp-demo` con la descripción `Repositorio de pruebas para mi servidor MCP`.

### `create_issue`

Crea un issue en un repositorio existente.

**Parámetros:**

| Nombre | Tipo | Obligatorio | Descripción |
| --- | --- | --- | --- |
| `owner` | `string` | Sí | Usuario u organización propietaria del repositorio. |
| `repo` | `string` | Sí | Nombre del repositorio. |
| `title` | `string` | Sí | Título del issue. |
| `body` | `string` | Sí | Descripción del problema o tarea. |

**Prompt de ejemplo:**

> Crea un issue en `usuario/mi-repo` con el título `Actualizar documentación` y describe que falta documentar la configuración del token.

### `list_repositories`

Lista los repositorios de la cuenta autenticada, ordenados por actualización.

**Parámetros:**

| Nombre | Tipo | Obligatorio | Valor por defecto | Descripción |
| --- | --- | --- | --- | --- |
| `page` | `number` | No | `1` | Página de resultados. Entero entre 1 y 1000. |
| `per_page` | `number` | No | `30` | Cantidad de resultados. Entero entre 1 y 100. |

**Prompt de ejemplo:**

> Lista mis 20 repositorios más recientes de GitHub.

### `list_issues`

Lista los issues abiertos de un repositorio y excluye los pull requests, aunque GitHub los devuelva en la misma respuesta.

**Parámetros:**

| Nombre | Tipo | Obligatorio | Valor por defecto | Descripción |
| --- | --- | --- | --- | --- |
| `owner` | `string` | Sí | - | Usuario u organización propietaria. |
| `repo` | `string` | Sí | - | Nombre del repositorio. |
| `page` | `number` | No | `1` | Página de resultados. Entero entre 1 y 1000. |
| `per_page` | `number` | No | `30` | Cantidad de resultados. Entero entre 1 y 100. |

**Prompt de ejemplo:**

> Lista los issues abiertos de `usuario/mi-repo`, excluyendo pull requests, y muestra los primeros 50.

### `create_commit`

Crea o actualiza un archivo usando la Git Database API de GitHub. El flujo crea un blob, un árbol, un commit y actualiza la referencia de la rama.

Antes de escribir, valida que la rama exista y consulta si el archivo ya existe. Si el archivo existe, conserva su SHA para identificar la actualización; si responde 404, lo trata como un archivo nuevo.

**Parámetros:**

| Nombre | Tipo | Obligatorio | Descripción |
| --- | --- | --- | --- |
| `owner` | `string` | Sí | Usuario u organización propietaria. |
| `repo` | `string` | Sí | Nombre del repositorio. |
| `path` | `string` | Sí | Ruta relativa del archivo. No acepta rutas absolutas ni segmentos `..`. |
| `message` | `string` | Sí | Mensaje del commit. |
| `content` | `string` | Sí | Contenido completo del archivo. Máximo 1 MB. |
| `branch` | `string` | No | Rama destino. Usa la rama principal si se omite. |

**Prompts de ejemplo:**

> Crea `docs/instalacion.md` en `usuario/mi-repo`, en la rama `main`, con una guía breve de instalación y el commit `docs: agregar instalación`.

> Actualiza `README.md` en `usuario/mi-repo` con este contenido y crea el commit `docs: actualizar README`.

## Ejemplos de uso completos

Crear un repositorio:

> Crea un repositorio llamado `inventario-api` con la descripción `API para administrar productos`.

Crear un issue:

> Registra un issue en `usuario/inventario-api` titulado `Validar stock negativo`, con una descripción del error y pasos para reproducirlo.

Listar repositorios:

> Muestra mis repositorios de GitHub, 10 por página.

Listar issues:

> Revisa los issues abiertos de `usuario/inventario-api` en la primera página y no incluyas pull requests.

Crear un archivo y commit:

> En `usuario/inventario-api`, crea `docs/api.md` en la rama `main` con la documentación de los endpoints y usa el mensaje `docs: documentar API`.

Actualizar un archivo existente:

> Reemplaza el contenido de `README.md` en `usuario/inventario-api` por la documentación proporcionada y crea el commit `docs: actualizar README`.

## Testing

La suite sigue una pirámide de testing y no realiza llamadas a GitHub real:

- **Unit tests:** schemas Zod, errores, retry y autenticación del cliente.
- **Integration tests:** handlers de las tools con operaciones de GitHub mockeadas.
- **Wiring MCP:** conexión cliente-servidor con `InMemoryTransport`, sin red.
- **E2E real:** no se automatiza contra GitHub. Para una verificación manual se puede usar MCP Inspector.

Ejecuta todos los tests:

```bash
npm test
```

Ejecuta un archivo específico:

```bash
npx vitest run tests/schemas.test.ts
npx vitest run tests/tools.test.ts
npx vitest run tests/github.test.ts
```

Comprueba la compilación:

```bash
npm run build
```

Los tests utilizan mocks, no requieren `GITHUB_TOKEN` ni modifican repositorios reales.

## MCP Inspector

El Inspector permite verificar manualmente el wiring y ejecutar las tools contra GitHub usando el token local:

```bash
npm run build
npx @modelcontextprotocol/inspector node dist/server.js
```

Antes de usar una tool que escriba datos, comprueba que el token esté configurado y utiliza un repositorio de prueba. No ejecutes esta verificación en CI con credenciales reales.

## Troubleshooting

### `GITHUB_TOKEN no está configurado`

Crea `.env` en la raíz o configura `GITHUB_TOKEN` en el entorno desde el que se inicia el host MCP. Luego reinicia VS Code o Antigravity y ejecuta `npm run build`.

### Error `401` o autenticación rechazada

Verifica que el token no esté vencido o revocado, que tenga acceso al repositorio y que no hayas copiado espacios adicionales. Genera un token nuevo si fue expuesto.

### Error `403` o falta de permisos

Revisa los permisos fine-grained del token, el acceso del token a la organización y las políticas de aprobación de la organización. Para issues usa `Issues: Write`; para archivos y commits usa `Contents: Write`.

### Error `429` o límite de solicitudes

GitHub está limitando temporalmente las solicitudes. El servidor reintenta errores recuperables hasta tres veces, pero debes esperar si el límite continúa. Evita lanzar muchas tools repetidamente.

### Error `404` al crear un commit

Comprueba que el repositorio y la rama existan y que el token tenga acceso. La operación valida la rama antes de crear el blob y el commit.

### Error `422`

Revisa los parámetros: nombres válidos, campos no vacíos, ruta relativa, rama válida y contenido menor a 1 MB.

### El host no descubre las tools

Ejecuta `npm run build`, confirma que exista `dist/server.js`, revisa `.vscode/mcp.json` y reinicia el host MCP. Asegúrate de que el comando sea `node` y que la ruta apunte a `dist/server.js`.

### Los logs rompen la comunicación MCP

Los logs deben ir a `stderr`. No agregues `console.log` en el servidor ni en las tools, porque `stdout` está reservado para los mensajes del protocolo.

## Estructura del proyecto

```text
src/
  errors/       Errores clasificados y traducción segura de mensajes
  github/       Cliente Octokit y operaciones sobre GitHub
  schemas/      Schemas Zod y tipos inferidos
  tools/        Handlers MCP de cada herramienta
  utils/        Retry, logging, respuestas, tipos y ensamblado del servidor
  server.ts     Punto de entrada y transporte stdio

tests/
  client.test.ts
  errors.test.ts
  github.test.ts
  retry.test.ts
  schemas.test.ts
  server.test.ts
  tools.test.ts
```

## Seguridad

- No hardcodear tokens.
- No commitear `.env`.
- No imprimir tokens, headers de autorización ni mensajes técnicos sensibles.
- Usar tokens fine-grained con el mínimo de permisos.
- Revisar los cambios antes de ejecutar tools que escriben en GitHub.
- Revocar inmediatamente cualquier token expuesto.
- Mantener logs en `stderr`.

## Licencia

Este proyecto se distribuye bajo la licencia MIT. Consulta el archivo [LICENSE](LICENSE) para conocer los términos completos.