Skip to main content
Glama
gnvidia06-ux

GitHub MCP Server — AutomateHub

by gnvidia06-ux

🤖 GitHub MCP Server — AutomateHub

MCP Server en Node.js + TypeScript que permite a un agente de IA (Gemini, Claude u otro LLM) automatizar operaciones en GitHub usando lenguaje natural, a través del Model Context Protocol (MCP).

Proyecto Integrador 5 — Especialización Backend (Soy Henry).


📑 Índice

  1. ¿Qué hace?

  2. Casos de uso

  3. Arquitectura

  4. Requisitos

  5. Instalación paso a paso

  6. Configuración

  7. Documentación de las tools

  8. Ejemplos de uso

  9. Manejo de errores

  10. Tests

  11. Estructura del proyecto

  12. Decisiones técnicas

  13. Troubleshooting

  14. Licencia


Related MCP server: GitHub Dev Copilot

🎯 ¿Qué hace?

Este servidor expone 10 herramientas (tools) que un agente de IA puede usar para trabajar en GitHub. El usuario escribe en lenguaje natural, por ejemplo:

"Creá un repo llamado mi-api y abrile un issue para configurar el CI"

y el agente decide qué tools usar y con qué parámetros, las ejecuta y responde con el resultado.

Tool

Qué hace

Tipo

create_repository

Crea un repositorio nuevo

Obligatoria

create_issue

Abre un issue con título y descripción

Obligatoria

list_repositories

Lista los repositorios del usuario

Obligatoria

create_commit

Crea o modifica un archivo con un commit

Obligatoria

list_issues

Lista los issues de un repositorio

Obligatoria

create_branch

Crea una branch nueva

Extra

close_issue

Cierra un issue (con comentario opcional)

Extra

add_comment_to_issue

Comenta en un issue

Extra

list_commits

Lista los commits recientes

Extra

health_check

Verifica conexión, scopes del token y rate limit

Extra


💡 Casos de uso

  • Arrancar proyectos rápido: crear un repo con README y su primer issue en una sola frase.

  • Gestionar tareas sin salir del IDE: listar, crear, comentar y cerrar issues hablando con el agente.

  • Documentar: pedirle al agente que escriba y suba un archivo (docs/setup.md, CHANGELOG.md, etc.).

  • Revisar actividad: "¿qué cambios se hicieron últimamente en mi-api?"

  • Diagnosticar: "¿por qué no puedo crear issues?" → el agente usa health_check y revisa los permisos del token.


🏗️ Arquitectura

flowchart TD
    U["👤 Usuario<br/>(lenguaje natural)"] --> H
    H["🖥️ Antigravity<br/>(Host)"] --> C
    C["🧠 LLM — Gemini / Claude<br/>(Client)<br/>Lee las descripciones y elige la tool"] -- "JSON-RPC por stdio" --> S
    S["⚙️ MCP Server (este proyecto)<br/>Zod valida → Operations → Errores"] -- "HTTPS + token" --> G
    G["🐙 GitHub API<br/>(vía Octokit)"]
    G -- "respuesta" --> S
    S -- "resultado o error en lenguaje natural" --> C
    C -- "respuesta al usuario" --> H

Flujo de una solicitud (ejemplo: "abrí un issue en demo que diga 'arreglar login'"):

  1. Antigravity (Host) recibe el mensaje y lo pasa al LLM junto con la lista de tools disponibles.

  2. El LLM (Client) lee las descripciones, elige create_issue y arma los parámetros: { "repo": "demo", "title": "Arreglar login" }.

  3. El MCP Server recibe la llamada por stdio (JSON-RPC), valida los datos con Zod y ejecuta la operación con Octokit (con reintentos si hace falta).

  4. GitHub API crea el issue y responde.

  5. El servidor devuelve un resumen claro (o un error en lenguaje natural), y el LLM se lo comunica al usuario.

Capas internas del servidor

server.ts ──► tools/ ──► schemas/ (validación Zod)
                 │
                 └──► github/operations.ts ──► github/client.ts (Octokit)
                          │
                          ├──► utils/retry.ts   (exponential backoff)
                          ├──► errors/          (traducción a lenguaje natural)
                          └──► utils/logging.ts (logs a stderr, sin datos sensibles)

📋 Requisitos

Requisito

Versión

Node.js

18 o superior (probado con v24)

npm

9 o superior

Cuenta de GitHub

con un Personal Access Token (classic)

Antigravity

