@hubfluencer/mcp 0.17.0 → 0.18.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/README.md CHANGED
@@ -28,7 +28,7 @@ Hubfluencer app, and a scoped access token is saved locally to `~/.hubfluencer/c
28
28
  (mode 0600) — the MCP server reads it from there automatically.
29
29
 
30
30
  ```bash
31
- npx -y @hubfluencer/mcp@0.17.0 login "Claude Code"
31
+ npx -y @hubfluencer/mcp@0.18.0 login "Claude Code"
32
32
  # 1. Open: https://app.hubfluencer.com/connect?code=ABCD-EFGH
33
33
  # 2. Confirm code: ABCDEFGH
34
34
  # 3. Click Approve. → ✓ Connected.
@@ -37,14 +37,14 @@ npx -y @hubfluencer/mcp@0.17.0 login "Claude Code"
37
37
  Then register the server (no token env needed — it uses the stored credential):
38
38
 
39
39
  ```bash
40
- claude mcp add hubfluencer -- npx -y @hubfluencer/mcp@0.17.0 --profile creator
40
+ claude mcp add hubfluencer -- npx -y @hubfluencer/mcp@0.18.0 --profile creator
41
41
  ```
42
42
 
43
43
  Verify it connected:
44
44
 
45
45
  ```bash
46
46
  claude mcp list # → hubfluencer: ... ✓ Connected
47
- npx -y @hubfluencer/mcp@0.17.0 doctor --profile creator
47
+ npx -y @hubfluencer/mcp@0.18.0 doctor --profile creator
48
48
  ```
49
49
 
50
50
  ### Alternative: paste an access token
