Skip to main content
Glama
yoruuuchan

yoru-studio-mcp

by yoruuuchan

Yoru Studio

Ein selbst gehostetes Studio für einen einzelnen Creator.

Lies dies auf Vereinfachtem Chinesisch.

Yoru Studio ist der Arbeitsbereich einer einzelnen Person, um Ideen in fertige kreative Arbeiten zu verwandeln: einen Funken im Posteingang aufgreifen, ihn in ein Mutterprojekt ziehen, in Unterprojekte aufteilen (Video / Fotoessay / langer Artikel / Asset-Lieferung), Storyboards planen, Außendrehs mit einer offline-sicheren Warteschlange durchführen, protokollieren, was tatsächlich passiert ist, und dann mit einer Retrospektive den Kreis schließen. Die Ergebnisse liegen unter Plattformversionen vor, sodass derselbe Schnitt als Douyin / Bilibili / ein Xiaohongshu-Bilderset ausgeliefert werden kann, ohne das Projekt selbst zu duplizieren.

Es ist für eine Person geschrieben – den Creator –, die es auf ihrem eigenen Rechner betreibt. Es gibt keine Multi-Tenant-Geschichte, keine Team-Sitze, kein SaaS-Backend. Wenn du es installierst, lebt das gesamte System auf einer Maschine, die du kontrollierst.

Was hier ist

Den Quellcode zu lesen ist die maßgebliche Antwort auf „Was macht es eigentlich?“ – die Zusammenfassung unten ist eine Karte, nicht das Gebiet.

  • Posteingang → Mutterprojekt → Unterprojekt → Plattformversion: das vollständige Rückgrat eines kreativen Workflows, mit einer Schnellspur, die eine gute Idee direkt in ein aktives Unterprojekt springen lässt, wenn du weißt, wohin sie gehört.

  • Storyboards mit Listenansicht und Board-Ansicht, Ziehen zum Neuanordnen, Referenzbildern pro Einstellung, XLSX-Export und einer druckbaren Version für den Einsatz am Set.

  • Zeitplan und Kalender: präzise Zeiten, ganztägige Daten und vage Zeitfenster („diese Woche“, „das Wochenende“) koexistieren in einem Kalender; Überfälligkeit wird berechnet, nicht erinnert, sodass nichts still verrottet.

  • Erinnerungen und In-Site-Benachrichtigungen, auf Datenbankebene dedupliziert, sodass ein Neustart nie dieselbe Warnung zweimal auslöst.

  • Ausführungsaufzeichnungen für Drehs / Nachdrehs / Bildschirmaufnahmen / Schreibsitzungen – hänge den Datensatz an die Projektebene an, die tatsächlich zu dem passt, was du getan hast.

  • Retrospektiven, leicht oder vollständig; jedes Feld ist optional. Die Struktur ist da, um dich zu erinnern, nicht um zu fordern.

  • Anhänge in vier Formen: hochgeladene Bilder (mit Thumbnails), Pfadverweise (z. B. NAS/2026/Aug shoots/), externe Links und Textausschnitte. Soft gelöschte Dateien liegen 30 Tage lang im Papierkorb.

  • Feldmodus: mobile-first Seite für den Einsatz am Set. Wenn das Netzwerk ausfällt, werden Bearbeitungen in IndexedDB in die Warteschlange gestellt und synchronisieren sich, wenn die Verbindung zurückkehrt.

  • Vollständiger Export: JSON + Uploads-Bundle für Takeout, entweder über die CLI oder die Einstellungsseite.

  • Backups: Online-SQLite-Backup nach Zeitplan und optionale restic-Skripte für verschlüsselte Off-Site-Kopien mit einem echten Restore-Übungs-Runner.

  • MCP-Kanal für KI-Agenten (Claude, ChatGPT, Codex, …) – siehe Abschnitt unten.

Related MCP server: todos