IDE/Host para conectar el servidor con el LLM

Git

para clonar el repositorio


🚀 Instalación paso a paso

1. Clonar el repositorio

git clone https://github.com/gnvidia06-ux/github-mcp-server.git
cd github-mcp-server

2. Instalar dependencias

npm install

3. Crear el archivo .env a partir del ejemplo

# macOS / Linux
cp .env.example .env

# Windows (PowerShell)
Copy-Item .env.example .env

4. Completar el token en .env (ver la sección de configuración).

5. Compilar TypeScript

npm run build

Esto genera la carpeta dist/ con dist/server.js, que es lo que ejecuta el host.

6. Verificar que todo funciona

npm test            # corre los tests unitarios
npm run inspector   # abre MCP Inspector para probar las tools

⚙️ Configuración

1. Obtener el GitHub Personal Access Token

  1. Entrá a GitHub → foto de perfil → Settings.

  2. Menú izquierdo, al final → Developer settings.

  3. Personal access tokens → Tokens (classic) → Generate new token (classic).

  4. Completá:

    • Note: mcp-server

    • Expiration: 30 o 60 días (recomendado: que expire).

    • Scopes: marcá los tres de la tabla de abajo.

  5. Generate token y copialo (GitHub lo muestra una sola vez).

2. Scopes que necesita el token

Scope

Para qué se usa

repo

Crear repositorios, issues, commits, branches y leer repos privados

user

Obtener el usuario autenticado (owner por defecto)

admin:org

Operar sobre repositorios de organizaciones

💡 Podés verificar los scopes en cualquier momento con la tool health_check.

3. Configurar el .env

# Token personal de GitHub (classic) con scopes: repo, user, admin:org
GITHUB_TOKEN=ghp_tuTokenAca

# Nivel de logs: debug | info | warn | error
LOG_LEVEL=info

⚠️ Nunca subas el .env a GitHub. Ya está incluido en .gitignore. Si el token se filtra, revocalo inmediatamente en GitHub y generá uno nuevo.

4. Configurar el MCP Server en Antigravity

  1. Abrí el archivo de configuración global de MCP de Antigravity:

    • Desde la app: panel del agente → … → MCP Servers → Manage MCP Servers → View raw config.

    • O directamente: ~/.gemini/config/mcp_config.json (en Windows: C:\Users\TU_USUARIO\.gemini\config\mcp_config.json).

  2. Agregá el servidor (reemplazá la ruta y el token):

{
  "mcpServers": {
    "github-automatehub": {
      "command": "node",
      "args": ["C:/ruta/absoluta/a/github-mcp-server/dist/server.js"],
      "env": {
        "GITHUB_TOKEN": "ghp_tuTokenAca",
        "LOG_LEVEL": "info"
      }
    }
  }
}

📌 En Windows usá barras normales / en la ruta (o dobles \\). Una barra simple \ rompe el JSON.

📌 Este archivo es global (está en tu usuario, fuera del proyecto), así que el token no se sube al repositorio.

  1. Reiniciá Antigravity.

  2. Abrí una conversación nueva y probá: "¿Qué repositorios tengo en GitHub?"

  3. La primera vez que el agente use una tool, Antigravity pedirá permiso. Elegí "Yes, and always allow in this conversation".

5. (Opcional) Probar con MCP Inspector

npm run build
npm run inspector

Se abre en el navegador. Activá la conexión, entrá a Tools y ejecutá cualquier tool completando sus campos.


🛠️ Documentación de las tools

En todas las tools que reciben owner: si se omite, se usa el usuario dueño del token.

create_repository

Crea un repositorio nuevo en la cuenta del usuario autenticado.

Parámetro

Tipo

Requerido

Descripción

name

string

✅

3–100 caracteres: letras, números, -, _ y .. Sin espacios. No puede terminar en .git

description

string

❌

Máximo 350 caracteres

private

boolean

❌

false por defecto (público)

autoInit

boolean

❌

true por defecto (crea un README inicial)

Prompt de ejemplo:

"Creá un repositorio privado llamado api-turnos con la descripción 'API para gestión de turnos'"


create_issue

Abre un issue nuevo en un repositorio.

Parámetro

Tipo

Requerido

Descripción

owner

string

❌

Usuario u organización dueña del repo

repo

string

✅

Nombre del repositorio

title

string

✅

1–256 caracteres

body

string

❌

Descripción (acepta Markdown)

labels

string[]

❌

