Skip to main content
Glama
yoruuuchan

yoru-studio-mcp

by yoruuuchan

Yoru Studio

Un estudio de ejecución autoalojado para un único creador.

Léelo en Chino simplificado.

Yoru Studio es el espacio de trabajo de una sola persona para convertir ideas en trabajo creativo terminado: atrapa una chispa en la bandeja de entrada, llévala a un proyecto principal, divídelo en subproyectos (vídeo / ensayo fotográfico / artículo largo / entrega de material), planifica guiones gráficos, realiza rodajes de campo con una cola segura sin conexión, registra lo que realmente ocurrió y cierra el ciclo con una retrospectiva. Los entregables viven bajo versiones de plataforma para que el mismo corte pueda publicarse como Douyin / Bilibili / un conjunto de imágenes de Xiaohongshu sin duplicar el proyecto en sí.

Está escrito para una sola persona — el creador — que lo ejecuta en su propia máquina. No hay historia multiusuario, ni equipos, ni backend SaaS. Cuando lo instalas, todo el sistema vive en una máquina que tú controlas.

Qué hay aquí

Leer el código fuente es la respuesta autoritativa a "¿qué hace realmente?" — el resumen siguiente es un mapa, no el territorio.

  • Bandeja de entrada → Proyecto principal → Subproyecto → Versión de plataforma: la columna vertebral completa de un flujo de trabajo creativo, con un carril rápido que permite que una buena idea salte directamente a un subproyecto activo cuando sabes dónde pertenece.

  • Guiones gráficos con vista de lista y vista de tablero, arrastrar para reordenar, imágenes de referencia por plano, exportación a XLSX y una versión imprimible para uso en rodaje.

  • Calendario y programación: horas precisas, fechas de día completo y ventanas difusas ("esta semana", "el fin de semana") conviven en un mismo calendario; lo atrasado se calcula, no se recuerda, así que nada se pudre en silencio.

  • Recordatorios y notificaciones en el sitio, deduplicados en la capa de base de datos para que un reinicio nunca dispare la misma alerta dos veces.

  • Registros de ejecución para rodajes / re-rodajes / grabaciones de pantalla / sesiones de escritura — adjunta el registro a la capa del proyecto que realmente coincida con lo que hiciste.

  • Retrospectivas, ligeras o completas; cada campo es opcional. La estructura está ahí para recordarte, no para exigirte.

  • Adjuntos en cuatro formatos: imágenes subidas (con miniaturas), punteros a rutas (p. ej. NAS/2026/Aug shoots/), enlaces externos y fragmentos de texto. Los archivos eliminados de forma suave permanecen en la papelera durante 30 días.

  • Modo de campo: página móvil-primero para uso en rodaje. Si la red falla, las ediciones se ponen en cola en IndexedDB y se sincronizan cuando vuelve la conectividad.

  • Exportación completa: paquete JSON + adjuntos para llevarte tus datos, desde la CLI o desde la página de ajustes.

  • Copias de seguridad: copia de seguridad en línea de SQLite con programación, y scripts opcionales de restic para copias cifradas fuera del sitio con un simulacro de restauración real.

  • Canal MCP para agentes de IA (Claude, ChatGPT, Codex, …) — consulta la sección siguiente.

Related MCP server: todos

Postura de diseño

  • Un solo usuario, una sola cuenta. El modelo de datos incluye una columna de espacio de trabajo para que una futura versión multiusuario no tenga que reconstruir el esquema, pero todo el código distribuido asume exactamente un usuario.

  • Sin servicios externos requeridos. SQLite en disco, archivos en disco. Sin Redis, sin cola de mensajes, sin autenticación de terceros. Puedes ejecutarlo en un VPS de 5 $/mes.

  • Huella pequeña. El objetivo es aplicación 512 MiB / planificador 256 MiB / (opcional) sidecar de proxy inverso 128 MiB. Una VM de 2 GiB es suficiente.

  • El servidor no compila el frontend. El bundle de Vite se construye localmente (o en CI) y se distribuye como archivos precompilados. Las máquinas de despliegue nunca necesitan Node.

  • Contenido sobre ceremonia. El formulario de retrospectiva no tiene campos obligatorios — el esquema existe para recordarte en qué pensar, no para poner puertas al guardado.