Design-Ansatz

  • Einzelner Benutzer, einzelnes Konto. Das Datenmodell trägt eine Workspace-Spalte, damit eine zukünftige Multi-User-Version das Schema nicht neu aufbauen muss, aber alles im ausgelieferten Code geht von genau einem Benutzer aus.

  • Keine externen Dienste erforderlich. SQLite auf der Festplatte, Dateien auf der Festplatte. Kein Redis, keine Nachrichtenwarteschlange, keine Drittanbieter-Authentifizierung. Du kannst es auf einem VPS für 5 $/Monat betreiben.

  • Kleiner Fußabdruck. Ziel sind App 512 MiB / Scheduler 256 MiB / (optional) Reverse-Proxy-Sidecar 128 MiB. Eine 2-GiB-VM reicht aus.

  • Der Server baut das Frontend nicht. Das Vite-Bundle wird lokal (oder in CI) gebaut und als vorgefertigte Dateien ausgeliefert. Deployment-Maschinen benötigen nie Node.

  • Inhalt vor Zeremonie. Das Retro-Formular hat keine Pflichtfelder – das Schema existiert, um dich daran zu erinnern, worüber du nachdenken sollst, nicht um das Speichern zu blockieren.

Tech-Stack

  • Backend: Python 3.12, FastAPI, SQLite (mit uv für die Abhängigkeitsverwaltung).

  • Frontend: React 19 + TypeScript, gebaut mit Vite.

  • Deployment: Docker Compose (Single-Host). Reverse-Proxy und TLS liegen bei dir – Cloudflare Tunnel, Caddy, Nginx, Tailscale Funnel oder einfach SSH-Tunnel für rein lokale Nutzung funktionieren alle.

  • Testen: pytest für das Backend, vitest für das Frontend.

MCP-Kanal: KI-Agenten verbinden

Yoru Studio stellt einen Model Context Protocol (MCP)-Server bereit, damit Agenten, die MCP sprechen – Claude Desktop, ChatGPT Desktop, Codex CLI, Claude Code und andere – aus deinem Studio lesen und (daran anhängen) können, ohne dass du kopierst und einfügst.

Insgesamt acht Werkzeuge, alle auf Append-Only-Schreibvorgänge mit Idempotenz beschränkt:

Lesen (5):

  • list_projects – Mutterprojektliste mit Zählern.

  • get_project – die vollständigen Details eines Mutterprojekts, einschließlich seiner Unterprojekte.

  • get_sub_project – ein Unterprojekt, mit Storyboard / Ausführungsaufzeichnungen / Retrospektive integriert.

  • get_schedule – anstehende (14 oder 30 Tage), alle überfälligen, kurzfristige vage Ereignisse.

  • get_inbox – ausstehende oder verworfene Posteingangselemente.

Schreiben (3, alle Append-Only, alle idempotent):

  • capture_inspiration – einen Funken in den Posteingang werfen.

  • append_storyboard_shots – atomar N Einstellungen zum Storyboard eines Video-Unterprojekts hinzufügen.

  • append_execution_record – einen Dreh / eine Schreibsitzung / einen Test protokollieren.

Jedes Schreibwerkzeug nimmt einen idempotency_key entgegen. Ein erneuter Versuch mit demselben Schlüssel gibt das erste Ergebnis zurück; eine andere Nutzlast mit demselben Schlüssel ist ein harter Konflikt. Nichts, was ein Agent tut, kann stillschweigend Arbeit überschreiben, die du bereits hast.

Zwei Authentifizierungspfade hinter demselben /mcp-Endpunkt (Spezifikation §5.1 von docs/spec/ im Quellcode):

  • Statisches Bearer-Token für den persönlichen / Einzel-Agenten-Gebrauch. Du erzeugst eine lange zufällige Zeichenfolge, speicherst ihren sha256 in der Umgebung und gibst das Token dem Agenten.

  • OAuth 2.0 mit PKCE + Dynamic Client Registration für Konnektoren, die es erwarten (ChatGPTs Konnektor ist der aktuelle Fall, der es erfordert).

Beide Pfade können koexistieren. Beide sind optional – lasse beide ungesetzt und die /mcp-Route wird nie gemountet.

Schnellstart

Zwei Wege, je nachdem, wie du es ausführen möchtest: aus dem Quellcode (für die Entwicklung oder wenn du Python selbst verwalten möchtest) oder über Docker Compose (für eine stabile Single-Host-Installation).

Aus dem Quellcode

Erfordert Python 3.12 und uv, plus Node 20+ für das 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

Der lokale Modus bindet an Loopback und überspringt die Authentifizierung zur Bequemlichkeit des Entwicklers. Um den Authentifizierungsablauf lokal auszuprobieren, folge dem Abschnitt „Aktivieren des Remote-Modus“ weiter unten.

Andere CLI-Befehle:

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

Führe die Tests aus:

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

Docker Compose