Etiquetas existentes. Ej: ["bug"]

Prompt de ejemplo:

"Abrí un issue en api-turnos con el título 'Agregar validación de fechas' y explicá que hoy se aceptan fechas pasadas"


list_repositories

Lista los repositorios del usuario autenticado (propios y de organizaciones). Resultados cacheados 5 minutos.

Parámetro

Tipo

Requerido

Descripción

visibility

"all" | "public" | "private"

❌

"all" por defecto

sort

"created" | "updated" | "pushed" | "full_name"

❌

"updated" por defecto

perPage

number

❌

1–100, 30 por defecto

Prompt de ejemplo:

"Mostrame mis 5 repositorios privados actualizados más recientemente"


create_commit

Crea un archivo nuevo o reemplaza el contenido de uno existente, haciendo un commit.

Parámetro

Tipo

Requerido

Descripción

owner

string

❌

Usuario u organización

repo

string

✅

Nombre del repositorio

path

string

✅

Ruta relativa (ej: docs/setup.md). Sin / inicial ni ..

content

string

✅

Contenido completo del archivo

message

string

✅

Mensaje del commit (1–500 caracteres)

branch

string

❌

Branch destino (por defecto, la principal)

Prompt de ejemplo:

"En api-turnos, creá el archivo docs/setup.md con instrucciones básicas de instalación usando npm, y commitealo con el mensaje 'docs: agrega guía de setup'"


list_issues

Lista los issues de un repositorio (no incluye pull requests).

Parámetro

Tipo

Requerido

Descripción

owner

string

❌

Usuario u organización

repo

string

✅

Nombre del repositorio

state

"open" | "closed" | "all"

❌

"open" por defecto

perPage

number

❌

1–100, 30 por defecto

Prompt de ejemplo:

"¿Qué issues abiertos tiene api-turnos?"


create_branch (extra)

Parámetro

Tipo

Requerido

Descripción

owner

string

❌

Usuario u organización

repo

string

✅

Nombre del repositorio

branch

string

✅

Nombre de la nueva branch (ej: feature/login)

fromBranch

string

❌

Branch base (por defecto, la principal)

Prompt de ejemplo:

"Creá una branch feature/validaciones en api-turnos"


close_issue (extra)

Parámetro

Tipo

Requerido

Descripción

owner

string

❌

Usuario u organización

repo

string

✅

Nombre del repositorio

issueNumber

number

✅

Número del issue (entero positivo)

comment

string

❌

Comentario a dejar antes de cerrar

Prompt de ejemplo:

"Cerrá el issue #3 de api-turnos con el comentario 'Resuelto en el último commit'"


add_comment_to_issue (extra)

Parámetro

Tipo

Requerido

Descripción

owner

string

❌

Usuario u organización

repo

string

✅

Nombre del repositorio

issueNumber

number

✅

Número del issue

body

string

✅

Texto del comentario (acepta Markdown)

Prompt de ejemplo:

"Comentá en el issue #2 de api-turnos que ya estoy trabajando en eso"


list_commits (extra)

Parámetro

Tipo

Requerido

Descripción

owner

string

❌

Usuario u organización

repo

string

✅

Nombre del repositorio

branch

string

❌

Branch (por defecto, la principal)

perPage

number

❌

1–100, 30 por defecto

Prompt de ejemplo:

"¿Cuáles fueron los últimos 5 commits de api-turnos?"


health_check (extra)

Sin parámetros. Devuelve el usuario autenticado, los scopes del token (y los que faltan), el rate limit restante y métricas de uso de cada tool.

Prompt de ejemplo:

"¿Funciona la conexión con GitHub? ¿Qué permisos tiene mi token?"


