Skip to main content
Glama
yoru-studio-mcp

yoru-studio-mcp

by yoruuuchan

Yoru Studio

一个为单一创作者提供的自托管执行工作室。

阅读此文档的简体中文版本。

Yoru Studio 是一个人的工作空间,用于将想法转化为完成的创意作品:在收件箱中捕捉灵感,将其拉入母项目,拆分为子项目(视频 / 图片散文 / 长文 / 资产交付),规划故事板,使用离线安全队列进行外景拍摄,记录实际发生的情况,然后通过回顾来闭环。交付物位于平台版本之下,因此同一剪辑可以作为抖音 / 哔哩哔哩 / 小红书图片集发布,而无需复制项目本身。

它是为一个人——创作者——在自己的机器上运行而编写的。没有多租户的故事,没有团队席位,没有 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 的虚拟机就足够了。

  • 服务器不构建前端。 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 等——可以读取你的工作室并向其追加内容,而无需你复制粘贴。

总共八个工具,全部限定为仅追加写入并具有幂等性:

读取(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 与 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

本地模式绑定到回环地址并跳过认证,以方便开发。要在本地尝试认证流程,请按照下面的“启用远程模式”部分操作。

其他 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,带有会话 cookie”。至少设置以下内容:

  • STUDIO_MODE=remote

  • STUDIO_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 配置中读取,因此将配置文件与部署捆绑在一起永远不会泄露它们。

变量

用途

默认值

STUDIO_MODE

local(仅回环,无认证)或 remote(会话 Cookie + 密码)

local

STUDIO_BIND_HOST

服务器绑定的地址

127.0.0.1

STUDIO_BIND_PORT

服务器绑定的端口

8000

STUDIO_ALLOWED_HOSTS

在 Host: 头中接受的主机名逗号分隔列表(远程模式必需)

(空)

STUDIO_TRUSTED_PROXY_IPS

逗号分隔的代理 IP 列表,这些代理的 CF-Connecting-IP / X-Forwarded-For 将被信任

(空)

STUDIO_SESSION_SECRET

用于签名会话 Cookie 的随机字符串,长度 ≥32 字符(远程模式必需)

(空)

STUDIO_AUTH_PASSWORD_HASH

来自 studio hash-password 的 scrypt 哈希登录密码(远程模式必需)

(空)

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 十六进制值;未设置则禁用摄取端点

(未设置)

STUDIO_MCP_TOKEN_HASH

MCP 静态 Bearer 令牌的 sha256 十六进制值;未设置则禁用静态 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

外部摄取:将你自己的源交给收件箱

有一个 HTTP 端点,用于接收来自外部供给器的条目——可以是 RSS 抓取器、主题雷达工具、定时抓取任务,或任何代你摄取内容的程序。该端点是通用的:自带上游,接到这里,条目就会进入收件箱,由你进行分流处理。

端点:POST /api/inbox

认证:Authorization: Bearer <token>。服务器以常数时间将 sha256(token) 与 STUDIO_RADAR_TOKEN_HASH 进行比较。如果该环境变量未设置,端点会对每次 Bearer 调用返回 401——摄取通道始终保持完全关闭。

此路径不需要 CSRF:CSRF cookie 用于防御浏览器会话重放,而当调用方自带 bearer 头时,这并不构成威胁。

请求体(JSON):

字段

类型

说明

title

string,必填,≤500 字符

收件箱条目标题。空白 / 缺失 → 400。

first_reaction

string,可选

你的一句话热评。

links

string,可选

自由文本——粘贴 URL 即可。

radar_topic_id

string,可选,≤500 字符

你的供给器对该主题的标识符。第二强的去重键。

canonical_url

string,可选,≤2000 字符

条目的规范 URL。第三强的去重键。

idempotency_key

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 通用公共许可证,仅第 3 版(AGPL-3.0-only)授权。LICENSE 包含逐字许可证文本。

一句话概括:你可以自由地自行托管、使用和修改代码,用于你自己的创作;如果你将修改后的版本作为网络服务运行供他人交互,你必须向他们提供该修改版本的源代码。这正是 AGPL 的设计目标——“网络使用”条款(§13)使互惠义务在运行该服务时即触发,而不仅仅是在分发时触发。

期望

这是一个个人项目。它之所以存在,是因为一位创作者需要它,并决定将其分享出来。

  • 不是产品。 没有哪条路线图是别人有权要求的,没有支持 SLA,也不保证下一个版本不会破坏你的现有环境。

  • 按作者自己的节奏维护。 欢迎提交 issue 和 pull request,但回复时间不定。

  • 由你自己托管。 不存在托管版本,也没有相关计划。

  • 数据保存在你的机器上。 没有任何东西会回传,也不会向第三方发送任何内容。这正是自我托管的意义所在;也是如果你丢失数据,没有人会来救你的原因。请做好备份。

如果其中任何一条让你觉得“不适合我”,那这就是真实的信号——请选择其他方案,彼此无需介怀。

贡献

欢迎提交错误报告。请提供足够的细节,使错误能够在干净检出(clean checkout)上重现。

功能请求:这个项目刻意保持小范围,只有在实际使用暴露出需求后才会添加功能。一个读起来像“这是我在使用应用时实际遇到的问题”的功能请求,远比读起来像“这是一个锦上添花的功能”的请求更有可能被采纳。

Pull request:对于任何超过单文件错误修复规模的改动,请先开一个 issue,确认方向是否合适。AGPL-3.0-only 意味着贡献必须与该许可证兼容——通过提交 pull request,你即同意你的贡献与项目其余部分遵循相同的条款。

致谢

由 Yoru、Claude Fable 5 和 GPT 5.6 Sol 共同构建——我们三人。

Related MCP Connectors

Related MCP Servers

  • A
    license
    B
    quality
    D
    maintenance
    Production-grade MCP server that gives AI agents safe access to your local dev environment: filesystem, databases, processes, and OpenAPI specs.
    15
    65 npm
    4
    MIT
  • 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 npm
    Apache 2.0
  • F
    license
    A
    quality
    C
    maintenance
    A 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
    -