Skip to main content
Glama

akij-hr-data-mcp

Un servidor Model Context Protocol (MCP) remoto, de solo lectura y listo para producción, que expone una única carpeta de Google Drive — el repositorio AKIJ HR DATA — a clientes compatibles con MCP mediante el moderno transporte Streamable HTTP.

Es un MCP de Drive de propósito general: maneja archivos XLSX, XLS, CSV, PDF, DOCX, TXT, imágenes y archivos nativos de Google Docs/Sheets/Slides — no solo una herramienta de Excel.


1. Qué hace este proyecto

  • Se conecta a Google Drive mediante una cuenta de servicio (sin flujo OAuth de usuario ni inicio de sesión en el navegador).

  • Restringe todas las operaciones a una carpeta configurada (GOOGLE_DRIVE_FOLDER_ID) y sus subcarpetas. Los archivos fuera de ese árbol nunca se devuelven, aunque la cuenta de servicio pudiera verlos técnicamente.

  • Expone 11 herramientas MCP para descubrir y leer archivos (listar, buscar, metadatos, contenido y extracción específica por formato para Excel/CSV/PDF/DOCX).

  • Se ejecuta como un servidor HTTP estándar de Node/Express con un único endpoint POST /mcp (transporte Streamable HTTP) y un endpoint GET /health, desplegable en Render (o cualquier host de Node) para que siga funcionando cuando tu PC está apagado.

  • Exige autenticación mediante clave de API en cada solicitud MCP.

  • Es estrictamente de solo lectura — no existe ninguna ruta de código que pueda subir, editar, eliminar, renombrar, mover o compartir un archivo de Drive, ni cambiar permisos.

Related MCP server: Google Drive MCP Server

2. Arquitectura

Google Drive (AKIJ HR DATA folder)
        ↓ Drive API v3 (read-only scope)
Google Service Account (GCP_KEY_BASE64)
        ↓
GoogleDriveClient (src/google-drive.ts) — enforces folder-tree scope
        ↓
MCP Server (src/mcp-server.ts) — 11 tools, Zod-validated inputs
        ↓
Express app (src/index.ts) — API-key auth, Streamable HTTP transport
        ↓ POST /mcp  (stateless, one transport per request)
        ↓
Render (always-on host)
        ↓ HTTPS
Remote MCP Clients (Claude, other MCP-compatible clients)

El servidor es sin estado: cada solicitud POST /mcp recibe su propia instancia de McpServer + StreamableHTTPServerTransport (sessionIdGenerator: undefined), por lo que no hay requisito de afinidad de sesión y se escala horizontalmente en Render sin sesiones adhesivas.

Estructura del proyecto

src/
  index.ts            Express app: /health, /mcp, startup
  config.ts           Environment variable loading/validation
  auth.ts             API-key authentication middleware
  google-auth.ts      Decodes GCP_KEY_BASE64 → JWT auth client
  google-drive.ts      Drive API client with folder-scope enforcement
  mcp-server.ts        McpServer wiring: registers all 11 tools

  tools/
    files.ts           list_files, get_file_metadata, get_file_content, list_supported_files
    search.ts           search_files, search_repository
    excel.ts            inspect_excel, read_excel_sheet
    csv.ts               read_csv
    pdf.ts               extract_pdf_text
    docx.ts              extract_docx_text

  utils/
    errors.ts            Typed AppError hierarchy + safe error serialization
    limits.ts            Size/row/timeout/pagination limits
    mime-types.ts         MIME → file-category classification

tests/                  Jest test suite (46 tests, 10 suites)
.env.example
.gitignore
render.yaml             Render Blueprint (optional one-click deploy)
README.md
package.json
tsconfig.json
jest.config.cjs

3. Requisitos previos

  • Node.js 20+ y npm

  • Un proyecto de Google Cloud con la API de Google Drive habilitada

  • Una cuenta de servicio de Google con acceso de Lector compartida en la carpeta de Drive de AKIJ HR DATA

  • Una cuenta de GitHub (para desplegar en Render desde un repositorio)

  • Una cuenta de Render

4. Instalación

npm install

5. Variables de entorno

Variable

Requerida

Descripción

PORT

