@hubfluencer/mcp 0.13.0 → 0.14.0
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/dist/index.js +46 -4
- package/package.json +1 -1
- package/src/core.ts +18 -0
- package/src/index.ts +47 -4
- package/src/output-schemas.ts +6 -0
package/dist/index.js
CHANGED
|
@@ -29510,6 +29510,13 @@ function normalizeStatus(kind, slug, data) {
|
|
|
29510
29510
|
status.failure_attempt = d.failure_attempt;
|
|
29511
29511
|
if (typeof d.generation_attempt === "number")
|
|
29512
29512
|
status.generation_attempt = d.generation_attempt;
|
|
29513
|
+
if (typeof d.segments_completed === "number")
|
|
29514
|
+
status.segments_completed = d.segments_completed;
|
|
29515
|
+
if (typeof d.segments_total === "number")
|
|
29516
|
+
status.segments_total = d.segments_total;
|
|
29517
|
+
if (Array.isArray(d.active_segment_positions) && d.active_segment_positions.every((position) => typeof position === "number")) {
|
|
29518
|
+
status.active_segment_positions = d.active_segment_positions;
|
|
29519
|
+
}
|
|
29513
29520
|
if (typeof d.latest_render_free === "boolean") {
|
|
29514
29521
|
status.latest_render_free = d.latest_render_free;
|
|
29515
29522
|
}
|
|
@@ -30259,7 +30266,7 @@ function readStoredCredentials() {
|
|
|
30259
30266
|
// package.json
|
|
30260
30267
|
var package_default = {
|
|
30261
30268
|
name: "@hubfluencer/mcp",
|
|
30262
|
-
version: "0.
|
|
30269
|
+
version: "0.14.0",
|
|
30263
30270
|
description: "Model Context Protocol server for Hubfluencer — let AI agents generate post-ready shorts and editor ads.",
|
|
30264
30271
|
license: "MIT",
|
|
30265
30272
|
author: "Monocursive <contact@monocursive.com>",
|
|
@@ -30578,6 +30585,9 @@ var getStatusOutput = exports_external.object({
|
|
|
30578
30585
|
failure_source: exports_external.string().optional().describe("Short only: worker/recovery layer that finalized the failure."),
|
|
30579
30586
|
failure_attempt: exports_external.number().optional().describe("Short only: paid generation attempt number that failed."),
|
|
30580
30587
|
generation_attempt: exports_external.number().optional().describe("Short only: current paid attempt; echo when cancelling."),
|
|
30588
|
+
segments_completed: exports_external.number().optional(),
|
|
30589
|
+
segments_total: exports_external.number().optional(),
|
|
30590
|
+
active_segment_positions: exports_external.array(exports_external.number()).optional(),
|
|
30581
30591
|
latest_render_free: exports_external.boolean().optional(),
|
|
30582
30592
|
last_free_rerender_failed: exports_external.boolean().optional()
|
|
30583
30593
|
}).passthrough();
|
|
@@ -30598,6 +30608,9 @@ var waitForCompletionOutput = exports_external.object({
|
|
|
30598
30608
|
failure_source: exports_external.string().optional().describe("Short only: worker/recovery layer that finalized the failure."),
|
|
30599
30609
|
failure_attempt: exports_external.number().optional().describe("Short only: paid generation attempt number that failed."),
|
|
30600
30610
|
generation_attempt: exports_external.number().optional().describe("Short only: current paid attempt; echo when cancelling."),
|
|
30611
|
+
segments_completed: exports_external.number().optional(),
|
|
30612
|
+
segments_total: exports_external.number().optional(),
|
|
30613
|
+
active_segment_positions: exports_external.array(exports_external.number()).optional(),
|
|
30601
30614
|
latest_render_free: exports_external.boolean().optional(),
|
|
30602
30615
|
last_free_rerender_failed: exports_external.boolean().optional(),
|
|
30603
30616
|
saved_to: exports_external.union([exports_external.string(), exports_external.null()]).optional(),
|
|
@@ -32130,7 +32143,30 @@ registerTool("list_voices", {
|
|
|
32130
32143
|
description: "Lists available narration voices (id + name). Pass a voice id as voice_id to create_editor_ad / " + "make_video to pick the narration voice for an editor ad. Shorts have no voiceover.",
|
|
32131
32144
|
inputSchema: {},
|
|
32132
32145
|
annotations: { title: "List voices", ...RO }
|
|
32133
|
-
}, tool(async (_args, client) =>
|
|
32146
|
+
}, tool(async (_args, client) => {
|
|
32147
|
+
const response = asRecord(await client.get("/voices"));
|
|
32148
|
+
const data = asRecord(response.data ?? response);
|
|
32149
|
+
const voices = Array.isArray(data.voices) ? data.voices.map(asRecord) : [];
|
|
32150
|
+
return ok({
|
|
32151
|
+
voices: voices.map((voice) => {
|
|
32152
|
+
const verified = Array.isArray(voice.verified_languages) ? voice.verified_languages.map(asRecord) : [];
|
|
32153
|
+
return {
|
|
32154
|
+
voice_id: voice.voice_id,
|
|
32155
|
+
name: voice.name,
|
|
32156
|
+
category: voice.category,
|
|
32157
|
+
description: voice.description,
|
|
32158
|
+
labels: voice.labels,
|
|
32159
|
+
preview_url: voice.preview_url,
|
|
32160
|
+
languages: [
|
|
32161
|
+
...new Set(verified.map((language) => language.language).filter((language) => typeof language === "string"))
|
|
32162
|
+
]
|
|
32163
|
+
};
|
|
32164
|
+
}),
|
|
32165
|
+
has_more: data.has_more,
|
|
32166
|
+
total_count: data.total_count,
|
|
32167
|
+
next_page_token: data.next_page_token
|
|
32168
|
+
});
|
|
32169
|
+
}));
|
|
32134
32170
|
registerTool("list_projects", {
|
|
32135
32171
|
title: "List recent projects",
|
|
32136
32172
|
description: "Lists the caller's recent shorts and editor/video-factory projects, each normalized to " + "{slug, stage, terminal, ready, video_url}. By default the shorts listing is limited to " + "in-progress/failed; pass include_completed:true to also surface finished shorts — useful to " + "recover a lost slug. Capped to the most recent items per kind (use get_status for authoritative state).",
|
|
@@ -32369,7 +32405,13 @@ registerTool("update_short", {
|
|
|
32369
32405
|
const res = await client.patch(`/shorts/${args.slug}`, body);
|
|
32370
32406
|
const data = asRecord(res).data ?? res;
|
|
32371
32407
|
return ok({
|
|
32372
|
-
|
|
32408
|
+
slug: args.slug,
|
|
32409
|
+
kind: "short",
|
|
32410
|
+
stage: asRecord(data).stage,
|
|
32411
|
+
status: asRecord(data).status,
|
|
32412
|
+
updated: body,
|
|
32413
|
+
end_card_mode: asRecord(data).end_card_mode,
|
|
32414
|
+
resolved_cta_text: asRecord(data).resolved_cta_text,
|
|
32373
32415
|
next: "Saved. Only text/style/CTA/end-card/logo changed on an already-generated short? " + `rerender_short({ slug: "${args.slug}" }) applies it for 0 credits. Footage/music edits ` + "(prompt, product image, format, visual_language, theme, music_*, language) need " + "generate_short (15 credits)."
|
|
32374
32416
|
});
|
|
32375
32417
|
}));
|
|
@@ -33593,7 +33635,7 @@ registerTool("generate_music", {
|
|
|
33593
33635
|
mood: exports_external.string().optional().describe("Optional mood hint"),
|
|
33594
33636
|
genre: exports_external.string().optional().describe("Optional genre hint"),
|
|
33595
33637
|
tempo: exports_external.string().optional().describe("Optional tempo hint"),
|
|
33596
|
-
instruments: exports_external.string().optional().describe(
|
|
33638
|
+
instruments: exports_external.array(exports_external.string().min(1).max(80)).max(10).optional().describe('Optional instrument hints, e.g. ["piano", "strings"]')
|
|
33597
33639
|
},
|
|
33598
33640
|
annotations: { title: "Generate music", ...WRITE, idempotentHint: false }
|
|
33599
33641
|
}, tool(async (args, client) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hubfluencer/mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.14.0",
|
|
4
4
|
"description": "Model Context Protocol server for Hubfluencer — let AI agents generate post-ready shorts and editor ads.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Monocursive <contact@monocursive.com>",
|
package/src/core.ts
CHANGED
|
@@ -277,6 +277,12 @@ export interface NormalizedStatus {
|
|
|
277
277
|
failure_attempt?: number;
|
|
278
278
|
/** Short only: current paid attempt; echo when cancelling. */
|
|
279
279
|
generation_attempt?: number;
|
|
280
|
+
/** Short only: completed/current Veo clip count for useful long-poll progress. */
|
|
281
|
+
segments_completed?: number;
|
|
282
|
+
/** Short only: total current Veo clips in the paid attempt. */
|
|
283
|
+
segments_total?: number;
|
|
284
|
+
/** Short only: clip positions that are pending or processing. */
|
|
285
|
+
active_segment_positions?: number[];
|
|
280
286
|
/** Editor only: the newest delivered render no longer matches the live project. */
|
|
281
287
|
stale?: boolean;
|
|
282
288
|
/** Editor only: current scene ids that are still generating. */
|
|
@@ -365,6 +371,18 @@ export function normalizeStatus(
|
|
|
365
371
|
status.failure_attempt = d.failure_attempt;
|
|
366
372
|
if (typeof d.generation_attempt === "number")
|
|
367
373
|
status.generation_attempt = d.generation_attempt;
|
|
374
|
+
if (typeof d.segments_completed === "number")
|
|
375
|
+
status.segments_completed = d.segments_completed;
|
|
376
|
+
if (typeof d.segments_total === "number")
|
|
377
|
+
status.segments_total = d.segments_total;
|
|
378
|
+
if (
|
|
379
|
+
Array.isArray(d.active_segment_positions) &&
|
|
380
|
+
d.active_segment_positions.every(
|
|
381
|
+
(position) => typeof position === "number",
|
|
382
|
+
)
|
|
383
|
+
) {
|
|
384
|
+
status.active_segment_positions = d.active_segment_positions as number[];
|
|
385
|
+
}
|
|
368
386
|
// Additive free-re-render bookkeeping (2026-07 API): surfaced only when
|
|
369
387
|
// the server actually sends the booleans, so older payloads normalize
|
|
370
388
|
// byte-identically. A failed free re-render does NOT flip stage to
|
package/src/index.ts
CHANGED
|
@@ -1417,7 +1417,40 @@ registerTool(
|
|
|
1417
1417
|
inputSchema: {},
|
|
1418
1418
|
annotations: { title: "List voices", ...RO },
|
|
1419
1419
|
},
|
|
1420
|
-
tool(async (_args, client) =>
|
|
1420
|
+
tool(async (_args, client) => {
|
|
1421
|
+
const response = asRecord(await client.get("/voices"));
|
|
1422
|
+
const data = asRecord(response.data ?? response);
|
|
1423
|
+
const voices = Array.isArray(data.voices) ? data.voices.map(asRecord) : [];
|
|
1424
|
+
|
|
1425
|
+
return ok({
|
|
1426
|
+
voices: voices.map((voice) => {
|
|
1427
|
+
const verified = Array.isArray(voice.verified_languages)
|
|
1428
|
+
? voice.verified_languages.map(asRecord)
|
|
1429
|
+
: [];
|
|
1430
|
+
return {
|
|
1431
|
+
voice_id: voice.voice_id,
|
|
1432
|
+
name: voice.name,
|
|
1433
|
+
category: voice.category,
|
|
1434
|
+
description: voice.description,
|
|
1435
|
+
labels: voice.labels,
|
|
1436
|
+
preview_url: voice.preview_url,
|
|
1437
|
+
languages: [
|
|
1438
|
+
...new Set(
|
|
1439
|
+
verified
|
|
1440
|
+
.map((language) => language.language)
|
|
1441
|
+
.filter(
|
|
1442
|
+
(language): language is string =>
|
|
1443
|
+
typeof language === "string",
|
|
1444
|
+
),
|
|
1445
|
+
),
|
|
1446
|
+
],
|
|
1447
|
+
};
|
|
1448
|
+
}),
|
|
1449
|
+
has_more: data.has_more,
|
|
1450
|
+
total_count: data.total_count,
|
|
1451
|
+
next_page_token: data.next_page_token,
|
|
1452
|
+
});
|
|
1453
|
+
}),
|
|
1421
1454
|
);
|
|
1422
1455
|
|
|
1423
1456
|
// ── Projects ──────────────────────────────────────────────────────────────
|
|
@@ -2113,7 +2146,13 @@ registerTool(
|
|
|
2113
2146
|
);
|
|
2114
2147
|
const data = asRecord(res).data ?? res;
|
|
2115
2148
|
return ok({
|
|
2116
|
-
|
|
2149
|
+
slug: args.slug,
|
|
2150
|
+
kind: "short",
|
|
2151
|
+
stage: asRecord(data).stage,
|
|
2152
|
+
status: asRecord(data).status,
|
|
2153
|
+
updated: body,
|
|
2154
|
+
end_card_mode: asRecord(data).end_card_mode,
|
|
2155
|
+
resolved_cta_text: asRecord(data).resolved_cta_text,
|
|
2117
2156
|
next:
|
|
2118
2157
|
"Saved. Only text/style/CTA/end-card/logo changed on an already-generated short? " +
|
|
2119
2158
|
`rerender_short({ slug: "${args.slug}" }) applies it for 0 credits. Footage/music edits ` +
|
|
@@ -4778,7 +4817,11 @@ registerTool(
|
|
|
4778
4817
|
mood: z.string().optional().describe("Optional mood hint"),
|
|
4779
4818
|
genre: z.string().optional().describe("Optional genre hint"),
|
|
4780
4819
|
tempo: z.string().optional().describe("Optional tempo hint"),
|
|
4781
|
-
instruments: z
|
|
4820
|
+
instruments: z
|
|
4821
|
+
.array(z.string().min(1).max(80))
|
|
4822
|
+
.max(10)
|
|
4823
|
+
.optional()
|
|
4824
|
+
.describe('Optional instrument hints, e.g. ["piano", "strings"]'),
|
|
4782
4825
|
},
|
|
4783
4826
|
annotations: { title: "Generate music", ...WRITE, idempotentHint: false },
|
|
4784
4827
|
},
|
|
@@ -4790,7 +4833,7 @@ registerTool(
|
|
|
4790
4833
|
mood?: string;
|
|
4791
4834
|
genre?: string;
|
|
4792
4835
|
tempo?: string;
|
|
4793
|
-
instruments?: string;
|
|
4836
|
+
instruments?: string[];
|
|
4794
4837
|
},
|
|
4795
4838
|
client,
|
|
4796
4839
|
) => {
|
package/src/output-schemas.ts
CHANGED
|
@@ -95,6 +95,9 @@ export const getStatusOutput = z
|
|
|
95
95
|
.number()
|
|
96
96
|
.optional()
|
|
97
97
|
.describe("Short only: current paid attempt; echo when cancelling."),
|
|
98
|
+
segments_completed: z.number().optional(),
|
|
99
|
+
segments_total: z.number().optional(),
|
|
100
|
+
active_segment_positions: z.array(z.number()).optional(),
|
|
98
101
|
latest_render_free: z.boolean().optional(),
|
|
99
102
|
last_free_rerender_failed: z.boolean().optional(),
|
|
100
103
|
})
|
|
@@ -142,6 +145,9 @@ export const waitForCompletionOutput = z
|
|
|
142
145
|
.number()
|
|
143
146
|
.optional()
|
|
144
147
|
.describe("Short only: current paid attempt; echo when cancelling."),
|
|
148
|
+
segments_completed: z.number().optional(),
|
|
149
|
+
segments_total: z.number().optional(),
|
|
150
|
+
active_segment_positions: z.array(z.number()).optional(),
|
|
145
151
|
latest_render_free: z.boolean().optional(),
|
|
146
152
|
last_free_rerender_failed: z.boolean().optional(),
|
|
147
153
|
saved_to: z.union([z.string(), z.null()]).optional(),
|