Die docker-compose.yml in diesem Repository definiert drei Dienste: app (das FastAPI + gebaute SPA), scheduler (eine Schleife mit 60-Sekunden-Takt, die Backups, Erinnerungen und Aufbewahrung ausführt) und cloudflared (ein Referenz-Reverse-Proxy-Sidecar – tausche es gegen das aus, was zu deiner Infrastruktur passt).

Reverse-Proxy / TLS ist bewusst außerhalb des Anwendungsbereichs der App: Wähle deine eigene. Vernünftige Optionen sind:

  • Cloudflare Tunnel (der Referenz-cloudflared-Dienst in docker-compose.yml, mit dem Bereitstellungsskript in scripts/provision-cloudflare-tunnel.py).

  • Caddy oder Nginx als Reverse-Proxy auf Host-Ebene, der TLS mit deinen eigenen Zertifikaten beendet.

  • Tailscale Funnel für privates Hosting an erster Stelle.

  • Einfach SSH weiterleiten -L 8000, wenn du es nur auf deiner eigenen Maschine haben möchtest.

Wenn du Cloudflare Tunnel verwendest, bearbeite oder entferne entweder den cloudflared-Dienst und setze STUDIO_TRUSTED_PROXY_IPS in .env.production zurück. Wenn du einen anderen Proxy verwendest, setze STUDIO_TRUSTED_PROXY_IPS auf die IP deines Proxys, damit echte Client-IPs im Audit-Log landen.

Bereitstellungsschritte (sobald dein Docker-Host bereit ist):

# 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 enthält eine längere Anleitung, die das Referenzlayout, die Backup-Automatisierungsskripte unter scripts/ und die Betriebssperre abdeckt, die die Bereitstellungs- und Backup-Jobs teilen.

Aktivieren des Remote-Modus

Der Remote-Modus verwandelt die App von „lokale Entwicklung ohne Authentifizierung“ in „öffentliche URL hinter einem Proxy mit Session-Cookies“. Setze mindestens:

  • STUDIO_MODE=remote

  • STUDIO_SESSION_SECRET – eine zufällige Zeichenfolge, mindestens 32 Zeichen.

  • STUDIO_AUTH_PASSWORD_HASH – die Ausgabe von uv run studio hash-password.

  • STUDIO_ALLOWED_HOSTS – die genauen Hostnamen, auf die die App antworten wird (keine Wildcards; die App weigert sich, mit * zu starten).

  • STUDIO_TRUSTED_PROXY_IPS – wenn ein Reverse-Proxy davor ist, die IP(s), die er verwendet, um mit der App zu sprechen.

Die App weigert sich, im Remote-Modus zu starten, wenn eines der erforderlichen Geheimnisse fehlt oder wenn allowed_hosts leer ist – das ist beabsichtigt. Es gibt keine „still offene“ Konfiguration.

Konfiguration

Die meisten Werte leben in Umgebungsvariablen (Produktion ist auf diese Weise Docker-freundlich). Eine Teilmenge kann auch in einer TOML-Datei leben, die über --config oder STUDIO_CONFIG geladen wird – siehe config/config.example.toml für die Form.

Geheimnisse sind nur über Umgebungsvariablen konzipiert: Sie werden nie aus der TOML-Konfiguration gelesen, sodass das Bündeln der Konfigurationsdatei mit einer Bereitstellung sie niemals preisgeben kann.

Variable

Zweck

Standard

STUDIO_MODE

local (nur Loopback, keine Authentifizierung) oder remote (Sitzungs-Cookies + Passwort)

local

STUDIO_BIND_HOST

Adresse, an die der Server bindet

127.0.0.1

STUDIO_BIND_PORT

Port, an den der Server bindet

8000

STUDIO_ALLOWED_HOSTS

Kommagetrennte Liste von Hostnamen, die im Host:-Header akzeptiert werden (erforderlich im Remote-Modus)

(leer)

STUDIO_TRUSTED_PROXY_IPS

Kommagetrennte Liste von Proxy-IPs, deren CF-Connecting-IP / X-Forwarded-For vertraut wird

(leer)

STUDIO_SESSION_SECRET

Zufällige Zeichenkette mit ≥32 Zeichen zum Signieren von Sitzungs-Cookies (erforderlich im Remote-Modus)

(leer)

STUDIO_AUTH_PASSWORD_HASH

scrypt-gehashtes Anmeldekennwort von studio hash-password (erforderlich im Remote-Modus)

(leer)

STUDIO_DATA_DIR

Wo die SQLite-Datenbank liegt

./data

STUDIO_UPLOADS_DIR

