bitacora-mcp
This server provides Git-based version control and deployment management for HTML presentations, with Google Workspace integration for authentication and publishing.
Create/Update presentations: Add new HTML decks (with title, optional tags, and owner) or update existing ones; each change creates a new Git commit, preserving full history. Supports large decks via file uploads and chunked content for model-generated presentations. HTML is normalized (fragments wrapped into full documents).
Retrieve/List presentations: Fetch the latest (HEAD) or any historical version by commit SHA. List all saved decks, optionally filtered by owner.
Version control features: View the commit history of a presentation and perform non-destructive rollbacks (a new commit that restores an earlier version).
Deploy to Google Apps Script: Publish a specific commit as a web app with idempotent deployments (same commit returns existing URL). Supports configurable access levels (domain, anyone, etc.) and applies sandbox-safe HTML transformations.
Authentication & identity: Over HTTP, enforces Google Workspace login with domain restriction; the authenticated email automatically becomes the owner. In stdio mode, no authentication context is available, suitable for local use.
Additional capabilities: Check deployment status (URL, script ID, etc.), manage metadata (tags/titles), and use configurable local Git storage. Environment variables allow further customization.
Allows deploying HTML presentations as Google Apps Script web apps, including deployment status queries and idempotent publication of specific versions.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@bitacora-mcpCreate a presentation titled 'Q3 Review' with HTML Q3 Results"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
bitacora-mcp — Fase 3 (código local)
MCP server en NestJS para crear, versionar, recuperar y publicar presentaciones HTML. El store git es la fuente de verdad; Apps Script (Google Workspace) es el target de publicación, descartable y reconstruible desde cualquier commit. Corriendo por HTTP, la identidad es un login real de Google Workspace, no un argumento de texto libre.
Qué hace (y qué no, todavía)
✅
create/update/get/list/list_versions/rollback✅ Cada operación es un commit → historial real en git, rollback no destructivo
✅ Normaliza el HTML: envuelve fragments en documento completo con
<title>escapado (mismo patrónescHtmldel review de XSS)✅
deploy/get_deployment: publica un commit como web app de Apps Script (idempotente por versión) y consulta el estado de publicación✅ Transform sandbox-safe antes de publicar: fuerza
<!DOCTYPE html>,<base target="_top">y bloquea assetshttp://(mixed content)✅ Bootstrap HTTP alternativo (
npm run start:http) con login de Google Workspace:presentation_createusa el email autenticado comoownerreal, ignorando lo que mande el cliente. Restringido a un dominio (bidcom.com.arpor defecto).✅
create_from_file/update_from_file: leen el HTML directo de un archivo local, byte a byte, para decks grandes o con contenido binario embebido (imágenes en base64) que un modelo no puede reproducir de forma confiable como argumento de texto.⛔ Sigue corriendo solo local — el service account de dominio (en vez de cuenta personal) queda pendiente, fuera del alcance de "solo código" de este momento. Este MCP nunca se hostea en un cluster propio: lo único que se publica en infraestructura externa son las presentaciones, como web apps de Google Workspace vía Apps Script.
Related MCP server: marp-agent-mcp
Arquitectura interna
Los módulos mapean 1:1 a los futuros packages/ del monorepo:
core/→ normalización y validación de HTML (DeckService,escHtml)store/→GitSpecStore, el store versionado en git (decks + índice de deployments)presentations/→ orquestación +@McpControllercon las 6 tools de versionadodeployer/→ toda la fricción de Google (Apps Script) en un lugar: OAuth, cliente de la Apps Script API, transform sandbox-safe, y las 2 tools de publicaciónauth/→ guard de dominio + config del servidor de autorización OAuth para el bootstrap HTTPshared-tools.module.ts→ controllers/providers de las 8 tools, importado tanto por el bootstrap stdio (app.module.ts) como por el HTTP (http-app.module.ts) para no duplicar la lista
Correr
npm install
npm run build
npm start # levanta el server por stdioEl store se crea en ~/.bitacora-store (configurable con DECK_STORE_DIR).
Publicar en Apps Script (setup de Google, una sola vez)
El deploy corre bajo cuenta personal en esta fase (Fase 3 migra a service account de dominio). Pasos previos, una sola vez por máquina/cuenta:
En Google Cloud Console, un proyecto (o uno nuevo).
Habilitar la Google Apps Script API en ese proyecto (APIs & Services → Library).
Credentials → Create credentials → OAuth client ID, tipo Desktop app.
Descargar el JSON y guardarlo en
~/.bitacora-google/oauth-client.json(override conGOOGLE_OAUTH_CLIENT_PATH).Correr el consent flow local:
npm run build npm run google:authorizeAbre una URL de consentimiento, levanta un server local (loopback) para recibir el redirect, y cachea el refresh token en
~/.bitacora-google/token.json(override conGOOGLE_TOKEN_PATH). Se refresca solo de ahí en más.
Las credenciales de Google se guardan fuera del store git a propósito
(~/.bitacora-google/, no DECK_STORE_DIR): el store se versiona y podría
compartirse; nada con secretos debe vivir ahí.
Variables opcionales para el manifest del web app:
Env var | Default | Qué controla |
|
| Quién puede abrir la URL publicada ( |
|
| Con qué identidad corre el |
Prueba end-to-end
npm run smoke # cliente MCP que ejercita todo el ciclo sobre stdioEl smoke test corre con DECK_DEPLOYER_MOCK=1: el ciclo deploy /
get_deployment se ejercita contra un cliente de Apps Script en memoria, sin
tocar Google ni requerir credenciales. Para probar contra la API real, corré
el server con DECK_DEPLOYER_MOCK sin setear (o en 0) y las credenciales de
la sección anterior ya cacheadas.
Correr con login de Google Workspace (HTTP, local)
Bootstrap alternativo al stdio de siempre: el server escucha por HTTP y exige un login real de Workspace antes de dejar usar cualquier tool. Pensado para probar el flujo de identidad localmente antes de decidir dónde corre este proceso para uso remoto (Fase 3 completa, fuera de alcance por ahora) — nunca en un cluster propio como EKS; lo único que este proyecto publica en infraestructura externa son las presentaciones, vía Apps Script.
Es un segundo OAuth client, distinto del "Desktop app" que ya usa el deployer de Apps Script — este es para loguear usuarios, no para llamar a una API:
En el mismo proyecto de Google Cloud Console → Create Credentials → OAuth client ID → tipo Web application (¡no Desktop app! ese tipo no tiene redirect URI configurable).
Authorized JavaScript origins:
http://localhost:3030(sin path, sin/final).Authorized redirect URIs:
http://localhost:3030/auth/callback(con path, exacto).Anotá el Client ID y el Client secret (o descargá el JSON).
Variables de entorno para levantar el bootstrap HTTP:
Env var | Requerida | Qué es |
| sí | Client ID del OAuth client "Web application" de arriba |
| sí | Su client secret |
| sí | Firma los tokens que emite el servidor de autorización propio. Generá uno con |
| no (default | Dominio al que se restringen los logins — cualquier otra cuenta de Google recibe 403 |
| no (default | Base URL del server |
| no (default | Puerto HTTP |
npm run build
export GOOGLE_WORKSPACE_CLIENT_ID=...
export GOOGLE_WORKSPACE_CLIENT_SECRET=...
export JWT_SECRET=$(openssl rand -hex 32)
npm run start:httpEl server queda escuchando en http://localhost:3030/mcp, con los endpoints
OAuth estándar del servidor de autorización embebido bajo /auth/* y
/.well-known/* (discovery). Un cliente MCP real (Claude, MCP Inspector) hace
todo el baile de login solo; para un chequeo manual sin un cliente a mano, un
cliente OAuth de prueba (registro DCR + PKCE + tools/call) sirve para
verificar que owner termina siendo el email autenticado, no lo que mande
quien llama.
Por qué dos capas de OAuth: Google no soporta Dynamic Client
Registration, que es justo lo que un cliente MCP remoto (Claude) necesita
para autoregistrarse contra el servidor de autorización sin configuración
previa. Apuntar un cliente MCP directo a Google como authorization server
rompe con mcp_registration_failed — ya nos pasó antes. La solución (la que
usa este server) es que nuestro propio servidor de autorización (el
McpAuthModule de @rekog/mcp-nest-auth) hable el protocolo OAuth 2.1/MCP
completo con el cliente MCP (DCR, PKCE, discovery), y delegue solo el login
a Google por dentro. El cliente MCP nunca sabe que Google existe.
Conectar a Claude Desktop
En claude_desktop_config.json:
{
"mcpServers": {
"bitacora": {
"command": "node",
"args": ["/RUTA/ABSOLUTA/bitacora-mcp/dist/main.js"],
"env": { "DECK_STORE_DIR": "/RUTA/ABSOLUTA/deck-store" }
}
}
}Decks grandes
Hay dos problemas distintos detrás de "el HTML es grande", con soluciones distintas:
1. El HTML ya existe como archivo en disco. Usá create_from_file /
update_from_file — el server lo lee directo del filesystem, byte a byte. El
modelo nunca ve ni reproduce el contenido, así que no importa cuán grande sea
ni si tiene imágenes en base64 embebidas: no hay riesgo de truncamiento ni de
corrupción por transcripción.
presentation_create_from_file({ path: "/ruta/absoluta/deck.html", title, owner })
presentation_deploy({ id })2. El HTML lo está generando el modelo mismo (no existe como archivo) y es demasiado grande para una sola tool call — el límite real lo pone el cliente MCP emitiendo el argumento (en la práctica, unos ~40 KB por llamada), no este server. Para ese caso existe la carga por chunks:
presentation_create({ title, html: chunk0, owner, partial: true }) -> { id }
presentation_append({ id, html: chunk1, done: false }) // repetir N veces
presentation_append({ id, html: chunkN, done: true }) // cierra y comitea
presentation_deploy({ id }) // igual que siempreCon partial: true no se toca git todavía — solo se reserva el id y se
guarda el HTML recibido en memoria. Recién en el done: true corre la
normalización de siempre (Fase 1) y se comitea, exactamente como si hubiera
llegado en una sola llamada. Una carga sin cerrar (sin done: true) no deja
rastro en el store; se pierde si el proceso reinicia, que es aceptable porque
solo afecta a esa carga en curso, no a decks ya guardados.
Chunking no resuelve el problema (1): un modelo tiene que regenerar cada
byte del argumento de cada chunk, y para contenido grande con base64 embebido
eso es un problema de fidelidad de transcripción, no de tamaño — por eso
existe create_from_file como camino aparte.
Tools
Tool | Qué hace |
| Crea un deck y lo guarda versionado. Devuelve |
| Igual que |
| Agrega un chunk de HTML a una carga iniciada con |
| Nueva versión con HTML y/o metadata nuevos. |
| Igual que |
| HTML + metadata en HEAD o en un |
| Lista los decks, filtrable por |
| Historial de commits de un deck. |
| Vuelve a un |
| Publica un |
| Devuelve el estado de publicación actual (commit, scriptId, deploymentId, url). |
Notas de stack
@rekog/mcp-nestv2 — APIMcpStrategy+@McpController(noMcpModule.forRoot).Transporte stdio:
logger: falseporque stdout está reservado para el protocolo.@rekog/mcp-nest-auth— servidor de autorización OAuth 2.1/MCP embebido (McpAuthModule), conGoogleOAuthProviderdelegando el login. Solo se usa en el bootstrap HTTP (http-app.module.ts/main-http.ts); el stdio (app.module.ts/main.ts) no lo toca.Bajo stdio no hay request HTTP, así que ninguna tool ve un usuario autenticado (
@McpUser()daundefined) — es el comportamiento esperado para uso local en Claude Desktop, documentado por la propia librería.
Maintenance
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
Flicense-qualityBmaintenanceMCP server that wraps the Slideless HTTP API as tools for listing, sharing, uploading, and managing HTML presentations from any MCP host without installing the CLI.Last updated- Flicense-qualityAmaintenanceMCP server for generating slides from natural language, with interactive preview and export to PDF, PPTX, and Markdown.Last updated17
- Alicense-qualityCmaintenanceProvides MCP server for Google Slides API, enabling creation, reading, modification, and management of Google Slides presentations using service account authentication.Last updated254GPL 3.0
- Flicense-qualityBmaintenanceMCP server for building presentations (PDF/web) with a task-based async pipeline, enabling session management, project creation, presentation IR saving, git commits, building, and deployment.Last updated
Related MCP Connectors
List, share, upload, and manage Slideless HTML presentations from any MCP host.
Streamable HTTP MCP server for Google Calendar and Sheets with OAuth login.
A MCP server built for developers enabling Git based project management with project and personal…
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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/diohernandez/bitacora-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server