Pila tecnológica

  • Backend: Python 3.12, FastAPI, SQLite (con uv para la gestión de dependencias).

  • Frontend: React 19 + TypeScript, compilado con Vite.

  • Despliegue: Docker Compose (host único). El proxy inverso y TLS son cosa tuya — Cloudflare Tunnel, Caddy, Nginx, Tailscale Funnel, o simplemente túneles SSH para uso solo local.

  • Pruebas: pytest para el backend, vitest para el frontend.

Canal MCP: conecta agentes de IA

Yoru Studio expone un servidor Model Context Protocol (MCP) para que los agentes que hablan MCP — Claude Desktop, ChatGPT desktop, Codex CLI, Claude Code y otros — puedan leer y añadir a tu estudio sin que tengas que copiar y pegar.

Ocho herramientas en total, todas limitadas a escrituras de solo añadir con idempotencia:

Lectura (5):

  • list_projects — lista de proyectos principales con recuentos.

  • get_project — detalle completo de un proyecto principal, incluidos sus subproyectos.

  • get_sub_project — un subproyecto, con guion gráfico / registros de ejecución / retrospectiva incluidos.

  • get_schedule — próximos eventos (14 o 30 días), todos los atrasados, eventos difusos a corto plazo.

  • get_inbox — elementos pendientes o descartados de la bandeja de entrada.

Escritura (3, todas de solo añadir, todas idempotentes):

  • capture_inspiration — deja caer una chispa en la bandeja de entrada.

  • append_storyboard_shots — añade atómicamente N planos al guion gráfico de un subproyecto de vídeo.

  • append_execution_record — registra un rodaje / sesión de grabación de pantalla / prueba.

Cada herramienta de escritura acepta una idempotency_key. Reintentar con la misma clave devuelve el primer resultado; una carga útil diferente con la misma clave produce un conflicto duro. Nada de lo que un agente haga puede sobrescribir silenciosamente trabajo que ya tienes.

Dos rutas de autenticación detrás del mismo endpoint /mcp (especificación §5.1 de docs/spec/ en el código fuente):

  • Token Bearer estático para uso personal / de un solo agente. Generas una cadena aleatoria larga, guardas su sha256 en el entorno y le das el token al agente.

  • OAuth 2.0 con PKCE + Registro Dinámico de Clientes para los conectores que lo esperan (el conector de ChatGPT es el caso actual que lo requiere).

Ambas rutas pueden coexistir. Ambas son opcionales — si no configuras ninguna, la ruta /mcp ni siquiera se monta.

Inicio rápido

Dos caminos según cómo quieras ejecutarlo: desde el código fuente (para desarrollo, o si prefieres gestionar Python tú mismo), o mediante Docker Compose (para una instalación estable en un solo host).

Desde el código fuente

Requiere Python 3.12 y uv, además de Node 20+ para el frontend.

# 1. Install Python deps and set up the venv
uv sync

# 2. Initialize / migrate the database (creates ./data/studio.sqlite3)
uv run studio init-db

# 3. Start the API server on http://127.0.0.1:8000 (local mode — no auth)
uv run studio serve

# 4. In another terminal, run the frontend dev server
cd frontend
npm install
npm run dev        # http://localhost:5173, proxies to the API

El modo local se vincula a loopback y omite la autenticación por comodidad del desarrollador. Para probar el flujo de autenticación localmente, sigue la sección "Activación del modo remoto" más abajo.

Otros comandos de la CLI:

uv run studio db-backup            # verified online SQLite backup
uv run studio db-restore <path> --confirm-database ./data/studio.sqlite3
uv run studio export               # full JSON + uploads takeout
uv run studio schedule-tick        # run the periodic maintenance jobs once
uv run studio hash-password        # interactively hash a password for STUDIO_AUTH_PASSWORD_HASH

Ejecuta las pruebas:

uv run pytest                      # backend
cd frontend && npm test            # frontend

Docker Compose

El archivo docker-compose.yml de este repositorio define tres servicios: app (la SPA de FastAPI + compilada), scheduler (un bucle de 60 segundos que ejecuta copias de seguridad, recordatorios y retención) y cloudflared (un sidecar de proxy inverso de referencia — sustitúyelo por lo que se adapte a tu infraestructura).