Wo hochgeladene Anhänge gespeichert werden

<data-dir>/uploads

STUDIO_BACKUPS_DIR

Wo SQLite-Online-Backups geschrieben werden

./backups

STUDIO_LOGS_DIR

Wo Anwendungsprotokolle abgelegt werden

./logs

STUDIO_BACKUP_STATE_DIR

Optionaler schreibgeschützter Pfad, in den die Backup-Jobs des Hosts capacity.json für das In-App-Status-Widget ablegen

(nicht gesetzt — Status zeigt unknown)

STUDIO_UPLOAD_MAX_FILE_BYTES

Obergrenze für Upload pro Datei

26214400 (25 MiB)

STUDIO_UPLOAD_QUOTA_BYTES

Gesamt-Upload-Kontingent pro Unterbaum des Mutterprojekts

2147483648 (2 GiB)

STUDIO_UPLOAD_MAX_IMAGE_PIXELS

Schutz vor Dekompressionsbomben

40000000 (40M px)

STUDIO_RADAR_TOKEN_HASH

sha256-Hex des Bearer-Tokens des Aufnahmekanals; nicht gesetzt deaktiviert den Aufnahme-Endpunkt

(nicht gesetzt)

STUDIO_MCP_TOKEN_HASH

sha256-Hex des statischen Bearer-Tokens von MCP; nicht gesetzt deaktiviert den statischen Bearer-Pfad

(nicht gesetzt)

STUDIO_MCP_OAUTH_ISSUER_URL

Öffentliche URL, die die OAuth-AS-Metadaten hostet; das Setzen aktiviert den OAuth-Pfad

(nicht gesetzt)

STUDIO_MCP_OAUTH_ALLOWED_REDIRECT_HOSTS

Kommagetrennte Hostnamen, die in DCR-Weiterleitungs-URIs erlaubt sind (Loopback ist immer erlaubt)

chatgpt.com

STUDIO_MCP_OAUTH_ACCESS_TOKEN_TTL_SECONDS

Lebensdauer des OAuth-Zugriffstokens

3600

STUDIO_MCP_OAUTH_REFRESH_TOKEN_TTL_SECONDS

Lebensdauer des OAuth-Refresh-Tokens

2592000 (30 Tage)

STUDIO_MCP_OAUTH_CODE_TTL_SECONDS

Lebensdauer des OAuth-Autorisierungscodes

300

Generieren von gehashten Tokens

Der Aufnahme-Endpunkt und der MCP-Statisch-Bearer-Pfad speichern beide sha256(token) – niemals das Token selbst –, sodass ein durchgesickertes .env.production nichts Wiederverwendbares liefert.

# 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

Externer Eingang: Übergebe deinen eigenen Feed an den Posteingang

Es gibt einen HTTP-Endpunkt, der dafür ausgelegt ist, Elemente von einem externen Zuführer zu empfangen – einen RSS-Scraper, ein Themen-Radar-Tool, einen geplanten Scrape-Job, was auch immer Inhalte in deinem Namen aufnimmt. Der Endpunkt ist generisch: Bringe deine eigene Quelle mit, verbinde sie hier, und die Elemente landen im Posteingang, wo du sie sortierst.

Endpunkt: POST /api/inbox

Authentifizierung: Authorization: Bearer <token>. Der Server vergleicht sha256(token) mit STUDIO_RADAR_TOKEN_HASH in konstanter Zeit. Wenn diese Umgebungsvariable nicht gesetzt ist, gibt der Endpunkt bei jedem Bearer-Aufruf 401 zurück – der Eingang bleibt vollständig geschlossen.

CSRF ist auf diesem Pfad nicht erforderlich: Das CSRF-Cookie schützt vor Browser-Sitzungs-Wiedergabe, was keine Bedrohung darstellt, wenn der Aufrufer seinen eigenen Bearer-Header liefert.

Anfragekörper (JSON):

Feld

Typ

Hinweise

title

Zeichenkette, erforderlich, ≤500 Zeichen

Der Titel des Posteingangselements. Leer / fehlend → 400.

first_reaction

Zeichenkette, optional

Deine einzeilige Kurzmeinung.

links

Zeichenkette, optional

Freitext – eingefügte URLs sind in Ordnung.

radar_topic_id

Zeichenkette, optional, ≤500 Zeichen

Die Kennung deines Zuführers für dieses Thema. Zweitstärkster Deduplizierungsschlüssel.

canonical_url

Zeichenkette, optional, ≤2000 Zeichen