✍️ Tips para prompts efectivos

  • Nombrá el repositorio exactamente como está en GitHub.

  • Para issues existentes, mencioná el número (#3). Si no lo sabés, pedí primero la lista.

  • Podés encadenar acciones en una sola frase: el agente usará varias tools seguidas.

  • Si el repo es de una organización, mencioná la organización: "en la org acme, repo web..."


🎬 Ejemplos de uso

Flujo completo de un proyecto nuevo (usa 5 tools distintas):

👤 Creá un repo público llamado demo-agente con la descripción "Demo de MCP"
🤖 [create_repository] Repositorio gnvidia06-ux/demo-agente creado como público.

👤 Agregale un archivo TODO.md con una lista de 3 tareas para una API REST
🤖 [create_commit] Archivo "TODO.md" creado con el commit a1b2c3d.

👤 Creá un issue por cada tarea del TODO
🤖 [create_issue x3] Issues #1, #2 y #3 creados.

👤 Creá una branch feature/auth para la primera tarea
🤖 [create_branch] Branch "feature/auth" creada a partir de "main".

👤 ¿Qué issues abiertos quedan?
🤖 [list_issues] Se encontraron 3 issues abiertos en demo-agente: ...

👤 Cerrá el #1 diciendo que ya se terminó
🤖 [close_issue] Issue #1 cerrado.

👤 Mostrame los últimos commits
🤖 [list_commits] Últimos 2 commits de demo-agente: ...

Ejemplo de error manejado:

👤 Mostrame los issues del repo repo-fantasma-123
🤖 No se pudo encontrar el repositorio gnvidia06-ux/repo-fantasma-123.
   Verificá que el nombre esté bien escrito.

🚨 Manejo de errores

Los errores técnicos se transforman en mensajes en lenguaje natural que el LLM puede comunicar al usuario. Nunca se devuelven stack traces.

Tipo

Cuándo ocurre

Mensaje (ejemplo)

¿Reintenta?

ValidationError

Input inválido (Zod)

"name: El nombre del repositorio debe tener al menos 3 caracteres."

No

AuthenticationError

401, 403 o falta el token

"El token de GitHub es inválido o expiró..."

No

GitHubAPIError 404

Recurso inexistente

"El repositorio X no fue encontrado. Verifica el nombre e intenta de nuevo."

No

GitHubAPIError 422

Datos rechazados / ya existe

"Ya existe un repositorio llamado X..."

No

GitHubAPIError rate limit

403/429 por límite de API

"Se alcanzó el límite de solicitudes de GitHub..."

Sí, con backoff*

GitHubAPIError 5xx

Falla temporal de GitHub

"GitHub está teniendo problemas temporales..."

Sí, con backoff

NetworkError

Sin internet, DNS, timeout

"No se pudo conectar con GitHub..."

Sí, con backoff

Retry con exponential backoff: espera 0,5 s → 1 s → 2 s (máximo 3 reintentos) en lugar de reintentar inmediatamente. * Si GitHub pide esperar más de 8 segundos (por ejemplo, un rate limit que se reinicia en una hora), no se reintenta: se devuelve el mensaje al usuario para no bloquear al agente.

Logging: todos los logs se escriben en stderr en formato JSON con niveles (debug, info, warn, error). Los tokens (ghp_..., github_pat_...) y los campos sensibles se reemplazan por [REDACTED].


🧪 Tests

npm test              # ejecuta todos los tests una vez
npm run test:watch    # modo watch (re-ejecuta al guardar)

38 tests unitarios con Vitest, en 3 archivos:

Archivo

Qué verifica

tests/tools.test.ts

Schemas de Zod (inputs válidos pasan, inválidos fallan con el mensaje correcto) y el helper común de las tools

tests/github.test.ts

Operaciones de GitHub con Octokit mockeado (vi.mock): parámetros enviados, caché, creación vs. actualización de archivos, 404, 401 y rate limit

tests/errors.test.ts

Transformación de errores a lenguaje natural, retry con backoff, ocultamiento de tokens en logs y validación del token

Los tests no llaman a la API real de GitHub: son rápidos (menos de 1 segundo), determinísticos y no crean nada en tu cuenta.


📁 Estructura del proyecto

github-mcp-server/
├── src/
│   ├── server.ts                 # Entry point: crea el server MCP y conecta por stdio
│   ├── types.ts                  # Tipos compartidos de las respuestas
│   ├── tools/
│   │   ├── index.ts              # Registra todas las tools
│   │   ├── helpers.ts            # Lógica común: validar → ejecutar → responder + métricas
│   │   ├── create-repository.ts
│   │   ├── create-issue.ts
│   │   ├── list-repositories.ts
│   │   ├── create-commit.ts
│   │   ├── list-issues.ts
│   │   └── extra-tools.ts        # create_branch, close_issue, add_comment, list_commits, health_check
│   ├── schemas/
│   │   └── index.ts              # Schemas de Zod de cada tool + validateInput
│   ├── github/
│   │   ├── client.ts             # Configuración de Octokit (token desde env)
│   │   └── operations.ts         # Llamadas a la API de GitHub
│   ├── errors/
│   │   └── index.ts              # Errores custom + traducción a lenguaje natural
│   └── utils/
│       ├── logging.ts            # Logger estructurado a stderr con redacción de secretos
│       └── retry.ts              # Exponential backoff
├── tests/
│   ├── tools.test.ts
│   ├── github.test.ts
│   └── errors.test.ts
├── .env.example
├── .gitignore
├── package.json
├── tsconfig.json
├── vitest.config.ts
├── LICENSE
└── README.md

Scripts disponibles

Script

Qué hace

npm run build

Compila TypeScript a dist/

npm start

Ejecuta el servidor compilado

npm run dev

Ejecuta el servidor en desarrollo con tsx (sin compilar)

npm test

Corre los tests con Vitest

npm run test:watch

Tests en modo watch

npm run lint

Chequeo de tipos con TypeScript (tsc --noEmit)

npm run inspector

Abre MCP Inspector conectado al servidor


🧭 Decisiones técnicas

  • Separación client.ts / operations.ts: el cliente de Octokit está aislado, lo que permite mockearlo en los tests sin tocar la lógica de negocio.

  • Descripciones de tools orientadas al LLM: cada descripción dice cuándo usar la tool y cuándo no (y cuál usar en su lugar). Es lo que permite que el agente elija bien.

  • Doble rol de Zod: valida antes de llamar a GitHub (ahorra requests y da mejores mensajes) y genera el esquema que el LLM lee para saber qué parámetros enviar.

  • owner opcional: si no se indica, se usa el dueño del token. Simplifica los prompts ("creá un issue en mi repo X").

  • stdio en lugar de HTTP: el host lanza el servidor como proceso local y se comunican por stdin/stdout. No hay puertos abiertos ni servidor expuesto en la red, y el token nunca sale de la máquina más que hacia GitHub.

  • Logs solo a stderr: stdout está reservado para el protocolo JSON-RPC. Un console.log rompería la comunicación.

  • dotenv con quiet: true: evita que dotenv escriba mensajes en stdout.

  • Respuestas resumidas: se devuelve una frase en lenguaje natural más un JSON con solo los campos útiles, en lugar de la respuesta completa de GitHub (que es enorme y gasta contexto del LLM).


🔧 Troubleshooting

Problema

Causa probable

Solución

El agente no ve las tools

El host no cargó el servidor

Verificá la ruta absoluta a dist/server.js en mcp_config.json, corré npm run build y reiniciá Antigravity

Cannot find module .../dist/server.js

No se compiló o la ruta está mal

npm run build y revisá la ruta (usá / en Windows)

"No se encontró GITHUB_TOKEN"

Falta la variable de entorno

Agregala en env dentro de mcp_config.json (o en .env si usás Inspector)

"El token de GitHub es inválido o expiró" (401)

Token vencido, revocado o mal copiado

Generá un token nuevo y actualizalo

"No tenés permisos..." (403)

Al token le faltan scopes

Usá health_check para ver qué falta y regenerá el token con repo, user y admin:org

"El repositorio X no fue encontrado"

Nombre mal escrito o repo de otro owner

Pedí list_repositories para ver el nombre exacto, o indicá el owner

"Hay un conflicto... puede estar vacío" (409)

Repo sin commits

Crealo con autoInit: true (por defecto)

"Se alcanzó el límite de solicitudes"

Rate limit de GitHub (5000/hora)

Esperá al reinicio (lo indica health_check)

Error process / tipos de Node al compilar

Faltan los tipos de Node

Verificá "types": ["node"] en tsconfig.json y que esté instalado @types/node

El JSON de mcp_config.json no carga

Sintaxis inválida

Revisá comas y comillas; en Windows no uses \ simple en rutas

Inspector se conecta pero las tools fallan

El .env no está en la raíz

El .env debe estar junto a package.json


🔐 Seguridad

  • El token se lee solo desde variables de entorno. Nunca está en el código.

  • .env está en .gitignore; el repositorio incluye solo .env.example sin valores reales.

  • Los logs ocultan tokens y campos sensibles ([REDACTED]).

  • Antigravity pide aprobación del usuario antes de ejecutar cada tool (human in the loop).

  • Si un token se expone: revocalo inmediatamente en GitHub → Settings → Developer settings → Tokens.


📄 Licencia

Distribuido bajo la licencia MIT. Ver el archivo LICENSE.


👤 Autor

Agustín Vásquez — @gnvidia06-ux

Proyecto Integrador 5 · Especialización Backend · Soy Henry

Related MCP Connectors

Related MCP Servers