democut 0.4.0 → 0.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +62 -16
- package/dist/cli.js +116 -13
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -7,11 +7,15 @@ DemoCut(democut) 에이전트 인증 CLI — OAuth2 **Device Flow**(RFC 8628). H
|
|
|
7
7
|
## 설치
|
|
8
8
|
|
|
9
9
|
```bash
|
|
10
|
-
npm install -g democut
|
|
10
|
+
npm install -g democut # 전역 설치 (선택)
|
|
11
|
+
npx -y democut@latest auth login # 설치 없이 바로 (@latest 필수 — 아래 MCP 절 참고)
|
|
11
12
|
```
|
|
12
13
|
|
|
13
14
|
## 사용
|
|
14
15
|
|
|
16
|
+
아래 예시는 **전역 설치한 경우**다. npx 로 쓰고 있다면 `democut` 을
|
|
17
|
+
`npx -y democut@latest` 로 바꿔 읽으면 된다.
|
|
18
|
+
|
|
15
19
|
```bash
|
|
16
20
|
democut auth login # device flow 로 로그인 → 토큰 저장
|
|
17
21
|
democut auth status # 현재 정체/워크스페이스/티어
|
|
@@ -123,23 +127,36 @@ npm run build # dist/cli.js (bin: democut) 번들
|
|
|
123
127
|
에이전트가 도구로 직접 영상을 만든다.
|
|
124
128
|
|
|
125
129
|
```bash
|
|
126
|
-
claude mcp add democut -- npx -y democut mcp
|
|
130
|
+
claude mcp add democut -- npx -y democut@latest mcp
|
|
127
131
|
```
|
|
128
132
|
|
|
129
|
-
`npx
|
|
133
|
+
`npx` 를 쓰는 이유는 전역 설치가 **연결의 선행 조건이 되지 않게** 하기 위해서다.
|
|
130
134
|
설치가 빠지면 등록은 성립하는데(등록은 바이너리 존재를 검사하지 않는다) 연결만 실패하고,
|
|
131
135
|
그 실패는 클라이언트의 `Failed to reconnect …` 한 줄로만 드러난다 — 서버가 뜨지 못하므로
|
|
132
136
|
진단을 낼 주체가 없다. 자격증명은 패키지가 아니라 `~/.democut/credentials.json` 에 있어
|
|
133
137
|
실행 방식을 바꿔도 로그인 상태는 그대로다. 전역 설치는 선택이다.
|
|
134
138
|
|
|
135
|
-
|
|
139
|
+
★ **`@latest` 를 빼지 마라.** `-y` 는 설치 확인 프롬프트를 자동 승인할 뿐 **버전을 다시
|
|
140
|
+
해석하지 않는다** — 태그를 빼면 `~/.npm/_npx` 캐시에 남은 옛 버전이 그대로 뜬다
|
|
141
|
+
(2026-08-31 실측: 게시본이 0.4.0 인데 캐시는 0.3.0). 그 스큐가 실제로 사고를 냈다. 서버가
|
|
142
|
+
`project_slug` 를 필수화한 뒤 게시본이 갱신되기까지 **2시간 45분** 동안 stdio 사용자의 영상
|
|
143
|
+
생성이 전부 422 였고, 원격 HTTP 사용자는 아무 영향이 없었다. 대가로 실행할 때마다
|
|
144
|
+
레지스트리를 한 번 보므로 npm 에 닿지 못하면 서버가 아예 뜨지 않는데, **조용히 옛 도구를
|
|
145
|
+
쓰는 것보다 큰 소리로 안 뜨는 편이 낫다**(레지스트리가 막힌 사내망이면 아래 원격 HTTP 나
|
|
146
|
+
전역 설치를 쓴다).
|
|
147
|
+
|
|
148
|
+
노출 도구 8개 — 쓰기는 둘뿐이고 과금은 하나뿐이다:
|
|
136
149
|
|
|
137
150
|
| 도구 | 부작용 |
|
|
138
151
|
|---|---|
|
|
139
152
|
| `democut_auth_status` | 없음 — 로그인·워크스페이스·티어 확인 |
|
|
140
|
-
| `democut_estimate_video_cost` |
|
|
141
|
-
| `
|
|
153
|
+
| `democut_estimate_video_cost` | 없음 — 비용만 계산 |
|
|
154
|
+
| `democut_credit_balance` | 없음 — 크레딧 잔액 |
|
|
155
|
+
| `democut_credit_ledger` | 없음 — 크레딧 사용 내역 |
|
|
156
|
+
| `democut_list_projects` | 없음 — 프로젝트 목록(최근 수정순) |
|
|
142
157
|
| `democut_get_video_status` | 없음 — 상태 조회 + 선택적 저장 |
|
|
158
|
+
| `democut_create_project` | **쓰기**(과금 없음) — 같은 제목이면 기존 것을 돌려준다 |
|
|
159
|
+
| `democut_generate_video` | **과금** — `confirmed_cost_usd` 필수 |
|
|
143
160
|
|
|
144
161
|
### 비용 승인이 프로토콜에 맞게 바뀐다
|
|
145
162
|
|
|
@@ -151,23 +168,47 @@ CLI 는 TTY 에 `y/N` 을 물어 사람을 막지만 MCP 에는 물어볼 화면
|
|
|
151
168
|
보내야 하고, 서버가 방금 계산한 값과 대조해 어긋나면 거부한다. 모델이 추정을 건너뛰고
|
|
152
169
|
바로 생성하는 것을 막고, 사람에게 보여준 금액과 실제 청구액이 갈라지지 않게 한다.
|
|
153
170
|
|
|
154
|
-
### stdio 와 원격 HTTP —
|
|
171
|
+
### stdio 와 원격 HTTP — 어느 쪽을 언제 쓰나
|
|
155
172
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
생겨도 사라지지 않는다.
|
|
173
|
+
둘은 **대체가 아니라 병존**이고, 도구 이름·인자도 같다. 고르는 기준은 취향이 아니라
|
|
174
|
+
**클라이언트가 도는 자리**다.
|
|
159
175
|
|
|
160
|
-
|
|
161
|
-
|
|
176
|
+
| | 사람이 쓰는 클라이언트<br>(노트북의 Claude Code·Cursor…) | 헤드리스·자동화 호스트<br>(게이트웨이·CI·서버 박스) |
|
|
177
|
+
|---|---|---|
|
|
178
|
+
| **권장** | **원격 HTTP** | **stdio (이 CLI)** |
|
|
179
|
+
| 로그인 | 붙는 순간 브라우저가 열려 끝난다 | `democut auth login --no-browser` 1회 (device flow, RFC 8628) |
|
|
180
|
+
| 브라우저 없는 자리 | **불가** — 비대화형에서는 OAuth 흐름이 안 돈다 | **가능** — 코드를 다른 기기에서 승인 |
|
|
181
|
+
| 사전 준비 | 아래 두 옵션을 그대로 복사 | 없음 — redirect URI 등록도 브라우저도 불필요 |
|
|
182
|
+
| 버전 스큐 | **없다** — 띄울 로컬 바이너리가 없다 | `@latest` 로 막는다(위 참고) |
|
|
183
|
+
| 산출물 | 만료되는 링크로만 받는다 | `--output` 으로 디스크에 저장된다 |
|
|
184
|
+
|
|
185
|
+
헤드리스에서 갈리는 것은 편의가 아니라 **가능/불가능**이다. 원격 HTTP 의 OAuth 는 호스트가
|
|
186
|
+
브라우저를 띄워야 시작되는데, Claude Code 문서가 비대화형에서는 그 흐름을 돌릴 수 없다고
|
|
187
|
+
명시한다 — *"In non-interactive mode there's no `/mcp` panel, so Claude Code can't run the
|
|
188
|
+
OAuth flow for you."* 사람이 대화형 세션에서 **미리** 인증해 두는 것(`claude mcp login`)이
|
|
189
|
+
유일한 우회다. 거기에 Clerk 이 loopback redirect 의 포트를 정확 일치로 요구하므로 그 호스트가
|
|
190
|
+
쓸 포트의 redirect URI 도 OAuth 애플리케이션에 미리 등록해야 한다.
|
|
191
|
+
|
|
192
|
+
stdio 는 device flow(RFC 8628)라 redirect URI 자체가 없고, `--no-browser` 가 코드와 URL 을
|
|
193
|
+
출력하면 사람이 **다른 기기에서** 승인한다 — 그래서 브라우저가 없는 자리에서도 성립한다.
|
|
162
194
|
|
|
163
195
|
```bash
|
|
164
|
-
claude mcp add --transport http --client-id
|
|
196
|
+
claude mcp add --transport http --client-id 7ovjLP6E85qLNAyq --callback-port 33418 \
|
|
165
197
|
democut https://democut.ai/mcp
|
|
166
198
|
```
|
|
167
199
|
|
|
168
|
-
|
|
169
|
-
등록(DCR)을 **일부러 꺼
|
|
170
|
-
|
|
200
|
+
두 옵션은 **생략할 수 없고 임의로 바꿀 수도 없다.** `--client-id` 는 이 서버가 아무
|
|
201
|
+
클라이언트나 받지 않기 때문이고(동적 클라이언트 등록(DCR)을 **일부러 꺼 두었다** —
|
|
202
|
+
켜면 아무나 등록해 통과하는 confused-deputy 표면이 열린다), `--callback-port` 는 그 포트의
|
|
203
|
+
redirect URI 가 사전 등록돼 있어야 하기 때문이다. 미등록이면 Clerk 이 400
|
|
204
|
+
`redirect_uri … does not match … pre-registered redirect urls` 로 거부한다. 위 두 값은
|
|
205
|
+
공개값이고 웹 문서(<https://democut.ai/docs/agents>)가 같은 쌍을 안내한다. 설계 근거의
|
|
206
|
+
SSOT 는 `apps/api/app/mcp/auth.py` docstring.
|
|
207
|
+
|
|
208
|
+
> ⚠️ **"클라이언트 설정 파일에 토큰이 남지 않는다" 는 stdio 의 고유 장점이 아니다.**
|
|
209
|
+
> 이 문서가 한동안 그렇게 적고 있었는데 **사실이 아니다** — 원격 HTTP 등록도 설정에는
|
|
210
|
+
> 공개값 둘(`clientId`·`callbackPort`)만 남고 액세스 토큰은 호스트의 자격증명 저장소에
|
|
211
|
+
> 있다(2026-08-31 실측). 두 전송이 같으므로 선택 근거가 되지 못한다. 위 표의 기준으로 골라라.
|
|
171
212
|
|
|
172
213
|
> ⚠️ 이 문단은 원래 "원격은 동적 클라이언트 등록을 요구해서 체인을 새로 쌓아야 한다" 고
|
|
173
214
|
> 적혀 있었는데 **틀렸다.** DCR 은 MCP 명세에서 MUST 가 아니라 SHOULD 이고, 무엇보다 우리
|
|
@@ -183,6 +224,11 @@ claude mcp add --transport http --client-id <client_id> --callback-port <포트>
|
|
|
183
224
|
promote(사람이 누르는 버튼) → npm-publish-cli → deploy-dgx
|
|
184
225
|
```
|
|
185
226
|
|
|
227
|
+
게시본에는 **sigstore provenance 서명**이 붙는다 — npmjs.com 의 패키지 페이지에서
|
|
228
|
+
"Provenance" 배지로 "이 레포의 이 파이프라인이 만들었다" 를 확인할 수 있다.
|
|
229
|
+
⚠️ 서명은 **fail-soft** 다: sigstore·OIDC 장애 시 경고를 남기고 서명 없이 게시한다
|
|
230
|
+
(외부 서비스 장애가 프로덕션 배포를 막지 않게). 그 릴리스에는 배지가 없다.
|
|
231
|
+
|
|
186
232
|
`deploy-dgx` 가 게시 성공을 `needs` 로 요구하므로, **게시가 실패하면 문서가 프로덕션에
|
|
187
233
|
나가지 않는다.** `/docs/agents` 가 아직 없는 패키지를 안내하는 창이 구조적으로 열리지 않는다
|
|
188
234
|
(무스코프 이름이라 그 창에서 제3자가 선점하면 토큰 탈취로 이어질 수 있다 — CWE-829).
|
package/dist/cli.js
CHANGED
|
@@ -6915,6 +6915,9 @@ var require_dist = __commonJS({
|
|
|
6915
6915
|
import { realpathSync } from "fs";
|
|
6916
6916
|
import { fileURLToPath } from "url";
|
|
6917
6917
|
|
|
6918
|
+
// src/version.ts
|
|
6919
|
+
var VERSION = "0.6.1";
|
|
6920
|
+
|
|
6918
6921
|
// src/device-flow.ts
|
|
6919
6922
|
var DeviceFlowError = class extends Error {
|
|
6920
6923
|
constructor(code, message) {
|
|
@@ -6929,7 +6932,9 @@ var SLOW_DOWN_INCREMENT_MS = 5e3;
|
|
|
6929
6932
|
async function postJson(url, body, fetchImpl) {
|
|
6930
6933
|
const res = await fetchImpl(url, {
|
|
6931
6934
|
method: "POST",
|
|
6932
|
-
|
|
6935
|
+
// api-client 와 같은 이유로 버전을 밝힌다 — device flow 는 그 파일을 거치지 않는
|
|
6936
|
+
// 별도 HTTP 경로라, 여기를 빼면 로그인 경로의 설치본 분포만 보이지 않는다.
|
|
6937
|
+
headers: { "Content-Type": "application/json", "User-Agent": `democut/${VERSION}` },
|
|
6933
6938
|
body: JSON.stringify(body)
|
|
6934
6939
|
});
|
|
6935
6940
|
const text = await res.text();
|
|
@@ -7286,7 +7291,10 @@ function parseDetail(status2, body) {
|
|
|
7286
7291
|
async function apiRequest(baseUrl, path, init = {}, deps = {}) {
|
|
7287
7292
|
const fetchImpl = deps.fetchImpl ?? fetch;
|
|
7288
7293
|
const token = await getValidAccessToken(baseUrl, deps);
|
|
7289
|
-
const headers = {
|
|
7294
|
+
const headers = {
|
|
7295
|
+
Authorization: `Bearer ${token}`,
|
|
7296
|
+
"User-Agent": `democut/${VERSION}`
|
|
7297
|
+
};
|
|
7290
7298
|
if (init.body !== void 0) headers["Content-Type"] = "application/json";
|
|
7291
7299
|
const res = await fetchImpl(`${baseUrl}${path}`, {
|
|
7292
7300
|
method: init.method ?? "GET",
|
|
@@ -7322,6 +7330,28 @@ function usd(v) {
|
|
|
7322
7330
|
}
|
|
7323
7331
|
function classifyApiError(e, ctx) {
|
|
7324
7332
|
const hint = ctx.statusHint ?? "\uC0C1\uD0DC \uC870\uD68C";
|
|
7333
|
+
if (e.status === 422 && e.code === "VIDEOGEN_UPSTREAM_REJECTED") {
|
|
7334
|
+
return {
|
|
7335
|
+
safety: "unsafe",
|
|
7336
|
+
// 돈이 나갔다가 돌아왔다 — "애초에 과금이 없었다" 와는 다르다. 그 구분을 흐리면
|
|
7337
|
+
// 원장을 보는 사람이 이 거래를 설명하지 못한다.
|
|
7338
|
+
notCharged: false,
|
|
7339
|
+
lines: [
|
|
7340
|
+
"\uC5C5\uC2A4\uD2B8\uB9BC\uC774 \uC774 \uC791\uC5C5\uC744 \uC601\uAD6C \uAC70\uBD80\uD588\uC2B5\uB2C8\uB2E4. \uB2E4\uC2DC \uC870\uD68C\uD574\uB3C4 \uBCF5\uAD6C\uB418\uC9C0 \uC54A\uC73C\uBA70, \uACFC\uAE08\uC740 \uD658\uBD88\uB410\uC2B5\uB2C8\uB2E4.",
|
|
7341
|
+
"\uACE0\uCE60 \uD30C\uB77C\uBBF8\uD130\uAC00 \uC788\uB294 \uC624\uB958\uAC00 \uC544\uB2D9\uB2C8\uB2E4 \u2014 \uC0C8\uB85C \uB9CC\uB4E4\uB824\uBA74 \uD504\uB86C\uD504\uD2B8\xB7\uC124\uC815\uC744 \uBC14\uAFD4 **\uC0C8\uB85C \uC81C\uCD9C**\uD574\uC57C \uD558\uACE0, \uADF8\uAC74 \uB2E4\uC2DC \uACFC\uAE08\uB429\uB2C8\uB2E4(\uC0AC\uC6A9\uC790 \uB3D9\uC758\uB97C \uBC1B\uC73C\uC138\uC694)."
|
|
7342
|
+
]
|
|
7343
|
+
};
|
|
7344
|
+
}
|
|
7345
|
+
if (e.status === 404 && e.code === "VIDEOGEN_JOB_NOT_FOUND") {
|
|
7346
|
+
return {
|
|
7347
|
+
safety: "unsafe",
|
|
7348
|
+
notCharged: false,
|
|
7349
|
+
lines: [
|
|
7350
|
+
"\uADF8 \uC791\uC5C5\uC744 \uD655\uC778\uD558\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4. job_id \uAC00 \uB9DE\uB294\uC9C0 \uBA3C\uC800 \uD655\uC778\uD558\uC138\uC694.",
|
|
7351
|
+
"\u26A0\uFE0F \uC791\uC5C5\uC774 \uC0B4\uC544 \uC788\uB294\uB370 \uC870\uD68C\uB9CC \uC5B4\uAE0B\uB0AC\uC744 \uC218 \uC788\uC2B5\uB2C8\uB2E4 \u2014 \uC0C8\uB85C \uC81C\uCD9C\uD558\uBA74 **\uBCC4\uB3C4 \uC791\uC5C5\uC73C\uB85C \uB2E4\uC2DC \uACFC\uAE08**\uB429\uB2C8\uB2E4."
|
|
7352
|
+
]
|
|
7353
|
+
};
|
|
7354
|
+
}
|
|
7325
7355
|
if (e.status === 402) {
|
|
7326
7356
|
const lines = [];
|
|
7327
7357
|
const limit = e.extra.limit_usd;
|
|
@@ -7553,7 +7583,10 @@ function buildEstimateIn(opts) {
|
|
|
7553
7583
|
duration_s: parseIntOpt(opts.duration, "duration") ?? 5,
|
|
7554
7584
|
resolution: opts.resolution ?? "720p",
|
|
7555
7585
|
ratio: opts.ratio ?? "16:9",
|
|
7556
|
-
...opts.model ? { model: opts.model } : {}
|
|
7586
|
+
...opts.model ? { model: opts.model } : {},
|
|
7587
|
+
// ★ 이미지 유무가 모델 계열을, 계열이 단가를 정한다 — 추정과 생성이 같은 값을 봐야
|
|
7588
|
+
// 승인받은 금액과 실제 청구가 일치한다.
|
|
7589
|
+
has_image: Boolean(opts.imageUrls?.length)
|
|
7557
7590
|
};
|
|
7558
7591
|
}
|
|
7559
7592
|
function estimateCommand(opts, deps = {}) {
|
|
@@ -16312,9 +16345,6 @@ var StdioServerTransport = class {
|
|
|
16312
16345
|
}
|
|
16313
16346
|
};
|
|
16314
16347
|
|
|
16315
|
-
// src/version.ts
|
|
16316
|
-
var VERSION = "0.4.0";
|
|
16317
|
-
|
|
16318
16348
|
// src/mcp/tools.ts
|
|
16319
16349
|
import { existsSync as existsSync2 } from "fs";
|
|
16320
16350
|
|
|
@@ -16347,6 +16377,22 @@ var PROJECTS_MAX_LIMIT = 100;
|
|
|
16347
16377
|
function list(baseUrl, deps = {}) {
|
|
16348
16378
|
return apiRequest(baseUrl, "/api/projects", {}, deps);
|
|
16349
16379
|
}
|
|
16380
|
+
function create(baseUrl, body, deps = {}) {
|
|
16381
|
+
return apiRequest(baseUrl, "/api/projects", { method: "POST", body }, deps);
|
|
16382
|
+
}
|
|
16383
|
+
async function defaultVoiceId(baseUrl, deps = {}) {
|
|
16384
|
+
const out3 = await apiRequest(
|
|
16385
|
+
baseUrl,
|
|
16386
|
+
"/api/projects/voices",
|
|
16387
|
+
{},
|
|
16388
|
+
deps
|
|
16389
|
+
);
|
|
16390
|
+
const id = out3.default_voice_id;
|
|
16391
|
+
if (!id) {
|
|
16392
|
+
throw new Error("\uC11C\uBC84\uAC00 \uAE30\uBCF8 \uC74C\uC131\uC744 \uC54C\uB824\uC8FC\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4 (default_voice_id \uC5C6\uC74C).");
|
|
16393
|
+
}
|
|
16394
|
+
return id;
|
|
16395
|
+
}
|
|
16350
16396
|
|
|
16351
16397
|
// src/mcp/tools.ts
|
|
16352
16398
|
var COST_TOLERANCE_USD = 5e-3;
|
|
@@ -16397,7 +16443,10 @@ function toEstimateIn(a) {
|
|
|
16397
16443
|
duration_s: a.duration_s ?? 5,
|
|
16398
16444
|
resolution: a.resolution ?? "720p",
|
|
16399
16445
|
ratio: a.ratio ?? "16:9",
|
|
16400
|
-
...a.model ? { model: a.model } : {}
|
|
16446
|
+
...a.model ? { model: a.model } : {},
|
|
16447
|
+
// ★ 추정과 생성이 **같은 모델 계열**을 봐야 confirmed_cost_usd 대조가 성립한다.
|
|
16448
|
+
// 생성 경로는 `image_urls` 를, 추정 전용 호출은 `has_image` 를 준다.
|
|
16449
|
+
has_image: Boolean(a.has_image || a.image_urls?.length)
|
|
16401
16450
|
};
|
|
16402
16451
|
}
|
|
16403
16452
|
var MOCK_BANNER = "\u26A0\uFE0F \uC774 \uBC30\uD3EC\uB294 mock \uBAA8\uB4DC\uC785\uB2C8\uB2E4 \u2014 \uC601\uC0C1\uC774 **\uC2E4\uC81C\uB85C \uC0DD\uC131\uB418\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4**. \uC544\uB798 \uAE08\uC561\xB7job_id\xB7URL \uC740 \uC804\uBD80 \uAC00\uC9DC\uC774\uBA70 \uC2E4\uC81C\uB85C \uACFC\uAE08\uB418\uC9C0\uB3C4 \uC54A\uC2B5\uB2C8\uB2E4. \uC0AC\uC6A9\uC790\uC5D0\uAC8C \uC0DD\uC131\uC774 \uB418\uC5C8\uB2E4\uACE0 \uBCF4\uACE0\uD558\uC9C0 \uB9C8\uC138\uC694.";
|
|
@@ -16683,6 +16732,33 @@ function listProjects(a = {}, deps = {}) {
|
|
|
16683
16732
|
return { text: lines.join("\n") };
|
|
16684
16733
|
});
|
|
16685
16734
|
}
|
|
16735
|
+
function createProject(a = {}, deps = {}) {
|
|
16736
|
+
return guarded2(READ_ONLY, async () => {
|
|
16737
|
+
const title = (a.title ?? "").trim();
|
|
16738
|
+
if (!title) {
|
|
16739
|
+
return {
|
|
16740
|
+
isError: true,
|
|
16741
|
+
text: "title \uC774 \uD544\uC694\uD569\uB2C8\uB2E4. \uC0AC\uC6A9\uC790\uAC00 \uC54C\uC544\uBCFC \uC218 \uC788\uB294 \uD504\uB85C\uC81D\uD2B8 \uC774\uB984\uC744 \uB123\uC5B4 \uB2E4\uC2DC \uD638\uCD9C\uD558\uC138\uC694."
|
|
16742
|
+
};
|
|
16743
|
+
}
|
|
16744
|
+
const base = resolveBaseUrl(deps.baseUrl);
|
|
16745
|
+
const voiceId = await defaultVoiceId(base, deps);
|
|
16746
|
+
const p = await create(
|
|
16747
|
+
base,
|
|
16748
|
+
{ title, voice_id: voiceId, external_ref: `mcp:project:${title}` },
|
|
16749
|
+
deps
|
|
16750
|
+
);
|
|
16751
|
+
return {
|
|
16752
|
+
text: [
|
|
16753
|
+
`\uD504\uB85C\uC81D\uD2B8 \uC900\uBE44\uB428 \u2014 slug: ${p.slug}`,
|
|
16754
|
+
`\uC81C\uBAA9: ${p.title}`,
|
|
16755
|
+
"",
|
|
16756
|
+
"democut_generate_video \uC758 project_slug \uC5D0 \uC704 slug \uB97C \uADF8\uB300\uB85C \uB123\uC73C\uC138\uC694.",
|
|
16757
|
+
"\uAC19\uC740 \uC81C\uBAA9\uC73C\uB85C \uC774 \uB3C4\uAD6C\uB97C \uB2E4\uC2DC \uBD88\uB7EC\uB3C4 \uC0C8\uB85C \uB9CC\uB4E4\uC9C0 \uC54A\uACE0 \uC774 \uD504\uB85C\uC81D\uD2B8\uAC00 \uB098\uC635\uB2C8\uB2E4."
|
|
16758
|
+
].join("\n")
|
|
16759
|
+
};
|
|
16760
|
+
});
|
|
16761
|
+
}
|
|
16686
16762
|
|
|
16687
16763
|
// src/mcp/server.ts
|
|
16688
16764
|
var RESOLUTIONS = ["480p", "720p", "1080p", "4k"];
|
|
@@ -16694,7 +16770,10 @@ var GENERATION_PARAMS = {
|
|
|
16694
16770
|
},
|
|
16695
16771
|
resolution: { type: "string", enum: RESOLUTIONS, description: "\uAE30\uBCF8 720p." },
|
|
16696
16772
|
ratio: { type: "string", enum: RATIOS, description: "\uAE30\uBCF8 16:9." },
|
|
16697
|
-
model: {
|
|
16773
|
+
model: {
|
|
16774
|
+
type: "string",
|
|
16775
|
+
description: "\uC0DD\uB7B5\uD558\uBA74 image_urls \uC720\uBB34\uB85C \uC790\uB3D9 \uC120\uD0DD\uB41C\uB2E4(\uC788\uC73C\uBA74 image-to-video, \uC5C6\uC73C\uBA74 text-to-video). \uBA85\uC2DC\uD558\uBA74 \uADF8 \uBAA8\uB378\uC744 \uC4F0\uB418 \uACC4\uC5F4\uC774 \uC5B4\uAE0B\uB098\uBA74 \uAC70\uBD80\uB41C\uB2E4."
|
|
16776
|
+
}
|
|
16698
16777
|
};
|
|
16699
16778
|
var TOOLS = [
|
|
16700
16779
|
{
|
|
@@ -16704,10 +16783,16 @@ var TOOLS = [
|
|
|
16704
16783
|
},
|
|
16705
16784
|
{
|
|
16706
16785
|
name: "democut_estimate_video_cost",
|
|
16707
|
-
description: "\uC601\uC0C1 \uC0DD\uC131 \uC608\uC0C1 \uBE44\uC6A9\uC744 \uACC4\uC0B0\uD55C\uB2E4. **\uBD80\uC791\uC6A9\uB3C4 \uACFC\uAE08\uB3C4 \uC5C6\uB2E4.** \uBE44\uC6A9\uC740 \uD574\uC0C1\uB3C4\xB7\uAE38\uC774\xB7\uBE44\uC728\
|
|
16786
|
+
description: "\uC601\uC0C1 \uC0DD\uC131 \uC608\uC0C1 \uBE44\uC6A9\uC744 \uACC4\uC0B0\uD55C\uB2E4. **\uBD80\uC791\uC6A9\uB3C4 \uACFC\uAE08\uB3C4 \uC5C6\uB2E4.** \uBE44\uC6A9\uC740 \uD574\uC0C1\uB3C4\xB7\uAE38\uC774\xB7\uBE44\uC728\uC5D0 \uB354\uD574 **\uBAA8\uB378 \uACC4\uC5F4**\uB85C \uACB0\uC815\uB41C\uB2E4 \u2014 \uCC38\uC870 \uC774\uBBF8\uC9C0\uB97C \uB123\uC744 \uAC70\uBA74 has_image=true \uB85C \uACC4\uC0B0\uD574\uC57C \uC2E4\uC81C \uCCAD\uAD6C\uC640 \uB9DE\uB294\uB2E4(\uACC4\uC5F4\uB9C8\uB2E4 \uD1A0\uD070 \uB2E8\uAC00\uAC00 \uB2E4\uB974\uB2E4). democut_generate_video \uB97C \uBD80\uB974\uAE30 \uC804\uC5D0 \uBA3C\uC800 \uD638\uCD9C\uD574 \uC0AC\uC6A9\uC790\uC5D0\uAC8C \uAE08\uC561\uC744 \uC54C\uB9AC\uACE0 \uB3D9\uC758\uB97C \uBC1B\uC544\uB77C.",
|
|
16708
16787
|
inputSchema: {
|
|
16709
16788
|
type: "object",
|
|
16710
|
-
properties: {
|
|
16789
|
+
properties: {
|
|
16790
|
+
...GENERATION_PARAMS,
|
|
16791
|
+
has_image: {
|
|
16792
|
+
type: "boolean",
|
|
16793
|
+
description: "\uC0DD\uC131 \uC2DC \uCC38\uC870 \uC774\uBBF8\uC9C0\uB97C \uB123\uC744 \uC608\uC815\uC778\uAC00(\uAE30\uBCF8 false). \u2605 \uAE08\uC561\uC774 \uB2EC\uB77C\uC9C4\uB2E4 \u2014 \uC774\uBBF8\uC9C0 \uC720\uBB34\uAC00 \uBAA8\uB378 \uACC4\uC5F4\uC744 \uC815\uD558\uACE0 \uACC4\uC5F4\uB9C8\uB2E4 \uD1A0\uD070 \uB2E8\uAC00\uAC00 \uB2E4\uB974\uB2E4. \uC0DD\uC131 \uB54C image_urls \uB97C \uB123\uC744 \uAC70\uBA74 \uC5EC\uAE30\uC11C\uB3C4 true \uB85C \uB450\uC5B4\uC57C \uCD94\uC815 \uAE08\uC561\uACFC \uC2E4\uC81C \uCCAD\uAD6C\uAC00 \uC77C\uCE58\uD55C\uB2E4."
|
|
16794
|
+
}
|
|
16795
|
+
},
|
|
16711
16796
|
additionalProperties: false
|
|
16712
16797
|
}
|
|
16713
16798
|
},
|
|
@@ -16727,7 +16812,7 @@ var TOOLS = [
|
|
|
16727
16812
|
image_urls: {
|
|
16728
16813
|
type: "array",
|
|
16729
16814
|
items: { type: "string" },
|
|
16730
|
-
description: "
|
|
16815
|
+
description: "\uCC38\uC870 \uC774\uBBF8\uC9C0. **\uACF5\uAC1C HTTPS URL** \uB9CC \uAC00\uB2A5(\uC2DC\uC791 \uD504\uB808\uC784 1\uC7A5 + \uB05D \uD504\uB808\uC784 1\uC7A5, \uCD5C\uB300 2\uAC1C). \u2605 \uC774 \uAC12\uC774 **\uBAA8\uB378\uACFC \uB2E8\uAC00\uB97C \uC815\uD55C\uB2E4** \u2014 \uC8FC\uBA74 image-to-video, \uBE44\uC6B0\uBA74 text-to-video \uB85C \uC790\uB3D9 \uC120\uD0DD\uB418\uACE0 \uD1A0\uD070 \uB2E8\uAC00\uAC00 \uB2E4\uB974\uB2E4. \uC778\uBB3C\xB7\uC81C\uD488 \uB4F1 \uD2B9\uC815 \uB300\uC0C1\uC744 \uC720\uC9C0\uD574\uC57C \uD558\uBA74 \uBC18\uB4DC\uC2DC \uB123\uC5B4\uB77C."
|
|
16731
16816
|
},
|
|
16732
16817
|
generate_audio: { type: "boolean", description: "\uC624\uB514\uC624 \uD568\uAED8 \uC0DD\uC131. \uAE30\uBCF8 false." },
|
|
16733
16818
|
watermark: { type: "boolean", description: "\uC6CC\uD130\uB9C8\uD06C. \uAE30\uBCF8 false." },
|
|
@@ -16779,7 +16864,7 @@ var TOOLS = [
|
|
|
16779
16864
|
},
|
|
16780
16865
|
{
|
|
16781
16866
|
name: "democut_list_projects",
|
|
16782
|
-
description: "\uC774 \uC6CC\uD06C\uC2A4\uD398\uC774\uC2A4\uC758 \uD504\uB85C\uC81D\uD2B8 \uBAA9\uB85D\uC744 \uCD5C\uADFC \uC218\uC815\uC21C\uC73C\uB85C \uD655\uC778\uD55C\uB2E4. \uBD80\uC791\uC6A9\uB3C4 \uACFC\uAE08\uB3C4 \uC5C6\uB2E4. democut_generate_video \uC758 project_slug \uB294 **\uC2E4\uC7AC\uD558\uB294 \uBCF8\uC778 \uD504\uB85C\uC81D\uD2B8\uC5EC\uC57C** \uD558\uACE0 \uD2C0\uB9AC\uBA74 404 \uB2E4 \u2014 \uC2AC\uB7EC\uADF8\uB97C \uBAA8\uB974\uBA74 \uCD94\uCE21\uD558\uC9C0 \uB9D0\uACE0 \uC774\uAC78\uB85C \uBA3C\uC800 \uD655\uC778\uD558\uB77C. \uBAA9\uB85D\uC774 \uBE44\uC5B4 \uC788\
|
|
16867
|
+
description: "\uC774 \uC6CC\uD06C\uC2A4\uD398\uC774\uC2A4\uC758 \uD504\uB85C\uC81D\uD2B8 \uBAA9\uB85D\uC744 \uCD5C\uADFC \uC218\uC815\uC21C\uC73C\uB85C \uD655\uC778\uD55C\uB2E4. \uBD80\uC791\uC6A9\uB3C4 \uACFC\uAE08\uB3C4 \uC5C6\uB2E4. democut_generate_video \uC758 project_slug \uB294 **\uC2E4\uC7AC\uD558\uB294 \uBCF8\uC778 \uD504\uB85C\uC81D\uD2B8\uC5EC\uC57C** \uD558\uACE0 \uD2C0\uB9AC\uBA74 404 \uB2E4 \u2014 \uC2AC\uB7EC\uADF8\uB97C \uBAA8\uB974\uBA74 \uCD94\uCE21\uD558\uC9C0 \uB9D0\uACE0 \uC774\uAC78\uB85C \uBA3C\uC800 \uD655\uC778\uD558\uB77C. \uBAA9\uB85D\uC774 \uBE44\uC5B4 \uC788\uAC70\uB098 \uB9C8\uB545\uD55C \uAC83\uC774 \uC5C6\uC73C\uBA74 democut_create_project \uB85C \uB9CC\uB4E4 \uC218 \uC788\uB2E4 \u2014 \uB2E8 \uBA3C\uC800 \uC0AC\uC6A9\uC790\uC5D0\uAC8C \uC5B4\uB290 \uAC83\uC5D0 \uB123\uC744\uC9C0, \uC0C8\uB85C \uB9CC\uB4E0\uB2E4\uBA74 \uC5B4\uB5A4 \uC774\uB984\uC73C\uB85C \uD560\uC9C0 \uBB3C\uC5B4\uB77C.",
|
|
16783
16868
|
inputSchema: {
|
|
16784
16869
|
type: "object",
|
|
16785
16870
|
properties: {
|
|
@@ -16791,6 +16876,21 @@ var TOOLS = [
|
|
|
16791
16876
|
},
|
|
16792
16877
|
additionalProperties: false
|
|
16793
16878
|
}
|
|
16879
|
+
},
|
|
16880
|
+
{
|
|
16881
|
+
name: "democut_create_project",
|
|
16882
|
+
description: "\uD504\uB85C\uC81D\uD2B8\uB97C \uC0C8\uB85C \uB9CC\uB4E0\uB2E4. **\uACFC\uAE08\uC740 \uC5C6\uC9C0\uB9CC \uACC4\uC815\uC5D0 \uB0A8\uB294 \uC4F0\uAE30 \uC791\uC5C5\uC774\uB2E4.** \uC601\uC0C1 \uC0DD\uC131\uC740 \uBE44\uC6A9\uC744 \uADC0\uC18D\uC2DC\uD0AC \uD504\uB85C\uC81D\uD2B8\uAC00 \uC788\uC5B4\uC57C \uD558\uBBC0\uB85C, democut_list_projects \uAC00 \uBE44\uC5B4 \uC788\uAC70\uB098 \uB9C8\uB545\uD55C \uAC83\uC774 \uC5C6\uC744 \uB54C \uC4F4\uB2E4. \u2605 \uBA3C\uC800 democut_list_projects \uB85C **\uC4F8 \uB9CC\uD55C \uAC83\uC774 \uC774\uBBF8 \uC788\uB294\uC9C0 \uBCF4\uACE0**, \uC0AC\uC6A9\uC790\uC5D0\uAC8C \uC5B4\uB290 \uAC83\uC5D0 \uB123\uC744\uC9C0 \uBB3C\uC5B4\uB77C \u2014 \uBB3C\uC5B4\uBCF4\uC9C0 \uC54A\uACE0 \uC0C8\uB85C \uB9CC\uB4E4\uBA74 \uBE44\uC2B7\uD55C \uD504\uB85C\uC81D\uD2B8\uAC00 \uC313\uC778\uB2E4. \uAC19\uC740 \uC81C\uBAA9\uC73C\uB85C \uB2E4\uC2DC \uBD80\uB974\uBA74 \uC0C8\uB85C \uB9CC\uB4E4\uC9C0 \uC54A\uACE0 **\uAE30\uC874 \uAC83\uC744 \uB3CC\uB824\uC900\uB2E4**(\uC7AC\uC2DC\uB3C4 \uC548\uC804).",
|
|
16883
|
+
inputSchema: {
|
|
16884
|
+
type: "object",
|
|
16885
|
+
properties: {
|
|
16886
|
+
title: {
|
|
16887
|
+
type: "string",
|
|
16888
|
+
description: "\uD504\uB85C\uC81D\uD2B8 \uC774\uB984 1~100\uC790. \uC0AC\uC6A9\uC790\uAC00 \uC54C\uC544\uBCFC \uC218 \uC788\uAC8C \uC9D3\uACE0, \uAC00\uB2A5\uD558\uBA74 \uC0AC\uC6A9\uC790\uAC00 \uBD80\uB978 \uC774\uB984\uC744 \uADF8\uB300\uB85C \uC4F0\uB77C."
|
|
16889
|
+
}
|
|
16890
|
+
},
|
|
16891
|
+
required: ["title"],
|
|
16892
|
+
additionalProperties: false
|
|
16893
|
+
}
|
|
16794
16894
|
}
|
|
16795
16895
|
];
|
|
16796
16896
|
function dispatch(name, args, deps = {}) {
|
|
@@ -16809,6 +16909,8 @@ function dispatch(name, args, deps = {}) {
|
|
|
16809
16909
|
return creditLedger(args, deps);
|
|
16810
16910
|
case "democut_list_projects":
|
|
16811
16911
|
return listProjects(args, deps);
|
|
16912
|
+
case "democut_create_project":
|
|
16913
|
+
return createProject(args, deps);
|
|
16812
16914
|
default:
|
|
16813
16915
|
return Promise.resolve({ isError: true, text: `\uC54C \uC218 \uC5C6\uB294 \uB3C4\uAD6C: ${name}` });
|
|
16814
16916
|
}
|
|
@@ -16848,7 +16950,8 @@ var HELP = `democut \u2014 DemoCut \uC5D0\uC774\uC804\uD2B8 CLI (OAuth2 device f
|
|
|
16848
16950
|
democut video status <job_id> [--wait] [--output <\uACBD\uB85C>]
|
|
16849
16951
|
|
|
16850
16952
|
democut mcp MCP \uC11C\uBC84(stdio) \u2014 \uC5D0\uC774\uC804\uD2B8\uC5D0 \uB3C4\uAD6C\uB85C \uBD99\uC778\uB2E4
|
|
16851
|
-
\uB4F1\uB85D: claude mcp add democut -- npx -y democut mcp
|
|
16953
|
+
\uB4F1\uB85D: claude mcp add democut -- npx -y democut@latest mcp
|
|
16954
|
+
(@latest \uD544\uC218 \u2014 -y \uB294 npx \uCE90\uC2DC\uC758 \uC61B \uBC84\uC804\uC744 \uADF8\uB300\uB85C \uB744\uC6B4\uB2E4)
|
|
16852
16955
|
|
|
16853
16956
|
\uC0DD\uC131 \uC635\uC158:
|
|
16854
16957
|
--duration <\uCD08> \uAE30\uBCF8 5 (\uBAA8\uB378\uBCC4 \uD5C8\uC6A9 \uBC94\uC704 \uB2E4\uB984: 2.0=4~15, 2.5=4~30)
|