@@ -53,13 +53,13 @@ Create a token in the app (**Settings → Access tokens**, scoped `video:generat
53
53
  it **cannot** delete your account, change credentials, publish, or create more tokens), then:
54
54
 
55
55
  ```bash
56
- claude mcp add hubfluencer --env HUBFLUENCER_API_TOKEN=YOUR_TOKEN -- npx -y @hubfluencer/mcp@0.17.0 --profile creator
56
+ claude mcp add hubfluencer --env HUBFLUENCER_API_TOKEN=YOUR_TOKEN -- npx -y @hubfluencer/mcp@0.18.0 --profile creator
57
57
  ```
58
58
 
59
59
  Install the concise Agent Skill and its advanced reference in one command:
60
60
 
61
61
  ```bash
62
- npx -y @hubfluencer/mcp@0.17.0 install-skill --client claude-code
62
+ npx -y @hubfluencer/mcp@0.18.0 install-skill --client claude-code
63
63
  # clients: claude-code, codex, opencode, pi; add --project for project scope
64
64
  ```
65
65
 
@@ -114,7 +114,6 @@ instead draw a **free daily quota of 20 AI assists** (top up with `unlock_ai_ass
114
114
  | `create_short` | Create a short draft (12s vertical: two 6s AI segments + title overlay + music; 14s when it ends on a poster or brand-lockup end card). Set `headline` (≈4 words, ≤40 chars), `subheadline`, `music_vibe`, and an explicit `visual_language` (`kinetic_creator` is a strong default) — and **always `cta_text`** (a short without a CTA doesn't convert; blank `cta_text` → the server renders a neutral localized ask, e.g. "Learn more" — a truly CTA-less short is not currently supported). End-card fields: `closing_claim` (≤80), `brand_name` (≤40), `end_card` (`"auto"`\|`"none"`). Other opt-in conversion graphics: `offer_text`/`badge_text`/`star_rating` — only what you can substantiate. | **0** |
115
115
  | `update_short` | Patch an existing short draft — brief (`product_prompt`), copy, styling, end-card fields (`closing_claim`/`brand_name`/`poster_includes_lockup`/`end_card`), logo overlay placement (`short_logo_position`/`short_logo_treatment`), or the opt-in conversion graphics; only the fields you pass change. Clear one with `""` (`[]` for `text_beats`, `0` for `star_rating`). Apply text/style/CTA/end-card/logo edits to a generated short free with `rerender_short`; footage/music edits need `generate_short`. | **0** |
116
116
  | `generate_short` | Render an existing short — re-rolls the footage + music (fresh AI generation). If headline/subheadline/beats are all blank the server auto-writes the copy first (`skip_auto_text:true` for a deliberately bare clip). Safe to re-call (in-flight = reported, no double charge; a failed or cancelled paid Short can re-generate when its summary advertises `start_generation`). | **15** |
117
- | `cancel_short_generation` | Stop the caller-observed paid short run, fence late workers from publishing, preserve the editable draft, and restore its 15 credits idempotently. The MCP tool re-reads the canonical summary and sends its run fence automatically; callers may optionally supply `generation_run_id` to reject a stale command. Raw REST callers must send the latest `generation_summary.run_id` plus `Idempotency-Key`, reusing the key only for transport retries of this exact cancellation. After cancellation, re-read the summary and generate a successor only when it advertises `start_generation`. | **full refund** |
118
117
  | `rerender_short` | **FREE re-render** — applies the short's current text/style/CTA/end-card/logo state over the already-paid footage + music. Use after `update_short` for copy/style/CTA tweaks, or after a logo change (`set_short_logo`, or `short_logo_position`/`short_logo_treatment`); footage or music changes need `generate_short` instead. Needs one completed generation first (422 `short_not_ready` otherwise); changed footage/music inputs return 422 `short_paid_regeneration_required`. A failed free re-render leaves the delivered video intact — retry `rerender_short`, it stays free. | **0** |
119
118
  | `generate_short_text` | AI-draft editable headline / subheadline / caption beats for a short. | 1 assist |
120
119
  | `create_editor_ad` | Create an editor project, attach optional local product/logo/closing assets, and return the live autopilot quote. Pass `segments_count` (3–10) as the exact structural target. Omit `max_credits` to stop free; provide an approved cap to launch. Write every required person, product, object, and continuity decision directly in the prompt. | **0** until capped launch |
@@ -394,7 +393,7 @@ start a NEW project (omit `slug`, pass `video_path`).
394
393
  | `/mcp` → **Failed to reconnect: -32000** | The server process never started — almost always because `claude mcp add` was run **inside a Claude session** (a nested `claude` runs the line as a prompt, not the subcommand), so nothing was registered. Re-run the `claude mcp add` above in a **normal terminal**, then `claude mcp list` to confirm. |
395
394
  | `npm error could not determine executable to run` | You're on a cached **0.1.x** (which shipped two bins). 0.2.0+ ships a single bin and resolves cleanly. Force a fresh fetch: `npx --ignore-existing -y @hubfluencer/mcp`. |
396
395
  | `npm error 404 … @hubfluencer/mcp` immediately after a release | npm registry/CDN propagation lag (a couple of minutes after publish). Wait and retry — it self-heals. |
397
- | Tools fail with **"Not connected to Hubfluencer"** | No token resolved. Run `npx -y @hubfluencer/mcp@0.17.0 login`, or pass `--env HUBFLUENCER_API_TOKEN=…`. |
396
+ | Tools fail with **"Not connected to Hubfluencer"** | No token resolved. Run `npx -y @hubfluencer/mcp@0.18.0 login`, or pass `--env HUBFLUENCER_API_TOKEN=…`. |
398
397
  | A local-file tool fails with a **path-outside-base** error | The file is outside `HUBFLUENCER_INPUT_DIR` (reads) or `save_path` is outside `HUBFLUENCER_OUTPUT_DIR` (writes). Move the file into the allowed dir, or point the env var at it. |
399
398
  | An asset-catalog tool returns **subscription required** | `list_assets` / `get_asset_quota` / `upload_asset` need an active subscription — subscribe in the app. |
400
399
 
@@ -409,7 +408,7 @@ bun run build # emits dist/
409
408
 
410
409
  The package exposes a single bin, `hubfluencer-mcp`: with no args it starts the stdio MCP
411
410
  server; `hubfluencer-mcp login [name]` runs the device-link login. This is why
412
- `npx -y @hubfluencer/mcp@0.17.0` and `npx -y @hubfluencer/mcp@0.17.0 login` both work without `-p`.
411
+ `npx -y @hubfluencer/mcp@0.18.0` and `npx -y @hubfluencer/mcp@0.18.0 login` both work without `-p`.
413
412
 
414
413
  ### Release
415
414
 
package/dist/index.js CHANGED
@@ -33979,7 +33979,6 @@ function knownGenerationActionTypesFrom(summary) {
33979
33979
  }
33980
33980
  var operation = (tool, required_fences = []) => ({ tool, required_fences });
33981
33981
  var generationProductOperations = {
33982
- "short:short.generation:cancel_generation": operation("cancel_short_generation", ["generation_run_id", "idempotency_key"]),
33983
33982
  "short:*:start_generation": operation("generate_short", ["idempotency_key"]),
33984
33983
  "short:*:download_result": operation("download_result"),
33985
33984
  "short:*:edit_required_input": operation("provide_generation_input", [
@@ -34942,7 +34941,7 @@ function readStoredCredentials() {
34942
34941
  // package.json
34943
34942
  var package_default = {
34944
34943
  name: "@hubfluencer/mcp",
34945
- version: "0.17.0",
34944
+ version: "0.18.0",
34946
34945
  mcpName: "io.github.monocursive/hubfluencer",
34947
34946
  description: "Model Context Protocol server for Hubfluencer — let AI agents generate post-ready shorts and editor ads.",
34948
34947
  license: "MIT",
@@ -36044,7 +36043,6 @@ var CREATOR_TOOL_NAMES = [
36044
36043
  "create_short",
36045
36044
  "update_short",
36046
36045
  "generate_short",
36047
- "cancel_short_generation",
36048
36046
  "rerender_short",
36049
36047
  "set_short_product",
36050
36048
  "set_short_logo",
@@ -37692,45 +37690,6 @@ registerTool("generate_short", {
37692
37690
  throw e;
37693
37691
  }
37694
37692
  }));
37695
- registerTool("cancel_short_generation", {
37696
- title: "Cancel a running short generation",
37697
- description: "Stops the currently observed paid Short generation through the product-scoped cancellation route, " + "fences late provider callbacks, and settles its refund exactly once. The canonical generation_run_id is " + "read from get_status when omitted. The draft is preserved for editing and " + "regeneration. Safe to repeat after a successful cancellation. The raw REST route requires Idempotency-Key; " + "reuse one only for transport retries of this exact run. Scope: video:generate.",
37698
- inputSchema: {
37699
- slug: exports_external.string().describe("Slug of the processing short"),
37700
- generation_run_id: exports_external.string().uuid().optional().describe("Exact run fence from get_status; normally omitted because the tool reads current status first")
37701
- },
37702
- annotations: {
37703
- title: "Cancel short generation",
37704
- readOnlyHint: false,
37705
- destructiveHint: true,
37706
- openWorldHint: true,
37707
- idempotentHint: true
37708
- }
37709
- }, tool(async (args, client) => {
37710
- const observed = await observedGenerationAction(client, "short", args.slug, "cancel_generation", {
37711
- workflows: ["short.generation"],
37712
- statuses: ["queued", "running", "cancelled"],
37713
- recoverCancelled: true
37714
- });
37715
- const generationRunId = observed.summary.run_id;
37716
- if (typeof generationRunId !== "string" || generationRunId.length === 0) {
37717
- throw new Error("The Short response did not include a canonical run_id; refresh get_status before cancelling safely.");
37718
- }
37719
- if (args.generation_run_id !== undefined && args.generation_run_id !== generationRunId) {
37720
- throw new Error("The supplied generation_run_id does not match the authoritative Short state; refresh before cancelling.");
37721
- }
37722
- const receiptKey = idemKey("cancel-short-generation", args.slug, generationRunId);
37723
- const data = observed.settledReplay ? observed.state : asRecord(asRecord(await client.post(`/shorts/${args.slug}/cancel`, { generation_run_id: generationRunId }, receiptKey)).data);
37724
- return ok({
37725
- ...data,
37726
- slug: args.slug,
37727
- run_id: observed.summary.run_id,
37728
- workflow: observed.summary.workflow,
37729
- charged: false,
37730
- refund: "refunded" in data ? data.refunded : "settled (idempotent — no new credits minted on repeat)",
37731
- next: "Edit the preserved draft, then call generate_short when ready."
37732
- });
37733
- }));
37734
37693
  registerTool("rerender_short", {
37735
37694
  title: "Re-render a short (FREE — 0 credits)",
37736
37695
  description: "FREE re-render: applies the short's current text/style/CTA/end-card/logo state over the already-paid " + "footage and music — 0 credits. Use after update_short for copy/style/CTA tweaks, or after a logo change " + "(set_short_logo, or short_logo_position/short_logo_treatment via update_short). Footage or music " + "changes need generate_short (15 credits) instead. Edits that add/remove the end card (poster, " + "end_card) can shift the video between 12s and 14s; when the pinned music bed is shorter than the " + "export it crossfades into a repeated continuation, then fades at the export end, without regeneration. " + "Requires a completed generation to re-render over " + "(422 short_not_ready otherwise — run generate_short once first); while any generation/render is in " + "flight it reports in-progress (409) rather than duplicating. Then poll with get_status or " + "wait_for_completion (kind=short). A failed free re-render leaves the delivered video intact — retry " + "rerender_short, it stays free (the status fields latest_render_free / last_free_rerender_failed " + "report this when the server sends them).",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hubfluencer/mcp",
3
- "version": "0.17.0",
3
+ "version": "0.18.0",
4
4
  "mcpName": "io.github.monocursive/hubfluencer",
5
5
  "description": "Model Context Protocol server for Hubfluencer — let AI agents generate post-ready shorts and editor ads.",
6
6
  "license": "MIT",
package/server.json CHANGED
@@ -9,12 +9,12 @@
9
9
  "source": "github",
10
10
  "subfolder": "packages/mcp"
11
11
  },
12
- "version": "0.17.0",
12
+ "version": "0.18.0",
13
13
  "packages": [
14
14
  {
15
15
  "registryType": "npm",
16
16
  "identifier": "@hubfluencer/mcp",
17
- "version": "0.17.0",
17
+ "version": "0.18.0",
18
18
  "transport": {
19
19
  "type": "stdio"
20
20
  },
@@ -21,8 +21,8 @@ substitute.
21
21
  If Hubfluencer is not connected, tell the user to run:
22
22
 
23
23
  ```bash
24
- npx -y @hubfluencer/mcp@0.17.0 login
25
- npx -y @hubfluencer/mcp@0.17.0 doctor --profile creator
24
+ npx -y @hubfluencer/mcp@0.18.0 login
25
+ npx -y @hubfluencer/mcp@0.18.0 doctor --profile creator
26
26
  ```
27
27
 
28
28
  Never invent, request in chat, or echo a token. A PAT may instead be supplied to
@@ -98,9 +98,9 @@ create_short -> edit/attach assets -> generate_short
98
98
 
99
99
  `generate_short` is the paid footage/music generation. After it completes,
100
100
  `update_short` plus `rerender_short` applies text/style/CTA/end-card/logo changes
101
- over the existing footage for free. `cancel_short_generation` reads the
102
- canonical summary and uses `generation_run_id` only when the caller supplies
103
- that optional stale-command fence.
101
+ over the existing footage for free. A paid Short run cannot be stopped once
102
+ started: there is no cancel tool or route, and the draft cannot be deleted until
103
+ the run reaches a terminal state. A failed run still refunds its 15 credits.
104
104
 
105
105
  Editor ad:
106
106
 
@@ -37,8 +37,8 @@ or guess a fence. Re-read status after the command.
37
37
  ## Prerequisites
38
38
 
39
39
  - The `hubfluencer` MCP server must be connected (tools like `make_video`, `get_credits`, `wait_for_completion` are available).
40
- - The user must have an access token configured (via `HUBFLUENCER_API_TOKEN`, or by having run `npx -y @hubfluencer/mcp@0.17.0 login` — a scoped token is then saved to `~/.hubfluencer/credentials.json` and the server reads it automatically).
41
- - **Never invent a token, and never echo a token in your output.** If no token is configured, tell the user to create one in the app (Settings → Access tokens, "Generate videos" scope) or to run `npx -y @hubfluencer/mcp@0.17.0 login`, then stop.
40
+ - The user must have an access token configured (via `HUBFLUENCER_API_TOKEN`, or by having run `npx -y @hubfluencer/mcp@0.18.0 login` — a scoped token is then saved to `~/.hubfluencer/credentials.json` and the server reads it automatically).
41
+ - **Never invent a token, and never echo a token in your output.** If no token is configured, tell the user to create one in the app (Settings → Access tokens, "Generate videos" scope) or to run `npx -y @hubfluencer/mcp@0.18.0 login`, then stop.
42
42
 
43
43
  ## Native macOS Studio
44
44
 
@@ -81,7 +81,7 @@ advertised; never guess fences. Retry targets the exact failed canonical step. O
81
81
  retrying it does not authorize a new parent run. For an insufficient-credit blocker, top up or reduce
82
82
  scope and follow the action in the newly read summary.
83
83
 
84
- Cancellation is run-fenced. `cancel_short_generation { slug, generation_run_id }` uses `generation_summary.run_id`, keeps the draft, and refunds 15 credits idempotently. `cancel_segment_generation { slug, segment_id, generation_claim_token }` uses the current token from `get_editor` and refunds an individually generated scene; batch/Autopilot scenes use workflow controls. `cancel_autopilot { slug }` re-reads and forwards the summary run/start fence, stopping only that parent chain while keeping completed work and already charged scenes. Re-read state after a stale fence error; never guess a fence value.
84
+ Cancellation is run-fenced. A paid short is not cancellable once `generate_short` starts, and its draft cannot be deleted until the run is terminal; a failure still refunds its 15 credits. `cancel_segment_generation { slug, segment_id, generation_claim_token }` uses the current token from `get_editor` and refunds an individually generated scene; batch/Autopilot scenes use workflow controls. `cancel_autopilot { slug }` re-reads and forwards the summary run/start fence, stopping only that parent chain while keeping completed work and already charged scenes. Re-read state after a stale fence error; never guess a fence value.
85
85
 
86
86
  **Minimum sellable short** — check all seven before you spend:
87
87
 
@@ -165,10 +165,6 @@ const operation = (
165
165
  * can carry out an already-advertised intent.
166
166
  */
167
167
  export const generationProductOperations = {
168
- "short:short.generation:cancel_generation": operation(
169
- "cancel_short_generation",
170
- ["generation_run_id", "idempotency_key"],
171
- ),
172
168
  "short:*:start_generation": operation("generate_short", ["idempotency_key"]),
173
169
  "short:*:download_result": operation("download_result"),
174
170
  "short:*:edit_required_input": operation("provide_generation_input", [
package/src/index.ts CHANGED
@@ -2947,96 +2947,6 @@ registerTool(
2947
2947
  }),
2948
2948
  );
2949
2949
 
2950
- registerTool(
2951
- "cancel_short_generation",
2952
- {
2953
- title: "Cancel a running short generation",
2954
- description:
2955
- "Stops the currently observed paid Short generation through the product-scoped cancellation route, " +
2956
- "fences late provider callbacks, and settles its refund exactly once. The canonical generation_run_id is " +
2957
- "read from get_status when omitted. The draft is preserved for editing and " +
2958
- "regeneration. Safe to repeat after a successful cancellation. The raw REST route requires Idempotency-Key; " +
2959
- "reuse one only for transport retries of this exact run. Scope: video:generate.",
2960
- inputSchema: {
2961
- slug: z.string().describe("Slug of the processing short"),
2962
- generation_run_id: z
2963
- .string()
2964
- .uuid()
2965
- .optional()
2966
- .describe(
2967
- "Exact run fence from get_status; normally omitted because the tool reads current status first",
2968
- ),
2969
- },
2970
- annotations: {
2971
- title: "Cancel short generation",
2972
- readOnlyHint: false,
2973
- destructiveHint: true,
2974
- openWorldHint: true,
2975
- idempotentHint: true,
2976
- },
2977
- },
2978
- tool(async (args: { slug: string; generation_run_id?: string }, client) => {
2979
- const observed = await observedGenerationAction(
2980
- client,
2981
- "short",
2982
- args.slug,
2983
- "cancel_generation",
2984
- {
2985
- workflows: ["short.generation"],
2986
- statuses: ["queued", "running", "cancelled"],
2987
- recoverCancelled: true,
2988
- },
2989
- );
2990
- const generationRunId = observed.summary.run_id;
2991
- if (typeof generationRunId !== "string" || generationRunId.length === 0) {
2992
- throw new Error(
2993
- "The Short response did not include a canonical run_id; refresh get_status before cancelling safely.",
2994
- );
2995
- }
2996
- if (
2997
- args.generation_run_id !== undefined &&
2998
- args.generation_run_id !== generationRunId
2999
- ) {
3000
- throw new Error(
3001
- "The supplied generation_run_id does not match the authoritative Short state; refresh before cancelling.",
3002
- );
3003
- }
3004
- const receiptKey = idemKey(
3005
- "cancel-short-generation",
3006
- args.slug,
3007
- generationRunId,
3008
- );
3009
-
3010
- const data = observed.settledReplay
3011
- ? observed.state
3012
- : asRecord(
3013
- asRecord(
3014
- await client.post<{ data: unknown }>(
3015
- `/shorts/${args.slug}/cancel`,
3016
- { generation_run_id: generationRunId },
3017
- receiptKey,
3018
- ),
3019
- ).data,
3020
- );
3021
- return ok({
3022
- ...data,
3023
- slug: args.slug,
3024
- run_id: observed.summary.run_id,
3025
- workflow: observed.summary.workflow,
3026
- charged: false,
3027
- // The cancel endpoint returns the short's STATE, not a refund receipt,
3028
- // so don't assert refunded:true on every call — a repeat cancel is a
3029
- // no-op that mints no new credits. Echo the server's own flag if it ever
3030
- // sends one; otherwise describe the honest idempotent settlement.
3031
- refund:
3032
- "refunded" in data
3033
- ? data.refunded
3034
- : "settled (idempotent — no new credits minted on repeat)",
3035
- next: "Edit the preserved draft, then call generate_short when ready.",
3036
- });
3037
- }),
3038
- );
3039
-
3040
2950
  registerTool(
3041
2951
  "rerender_short",
3042
2952
  {
@@ -18,7 +18,6 @@ export const CREATOR_TOOL_NAMES = [
18
18
  "create_short",
19
19
  "update_short",
20
20
  "generate_short",
21
- "cancel_short_generation",
22
21
  "rerender_short",
23
22
  "set_short_product",
24
23
  "set_short_logo",