yoru-studio-mcp
Yoru Studio
한 명의 크리에이터를 위한 셀프 호스팅 실행 스튜디오.
중국어(간체)로도 읽을 수 있습니다.
Yoru Studio는 한 사람이 아이디어를 완성된 창작물로 바꾸는 작업 공간입니다. 인박스에서 아이디어를 포착하고, 이를 모 프로젝트로 가져오고, 하위 프로젝트(비디오 / 포토 에세이 / 장문 기사 / 자산 전달)로 나누고, 스토리보드를 계획하고, 오프라인 안전 큐로 현장 촬영을 진행하고, 실제로 일어난 일을 기록한 후, 회고로 마무리합니다. 결과물은 플랫폼 버전 아래에 있어서 같은 컷을 Douyin / Bilibili / Xiaohongshu 이미지 세트로 배포할 수 있으며 프로젝트 자체를 중복할 필요가 없습니다.
이 도구는 한 사람 — 크리에이터 — 을 위해 작성되었으며, 자신의 컴퓨터에서 실행합니다. 멀티 테넌트, 팀 시트, SaaS 백엔드가 없습니다. 설치하면 전체 시스템이 사용자가 제어하는 한 대의 머신에 존재합니다.
여기에 무엇이 있나
소스를 읽는 것이 "실제로 무엇을 하는가?"에 대한 권위 있는 답변입니다 — 아래 요약은 지도일 뿐, 영토가 아닙니다.
인박스 → 모 프로젝트 → 하위 프로젝트 → 플랫폼 버전: 창의적 워크플로우의 전체 뼈대이며, 좋은 아이디어가 어디에 속하는지 알 때 활성 하위 프로젝트로 바로 건너뛸 수 있는 빠른 경로가 있습니다.
스토리보드: 목록 보기와 보드 보기, 드래그로 재정렬, 샷별 참조 이미지, XLSX 내보내기, 현장 사용을 위한 인쇄 가능한 버전.
일정 및 캘린더: 정확한 시간, 하루 종일 날짜, 그리고 "이번 주", "주말" 같은 모호한 기간이 하나의 캘린더에 공존합니다. 지연은 계산되며 기억되지 않으므로 조용히 썩지 않습니다.
알림 및 사이트 내 알림: 데이터베이스 계층에서 중복 제거되어 재시작 시 동일한 알림이 두 번 발생하지 않습니다.
실행 기록: 촬영 / 재촬영 / 화면 녹화 / 글쓰기 세션 — 실제로 한 일과 일치하는 프로젝트 계층에 기록을 첨부합니다.
회고: 가볍거나 전체; 모든 필드는 선택 사항입니다. 구조는 요구가 아니라 상기시키기 위한 것입니다.
첨부 파일: 네 가지 형태 — 업로드된 이미지(썸네일 포함), 경로 포인터(예:
NAS/2026/Aug shoots/), 외부 링크, 텍스트 스니펫. 소프트 삭제된 파일은 휴지통에 30일 동안 보관됩니다.현장 모드: 현장 사용을 위한 모바일 우선 페이지. 네트워크가 끊기면 편집 내용이 IndexedDB에 큐에 쌓이고 연결이 복구되면 동기화됩니다.
전체 내보내기: JSON + 업로드 번들로 테이크아웃용, CLI 또는 설정 페이지에서.
백업: 예약된 온라인 SQLite 백업, 그리고 실제 복원 드릴 러너가 있는 암호화된 오프사이트 복사본을 위한 선택적 restic 스크립트.
MCP 채널: AI 에이전트(Claude, ChatGPT, Codex, …)용 — 아래 섹션 참조.
Related MCP server: todos
설계 입장
단일 사용자, 단일 계정. 데이터 모델에는 워크스페이스 열이 있어서 미래의 다중 사용자 버전이 스키마를 재구축할 필요가 없지만, 배포된 코드는 정확히 한 명의 사용자를 가정합니다.
외부 서비스 불필요. 디스크의 SQLite, 디스크의 파일. Redis, 메시지 큐, 타사 인증 없음. $5/월 VPS에서 실행할 수 있습니다.
작은 공간. 목표는 앱 512 MiB / 스케줄러 256 MiB / (선택) 리버스 프록시 사이드카 128 MiB. 2 GiB VM이면 충분합니다.
서버는 프론트엔드를 빌드하지 않습니다. 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 채널: AI 에이전트 연결
Yoru Studio는 MCP(모델 컨텍스트 프로토콜) 서버를 노출하여 MCP를 사용하는 에이전트 — Claude Desktop, ChatGPT 데스크톱, Codex CLI, Claude Code 등 — 가 복사-붙여넣기 없이 스튜디오를 읽고 (추가)할 수 있게 합니다.
총 8개 도구, 모두 추가 전용 쓰기와 멱등성으로 범위가 제한됩니다:
읽기(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 엔드포인트 뒤에 두 가지 인증 경로 (소스의 docs/spec/ §5.1):
정적 Bearer 토큰 — 개인 / 단일 에이전트용. 긴 임의 문자열을 만들고,
sha256을 환경에 저장하고, 토큰을 에이전트에 제공합니다.OAuth 2.0 with PKCE + Dynamic Client Registration — 이를 기대하는 커넥터용(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로컬 모드는 루프백에 바인딩하고 개발자 편의를 위해 인증을 건너뜁니다. 로컬에서 인증 흐름을 시도하려면 아래 "원격 모드 활성화" 섹션을 따르세요.
다른 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 (
docker-compose.yml의 참조cloudflared서비스,scripts/provision-cloudflare-tunnel.py의 프로비저닝 스크립트 포함).Caddy 또는 Nginx 호스트 수준 리버스 프록시, 자체 인증서로 TLS 종료.
Tailscale Funnel — 개인 우선 호스팅.
SSH 포워드
-L 8000— 자신의 머신에서만 사용하려는 경우.
Cloudflare Tunnel을 사용하는 경우 cloudflared 서비스를 편집하거나 제거하고 .env.production에서 STUDIO_TRUSTED_PROXY_IPS를 해제하세요. 다른 프록시를 사용하는 경우 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 -ddocs/deploy.md에는 참조 레이아웃, scripts/ 아래의 백업 자동화 스크립트, 배포 및 백업 작업이 공유하는 운영 잠금에 대한 더 긴 워크스루가 있습니다.
원격 모드 활성화
원격 모드는 앱을 "인증 없는 로컬 개발"에서 "프록시 뒤의 공개 URL + 세션 쿠키"로 전환합니다. 최소한 다음을 설정하세요:
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 친화적). 일부는 --config 또는 STUDIO_CONFIG로 로드되는 TOML 파일에 있을 수 있습니다 — config/config.example.toml 참조.
비밀은 환경 전용으로 설계되었습니다: TOML 구성에서 절대 읽지 않으므로, 배포에 구성 파일을 번들로 포함해도 비밀이 유출되지 않습니다.
변수 | 용도 | 기본값 |
|
|
|
| 서버가 바인딩하는 주소 |
|
| 서버가 바인딩하는 포트 |
|
|
| (비어 있음) |
| 신뢰할 | (비어 있음) |
| 세션 쿠키 서명에 사용되는 32자 이상의 임의 문자열 (remote 모드에서 필수) | (비어 있음) |
|
| (비어 있음) |
| SQLite 데이터베이스가 위치하는 곳 |
|
| 업로드된 첨부 파일이 위치하는 곳 |
|
| SQLite 온라인 백업이 기록되는 곳 |
|
| 앱 로그가 저장되는 곳 |
|
| 호스트의 백업 작업이 앱 내 상태 위젯용 | (미설정 — 상태는 |
| 파일별 업로드 상한 |
|
| 모 프로젝트 하위 트리당 총 업로드 할당량 |
|
| 압축 해제 폭탄 방지 |
|
| 수신 채널의 bearer 토큰의 | (미설정) |
| MCP 정적 bearer 토큰의 | (미설정) |
| OAuth AS 메타데이터를 호스팅하는 공개 URL; 설정하면 OAuth 경로 활성화 | (미설정) |
| DCR 리다이렉트 URI에서 허용되는 호스트 이름 쉼표로 구분된 목록 (루프백은 항상 허용) |
|
| OAuth 액세스 토큰 수명 |
|
| OAuth 리프레시 토큰 수명 |
|
| OAuth 인증 코드 수명 |
|
해시 토큰 생성
수신 엔드포인트와 MCP 정적 Bearer 경로는 모두 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외부 수신: 자신의 피드를 인박스에 넘기기
외부 피더 — RSS 스크레이퍼, 토픽 레이더 도구, 예약된 스크레이프 작업 등 콘텐츠를 대신 수집하는 어떤 것이든 — 로부터 항목을 받도록 설계된 HTTP 엔드포인트가 있습니다. 이 엔드포인트는 범용적입니다: 자체 업스트림을 가져와 여기에 연결하면 항목이 인박스에 들어가 분류할 수 있습니다.
엔드포인트: POST /api/inbox
인증: Authorization: Bearer <token>. 서버는 sha256(token)을 STUDIO_RADAR_TOKEN_HASH와 상시 시간에 비교합니다. 해당 환경 변수가 설정되지 않으면 엔드포인트는 모든 Bearer 호출에 401을 반환합니다 — 수신은 완전히 닫힌 상태로 유지됩니다.
이 경로에는 CSRF가 필요하지 않습니다: CSRF 쿠키는 브라우저 세션 재생을 방어하는데, 호출자가 자체 bearer 헤더를 제공할 때는 그 위협이 없습니다.
요청 본문 (JSON):
필드 | 유형 | 참고 |
| string, 필수, ≤500자 | 인박스 항목의 제목. 비어 있음 / 없음 → |
| string, 선택 | 한 줄 요약 의견. |
| string, 선택 | 자유 텍스트 — 붙여넣은 URL도 괜찮습니다. |
| string, 선택, ≤500자 | 피더의 이 토픽 식별자. 두 번째로 강한 중복 제거 키. |
| string, 선택, ≤2000자 | 항목의 canonical URL. 세 번째로 강한 중복 제거 키. |
| string, 선택, ≤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, version 3, only (AGPL-3.0-only)로 라이선스가 부여됩니다. LICENSE에는 라이선스 원문이 포함되어 있습니다.
한 문장으로: 자신의 창작 작업을 위해 코드를 자유롭게 자체 호스팅, 사용, 수정할 수 있습니다; 수정한 버전을 다른 사람들이 상호작용하는 네트워크 서비스로 운영한다면, 그 수정된 버전의 소스를 제공해야 합니다. 이것이 바로 AGPL이 강제하도록 설계된 것입니다 — "네트워크 사용" 조항(§13)은 배포뿐만 아니라 실행 시에도 상호 의무가 발생하게 합니다.
기대 사항
이것은 개인 프로젝트입니다. 한 창작자가 필요하고 공유하기로 결정했기 때문에 존재합니다.
제품이 아닙니다. 다른 사람이 기대할 수 있는 로드맵도, 지원 SLA도, 다음 릴리스가 설정을 깨뜨리지 않을 것이라는 약속도 없습니다.
작성자 자신의 리듬으로 유지됩니다. 이슈와 풀 리퀘스트는 환영하지만, 답변은 그때그때 옵니다.
직접 호스팅합니다. 호스팅 버전은 존재하지 않습니다. 계획도 없습니다.
데이터는 기기에 있습니다. 아무것도 외부로 전송되지 않습니다. 아무것도 제3자에게 보내지 않습니다. 그것이 자체 호스팅의 핵심입니다; 데이터를 잃어도 아무도 구해주지 않을 이유이기도 합니다. 백업을 하세요.
그 중 하나가 "나에게 맞지 않다"로 읽힌다면, 그것이 정직한 신호입니다 — 다른 것을 선택해 주시고 불편한 감정 없이 넘어가 주세요.
기여
버그 리포트는 환영합니다. 깨끗한 체크아웃에서 버그를 재현할 수 있을 만큼 충분한 세부 정보를 포함해 주세요.
기능 요청: 이 프로젝트는 의도적으로 작은 범위를 유지하며 실제 사용에서 필요가 드러난 후에만 기능을 추가합니다. "앱을 사용하다 실제로 부딪한 문제"처럼 읽히는 기능 요청이 "있으면 좋은 것"처럼 읽히는 것보다 훨씬 채택될 가능성이 높습니다.
풀 리퀘스트: 한 파일 버그 수정보다 큰 작업은 먼저 이슈를 열어 방향이 맞는지 확인해 주세요. AGPL-3.0-only는 기여가 해당 라이선스와 호환되어야 함을 의미합니다 — 풀 리퀘스트를 열면 기여가 프로젝트의 나머지와 동일한 조건으로 제공된다는 것에 동의하는 것입니다.
크레딧
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.
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.1565 npm4MIT
- 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-