El proxy inverso y TLS están deliberadamente fuera del alcance de la aplicación: elige el tuyo. Opciones razonables:

  • Cloudflare Tunnel (el servicio cloudflared de referencia en docker-compose.yml, con el script de aprovisionamiento en scripts/provision-cloudflare-tunnel.py).

  • Caddy o Nginx como proxy inverso a nivel de host, terminando TLS con tus propios certificados.

  • Tailscale Funnel para alojamiento de prioridad privada.

  • Simplemente reenvío SSH -L 8000 si solo lo quieres en tu propia máquina.

Si usas Cloudflare Tunnel, edita o elimina el servicio cloudflared y desactiva STUDIO_TRUSTED_PROXY_IPS en .env.production. Si usas otro proxy, establece STUDIO_TRUSTED_PROXY_IPS con la IP de tu proxy para que las IP reales de los clientes lleguen al registro de auditoría.

Pasos de despliegue (una vez que tu host Docker esté listo):

# 1. Build the frontend locally — the server never builds it.
cd frontend && npm ci && npm run build && cd ..

# 2. Copy the env template and fill in the required secrets.
cp deploy/env.production.example .env.production
chmod 600 .env.production
$EDITOR .env.production

# 3. Generate a scrypt-hashed password for STUDIO_AUTH_PASSWORD_HASH.
uv run studio hash-password
# Paste the "password_hash" value into .env.production, single-quoted.

# 4. Build and start.
docker compose --env-file .env.production build
docker compose --env-file .env.production up -d

docs/deploy.md contiene un recorrido más largo que cubre el diseño de referencia, los scripts de automatización de copias de seguridad en scripts/ y el bloqueo de operación que comparten los trabajos de despliegue y copia de seguridad.

Activación del modo remoto

El modo remoto es lo que convierte la aplicación de "desarrollo local sin autenticación" a "URL pública detrás de un proxy con cookies de sesión". Configura como mínimo:

  • STUDIO_MODE=remote

  • STUDIO_SESSION_SECRET — una cadena aleatoria, de al menos 32 caracteres.

  • STUDIO_AUTH_PASSWORD_HASH — la salida de uv run studio hash-password.

  • STUDIO_ALLOWED_HOSTS — el nombre(s) de host exacto(s) en los que la aplicación responderá (sin comodines; la aplicación se negará a arrancar con *).

  • STUDIO_TRUSTED_PROXY_IPS — si hay un proxy inverso delante, la(s) IP(s) que usa para hablar con la aplicación.

La aplicación se niega a arrancar en modo remoto si falta cualquiera de los secretos requeridos o si allowed_hosts está vacío — esto es deliberado. No existe una configuración "silenciosamente abierta".

Configuración

La mayoría de los valores viven en variables de entorno (la producción es así de amigable con Docker). Un subconjunto también puede vivir en un archivo TOML cargado por --config o STUDIO_CONFIG — consulta config/config.example.toml para ver la forma.

Los secretos son solo entorno por diseño: nunca se leen de la configuración TOML, así que incluir el archivo de configuración en un despliegue nunca puede filtrarlos.

Variable

Propósito

Predeterminado

STUDIO_MODE

local (solo loopback, sin autenticación) o remote (cookies de sesión + contraseña)

local

STUDIO_BIND_HOST

Dirección a la que se vincula el servidor

127.0.0.1

STUDIO_BIND_PORT

Puerto al que se vincula el servidor

8000

STUDIO_ALLOWED_HOSTS

Lista separada por comas de nombres de host aceptados en la cabecera Host: (obligatorio en modo remoto)

(vacío)

STUDIO_TRUSTED_PROXY_IPS

Lista separada por comas de IPs de proxy cuyos CF-Connecting-IP / X-Forwarded-For se deben confiar

(vacío)

STUDIO_SESSION_SECRET

Cadena aleatoria de ≥32 caracteres usada para firmar las cookies de sesión (obligatorio en modo remoto)

(vacío)

STUDIO_AUTH_PASSWORD_HASH

Contraseña de inicio de sesión con hash scrypt generada con studio hash-password (obligatorio en modo remoto)

(vacío)

STUDIO_DATA_DIR

Dónde reside la base de datos SQLite

./data

STUDIO_UPLOADS_DIR

Dónde residen los adjuntos subidos

<data-dir>/uploads

STUDIO_BACKUPS_DIR

Dónde se escriben las copias de seguridad en línea de SQLite