no (predeterminado 10000)

Puerto en el que escucha el servidor HTTP. Render lo establece automáticamente.

GOOGLE_DRIVE_FOLDER_ID

El ID de la carpeta de Drive a la que está restringido este MCP.

GCP_KEY_BASE64

Clave JSON de la cuenta de servicio codificada en Base64.

API_KEYS

Lista separada por comas de claves de API válidas para POST /mcp.

Consulta el archivo .env.example para ver la plantilla (no se incluyen secretos reales en el repositorio).

6. Configuración de Google Cloud

  1. Ve a console.cloud.google.com y selecciona/crea un proyecto.

  2. APIs y servicios → Biblioteca → habilita Google Drive API.

  3. APIs y servicios → Credenciales → Crear credenciales → Cuenta de servicio.

  4. Asígnale un nombre (p. ej., akij-hr-data-mcp); no se necesita ningún rol de IAM a nivel de proyecto.

  5. Abre la nueva cuenta de servicio → Claves → Añadir clave → Crear clave nueva → JSON. Esto descarga un archivo gcp-key.jsonno hagas commit de este archivo.

  6. Anota la dirección de correo de la cuenta de servicio (con el formato akij-hr-data-mcp@your-project.iam.gserviceaccount.com).

7. Permisos de Google Drive

  1. Abre la carpeta AKIJ HR DATA en Google Drive (ID de carpeta 1oxYLPcC9MPVuxsbeP0kGgYhLmkxt0w2o).

  2. Haz clic en Compartir, pega el correo de la cuenta de servicio y concede acceso de Lector.

  3. No concedas Editor/Propietario — este servidor nunca escribe en Drive, por lo que Lector es suficiente y más seguro.

8. Configuración local

npm install
cp .env.example .env
# fill in GOOGLE_DRIVE_FOLDER_ID, GCP_KEY_BASE64, API_KEYS in .env
npm run dev

npm run dev ejecuta el servidor TypeScript directamente con tsx watch (no se necesita paso de compilación para la iteración local).

9. Generar GCP_KEY_BASE64

Nunca debes pegar el JSON sin procesar de la cuenta de servicio en un chat, en el código fuente ni en .env.example. Genera el valor base64 localmente desde tu gcp-key.json descargado y colócalo únicamente en tu .env local (gitignored) o en la configuración de variables de entorno de Render.

PowerShell:

[Convert]::ToBase64String([IO.File]::ReadAllBytes("$HOME\Downloads\gcp-key.json")) | Set-Clipboard

Esto lee el archivo de clave y copia la cadena base64 directamente al portapapeles: pégala como valor de GCP_KEY_BASE64 en .env (localmente) o en el panel de Render (para el despliegue). Ajusta la ruta si gcp-key.json no está en tu carpeta de Descargas.

Si prefieres imprimirla en la terminal en lugar de en el portapapeles:

[Convert]::ToBase64String([IO.File]::ReadAllBytes("$HOME\Downloads\gcp-key.json"))

10. Pruebas locales

Inicia el servidor:

npm run dev

Comprueba el estado:

curl http://localhost:10000/health

Llama a una herramienta MCP (ejemplo: list_files) con curl, usando la secuencia initializetools/call, o apunta cualquier cliente MCP compatible con Streamable HTTP a http://localhost:10000/mcp con la cabecera X-Api-Key: <one of your API_KEYS>.

11. Compilación

npm run build

Compila src/ (TypeScript, NodeNext ESM) a dist/. Ejecuta npm run typecheck para verificar tipos sin generar archivos.

Ejecuta la suite de pruebas:

npm test

Esto ejecuta Jest en banda (46 pruebas en 10 suites: config, auth, Google auth, cumplimiento del ámbito de carpeta de Drive, las 11 herramientas y los endpoints HTTP /health y /mcp).

12. Configuración de GitHub

git init
git add .
git commit -m "Initial commit: akij-hr-data-mcp"
git branch -M main
git remote add origin https://github.com/<your-username>/akij-hr-data-mcp.git
git push -u origin main

.env, gcp-key.json, *.pem y *.key ya están en gitignore — verifica con git status antes de hacer commit que no haya nada secreto en el área de staging.

