@craftstory/mcp 0.1.0 → 0.1.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 +1 -1
- package/dist/client.js +6 -2
- package/dist/server.js +6 -3
- package/package.json +25 -6
package/README.md
CHANGED
|
@@ -61,7 +61,7 @@ Plus the prompt `talking_video_from_photo` (script + photo) that walks the model
|
|
|
61
61
|
|
|
62
62
|
The assistant will: `list_voices` -> `create_audio_clip` -> `wait_for_job(audio-clip)` -> `preview_cost` -> `create_craftstory2_video` (resolution `720_1280`, gestures `calm`) -> `wait_for_job(craftstory-2)` a few times -> `get_job_result` -> the video URL.
|
|
63
63
|
|
|
64
|
-
Long jobs: `wait_for_job`
|
|
64
|
+
Long jobs: `wait_for_job` returns after at most `timeout_s` (max 55 s) plus one in-flight status request (25 s HTTP timeout), which keeps it under the 60 s tool-call limit of most clients in normal conditions. A CraftStory 2.0 video needs several calls; that is by design so agent runtimes do not time out.
|
|
65
65
|
|
|
66
66
|
## Local files vs URLs
|
|
67
67
|
|
package/dist/client.js
CHANGED
|
@@ -5,7 +5,9 @@
|
|
|
5
5
|
import { readFile } from "node:fs/promises";
|
|
6
6
|
import { basename } from "node:path";
|
|
7
7
|
export const DEFAULT_BASE = "https://api.craftstory.com/api/v1";
|
|
8
|
-
export const USER_AGENT = "craftstory-mcp/0.1.
|
|
8
|
+
export const USER_AGENT = "craftstory-mcp/0.1.1";
|
|
9
|
+
/** Per-request HTTP timeout; keeps every tool call well under MCP clients' ~60 s limit. */
|
|
10
|
+
export const REQUEST_TIMEOUT_MS = 25_000;
|
|
9
11
|
export class ApiError extends Error {
|
|
10
12
|
status;
|
|
11
13
|
body;
|
|
@@ -47,10 +49,12 @@ export class CraftStoryClient {
|
|
|
47
49
|
}
|
|
48
50
|
let res;
|
|
49
51
|
try {
|
|
50
|
-
res = await this.fetchImpl(`${this.base}${path}`, { method, headers, body: payload });
|
|
52
|
+
res = await this.fetchImpl(`${this.base}${path}`, { method, headers, body: payload, signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS) });
|
|
51
53
|
}
|
|
52
54
|
catch (e) {
|
|
53
55
|
// Node's fetch hides the reason behind "fetch failed"; surface the cause (DNS, TLS, reset...).
|
|
56
|
+
if (e.name === "TimeoutError")
|
|
57
|
+
throw new Error(`Timeout after ${REQUEST_TIMEOUT_MS / 1000}s calling ${method} ${path}`);
|
|
54
58
|
const cause = e.cause;
|
|
55
59
|
throw new Error(`Network error calling ${method} ${path}: ${cause?.code ?? ""} ${cause?.message ?? e.message}`.trim());
|
|
56
60
|
}
|
package/dist/server.js
CHANGED
|
@@ -14,7 +14,7 @@ const JOB_KINDS = ["craftstory-2", "minimax-h3", "audio-clip"];
|
|
|
14
14
|
const text = (data) => ({ content: [{ type: "text", text: typeof data === "string" ? data : JSON.stringify(data, null, 2) }] });
|
|
15
15
|
const fail = (err) => ({ isError: true, content: [{ type: "text", text: err instanceof Error ? err.message : String(err) }] });
|
|
16
16
|
export function buildServer(client) {
|
|
17
|
-
const server = new McpServer({ name: "craftstory", version: "0.1.
|
|
17
|
+
const server = new McpServer({ name: "craftstory", version: "0.1.1" });
|
|
18
18
|
server.registerTool("list_models", {
|
|
19
19
|
title: "List CraftStory video models",
|
|
20
20
|
description: "Catalogue of the video models behind this server with their status, modes, limits and credit prices. " +
|
|
@@ -222,6 +222,8 @@ export function buildServer(client) {
|
|
|
222
222
|
let last;
|
|
223
223
|
try {
|
|
224
224
|
while (true) {
|
|
225
|
+
if (Date.now() >= deadline && last)
|
|
226
|
+
return text({ state: "running", ...last, hint: "still running - call wait_for_job again" });
|
|
225
227
|
last = await client.getStatus(model, id);
|
|
226
228
|
const state = classify(last.status);
|
|
227
229
|
if (token !== undefined) {
|
|
@@ -234,9 +236,10 @@ export function buildServer(client) {
|
|
|
234
236
|
const result = state === "done" ? await client.getResult(model, id) : undefined;
|
|
235
237
|
return text({ state, ...last, ...(result ? { result } : {}) });
|
|
236
238
|
}
|
|
237
|
-
|
|
239
|
+
const remaining = deadline - Date.now();
|
|
240
|
+
if (remaining <= 0)
|
|
238
241
|
return text({ state: "running", ...last, hint: "still running - call wait_for_job again" });
|
|
239
|
-
await new Promise((r) => setTimeout(r, model === "audio-clip" ? 2000 : 5000));
|
|
242
|
+
await new Promise((r) => setTimeout(r, Math.min(model === "audio-clip" ? 2000 : 5000, remaining)));
|
|
240
243
|
}
|
|
241
244
|
}
|
|
242
245
|
catch (e) {
|
package/package.json
CHANGED
|
@@ -1,21 +1,37 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@craftstory/mcp",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "MCP server for the CraftStory API: talking-avatar videos from a photo (CraftStory 2.0) and short clips with generated sound (MiniMax H3), from Claude, Cursor and other MCP clients.",
|
|
5
5
|
"type": "module",
|
|
6
|
-
"bin": {
|
|
6
|
+
"bin": {
|
|
7
|
+
"craftstory-mcp": "dist/index.js"
|
|
8
|
+
},
|
|
7
9
|
"main": "dist/index.js",
|
|
8
|
-
"files": [
|
|
9
|
-
|
|
10
|
+
"files": [
|
|
11
|
+
"dist",
|
|
12
|
+
"README.md",
|
|
13
|
+
"LICENSE"
|
|
14
|
+
],
|
|
15
|
+
"engines": {
|
|
16
|
+
"node": ">=18"
|
|
17
|
+
},
|
|
10
18
|
"scripts": {
|
|
11
19
|
"build": "tsc -p tsconfig.json && chmod +x dist/index.js",
|
|
12
20
|
"start": "node dist/index.js",
|
|
13
21
|
"test": "node --import tsx --test test/*.test.ts",
|
|
14
22
|
"smoke": "tsx test/smoke.ts"
|
|
15
23
|
},
|
|
16
|
-
"keywords": [
|
|
24
|
+
"keywords": [
|
|
25
|
+
"mcp",
|
|
26
|
+
"model-context-protocol",
|
|
27
|
+
"craftstory",
|
|
28
|
+
"ai-video",
|
|
29
|
+
"talking-avatar",
|
|
30
|
+
"lip-sync",
|
|
31
|
+
"text-to-video",
|
|
32
|
+
"minimax"
|
|
33
|
+
],
|
|
17
34
|
"license": "MIT",
|
|
18
|
-
"repository": { "type": "git", "url": "https://gitlab.itseez3d.com/craftstory/craftstory-mcp" },
|
|
19
35
|
"homepage": "https://craftstory.com",
|
|
20
36
|
"dependencies": {
|
|
21
37
|
"@modelcontextprotocol/sdk": "^1.30.0",
|
|
@@ -25,5 +41,8 @@
|
|
|
25
41
|
"@types/node": "^22.0.0",
|
|
26
42
|
"tsx": "^4.19.0",
|
|
27
43
|
"typescript": "^5.6.0"
|
|
44
|
+
},
|
|
45
|
+
"bugs": {
|
|
46
|
+
"url": "https://api.craftstory.com/api/v1/docs/public/"
|
|
28
47
|
}
|
|
29
48
|
}
|