Kanonische URL des Elements. Drittstärkster Deduplizierungsschlüssel.

idempotency_key

Zeichenkette, optional, ≤500 Zeichen

Eindeutiger Schlüssel pro Zustellung. Stärkster Deduplizierungsschlüssel.

Deduplizierungspriorität: idempotency_key > radar_topic_id > canonical_url. Bei einer wiederholten Zustellung gibt der Server die bereits vorhandene Zeile zurück, anstatt eine zweite zu erstellen – selbst wenn du diese Zeile bereits verworfen oder konvertiert hast. Eine erneute Zustellung darf deine Triage-Entscheidung nicht umstoßen.

Antwort:

  • 201 Created – eine brandneue Zeile wurde eingefügt.

  • 200 OK – eine wiederholte Zustellung wurde einer vorhandenen Zeile zugeordnet (beliebiger Status, einschließlich verworfen / konvertiert). Gleiche Antwortstruktur.

  • 400 Bad Request – fehlender / ungültiger title.

  • 401 Unauthorized – ungültiges oder fehlendes Bearer-Token oder Eingang nicht konfiguriert.

Antwortkörper:

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

Curl-Beispiel:

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"
  }'

Das Feld wird im gesamten Codebase als „radar“ bezeichnet, weil es ursprünglich mit einem externen Content-Radar-Tool verbunden war; der Endpunkt selbst ist generisch und funktioniert mit jedem Zuführer, der HTTP sprechen kann.

Lizenz

Copyright (C) 2026 yoruuuchan.

Yoru Studio ist unter der GNU Affero General Public License, Version 3, nur (AGPL-3.0-only) lizenziert. LICENSE enthält den wörtlichen Lizenztext.

In einem Satz: Du kannst den Code für deine eigene kreative Arbeit frei selbst hosten, verwenden und modifizieren; wenn du eine modifizierte Version als Netzwerkdienst betreibst, mit dem andere Personen interagieren, musst du ihnen den Quellcode dieser modifizierten Version anbieten. Genau das soll die AGPL durchsetzen – die „Netzwerknutzungs“-Klausel (§13) löst die wechselseitige Verpflichtung bereits beim Betreiben aus, nicht erst beim Verteilen.

Erwartungen

Dies ist ein persönliches Projekt. Es existiert, weil ein Ersteller es brauchte und beschloss, es zu teilen.

  • Kein Produkt. Es gibt keine Roadmap, auf die jemand anderes Anspruch hätte, keine Support-SLA und kein Versprechen, dass die nächste Version deine Einrichtung nicht bricht.

  • Wird im eigenen Rhythmus des Autors gepflegt. Issues und Pull-Requests sind willkommen, aber Antworten kommen, wann sie kommen.

  • Du hostest es selbst. Es gibt keine gehostete Version. Es gibt keinen Plan für eine.

  • Daten leben auf deinem Rechner. Nichts ruft nach Hause. Nichts wird an Dritte gesendet. Das ist der Sinn des Selbsthostens; es ist auch der Grund, warum niemand deine Daten retten wird, wenn du sie verlierst. Mache Backups.

Wenn das für dich wie „nichts für mich“ klingt, ist das das ehrliche Signal – bitte wähle etwas anderes, und es gibt keine bösen Gefühle.

Mitwirken

Fehlerberichte sind willkommen. Bitte füge genügend Details hinzu, damit der Fehler gegen einen sauberen Checkout reproduziert werden kann.

Feature-Anfragen: Dieses Projekt hält sich bewusst klein und fügt Funktionen nur hinzu, nachdem die reale Nutzung einen Bedarf aufgedeckt hat. Eine Feature-Anfrage, die sich liest wie „hier ist, worauf ich tatsächlich gestoßen bin, als ich die App benutzt habe“, hat weitaus bessere Chancen als eine, die sich liest wie „hier ist eine nette Sache, die man haben könnte“.

Pull-Requests: Für alles, was größer ist als ein Ein-Datei-Fehlerbehebung, öffne bitte zuerst ein Issue, um zu prüfen, ob die Richtung passt. AGPL-3.0-only bedeutet, dass Beiträge mit dieser Lizenz kompatibel sein müssen – mit dem Öffnen eines Pull-Requests stimmst du zu, dass dein Beitrag unter denselben Bedingungen wie der Rest des Projekts steht.

Namensnennung

Erstellt von Yoru, Claude Fable 5 und GPT 5.6 Sol – wir drei.

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