13. Despliegue en Render

  1. Ve a render.comNuevo → Web Service.

  2. Conecta tu repositorio de GitHub (akij-hr-data-mcp).

  3. Render detectará render.yaml (Blueprint) automáticamente, o configúralo manualmente:

    • Build Command: npm install && npm run build

    • Start Command: npm start

    • Health Check Path: /health

  4. Añade las variables de entorno (sección 14) en el panel de Render — nunca las hagas commit.

  5. Despliega. Render compila, inicia el servicio y lo mantiene en ejecución de forma independiente de tu PC.

14. Variables de entorno en Render

Configúralas en Render → tu servicio → Environment:

PORT=10000
GOOGLE_DRIVE_FOLDER_ID=1oxYLPcC9MPVuxsbeP0kGgYhLmkxt0w2o
GCP_KEY_BASE64=<paste the base64 string from step 9>
API_KEYS=<comma-separated production keys, e.g. key-abc123,key-def456>

Genera claves de API aleatorias y seguras, por ejemplo:

[Convert]::ToBase64String([Guid]::NewGuid().ToByteArray()) -replace '[+/=]',''

15. Endpoint de salud

GET /health
{ "status": "ok", "timestamp": "2026-08-17T12:00:00.000Z" }

No requiere autenticación; no expone secretos ni estado interno.

16. Endpoint MCP

POST /mcp
  • Implementa el transporte MCP Streamable HTTP (@modelcontextprotocol/sdk StreamableHTTPServerTransport), sin estado (sessionIdGenerator: undefined) — sin respaldo solo-SSE.

  • Requiere autenticación: cabecera Authorization: Bearer <API_KEY> o X-Api-Key: <API_KEY>.

  • GET /mcp y DELETE /mcp devuelven 405 — este servidor no mantiene sesiones ni soporta el flujo SSE opcional.

17. Conectar el MCP remoto a los clientes

Una vez desplegado, tu endpoint MCP es:

https://<your-render-service>.onrender.com/mcp

Para clientes MCP que soporten servidores remotos/HTTP, añade una entrada de servidor con:

  • URL: https://<your-render-service>.onrender.com/mcp

  • Transporte: Streamable HTTP

  • Cabeceras: X-Api-Key: <one of your API_KEYS> (o Authorization: Bearer <API_KEY>)

Ejemplo de configuración genérica de cliente:

{
  "mcpServers": {
    "akij-hr-data": {
      "url": "https://<your-render-service>.onrender.com/mcp",
      "headers": {
        "X-Api-Key": "<API_KEY>"
      }
    }
  }
}

18. Seguridad

  • Solo lectura: no existe ninguna herramienta de subir/eliminar/editar/renombrar/mover/compartir/permisos en este código.

  • Ámbito de carpeta: GoogleDriveClient.assertFileInScope recorre la cadena parents de cada archivo hasta la raíz configurada antes de devolver cualquier metadato o contenido; los archivos fuera del árbol lanzan un ForbiddenError.

  • Autenticación por clave de API: cada solicitud POST /mcp se comprueba contra API_KEYS con una comparación segura en tiempo (crypto.timingSafeEqual). Las claves ausentes o inválidas reciben 401.

  • Las credenciales nunca se registran ni se devuelven: el JSON de la cuenta de servicio decodificado permanece dentro de google-auth.ts; ninguna herramienta, línea de log o mensaje de error puede sacarlo a la luz. Las respuestas de error pasan por toSafeErrorMessage, que elimina los stack traces y los cuerpos de error sin procesar de los servicios ascendentes.

  • Límites de tamaño/salida: las descargas tienen un tope (LIMITS.MAX_DOWNLOAD_BYTES / MAX_PARSE_BYTES), la extracción de texto se trunca (MAX_TEXT_OUTPUT_CHARS), las filas se paginan (DEFAULT_ROW_LIMIT/MAX_ROW_LIMIT) y cada llamada saliente a la API de Google tiene un tiempo de espera (GOOGLE_API_TIMEOUT_MS).

  • Autenticación extensible: req.identity es una estructura pequeña y estable ({ keyId }) diseñada para que una futura capa de autorización por clave de usuario, OAuth o por roles pueda adjuntar claims más ricos sin cambiar todos los puntos de llamada.

  • Aviso conocido de dependencia: el paquete xlsx (SheetJS) utilizado para el análisis de .xls heredado tiene un aviso publicado de alta gravedad (prototype pollution / ReDoS). Solo se usa para archivos internos controlados por acceso de tu propia carpeta de Drive (no cargas arbitrarias de internet) y los archivos tienen un límite de tamaño antes de analizarse. Ejecuta npm audit periódicamente y considera reemplazarlo si hay una versión parcheada disponible.

