Skip to main content
Glama
yoruuuchan

yoru-studio-mcp

by yoruuuchan

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            # frontend

Docker 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 -d

docs/deploy.md에는 참조 레이아웃, scripts/ 아래의 백업 자동화 스크립트, 배포 및 백업 작업이 공유하는 운영 잠금에 대한 더 긴 워크스루가 있습니다.

원격 모드 활성화

원격 모드는 앱을 "인증 없는 로컬 개발"에서 "프록시 뒤의 공개 URL + 세션 쿠키"로 전환합니다. 최소한 다음을 설정하세요:

  • STUDIO_MODE=remote

  • STUDIO_SESSION_SECRET — 32자 이상의 무작위 문자열.

  • STUDIO_AUTH_PASSWORD_HASHuv run studio hash-password의 출력.

  • STUDIO_ALLOWED_HOSTS — 앱이 응답할 정확한 호스트 이름(와일드카드 없음; 앱은 *로 부팅을 거부합니다).

  • STUDIO_TRUSTED_PROXY_IPS — 앞에 리버스 프록시가 있는 경우, 앱과 통신하는 IP.

앱은 원격 모드에서 필수 비밀 중 하나가 없거나 allowed_hosts가 비어 있으면 부팅을 거부합니다 — 이는 의도적입니다. "조용히 열린" 구성은 없습니다.

구성

대부분의 값은 환경 변수에 있습니다(프로덕션은 Docker 친화적). 일부는 --config 또는 STUDIO_CONFIG로 로드되는 TOML 파일에 있을 수 있습니다 — config/config.example.toml 참조.

비밀은 환경 전용으로 설계되었습니다: TOML 구성에서 절대 읽지 않으므로, 배포에 구성 파일을 번들로 포함해도 비밀이 유출되지 않습니다.

변수

용도

기본값

STUDIO_MODE

local (루프백 전용, 인증 없음) 또는 remote (세션 쿠키 + 비밀번호)

local

STUDIO_BIND_HOST

서버가 바인딩하는 주소

127.0.0.1

STUDIO_BIND_PORT

서버가 바인딩하는 포트

8000

STUDIO_ALLOWED_HOSTS

Host: 헤더에서 허용되는 호스트 이름의 쉼표로 구분된 목록 (remote 모드에서 필수)

(비어 있음)

STUDIO_TRUSTED_PROXY_IPS

신뢰할 CF-Connecting-IP / X-Forwarded-For를 가진 프록시 IP의 쉼표로 구분된 목록

(비어 있음)

STUDIO_SESSION_SECRET

세션 쿠키 서명에 사용되는 32자 이상의 임의 문자열 (remote 모드에서 필수)

(비어 있음)

STUDIO_AUTH_PASSWORD_HASH

studio hash-password에서 생성된 scrypt 해시 로그인 비밀번호 (remote 모드에서 필수)

(비어 있음)

STUDIO_DATA_DIR

SQLite 데이터베이스가 위치하는 곳

./data

STUDIO_UPLOADS_DIR

업로드된 첨부 파일이 위치하는 곳

<data-dir>/uploads

STUDIO_BACKUPS_DIR

SQLite 온라인 백업이 기록되는 곳

./backups

STUDIO_LOGS_DIR

앱 로그가 저장되는 곳

./logs

STUDIO_BACKUP_STATE_DIR

호스트의 백업 작업이 앱 내 상태 위젯용 capacity.json을 놓는 선택적 읽기 전용 경로

(미설정 — 상태는 unknown으로 표시)

STUDIO_UPLOAD_MAX_FILE_BYTES

파일별 업로드 상한

26214400 (25 MiB)

STUDIO_UPLOAD_QUOTA_BYTES

모 프로젝트 하위 트리당 총 업로드 할당량

2147483648 (2 GiB)

STUDIO_UPLOAD_MAX_IMAGE_PIXELS

압축 해제 폭탄 방지

40000000 (40M px)

STUDIO_RADAR_TOKEN_HASH

수신 채널의 bearer 토큰의 sha256 16진수; 설정하지 않으면 수신 엔드포인트 비활성화

(미설정)

STUDIO_MCP_TOKEN_HASH

MCP 정적 bearer 토큰의 sha256 16진수; 설정하지 않으면 정적 Bearer 경로 비활성화

(미설정)

STUDIO_MCP_OAUTH_ISSUER_URL

OAuth AS 메타데이터를 호스팅하는 공개 URL; 설정하면 OAuth 경로 활성화

(미설정)

STUDIO_MCP_OAUTH_ALLOWED_REDIRECT_HOSTS

DCR 리다이렉트 URI에서 허용되는 호스트 이름 쉼표로 구분된 목록 (루프백은 항상 허용)

chatgpt.com

STUDIO_MCP_OAUTH_ACCESS_TOKEN_TTL_SECONDS

OAuth 액세스 토큰 수명

3600

STUDIO_MCP_OAUTH_REFRESH_TOKEN_TTL_SECONDS

OAuth 리프레시 토큰 수명

2592000 (30일)

STUDIO_MCP_OAUTH_CODE_TTL_SECONDS

OAuth 인증 코드 수명

300

해시 토큰 생성

수신 엔드포인트와 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):

필드

유형

참고

title

string, 필수, ≤500자

인박스 항목의 제목. 비어 있음 / 없음 → 400.

first_reaction

string, 선택

한 줄 요약 의견.

links

string, 선택

자유 텍스트 — 붙여넣은 URL도 괜찮습니다.

radar_topic_id

string, 선택, ≤500자

피더의 이 토픽 식별자. 두 번째로 강한 중복 제거 키.

canonical_url

string, 선택, ≤2000자

항목의 canonical URL. 세 번째로 강한 중복 제거 키.

idempotency_key

string, 선택, ≤500자

전달별 고유 키. 가장 강한 중복 제거 키.

중복 제거 우선순위: idempotency_key > radar_topic_id > canonical_url. 반복 전달 시 서버는 새 행을 만들지 않고 이미 존재하는 행을 반환합니다 — 이미 해당 행을 폐기했거나 변환했더라도 마찬가지입니다. 재전달은 분류 결정을 뒤집어서는 안 됩니다.

응답:

  • 201 Created — 새 행이 삽입되었습니다.

  • 200 OK — 반복 전달이 기존 행과 일치했습니다 (폐기/변환 포함 모든 상태). 동일한 본문 형태.

  • 400 Bad Requesttitle 누락 또는 유효하지 않음.

  • 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 — 우리 세 명이 만들었습니다.

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