yoru-studio-mcp
Yoru Studio
Самостоятельно размещаемая студия для работы одного творца.
Читать на упрощённом китайском.
Yoru Studio — это рабочее пространство одного человека для превращения идей в готовые творческие работы: поймать искру во входящих, перенести её в материнский проект, разбить на подпроекты (видео / фотоочерк / длинная статья / поставка материалов), спланировать раскадровки, провести полевые съёмки с офлайн-очередью, зафиксировать, что произошло на самом деле, и замкнуть цикл ретроспективой. Результаты живут в версиях под платформы, так что один и тот же монтаж можно выпустить как Douyin / Bilibili / набор изображений для Xiaohongshu без дублирования самого проекта.
Он написан для одного человека — творца — и работает на его собственном компьютере. Никакой мультитенантности, никаких командных мест, никакого SaaS-бэкенда. После установки вся система живёт на одной машине, которой вы управляете.
Что здесь есть
Чтение исходного кода — авторитетный ответ на вопрос «что это на самом деле делает?» — приведённое ниже резюме — это карта, а не территория.
Входящие → Материнский проект → Подпроект → Версия платформы: полный хребет творческого рабочего процесса, с быстрым путём, позволяющим хорошей идее сразу перейти в активный подпроект, когда вы знаете, куда она относится.
Раскадровки с представлением списком и представлением доски, перетаскиванием для изменения порядка, эталонными изображениями для каждого кадра, экспортом в XLSX и печатной версией для использования на площадке.
Расписание и календарь: точное время, события на весь день и размытые окна («на этой неделе», «на выходных») сосуществуют в одном календаре; просроченное вычисляется, а не запоминается, так что ничто тихо не гниёт.
Напоминания и внутрисайтовые уведомления, дедуплицированные на уровне базы данных, чтобы перезапуск никогда не срабатывал дважды на одно и то же предупреждение.
Записи о выполнении для съёмок / пересъёмок / записи экрана / писательских сессий — прикрепите запись к тому слою проекта, который действительно соответствует тому, что вы сделали.
Ретроспективы, лёгкие или полные; каждое поле необязательно. Структура существует, чтобы напомнить вам, а не требовать.
Вложения четырёх видов: загруженные изображения (с миниатюрами), указатели путей (например,
NAS/2026/Aug shoots/), внешние ссылки и текстовые фрагменты. Мягко удалённые файлы лежат в корзине 30 дней.Полевой режим: мобильная страница для использования на площадке. Если сеть пропадает, правки ставятся в очередь в IndexedDB и синхронизируются при восстановлении соединения.
Полный экспорт: JSON + пакет загрузок для выноса данных, либо из CLI, либо со страницы настроек.
Резервные копии: онлайн-резервное копирование SQLite по расписанию и опциональные скрипты restic для зашифрованных внешних копий с настоящим средством прогона восстановления.
Канал MCP для ИИ-агентов (Claude, ChatGPT, Codex, …) — см. раздел ниже.
Related MCP server: todos
Принципы дизайна
Один пользователь, одна учётная запись. Модель данных несёт колонку рабочего пространства, чтобы будущая многопользовательская версия не перестраивала схему, но всё в поставляемом коде предполагает ровно одного пользователя.
Никаких внешних сервисов. SQLite на диске, файлы на диске. Никакого Redis, никакой очереди сообщений, никакой сторонней аутентификации. Можно запустить на VPS за $5/месяц.
Малый след. Цель — приложение 512 МиБ / планировщик 256 МиБ / (опционально) боковой контейнер обратного прокси 128 МиБ. Виртуальной машины на 2 ГиБ достаточно.
Сервер не собирает фронтенд. Vite-сборка выполняется локально (или в CI) и поставляется как предварительно собранные файлы. На машинах развёртывания Node не нужен.
Содержание важнее церемоний. В форме ретроспективы нет обязательных полей — схема существует, чтобы напомнить вам, о чём подумать, а не чтобы блокировать сохранение.
Технологический стек
Бэкенд: Python 3.12, FastAPI, SQLite (с
uvдля управления зависимостями).Фронтенд: React 19 + TypeScript, собирается с помощью Vite.
Развёртывание: Docker Compose (один хост). Обратное проксирование и TLS — на ваше усмотрение — подойдут Cloudflare Tunnel, Caddy, Nginx, Tailscale Funnel или просто SSH-туннели для локального использования.
Тестирование: pytest для бэкенда, vitest для фронтенда.
Канал MCP: подключение ИИ-агентов
Yoru Studio предоставляет сервер Model Context Protocol (MCP), чтобы агенты, говорящие на MCP — Claude Desktop, ChatGPT desktop, Codex CLI, Claude Code и другие — могли читать из вашей студии и (дополнять её) без копипасты.
Всего восемь инструментов, все ограничены записью-добавлением с идемпотентностью:
Чтение (5):
list_projects— список материнских проектов со счётчиками.get_project— полные детали одного материнского проекта, включая его подпроекты.get_sub_project— один подпроект со встроенными раскадровкой / записями о выполнении / ретроспективой.get_schedule— предстоящие (14 или 30 дней), все просроченные, ближайшие размытые события.get_inbox— ожидающие или отклонённые элементы входящих.
Запись (3, все только-добавление, все идемпотентные):
capture_inspiration— бросить искру во входящие.append_storyboard_shots— атомарно добавить N кадров в раскадровку видеоподпроекта.append_execution_record— зафиксировать съёмку / писательскую сессию / тест.
Каждый инструмент записи принимает idempotency_key. Повтор с тем же ключом возвращает первый результат; другая полезная нагрузка с тем же ключом — жёсткий конфликт. Ничто из того, что делает агент, не может молча перезаписать уже имеющуюся у вас работу.
Два пути аутентификации за одной конечной точкой /mcp (спецификация §5.1 в docs/spec/ в исходниках):
Статический Bearer-токен для личного / одноагентного использования. Вы создаёте одну длинную случайную строку, сохраняете её
sha256в окружении и передаёте токен агенту.OAuth 2.0 с PKCE + динамическая регистрация клиентов для коннекторов, которые этого ожидают (коннектор ChatGPT — текущий случай, который этого требует).
Оба пути могут сосуществовать. Оба необязательны — оставьте оба не заданными, и маршрут /mcp никогда не смонтируется.
Быстрый старт
Два пути в зависимости от того, как вы хотите запускать: из исходников (для разработки или если предпочитаете управлять Python самостоятельно) или через Docker Compose (для стабильной установки на одном хосте).
Из исходников
Требуется Python 3.12 и uv, плюс Node 20+ для фронтенда.
# 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Локальный режим привязывается к loopback и пропускает аутентификацию для удобства разработчика. Чтобы попробовать поток аутентификации локально, следуйте разделу «Включение удалённого режима» ниже.
Другие команды 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Запустите тесты:
uv run pytest # backend
cd frontend && npm test # frontendDocker Compose
Файл docker-compose.yml в этом репозитории определяет три сервиса: app (FastAPI + собранный SPA), scheduler (цикл с тиком в 60 секунд, выполняющий резервное копирование, напоминания, хранение) и cloudflared (эталонный боковой контейнер обратного прокси — замените его на то, что подходит вашей инфраструктуре).
Обратное проксирование / TLS намеренно вне рамок приложения: выбирайте своё. Разумные варианты включают:
Cloudflare Tunnel (эталонный сервис
cloudflaredвdocker-compose.ymlсо скриптом подготовки вscripts/provision-cloudflare-tunnel.py).Caddy или Nginx как обратный прокси на уровне хоста с завершением TLS на ваших собственных сертификатах.
Tailscale Funnel для приватного размещения.
Просто SSH-форвард
-L 8000, если вам нужно только на своей машине.
Если вы используете Cloudflare Tunnel, либо отредактируйте, либо удалите сервис cloudflared и снимите STUDIO_TRUSTED_PROXY_IPS в .env.production. Если вы используете другой прокси, задайте STUDIO_TRUSTED_PROXY_IPS как IP вашего прокси, чтобы реальные IP клиентов попадали в журнал аудита.
Шаги развёртывания (когда ваш Docker-хост готов):
# 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 есть более подробное руководство, охватывающее эталонную компоновку, скрипты автоматизации резервного копирования в scripts/ и операционную блокировку, которую разделяют задания развёртывания и резервного копирования.
Включение удалённого режима
Удалённый режим превращает приложение из «локальной разработки без аутентификации» в «публичный URL за прокси с сессионными cookie». Задайте как минимум:
STUDIO_MODE=remoteSTUDIO_SESSION_SECRET— случайная строка не короче 32 символов.STUDIO_AUTH_PASSWORD_HASH— выводuv run studio hash-password.STUDIO_ALLOWED_HOSTS— точное имя (имена) хоста, на которые приложение будет отвечать (без подстановочных знаков; приложение откажется запускаться с*).STUDIO_TRUSTED_PROXY_IPS— если перед приложением стоит обратный прокси, IP-адрес(а), с которых он обращается к приложению.
Приложение отказывается запускаться в удалённом режиме, если отсутствует любой из обязательных секретов или allowed_hosts пуст — это намеренно. Не существует конфигурации «тихо открытой».
Конфигурация
Большинство значений живут в переменных окружения (так производство дружелюбно к Docker). Подмножество также может жить в TOML-файле, загружаемом через --config или STUDIO_CONFIG — см. config/config.example.toml для формы.
Секреты только в окружении по дизайну: они никогда не читаются из TOML-конфига, так что включение конфиг-файла в развёртывание никогда не может их утечь.
Переменная | Назначение | По умолчанию |
|
|
|
| Адрес, к которому привязывается сервер |
|
| Порт, к которому привязывается сервер |
|
| Список имён хостов через запятую, принимаемых в заголовке | (пусто) |
| Список IP прокси через запятую, чьим | (пусто) |
| Случайная строка ≥32 символов для подписи сессионных cookie (обязательно в remote-режиме) | (пусто) |
| scrypt-хеш пароля для входа из | (пусто) |
| Где хранится база данных SQLite |
|
| Где хранятся загруженные вложения |
|
| Куда записываются онлайн-резервные копии SQLite |
|
| Куда идут журналы приложения |
|
| Необязательный путь только для чтения, куда задания резервного копирования хоста кладут | (не задан — статус показывает |
| Лимит загрузки на один файл |
|
| Общая квота загрузки на поддерево каждого материнского проекта |
|
| Защита от бомбы декомпрессии |
|
|
| (не задан) |
|
| (не задан) |
| Публичный URL, на котором размещены метаданные OAuth AS; его установка активирует путь OAuth | (не задан) |
| Список имён хостов через запятую, разрешённых в redirect URI DCR (loopback разрешён всегда) |
|
| Время жизни OAuth access-токена |
|
| Время жизни OAuth refresh-токена |
|
| Время жизни OAuth кода авторизации |
|
Генерация хешированных токенов
Конечная точка приёма и путь статического Bearer MCP хранят sha256(token) — никогда не сам токен — поэтому утёкший .env.production не даёт ничего, что можно было бы воспроизвести.
# 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Внешний приём: передайте свой собственный поток входящих во входящие
Существует HTTP-конечная точка, предназначенная для приёма элементов от внешнего источника — скрапера RSS, инструмента радара тем, запланированного задания по сбору данных, любого инструмента, который загружает контент от вашего имени. Конечная точка универсальна: принесите свой собственный апстрим, подключите его сюда, и элементы попадут во входящие, где вы их разберёте.
Конечная точка: POST /api/inbox
Аутентификация: Authorization: Bearer <token>. Сервер сравнивает sha256(token) с STUDIO_RADAR_TOKEN_HASH за постоянное время. Если эта переменная окружения не задана, конечная точка возвращает 401 на каждый вызов Bearer — приём остаётся полностью закрытым.
CSRF не требуется на этом пути: CSRF-cookie защищает от воспроизведения браузерной сессии, что не является угрозой, когда вызывающая сторона предоставляет свой собственный bearer-заголовок.
Тело запроса (JSON):
Поле | Тип | Примечания |
| строка, обязательно, ≤500 символов | Заголовок элемента входящих. Пусто / отсутствует → |
| строка, необязательно | Ваш однострочный комментарий. |
| строка, необязательно | Произвольный текст — вставленные URL подойдут. |
| строка, необязательно, ≤500 символов | Идентификатор этой темы от вашего источника. Второй по силе ключ дедупликации. |
| строка, необязательно, ≤2000 символов | Канонический URL элемента. Третий по силе ключ дедупликации. |
| строка, необязательно, ≤500 символов | Уникальный ключ на каждую доставку. Самый сильный ключ дедупликации. |
Приоритет дедупликации: idempotency_key > radar_topic_id > canonical_url. При повторной доставке сервер возвращает уже существующую строку, а не создаёт вторую — даже если вы уже отклонили или преобразовали эту строку. Повторная доставка не должна отменять ваше решение по разбору.
Ответ:
201 Created— была вставлена новая строка.200 OK— повторная доставка была сопоставлена с существующей строкой (любой статус, включая отклонённый / преобразованный). Та же форма тела.400 Bad Request— отсутствует / недействителенtitle.401 Unauthorized— неверный или отсутствующий bearer-токен, или приём не настроен.
Тело ответа:
{
"item": {
"id": 42,
"title": "…",
"source": "radar",
"status": "pending",
"created_at": "2026-08-12T12:34:56Z",
"…": "…"
},
"deduplicated": false
}Пример 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"
}'Поле называется «radar» во всей кодовой базе, потому что изначально оно было подключено к внешнему инструменту радара контента; сама конечная точка универсальна и работает с любым источником, умеющим говорить по HTTP.
Лицензия
Copyright (C) 2026 yoruuuchan.
Yoru Studio лицензируется по GNU Affero General Public License, версия 3, только (AGPL-3.0-only). LICENSE содержит точный текст лицензии.
Одним предложением: вы можете свободно размещать у себя, использовать и изменять код для своей собственной творческой работы; если вы запускаете модифицированную версию как сетевой сервис, с которым взаимодействуют другие люди, вы должны предложить им исходный код этой модифицированной версии. Именно это AGPL и призвана обеспечивать — пункт о «сетевом использовании» (§13) делает взаимное обязательство срабатывающим при запуске, а не только при распространении.
Ожидания
Это личный проект. Он существует, потому что одному создателю он был нужен, и он решил им поделиться.
Не продукт. Нет дорожной карты, на которую кто-то другой имеет право, нет SLA поддержки и нет обещания, что следующий релиз не сломает вашу настройку.
Поддерживается в собственном ритме автора. Проблемы и pull request'ы приветствуются, но ответы приходят, когда приходят.
Вы размещаете его у себя. Хостинговая версия не существует. И планов на неё нет.
Данные живут на вашей машине. Ничего не обращается домой. Ничего не отправляется третьим лицам. В этом и смысл самостоятельного размещения; это также причина, по которой никто не спасёт ваши данные, если вы их потеряете. Делайте резервные копии.
Если что-то из этого читается как «не для меня» — это честный сигнал: пожалуйста, выберите что-то другое, и никаких обид.
Вклад в проект
Отчёты об ошибках приветствуются. Пожалуйста, включайте достаточно деталей, чтобы ошибку можно было воспроизвести на чистой копии репозитория.
Запросы функций: этот проект намеренно ограничивает свой масштаб и добавляет функции только после того, как реальное использование выявит потребность. Запрос функции, который звучит как «вот с чем я реально столкнулся, пытаясь использовать приложение», с гораздо большей вероятностью будет принят, чем тот, который звучит как «вот что было бы неплохо иметь».
Pull request'ы: для чего-то большего, чем исправление ошибки в одном файле, пожалуйста, сначала откройте issue, чтобы проверить, что направление подходит. AGPL-3.0-only означает, что вклад должен быть совместим с этой лицензией — открывая pull request, вы соглашаетесь, что ваш вклад распространяется на тех же условиях, что и остальная часть проекта.
Атрибуция
Создано Yoru, Claude Fable 5 и GPT 5.6 Sol — нами троими.
This server cannot be deployed
Maintenance
Related MCP Connectors
MCP server for your apps' tools and custom tools, plus hosted AI agents and approval-gated workflows
Remote MCP server for AI.TV creators — delegate account operations to your AI agent over MCP.
- UniPostOAuthai.unipost
Hosted MCP server for AI agents to post to LinkedIn profiles and X and upload to YouTube.
Nifty's MCP server — exposes tasks, projects, messages, and files as tools for AI agents.
Related MCP Servers
- AlicenseBqualityDmaintenanceProduction-grade MCP server that gives AI agents safe access to your local dev environment: filesystem, databases, processes, and OpenAPI specs.1533 npm3MIT
- AlicenseNot gradedqualityBmaintenanceMCP 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 npmApache 2.0
- AlicenseNot gradedqualityBmaintenanceA 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
- FlicenseAqualityCmaintenanceA local-first MCP server that handles daily work tasks through your AI assistant: converts meeting notes into todos, manages todo lifecycle, tracks work hours, generates daily/weekly reports, organizes files via move-only operations, and diagnoses dev environments, all guarded by a human-maintained preview/apply safety model.25-