Lista de verificación de seguridad

  • gcp-key.json nunca se hace commit en git

  • .env nunca se hace commit en git

  • API_KEYS configuradas con valores fuertes y aleatorios en Render (no el valor de desarrollo local)

  • La cuenta de servicio tiene solo Lector en la carpeta de Drive

  • GOOGLE_DRIVE_FOLDER_ID coincide con la carpeta del repositorio previsto

  • Las variables de entorno de Render se configuran directamente en el panel, nunca en los valores commiteados de render.yaml

19. Solución de problemas

Síntoma

Causa

Solución

El servidor se cierra inmediatamente con un ConfigError

Variable de entorno ausente o inválida

Comprueba la variable exacta mencionada en el mensaje de error en la sección 5

GCP_KEY_BASE64 is not valid base64

Se codificó un archivo equivocado, o el copiar/pegar truncó la cadena

Regenera con el comando de PowerShell de la sección 9

403 Forbidden de la API de Drive

La cuenta de servicio no está compartida en la carpeta, o está compartida con un correo incorrecto

Revisa la sección 7; confirma que el client_email de tu clave coincide

File ... is outside the configured repository folder

Pasaste un file_id que no está dentro del árbol de GOOGLE_DRIVE_FOLDER_ID

Usa list_supported_files o search_repository para obtener IDs válidos

401 en cada llamada /mcp

Clave de API ausente o incorrecta

Envía X-Api-Key o Authorization: Bearer <key> que coincida con una entrada de API_KEYS

Error FILE_TOO_LARGE

El archivo supera el límite de bytes configurado

Esto es intencional; los archivos grandes se rechazan en lugar de cargarse por completo en memoria (consulta src/utils/limits.ts)

El servicio de Render se duerme / tarda en arrancar en frío

Los planes gratuitos/de inicio de Render quedan inactivos tras un periodo de inactividad

Mejora el plan de Render o acepta el retraso de arranque en frío en la primera solicitud

Las pruebas se cuelgan durante minutos en local

ts-jest comprobando tipos de googleapis completos con workers paralelos

Ya está mitigado: npm test ejecuta Jest con --runInBand; no elimines esa bandera


Pasos manuales restantes (solo tú puedes hacerlos)

  1. Genera GCP_KEY_BASE64 a partir de tu gcp-key.json descargado (sección 9) y ponlo en tu .env local para probar.

  2. Comparte la carpeta de Drive de AKIJ HR DATA con el correo electrónico de tu cuenta de servicio como Viewer (sección 7).

  3. Ejecuta localmente (npm run dev) y confirma que GET /health y una llamada real a list_files funcionan con tu carpeta real de Drive.

  4. Haz push a GitHub (sección 12).

  5. Crea el Render Web Service, conecta el repositorio y configura las cuatro variables de entorno en el panel de Render (secciones 13–14): Render compilará y desplegará automáticamente.

  6. Genera API_KEYS de producción (diferentes de cualquier clave de desarrollo local) y guárdalas de forma segura para tus clientes MCP.

  7. Conecta tu cliente MCP a https://<your-render-service>.onrender.com/mcp (sección 17).

F
license - not found
-
quality - not tested
C
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

View all related MCP servers

Related MCP Connectors

  • MCP server for Google search results via SERP API

  • MCP server for AgentDocs (agentdocs.eu): read, search, write, comment on & share Markdown docs.

  • Agent-native MCP server over the public saagarpatel.dev corpus. Read-only, stateless.

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/mdshahabdulaziz-beep/mcp-akij'

If you have feedback or need assistance with the MCP directory API, please join our Discord server