./backups

STUDIO_LOGS_DIR

Dónde van los registros de la aplicación

./logs

STUDIO_BACKUP_STATE_DIR

Ruta opcional de solo lectura donde los trabajos de copia de seguridad del host dejan capacity.json para el widget de estado de la aplicación

(sin definir — el estado muestra unknown)

STUDIO_UPLOAD_MAX_FILE_BYTES

Límite de subida por archivo

26214400 (25 MiB)

STUDIO_UPLOAD_QUOTA_BYTES

Cuota total de subida por subárbol de proyecto madre

2147483648 (2 GiB)

STUDIO_UPLOAD_MAX_IMAGE_PIXELS

Protección contra bombas de descompresión

40000000 (40M px)

STUDIO_RADAR_TOKEN_HASH

Hex sha256 del token Bearer del canal de entrada; si no se define, desactiva el endpoint de entrada

(sin definir)

STUDIO_MCP_TOKEN_HASH

Hex sha256 del token Bearer estático de MCP; si no se define, desactiva la ruta Bearer estática

(sin definir)

STUDIO_MCP_OAUTH_ISSUER_URL

URL pública que aloja los metadatos del AS OAuth; definirla activa la ruta OAuth

(sin definir)

STUDIO_MCP_OAUTH_ALLOWED_REDIRECT_HOSTS

Nombres de host separados por comas permitidos en las URI de redirección DCR (loopback siempre permitido)

chatgpt.com

STUDIO_MCP_OAUTH_ACCESS_TOKEN_TTL_SECONDS

Duración del token de acceso OAuth

3600

STUDIO_MCP_OAUTH_REFRESH_TOKEN_TTL_SECONDS

Duración del token de actualización OAuth

2592000 (30 días)

STUDIO_MCP_OAUTH_CODE_TTL_SECONDS

Duración del código de autorización OAuth

300

Generación de tokens con hash

El endpoint de entrada y la ruta Bearer estática de MCP almacenan ambos sha256(token) — nunca el token en sí — por lo que una filtración de .env.production no produce nada reutilizable.

# Generate a token and its hash. The token goes to whichever caller needs it
# (your external intake, your MCP client). The hash goes into .env.production.
TOKEN=$(python -c "import secrets; print(secrets.token_urlsafe(32))")
printf %s "$TOKEN" | sha256sum | cut -d' ' -f1   # → STUDIO_RADAR_TOKEN_HASH / STUDIO_MCP_TOKEN_HASH
echo "$TOKEN"                                     # → give to the caller, nowhere else

Entrada externa: entrega tu propio feed a la bandeja de entrada

Existe un endpoint HTTP diseñado para recibir elementos de un alimentador externo — un raspador de RSS, una herramienta de radar de temas, un trabajo de raspado programado, cualquier cosa que ingiera contenido en tu nombre. El endpoint es genérico: trae tu propio upstream, conéctalo aquí, y los elementos llegan a la bandeja de entrada donde los clasificas.

Endpoint: POST /api/inbox

Autenticación: Authorization: Bearer <token>. El servidor compara sha256(token) con STUDIO_RADAR_TOKEN_HASH en tiempo constante. Si esa variable de entorno no está definida, el endpoint devuelve 401 a toda llamada Bearer — la entrada permanece totalmente cerrada.

CSRF no es necesario en esta ruta: la cookie CSRF defiende contra la repetición de sesión del navegador, que no es una amenaza cuando quien llama proporciona su propia cabecera Bearer.

Cuerpo de la solicitud (JSON):

Campo

Tipo

Notas

title

string, obligatorio, ≤500 caracteres

El título del elemento de la bandeja de entrada. Vacío / ausente → 400.

first_reaction

string, opcional

Tu comentario de una línea.

links

string, opcional

Texto libre — las URLs pegadas son válidas.

radar_topic_id

string, opcional, ≤500 caracteres

El identificador de tu alimentador para este tema. Segunda clave de deduplicación más fuerte.

canonical_url

string, opcional, ≤2000 caracteres

URL canónica del elemento. Tercera clave de deduplicación más fuerte.

idempotency_key

string, opcional, ≤500 caracteres

Clave única por entrega. Clave de deduplicación más fuerte.

