@hubfluencer/mcp 0.5.0 → 0.7.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
@@ -1,11 +1,15 @@
1
1
  # @hubfluencer/mcp
2
2
 
3
3
  A [Model Context Protocol](https://modelcontextprotocol.io) server that lets an AI agent
4
- (e.g. Claude Code) drive Hubfluencer end-to-end: turn a text prompt into a finished,
5
- post-ready short or multi-scene editor ad.
4
+ (e.g. Claude Code) drive Hubfluencer end-to-end from a single text prompt to a finished,
5
+ post-ready short or multi-scene editor ad, and up through the whole content operation:
6
+ ingest a product page, plan a campaign, draft a month of ads, mint review links, stage a
7
+ reminder calendar, and learn from performance.
6
8
 
7
- The server is a thin wrapper over the public Hubfluencer REST API. It holds **no state**
8
- auth is an opaque bearer token passed through from an env var.
9
+ The server is a thin wrapper over the public Hubfluencer REST API. Auth is an opaque bearer
10
+ token passed through from an env var, or read from a local credentials file written by the
11
+ device-link `login` command (see [Setup](#setup)). It keeps **no in-memory session state**;
12
+ the only thing it persists is that credentials file.
9
13
 
10
14
  ## Setup
11
15
 
@@ -25,7 +29,7 @@ Hubfluencer app, and a scoped access token is saved locally to `~/.hubfluencer/c
25
29
 
26
30
  ```bash
27
31
  npx -y @hubfluencer/mcp login "Claude Code"
28
- # 1. Open: https://hubfluencer.com/connect?code=ABCD-EFGH
32
+ # 1. Open: https://app.hubfluencer.com/connect?code=ABCD-EFGH
29
33
  # 2. Confirm code: ABCDEFGH
30
34
  # 3. Click Approve. → ✓ Connected.
31
35
  ```
@@ -51,49 +55,182 @@ it **cannot** delete your account, change credentials, publish, or create more t
51
55
  claude mcp add hubfluencer --env HUBFLUENCER_API_TOKEN=YOUR_TOKEN -- npx -y @hubfluencer/mcp
52
56
  ```
53
57
 
58
+ ### Environment variables
59
+
54
60
  | Env var | Required | Default | Purpose |
55
61
  |---|---|---|---|
56
- | `HUBFLUENCER_API_TOKEN` | no¹ | — | Access token (¹falls back to `~/.hubfluencer/credentials.json` from `login`) |
57
- | `HUBFLUENCER_BASE_URL` | no | `https://hubfluencer.com` | API base URL |
58
- | `HUBFLUENCER_OUTPUT_DIR` | no | current working dir | Allowlisted base dir for `save_path` downloads (writes are confined here) |
62
+ | `HUBFLUENCER_API_TOKEN` | no¹ | — | Access token. ¹Falls back to the credentials file written by `login`. |
63
+ | `HUBFLUENCER_BASE_URL` | no | `https://hubfluencer.com` | API base URL. The token is never sent over a non-https / private-IP origin. |
64
+ | `HUBFLUENCER_WEB_URL` | no | `https://app.hubfluencer.com` | Web-app origin used to build the absolute no-login **review URL** (`/review/<token>`). This is the front web app, a **different** host from the API base — set it only if your web app is served elsewhere. |
65
+ | `HUBFLUENCER_CREDENTIALS` | no | `~/.hubfluencer/credentials.json` | Path to the device-link credentials file (`login` writes it; the server reads it as the token fallback). |
66
+ | `HUBFLUENCER_INPUT_DIR` | no | current working dir | **Read confinement.** Every local file the agent uploads (video clips, product / logo / closing / poster images, catalog assets) must resolve **inside** this directory — a path outside it is refused. This is a security control: it stops an agent from reading arbitrary local files (`~/.ssh/...`, `.env`, …). |
67
+ | `HUBFLUENCER_OUTPUT_DIR` | no | current working dir | **Write confinement.** Downloads via `save_path` (`make_video` / `wait_for_completion` / `download_result` / `create_tracking_video`) must resolve inside this directory and end in `.mp4`; anything outside is refused. |
59
68
 
60
69
  ## Tools
61
70
 
62
- **One-shot & status**
71
+ 89 tools, grouped by workflow. Every tool prices its action in its own `description` — costs
72
+ below are the ground truth. **"$0" means it spends no video credits**; planning/AI-helper tools
73
+ instead draw a **free daily quota of 20 AI assists** (top up with `unlock_ai_assists`: 1 credit
74
+ → +10). Reads need the `video:read` scope; writes need `video:generate`. Nothing here needs
75
+ `account:admin`.
76
+
77
+ ### Make one asset (start here)
78
+
79
+ | Tool | What it does | Cost |
80
+ |---|---|---|
81
+ | **`make_video`** | **One shot: prompt → finished MP4** (create → **price** → start → poll → download). `kind:"auto"` picks a multi-scene editor ad for ad/promo/story briefs, a short for simple ones (reported as `kind_inferred`). Pass `dry_run:true` to preview the cost without spending, or `max_credits` to cap it. | short **15**, editor ~**28** (`dry_run`/`max_credits` gate it) |
82
+ | `create_short` | Create a short draft (12s vertical: two 6s AI segments + title overlay + music; 14s with an end-card poster). Set `headline`/`subheadline`/`music_vibe`/`visual_language` so it isn't bare. Optional opt-in conversion graphics: `offer_text`/`cta_text`/`badge_text`/`star_rating` (off unless you set them). | **0** |
83
+ | `update_short` | Patch an existing short draft — brief (`product_prompt`), copy, styling, or the opt-in conversion graphics; only the fields you pass change. Clear one with `""` (`[]` for `text_beats`, `0` for `star_rating`). Re-run `generate_short` to apply. | **0** |
84
+ | `generate_short` | Render an existing short. Safe to re-call (in-flight = reported, no double charge; a failed short can re-generate). | **15** |
85
+ | `generate_short_text` | AI-draft editable headline / subheadline / caption beats for a short. | 1 assist |
86
+ | `create_editor_ad` | Create an editor project **and** run autopilot end-to-end. Style it with `creative_format` + `visual_language` + `theme`. | credits (est. first) |
87
+ | `start_autopilot` | Run autopilot on an **existing** editor draft (resume a `make_video` `dry_run`, or after a top-up). | credits |
88
+ | `create_slider` | Create an image-carousel draft: one prompt → N still slides + a ready-to-post caption + hashtags. `mode` `creative` (story) or `ad_driven` (facts). | **0** |
89
+ | `generate_slider` | Render a carousel (copy → AI backgrounds → composite). Poll `get_slider` until `completed`. | **1 / slide** (3–10) |
90
+ | `get_slider` | Read a carousel's status and, when completed, the per-slide image URLs + caption + hashtags. | **0** |
91
+ | `restyle_slider` | Re-composite **all** slides of a completed carousel under a new template/accent/position — reuses the AI backgrounds. | **0** |
92
+ | `edit_slider_slide` | Rewrite one slide's headline/body/kicker and re-composite just that slide. | **0** |
93
+ | **`create_tracking_video`** | **One shot: upload a local clip → burn a CV object-tracking overlay → download.** Source ≤60s, ≤1080p. Optional `classes` (COCO-80 ids) / `color` ([r,g,b,a]). Times out on a slow upload / cold GPU → call again with `slug` to resume (no re-upload, no re-charge). A completed slug is final — for a variant, start a NEW project. | **1** on render (refunded on failure) |
94
+
95
+ ### Granular editor pipeline (write the scenario / scenes / audio yourself)
96
+
97
+ | Tool | What it does | Cost |
98
+ |---|---|---|
99
+ | `create_editor_draft` | Editor project, **no** autopilot. Accepts `creative_format` / `visual_language` / `theme`. | **0** |
100
+ | `get_editor` | Full project state (scenario, segments, narration, music, latest render, quota) — the review step. | **0** |
101
+ | `set_scenario` / `generate_scenario` | Write your own scenario (free) **or** AI-draft it. `generate_scenario` can also persist `creative_format` / `visual_language` / `theme`. | free / 1 assist |
102
+ | `set_scene_count` | Grow/shrink to N scenes (1–20); deletes only trailing un-generated scenes. Each AI scene is a fixed 8s. | **0** |
103
+ | `set_segment_prompt` | Write one scene's prompt (1–2000 chars), identified by segment id. | **0** |
104
+ | `generate_segment` | Render one scene (re-call to retry a failed one). | **5** |
105
+ | `generate_all_segments` | Render every not-yet-completed scene in order (continuity preserved); capped ~280s → re-run to continue. | **5 / segment** |
106
+ | `set_narration_script` / `generate_narration` | Write your own voiceover script (free) **or** AI-draft it. | free / 1 assist |
107
+ | `generate_voice` | Synthesize the voiceover. `voice_id` required (see `list_voices`). | **3** |
108
+ | `generate_music` | Generate background music (each call is a fresh take). | **5** |
109
+ | `render` | Final MP4. Auto-charges any still-ungenerated scenes first (4/scene in a batch of ≥3). | **0** |
110
+ | `list_renders` | List every render version for an editor project (id, version, status, video_url, error) — find a failed render or recover a finished URL. | **0** |
111
+ | `retry_render` | Re-run a **failed** render from its exact saved snapshot (recovery without re-driving the pipeline). | **0** |
112
+ | `enhance_prompt` / `suggest_next_scene` / `suggest_music_prompt` | AI helpers along the way. | 1 assist each |
113
+
114
+ ### Uploads & local media (bring your own footage / images)
115
+
116
+ Reads are confined to `HUBFLUENCER_INPUT_DIR`. All $0.
117
+
118
+ | Tool | What it does |
119
+ |---|---|
120
+ | `upload_video` | Upload a local clip into an editor project (presign → PUT, resumable multipart for large files → confirm → poll to ready) and, by default, add it to the timeline. An uploaded clip keeps its native duration. |
121
+ | `add_segment_from_upload` | Append a **ready** upload to the timeline as a new scene. |
122
+ | `use_asset_for_segment` | Set a specific scene's video from a ready upload **or** a completed scene in the same project (pass exactly one). |
123
+ | `set_product` | Upload a local product image and attach it as the project product. |
124
+ | `set_product_placement` | Set where the product appears on pending AI scenes: `throughout` or `end`. |
125
+ | `set_closing_image` | Set the ~2s end-card image (upload a file, or reuse the product image with `from_product:true`). |
126
+ | `set_logo` | Upload a brand logo overlay (editor only; optional treatment/position/duration). |
127
+ | `set_short_product` | Attach a product image to a **short**. |
128
+ | `set_short_poster` | Set a short's end-card poster (extends the render 12s → 14s). |
129
+
130
+ ### Status & delivery
131
+
132
+ | Tool | What it does |
133
+ |---|---|
134
+ | `get_status` | Normalized `{stage, terminal, ready, video_url, error}` for a short / editor / tracking / slider. |
135
+ | `wait_for_completion` | Block-poll until terminal (bounded ≤280s; returns `terminal:false` to re-call). `save_path` downloads the MP4 when ready. |
136
+ | `download_result` | Get (or save, to `HUBFLUENCER_OUTPUT_DIR`) the finished MP4 URL. Not for sliders — use `get_slider`. |
137
+ | `get_credits` / `list_voices` / `list_projects` | Credit balance; narration voices; recent projects (`include_completed:true` to recover a finished short's slug). |
138
+ | `get_ai_assists` / `unlock_ai_assists` | The free daily assist quota / spend 1 credit for +10. |
139
+
140
+ ### Campaign engine — onboard a product, plan, and draft (the delegation surface)
141
+
142
+ Everything here is **$0** (draft creates + planning against the free assist quota). Generation
143
+ of each draft stays a separate, explicit, paid step (`start_autopilot` / `generate_short` /
144
+ `generate_slider`).
63
145
 
64
146
  | Tool | What it does |
65
147
  |---|---|
66
- | **`make_video`** | **One shot: prompt finished MP4** (create **price** start poll download). Use this by default. Prices the job and checks your balance before charging; pass `dry_run:true` to preview the cost without spending, or `max_credits` to cap it. `kind:"auto"` picks a multi-scene editor ad for ad/promo/story briefs, a short for simple ones (reported as `kind_inferred`). |
67
- | `create_short` / `generate_short` / `generate_short_text` | Create a short draft (0 credits) / generate editable overlay copy (1 AI assist) / render it (15 credits) |
68
- | `create_slider` / `generate_slider` / `get_slider` | Create an image carousel draft (0 credits) / render it (1 credit per slide, 3–10) / read the per-slide image URLs + caption + hashtags. One prompt N still slides + ready-to-post text. |
69
- | `restyle_slider` / `edit_slider_slide` | Re-composite a **completed** carousel for **free** (0 credits): swap the template/accent on every slide, or rewrite one slide's headline/body/kicker. Reuses the AI backgrounds; poll `get_slider` until `completed`. |
70
- | `create_editor_ad` | Create an editor project **and** run autopilot end-to-end. Style it with `creative_format` (narrative arc) + `visual_language` (render look) + `theme` (genre overlay). |
71
- | `start_autopilot` | Run autopilot on an **existing** editor draft (e.g. resume a `make_video` `dry_run`, or after topping up) |
72
- | `get_status` / `wait_for_completion` | Normalized `{stage, terminal, ready, video_url, error}`; block-poll until terminal (bounded) |
73
- | `download_result` | Get (or save) the finished MP4 URL |
74
- | `get_credits` / `list_voices` / `list_projects` | Credit balance; narration voices; recent projects |
75
-
76
- **Granular editor pipeline** write the scenario / scenes / audio yourself, full control
148
+ | **`create_campaign`** | **One shot: a product URL (or `product_profile_id`)a persisted pack full of editable DRAFTS.** Runs extract save profile import image/logo plan hook variations create pack materialize drafts. Never generates/renders. |
149
+ | `extract_product_page` | Server-side, SSRF-guarded fetch of a product page parsed facts (name, description, benefits, price, brand) + candidate image/logo URLs (URLs only; no download). Rate limit 30/min. |
150
+ | `import_product_image` | Server-side, SSRF-guarded fetch of an image URL (JPEG/PNG, magic-byte verified) stored as a catalog asset linked to a product profile (`link_as` `primary_image` default / `logo`). Rate limit 30/min. |
151
+ | `list_product_profiles` / `create_product_profile` / `update_product_profile` | Reusable product fact sheets (benefits, offer, proof points, audience, CTA, banned claims, tone) that ground planning + generation. |
152
+ | `list_brand_profiles` / `create_brand_profile` / `update_brand_profile` | Reusable brand identities (logo, colors, fonts, tone, default CTA, preferred visual_language/creative_format). `update_brand_profile` also attaches/detaches catalog assets. |
153
+ | `plan_campaign` | Product facts a campaign PLAN: hooks, recommended formats, positioning line, and a credit ESTIMATE. Persists nothing. Rate limit 30/min. |
154
+ | `generate_hook_variations` | Product facts (+ optional brand) → 3–6 distinct hook variations, each with a script, caption, hashtags, suggested format, and a per-variation estimate. Rate limit 30/min. |
155
+ | `create_campaign_pack` | Persist a pack (the planning container) + any inline hook/caption text items. Link a product/brand profile so drafts inherit them. |
156
+ | `list_campaign_packs` | List your packs at the pack level (id, title, status, source, profiles). Per-item detail is NOT included — the list endpoint doesn't load items; use `get_campaign_pack` for that. |
157
+ | `get_campaign_pack` | Read one pack **with** its items (per-item kind, status, materialized draft slug + route, credit estimate). |
158
+ | `add_pack_variations` | Persist selected hook variations under a pack and (by default) materialize each into a draft. ≤12 per call; rate limit 15/min; per-variation best-effort. |
159
+ | `materialize_pack_item` | Materialize one planned item into a draft. Safe to retry — no duplicate is ever created; a sequential re-call of an already-materialized item returns **422 "already materialized"** (read the existing draft via `get_campaign_pack`). Rate limit 60/min. |
160
+
161
+ ### Series — recurring content shows
162
+
163
+ | Tool | What it does |
164
+ |---|---|
165
+ | `create_series` / `list_series` / `update_series` | A reusable recurring-content show template ("Myth vs Fact", "Founder Tip") bound to an optional brand + product profile; toggle `active`/`paused`/`archived`. |
166
+ | `plan_series_episodes` | Draft 3–5 upcoming episode ideas for a series (free assist quota). Rate limit 30/min. |
167
+ | `list_series_episodes` | List a series' episodes (idea → drafted → published) with their materialized draft slug + route. |
168
+ | `materialize_episode` | Turn an idea episode into a 0-credit draft under the series' rolling pack. Safe to retry — no duplicate is ever created; a sequential re-call of an already-materialized episode returns **422 "already materialized"** (find the draft via `list_series_episodes`). Rate limit 60/min. |
169
+ | `get_series_dashboard` | One series' episodes grouped into lanes: upcoming (ideas) / drafted / published, with per-item performance notes. |
170
+ | `mark_episode_posted` | Record that you posted a drafted episode manually (drafted → published; stamps `posted_at`; idempotent). |
171
+
172
+ ### Content calendar — reminder-only scheduling
173
+
174
+ These stage a **reminder** (a push to *you* at the due time) — they never attach a social
175
+ account, so publishing stays a human step in the app. All $0.
77
176
 
78
177
  | Tool | What it does |
79
178
  |---|---|
80
- | `create_editor_draft` | Editor project, no autopilot (0 credits). Accepts `creative_format` / `visual_language` / `theme`. |
81
- | `generate_scenario` / `set_scenario` | AI-draft the scenario (1 assist) **or** write your own (free). `generate_scenario` can also persist `creative_format` / `visual_language` / `theme`. |
82
- | `get_editor` | Full project state the review step |
83
- | `set_scene_count` | Grow/shrink to N scenes (1–20) |
84
- | `set_segment_prompt` / `generate_segment` / `generate_all_segments` | Write a scene prompt (free); render one (5 credits) or every scene in order |
85
- | `set_narration_script` / `generate_narration` | Write the voiceover script (free) **or** AI-draft it (1 assist) |
86
- | `generate_voice` / `generate_music` | TTS voiceover (3 credits) / background music (5 credits) |
87
- | `render` | Final MP4 (0 credits; auto-charges any still-ungenerated scenes) |
179
+ | `schedule_post` | Schedule a completed video result for a future UTC instant as a manual-posting reminder (≤500 pending posts per user). |
180
+ | `list_scheduled_posts` | Your calendar (ordered by `scheduled_at`), with the staged caption/hashtags + presigned export URL; filter by `from`/`to`/`status`. |
181
+ | `reschedule_post` | Move a scheduled/reminded post to a new future instant. |
182
+ | `cancel_scheduled_post` | Cancel a scheduled/reminded/failed post. |
183
+ | `mark_scheduled_posted` | Record that you posted it manually (scheduled/reminded posted). |
88
184
 
89
- **AI assists**a free daily quota of AI helper calls
185
+ ### Performancelearn from your own results
90
186
 
91
187
  | Tool | What it does |
92
188
  |---|---|
93
- | `get_ai_assists` / `unlock_ai_assists` | Check the daily quota / spend 1 credit for +10 |
94
- | `generate_short_text` / `enhance_prompt` / `suggest_next_scene` / `suggest_music_prompt` | AI helpers (1 assist each) |
189
+ | `record_performance` | Attach a performance snapshot (platform + engagement/conversion counts + optional revenue/watch time) to a campaign-pack item. Many per item. Rate limit 30/min. |
190
+ | `list_performance` | A campaign-pack item's snapshots (newest first) + a small summary. |
191
+ | `set_item_attributes` / `get_item_attributes` | The single creative-attributes row (hook_type, creative_format, visual_language, product_category, CTA, length, caption_style) the recommendation loop correlates with performance (atomic upsert). |
192
+ | `get_recommendations` | A **cautious**, sample-size-aware read of your own best hook/format/visual_language by average views, with an honest confidence tier and a non-causal `note` — present them as-is, never upgrade them. No LLM, no quota. |
193
+ | `make_more_like_winner` | Spin 3 fresh hook variations from a winning item, threading its angle/format while keeping its brand + product. Feed a chosen one back into `add_pack_variations`. Rate limit 30/min. |
95
194
 
96
- ## Typical flow
195
+ ### Review links — no-login approval loop
196
+
197
+ | Tool | What it does |
198
+ |---|---|
199
+ | `create_review_link` | Mint an expiring, hashed-token link for one completed output (a video result **or** a slider). The plaintext token + URL are returned **once** — surface them immediately. `expires_in_hours` default 168 (7 days). |
200
+ | `list_review_links` | Your links (pending → viewed → approved / changes_requested / revoked) with visible comment counts. Never returns the token. |
201
+ | `revoke_review_link` | Revoke a link — its no-login URL stops working immediately. |
202
+
203
+ ### Asset catalog — cross-project reusable media
204
+
205
+ Subscription-gated (a 402 `subscription_required` means the account needs an active subscription).
206
+
207
+ | Tool | What it does |
208
+ |---|---|
209
+ | `list_assets` | Your reusable asset catalog (images + videos) with presigned URLs + your storage quota; page with `limit`/`offset`. |
210
+ | `get_asset_quota` | Your catalog storage quota (limit / used / pending / reserved / remaining bytes). |
211
+ | `upload_asset` | Upload a local image (≤20 MiB) or video (≤500 MB; `duration_seconds` required, ≤60) into the catalog so it can be reused across projects. Reads confined to `HUBFLUENCER_INPUT_DIR`. Rate limit 30/min. |
212
+
213
+ ### Credit prices (reference)
214
+
215
+ Spend happens server-side; each tool prices the action first. `create_*` and every draft
216
+ edit are **0 credits** — you only pay to generate/render.
217
+
218
+ | Action | Credits |
219
+ |---|---|
220
+ | Any draft create / edit / reorder | 0 |
221
+ | Short render | **15** |
222
+ | Editor AI scene (`generate_segment`) | **5** (4 each in a batch of ≥3) |
223
+ | Editor voice | **3** |
224
+ | Editor music | **5** |
225
+ | Editor render | **0** (auto-charges only still-ungenerated scenes) |
226
+ | Editor autopilot (whole pipeline, ~5 scenes) | ~**28** (preview with `make_video` `dry_run`) |
227
+ | Carousel render | **1 / slide** (3–10 slides) |
228
+ | Carousel restyle / per-slide edit | **0** |
229
+ | Tracking render | **1** (refunded on failure) |
230
+ | Unlock AI assists | **1 credit → +10 assists** |
231
+ | Onboard / plan / pack / materialize / series / calendar / performance / review / profiles | **0** (planning tools draw the free daily assist quota) |
232
+
233
+ ## Typical flows
97
234
 
98
235
  **One shot (recommended):**
99
236
  `make_video({ prompt: "an ad for…", save_path: "ad.mp4" })` → returns `{ ready, video_url, saved_to, estimated_credits, available_credits }`.
@@ -112,6 +249,25 @@ returned `caption` + `hashtags`. To tweak the look afterward without re-paying,
112
249
  (new template/accent, re-renders every slide) or `edit_slider_slide` (rewrite one slide's text) — both
113
250
  free; poll `get_slider` again until `completed`.
114
251
 
252
+ **Tracking overlay (your own clip):**
253
+ `create_tracking_video({ video_path: "clip.mp4", save_path: "tracked.mp4" })` → uploads the clip, waits for it
254
+ to be ready, renders the CV object-tracking overlay (1 credit), polls to completion, and downloads the result.
255
+ Optionally pass `classes` (COCO-80 ids, e.g. `[0]`=person, `[16]`=dog; omit to track all) and `color` ([r,g,b,a]).
256
+ If it returns `terminal:false`, call it again with the returned `slug` to resume, or poll
257
+ `wait_for_completion({ slug, kind: "tracking" })` then `download_result`. Resuming a slug whose render already
258
+ **completed** just returns the finished video — a completed project is final; for a variant (different classes/color),
259
+ start a NEW project (omit `slug`, pass `video_path`).
260
+
261
+ **Delegate a content operation (the full loop — steps 1–3 are $0):**
262
+ 1. `extract_product_page(url)` → `create_product_profile` + `create_brand_profile` (persist the identity once).
263
+ 2. `plan_campaign` / `generate_hook_variations` (free quota), or `create_campaign(url | product_profile_id)` to do 1–2 end-to-end.
264
+ 3. `create_campaign_pack` → `add_pack_variations` / `materialize_pack_item` → editable **drafts**.
265
+ 4. Generate each draft explicitly (credits): `start_autopilot` / `generate_short` / `generate_slider`.
266
+ 5. `create_review_link` for a no-login human approval; gate spend/posting on it.
267
+ 6. `schedule_post` a reminder calendar; after you post the export, `mark_scheduled_posted`.
268
+ 7. `record_performance` + `set_item_attributes` → `get_recommendations` → `make_more_like_winner` → back to step 3.
269
+ 8. Recurring: `create_series` + `plan_series_episodes` → `materialize_episode`; `get_series_dashboard` tracks the lanes.
270
+
115
271
  > Result URLs are presigned and expire (~24h). Download promptly. Publishing to
116
272
  > TikTok/Instagram requires a human-linked social account and is out of scope —
117
273
  > return the MP4 + a suggested caption instead.
@@ -124,6 +280,8 @@ free; poll `get_slider` again until `completed`.
124
280
  | `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`. |
125
281
  | `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. |
126
282
  | Tools fail with **"Not connected to Hubfluencer"** | No token resolved. Run `npx -y @hubfluencer/mcp login`, or pass `--env HUBFLUENCER_API_TOKEN=…`. |
283
+ | 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. |
284
+ | An asset-catalog tool returns **subscription required** | `list_assets` / `get_asset_quota` / `upload_asset` need an active subscription — subscribe in the app. |
127
285
 
128
286
  ## Develop
129
287