Prioridad de deduplicación: idempotency_key > radar_topic_id > canonical_url. En una entrega repetida, el servidor devuelve la fila que ya existe en lugar de crear una segunda — incluso si ya habías descartado o convertido esa fila. La reentrega no debe anular tu decisión de clasificación.

Respuesta:

  • 201 Created — se insertó una fila completamente nueva.

  • 200 OK — una entrega repetida coincidió con una fila existente (cualquier estado, incluido descartado / convertido). Misma forma de cuerpo.

  • 400 Bad Requesttitle ausente / no válido.

  • 401 Unauthorized — token Bearer incorrecto o ausente, o entrada no configurada.

Cuerpo de la respuesta:

{
  "item": {
    "id": 42,
    "title": "…",
    "source": "radar",
    "status": "pending",
    "created_at": "2026-08-12T12:34:56Z",
    "…": "…"
  },
  "deduplicated": false
}

Ejemplo con curl:

curl -X POST https://studio.example.com/api/inbox \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Interesting minisite on typography systems",
    "first_reaction": "worth a look for the next essay",
    "links": "https://example.com/article",
    "canonical_url": "https://example.com/article",
    "idempotency_key": "myfeed-2026-08-12-a3f9"
  }'

El campo se apoda «radar» en todo el código porque originalmente estaba conectado a una herramienta externa de radar de contenido; el endpoint en sí es genérico y funciona con cualquier alimentador que pueda hablar HTTP.

Licencia

Copyright (C) 2026 yoruuuchan.

Yoru Studio está licenciado bajo la GNU Affero General Public License, versión 3, únicamente (AGPL-3.0-only). LICENSE contiene el texto de la licencia literal.

En una frase: puedes autoalojar, usar y modificar el código libremente para tu propio trabajo creativo; si ejecutas una versión modificada como servicio de red con el que otras personas interactúan, debes ofrecerles el código fuente de esa versión modificada. Esto es exactamente lo que AGPL está diseñada para imponer — la cláusula de «uso en red» (§13) hace que la obligación recíproca se active al ejecutarla, no solo al distribuirla.

Expectativas

Este es un proyecto personal. Existe porque un creador lo necesitó y decidió compartirlo.

  • No es un producto. No hay hoja de ruta a la que nadie más tenga derecho, ni SLA de soporte, ni promesa de que la próxima versión no rompa tu configuración.

  • Mantenido al ritmo del autor. Las issues y pull requests son bienvenidas, pero las respuestas llegan cuando llegan.

  • Tú lo autoalojas. No existe versión alojada. No hay plan para tenerla.

  • Los datos viven en tu máquina. Nada llama a casa. Nada se envía a un tercero. Ese es el sentido del autoalojamiento; también es la razón por la que nadie va a rescatar tus datos si los pierdes. Haz copias de seguridad.

Si algo de eso te suena a «no es para mí», esa es la señal honesta — por favor elige otra cosa y sin rencores.

Contribuciones

Los informes de errores son bienvenidos. Incluye suficientes detalles para que el error pueda reproducirse con una copia limpia del repositorio.

Solicitudes de funciones: este proyecto se limita deliberadamente a un alcance pequeño y solo añade funciones después de que el uso real exponga una necesidad. Una solicitud de función que suene a «esto es lo que me encontré al intentar usar la aplicación» tiene muchas más probabilidades de prosperar que una que suene a «esto sería bonito tenerlo».

Pull requests: para cualquier cosa más grande que una corrección de error de un solo archivo, abre primero una issue para comprobar que la dirección encaja. AGPL-3.0-only significa que las contribuciones deben ser compatibles con esa licencia — al abrir una pull request aceptas que tu contribución queda bajo los mismos términos que el resto del proyecto.

Atribución

Construido por Yoru, Claude Fable 5 y GPT 5.6 Sol — los tres.

Maintenance

ActivityMaintained
ResponsivenessSyncing

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

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

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    B
    maintenance
    MCP server for task management, project knowledge, workspace trust, runner sandboxes, extension registry, and workflow prompts, enabling AI agents to manage tasks and collaborate locally.
    5,117
    Apache 2.0
  • A
    license
    Not graded
    quality
    C
    maintenance
    A self-hosted MCP server that gives AI agents controlled access to a machine: filesystem, shell, background processes, git, web fetching and persistent key-value memory.
    GPL 3.0

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/yoruuuchan/yoru-studio-oss'

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