Resources
Get the Vibe System
⚡ Pro Tip

Keep music off your API-published posts. Both Instagram and TikTok reserve their commercial music libraries for mobile publishing only. Use Claude for the heavy lifting (file selection, captions, scheduling, multi-platform), then do the 10-second music tap on your phone for posts that need a trending sound.

Creator Workflow

Publish from
Claude Desktop or Claude Code

AITechDad AITechDad Updated May 2026

Publishing should be one sentence, not twelve clicks.

Claude + the ViralSpin MCP gets you there.

Two paths now — Claude Desktop in 60 seconds, or Claude Code for power users.

This is the full setup and workflow.

⚡ The 60-second version — 3 steps

1
In Claude (Desktop or claude.ai), open Settings → Connectors → Add custom connector.
2
Paste this URL, swapping in your key:
https://mcp.viralspin.ai/mcp?key=YOUR_API_KEY → Generate your vs_… key at viralspin.ai/settings
3
Open a new chat and publish in one sentence:
publish ~/videos/clip.mp4 to tiktok and instagram — write a punchy caption with 3 hashtags
Local file paths (~/videos/clip.mp4) work in Claude Code — see Path B below. On Claude Desktop, upload at viralspin.ai/publish first, then publish that URL.

If you already use Claude for everything else in your week, posting to Instagram and TikTok should be one more sentence to Claude — not a context-switch into a phone, a browser, and three different uploaders. The ViralSpin MCP server adds publishing as a first-class tool inside Claude itself.

There are two ways to wire it up. Pick the one that matches how you use Claude:

If you use… Use this path Setup time Best for
Claude Desktop or claude.ai web Paste one URL into "Custom connector" 60 seconds Anyone — most users
Claude Code CLI (or VS Code / Cursor / Antigravity terminal) Install the stdio MCP via npx, edit ~/.claude.json 10 minutes Power users with local-file workflows

Both surface the same publishing tools. The difference is that Claude Code can publish local files directly from your laptop (~/videos/clip.mp4), while Claude Desktop publishes URLs (you upload your file once at viralspin.ai/publish to get a URL, then chat with Claude about that URL).

This guide covers both. Skip to whichever section matches your setup.


Path A — Claude Desktop / claude.ai (60-second setup)

If you use Claude in the desktop app or in the browser at claude.ai, this is the path for you. No CLI to install, no JSON config file to edit. You paste one URL into Claude's custom-connector settings and ViralSpin's publishing tools show up in your chat.

Step 1 — Connect your TikTok and Instagram accounts

Before Claude can publish anything, ViralSpin needs OAuth-authorized access to your social accounts. This happens once and the connection works for both Claude Desktop AND Claude Code (same connections, same OAuth).

Go to viralspin.ai/publish and connect each platform from the left rail.

ViralSpin Publishing Hub at viralspin.ai/publish showing the Connected Accounts panel with TikTok and Instagram both showing 'Connected' badges and YouTube available to connect
Publishing Hub at viralspin.ai/publish — connect TikTok, Instagram, and YouTube once.

A few things to know about the connect step:

  • TikTok asks for video.publish, video.upload, and stats scopes during OAuth. Approve all of them — the stats scopes are what let Claude see follower and like counts later.
  • Instagram must be a Creator or Business account. Personal IG accounts can't publish via the Graph API. If your IG is still Personal, switch it in the IG app: Settings → Account → Switch to Professional → Creator.
  • Tokens auto-refresh in the background. You shouldn't have to re-authorize unless you change your IG password or revoke the app on TikTok's side.

Once both are showing the green Connected badge, you're done with this page.

Step 2 — Generate an MCP API key

Go to viralspin.ai/settingsClaude Code MCP section → Generate Key.

Copy the vs_... value immediately — it's shown only once. (The settings page calls it "Claude Code MCP" key, but the same key works for Claude Desktop too — one credential, both surfaces.)

Step 3 — Add ViralSpin as a custom connector in Claude

Open Claude Desktop (or claude.ai web) → SettingsConnectors (or "Tools & Connectors" depending on version) → Add custom connector.

Paste this URL, replacing YOUR_API_KEY with the vs_... value from Step 2:

https://mcp.viralspin.ai/mcp?key=YOUR_API_KEY

Name it whatever you want — "ViralSpinAI Publishing" is what we use. Save.

Claude Desktop Connectors page showing ViralSpinAI Publishing as a custom connector with 6 tools listed: cancel_post, list_connections, list_posts, publish_url, schedule_url, send_to_drafts — all set to 'Always allow'.
What "connected" looks like — ViralSpinAI Publishing in the Connectors list with 6 tools available.
Privacy note: the URL contains your API key — treat it like a password. Don't paste it into screenshots, chat threads, or anywhere public. If it leaks, revoke and regenerate at viralspin.ai/settings — takes 30 seconds.

You should see 6 tools listed under the connector: list_connections, list_posts, cancel_post, publish_url, schedule_url, send_to_drafts. Set permissions to "Always allow" (or "Ask each time" if you want approval prompts).

Step 4 — Smoke test

Open a new chat in Claude. Type:

list my connected social platforms

Claude calls list_connections, hits viralspin.ai, returns something like:

Connected platforms:
- instagram: @yourhandle · 1,078 followers
- tiktok: @yourhandle · 615 followers

If you see that, you're done. The MCP is fully wired up.

Step 5 — Publish (Claude Desktop edition)

Because Claude Desktop runs in the cloud, it can't read files from your local computer. The remote MCP gets a URL, not a file path. So the workflow is:

  1. Upload your media at viralspin.ai/publish (drag-and-drop in the browser) — get a hosted URL back, OR use any URL that's already on the web (Dropbox public, S3, etc.)
  2. In Claude chat, reference that URL and tell Claude what to do

Examples:

publish https://my-storage.example.com/clip.mp4 to tiktok and instagram
— write me a hooky caption that mentions AI agencies, ending with "link in bio".
Add 3-5 hashtags.
schedule https://my-storage.example.com/clip.mp4 to tiktok for tomorrow
at 9am Pacific with caption "..."
send https://my-storage.example.com/clip.mp4 to my tiktok drafts I want to add a trending sound in the app before publishing.
what posts do I have scheduled?
cancel post sp_abc123

That's the entire Claude Desktop workflow. If you want to publish straight from a local file path on your laptop without the upload step, jump down to Path B (Claude Code CLI).


Path B — Claude Code CLI (10-minute setup, local-file publishing)

This is the original setup. Use it if you live in the terminal, want to publish files straight from ~/videos/ or E:/AI test/news/ without uploading to a URL first, or want to do batch operations like "publish every video in this folder."

The Claude Code CLI runs locally on your machine, so it can read your local files and pass them to the MCP. The trade-off: more setup steps, no Claude Desktop integration (Claude Code is a separate product — see Section 3 below for the disambiguation).

Step 1 — Connect your TikTok and Instagram accounts

Same as Path A Step 1 above — connect each platform once at viralspin.ai/publish. The connection works for both Claude Desktop and Claude Code (one OAuth, both surfaces).


Step 2 — Generate an API key for Claude Code

Now head to viralspin.ai/settings and scroll to the Claude Code MCP section.

ViralSpin settings page showing the Claude Code MCP section with an API key generator and a code block showing the mcpServers JSON snippet to paste into ~/.claude.json
viralspin.ai/settings — generate a key, copy the ready-made MCP config block.
  1. Type a label that tells you which machine the key lives on. Mine says "My Mac" so I know which key to revoke if I sell the laptop.
  2. Click Generate Key. Copy the vs_... string immediately — it's only shown once.
  3. Below the generator, ViralSpin shows you the exact JSON to drop into ~/.claude.json. Replace vs_... with your real key.
{
  "mcpServers": {
    "viralspin": {
      "command": "npx",
      "args": ["-y", "@viralspin/mcp"],
      "env": {
        "VIRALSPIN_API_KEY": "vs_your_real_key_here",
        "VIRALSPIN_API_URL": "https://viralspinbackend.onrender.com"
      }
    }
  }
}

If you already have other MCP servers in ~/.claude.json, just add the "viralspin" entry alongside them — don't replace the whole mcpServers block.

Where to find ~/.claude.json on your machine

The ~ is shorthand for your home directory and the file itself is hidden by default (the leading dot). Specifically:

  • Windows: C:\Users\<your-username>\.claude.json — sits next to, not inside, the .claude folder. Enable View → Show → Hidden items in Explorer if you don't see it.
  • macOS / Linux: ~/.claude.json or /Users/<your-username>/.claude.json. In Finder press Cmd+Shift+. to reveal dotfiles.
Windows File Explorer showing the .claude.json file in C:/Users/Allen alongside a .claude.json.backup, .gitconfig, and .npmrc — confirming the file lives in the user home directory, not inside the .claude folder
On Windows, .claude.json lives in C:\Users\<you>\ — alongside .gitconfig and .npmrc, not inside the .claude\ folder.

If the file doesn't exist yet, create it with just the JSON block above as its entire contents. Claude Code will read it on next launch.

Where exactly does the snippet go inside the file?

If the file already exists (which it does the moment you've run Claude Code once), it's a fairly large JSON object — likely 30–40KB — with dozens of top-level keys. Don't be intimidated by the size. mcpServers is just one more top-level key that lives alongside the others.

The fastest way to find your insertion point: search the file for mcpServers (Ctrl+F in Notepad / Cmd+F on Mac). One of three things will happen.

The .claude.json file in Notepad with the Find dialog open and 'mcpServers' searched — the highlighted match is nested inside a project-path key 'E:/AI test/github/viralspin_new', not at the top level. The block contains 'render' and 'supabase' MCP servers.
Searching mcpServers reveals where MCP configs already exist — but check carefully whether the match is global or project-scoped.

Case 1 — search lands inside a project-path key. This is the screenshot above. The mcpServers block is nested inside something like "E:/AI test/github/viralspin_new": { ... }. This is project-scoped — those MCPs only load when Claude Code is opened in that specific directory.

For publishing, you'll be running Claude Code from wherever your videos and carousels live (~/videos/, ~/posts/, etc.), not from inside a specific project repo. So don't drop the ViralSpin entry here. Skip past this match and search for the next one, or jump to Case 3.

Case 2 — search lands at the top level. The mcpServers key sits directly inside the root object, not nested under any project path. This is the global block. Add the "viralspin": { ... } entry inside it, alongside the others:

"mcpServers": {
  "some-other-server": { ... },
  "viralspin": {
    "command": "npx",
    "args": ["-y", "@viralspin/mcp"],
    "env": {
      "VIRALSPIN_API_KEY": "vs_your_real_key_here",
      "VIRALSPIN_API_URL": "https://viralspinbackend.onrender.com"
    }
  }
}

Case 3 — no global mcpServers exists. Either there are no matches at all, or every match is inside a project-path block. You need to create the top-level key. Scroll to the very bottom of the file, find the last line before the final closing } — likely something like "officialMarketplaceAutoInstalled": true — add a comma at the end of that line, then drop in:

  "officialMarketplaceAutoInstalled": true,
  "mcpServers": {
    "viralspin": {
      "command": "npx",
      "args": ["-y", "@viralspin/mcp"],
      "env": {
        "VIRALSPIN_API_KEY": "vs_your_real_key_here",
        "VIRALSPIN_API_URL": "https://viralspinbackend.onrender.com"
      }
    }
  }
}

What "correct" looks like

Once you've saved, the bottom of your file should look like this:

The bottom of .claude.json after correctly adding the mcpServers block. A comma has been added after 'officialMarketplaceAutoInstalled': true, then a new top-level mcpServers key contains a single viralspin entry with command, args, and env fields. No trailing commas anywhere. The file closes with a single final brace.
Correct result: mcpServers added at the top level, comma added to the previous last entry, no trailing commas, final } closes the root object.

Anatomy: the comma and brace rules in 30 seconds

JSON has exactly two structural rules that trip people up when hand-editing .claude.json. If you remember these two, you'll never break the file:

Commas separate siblings. They do NOT terminate them. Inside any object or array, every entry except the last one needs a comma after it. The last one does not. So when you add a new entry at the end of an object, the previous "last" entry stops being last and now needs a comma. That's why this edit is wrong:

"officialMarketplaceAutoInstalled": true         missing comma; was OK before, broken now
"mcpServers": { ... }
}

…and this is right:

"officialMarketplaceAutoInstalled": true,        comma added when mcpServers was appended
"mcpServers": { ... }                            no trailing comma  mcpServers is now last
}

Every { needs a matching }. Every [ needs a matching ]. Count them. In the correct snippet above, you can trace them outward from the deepest level:

  • { opens the env object → its } closes it (line with "VIRALSPIN_API_URL" value just above)
  • { opens viralspin → its } closes it
  • { opens mcpServers → its } closes it
  • { (off-screen, at the very top of the file) opens the root → the final } closes it

If Claude Code throws a parse error, VS Code will highlight the broken bracket in red the moment you open the file. Even Notepad's status bar showing Ln 1024, Col 4 for a file that should be much shorter is a clue you've got an unclosed brace eating the rest of the document.

Quick sanity check before saving: count the opening braces of what you pasted ({) and the closing braces (}) — they should be equal. The ViralSpin block has exactly 3 of each (mcpServers, viralspin, env). Pair that mentally with the existing root {...} and you're done.
Global vs project-scoped, the short version: Top-level mcpServers = available in every Claude Code session. "<project-path>": { "mcpServers": {...} } = available only when you open Claude Code inside that directory. ViralSpin publishing is a personal productivity tool, so it belongs at the top level.

After saving, fully quit and relaunch Claude Code. Run /mcp — you should see viralspin come up in the server list.

Wait — how do I actually launch Claude Code?

Worth being explicit because the name overlaps with the chat product at claude.ai. Claude Code is a separate command-line tool that runs in your terminal. It is not the claude.ai web chat, and it is not the Claude Desktop app either — those are different products with different config files.

Here's the full disambiguation so you can ignore the noise:

Product Where publish commands work MCP config file
Claude Code CLI (claude in any terminal) ✅ Yes ~/.claude.json — the file you just edited
Claude Code in VS Code / Cursor / Windsurf / Antigravity ✅ Yes — same CLI, just embedded in the IDE's terminal ~/.claude.json
Claude Desktop app (the standalone chat app) ❌ No Different file: claude_desktop_config.json
claude.ai (the web chat) ❌ No None — no MCP support

The first two rows are the only places that read the mcpServers block you just added. Both use the exact same claude binary under the hood, so your viralspin MCP works in all of them.

Install it once (if you haven't already):

npm install -g @anthropic-ai/claude-code

You'll need Node.js 18+ for the install to succeed (node -v to check).

Launch it by opening any terminal you like and running claude. The terminal options on each platform:

  • Windows: PowerShell, Windows Terminal, Command Prompt, or WSL — any of them. Hit the Start key, type the terminal name, and pick it from the results. Then type claude → Enter.
Windows Start menu search showing Windows PowerShell and Command Prompt as the top results — either one works as a host for the Claude Code CLI.
On Windows, search the Start menu for PowerShell or Command Prompt — either one hosts Claude Code identically. PowerShell is the more modern default.
  • macOS / Linux: Terminal, iTerm, Warp, Ghostty — any of them. Type claude → Enter.
  • Inside an IDE: VS Code, Cursor, Windsurf, Antigravity, JetBrains — any IDE built on VS Code (or with a built-in terminal) works. Open the integrated terminal with Ctrl+` (Cmd+ on Mac) → type claude → Enter. This is the workflow I recommend — file tree on the left, Claude Code session below, drag-and-drop folder paths straight into your publish commands.
PowerShell window showing 'claude' being typed at the C:/Users/Allen prompt. The CLI launches with an 'Accessing workspace' banner and a 'Quick safety check: Is this a project you created or one you trust?' prompt with 'Yes, I trust this folder' and 'No, exit' options.
First launch in PowerShell. Claude Code asks you to confirm the working directory before it can read or edit files there — for the publishing workflow, your home folder (or wherever your videos live) is fine to trust.
Google's Antigravity IDE (a VS Code fork) showing the viralspin_new project open with file explorer on the left, an AI chat panel in the middle, and the standard VS Code editor pane on the right. Demonstrates that any VS-Code-family IDE works — open its integrated terminal and run 'claude'.
Any VS-Code-family IDE works — here, Google's Antigravity. Open the integrated terminal (Ctrl+`) and run claude. The IDE's built-in AI assistant (Gemini, in Antigravity's case) and Claude Code coexist — they don't conflict.

The first run will walk you through Anthropic login (this is what created the oauthAccount block in your .claude.json). Subsequent runs drop you straight into the interactive session. That session — with the > prompt — is where slash commands like /mcp, /release-notes, and your publishing commands all live.

Once you're in the session, type /mcp and press Enter. You should see something like this:

Claude Code /mcp panel showing 'User MCPs (C:/Users/Allen/.claude.json)' with viralspin marked connected and 6 tools available, plus other connected MCP servers (Gamma, Google Drive, Vercel) and two needing authentication (Gmail, Google Calendar).
A successful /mcp panel: viralspin · connected · 6 tools under the User MCPs section.

If you see viralspin with a green check and a tool count, you're done with setup. Time to publish.

Optional: poke around the /mcp panel to see what's there

Before leaving the /mcp view, you can drill into the viralspin server to confirm everything looks healthy. Arrow down to viralspin and press Enter — you'll see the server detail card:

Claude Code /mcp viralspin server detail panel. Status: connected (green check). Command: npx. Args: -y @viralspin/mcp. Config location: C:/Users/Allen/.claude.json. Capabilities: tools. Tools: 6 tools. Below are three options: View tools, Reconnect, Disable.
The viralspin server detail card. Useful for sanity-checking the config location, args, and tool count.

Hit Enter on View tools to see what the server exposes:

Tools for viralspin — 6 tools listed: list_connections, publish_now, schedule_post, list_posts, cancel_post, and a sixth tool below the visible area. Navigate with arrow keys, Enter to select, Esc to back.
The six tools the viralspin MCP server exposes. You'll never invoke these by name — Claude does the natural-language → tool mapping for you.

Drill into any tool (e.g. publish_now or schedule_post) to see the exact parameters it accepts:

Tool detail for publish_now. Description: Upload local file(s) and publish immediately to TikTok, Instagram, and/or YouTube. Pass a folder path to publish all images in it as a carousel. Parameters: paths (required, array — local file path(s) or folder path), platforms (required, array), caption (required, string), hashtags (array).
The publish_now tool — what Claude calls when you say "publish ~/videos/clip.mp4 to instagram and tiktok with caption ..."
Tool detail for schedule_post. Description: Upload local file(s) and schedule a post for a future time. Pass a folder path to schedule all images as a carousel. Parameters: paths (required), platforms (required), caption (required), hashtags, scheduled_time (required, ISO 8601 datetime string — uses local timezone if no offset provided), timezone (IANA timezone name, defaults to UTC).
The schedule_post tool — accepts ISO 8601 datetime strings, defaults to your local timezone.

Getting back to the prompt — Esc twice

The /mcp view is read-only inspection — you can't type natural-language commands while it's open. To return to the regular prompt where commands actually run:

  • One Esc dismisses the current sub-menu (e.g. closes a tool detail card)
  • Another Esc dismisses the /mcp panel entirely

Press Esc twice (sometimes three, depending on how deep you've navigated) until you see the bare > cursor with an empty input line. That's where you type publish commands.

The smoke test: confirm the round-trip works

With the /mcp panel dismissed and the cursor back at >, type:

list my scheduled posts
Claude Code interface showing /mcp dialog dismissed, then the user typed 'list my scheduled posts'. Claude is shown 'Calling viralspin...' and then 'Deciphering... (12s, 240 tokens, thought for 4s)'.
Claude recognizes the intent, picks the list_posts tool, and calls the viralspin MCP.

If everything is wired up correctly, you'll get back an empty result (because you haven't scheduled anything yet) — but it'll be an explicit empty result, not an error:

Successful viralspin MCP response: 'You have no scheduled (pending) posts. Want me to also check published, cancelled, or failed posts?' — proving end-to-end auth, MCP transport, and backend round-trip are all working.
Empty list = success. Auth, MCP transport, and backend round-trip all working.

That single round-trip is the proof. Your API key validated, the MCP server hit the backend, the backend queried Supabase, and the response came back. Time to ship a real post.

Restart Claude Code (or run /mcp and watch the viralspin server boot). You should see the server come up in the MCP list. If it doesn't, the most common causes are: stale Node version (need 18+), firewall blocking the backend URL, or a typo in the key.


Step 3 — Organize your content the way the MCP expects

The MCP supports two kinds of posts: single video and image carousel. The folder convention is what the MCP uses to figure out which is which.

Windows file explorer showing the folder E:/AI test/news/01_ai_arms_race_2026 containing five carousel slide PNGs numbered 01_hook through 05_cta, plus an images subfolder
Numbered slide files in a campaign folder — the MCP sorts them in filename order.

Single video: a single .mp4 file. Path it directly.

~/videos/launch-teaser.mp4

Image carousel: a folder containing numbered slide files. The MCP sorts them by filename — that's why you'll see real campaigns named 01_hook.png, 02_profit-problem.png, 03_china-gap.png, 04_your-job.png, 05_cta.png. Two-digit prefixes keep them in order past slide 9.

E:/AI test/news/01_ai_arms_race_2026/
├── 01_hook.png
├── 02_profit-problem.png
├── 03_china-gap.png
├── 04_your-job.png
├── 05_cta.png
└── images/    ignored by the publisher; safe to use as a working folder

A few practical specs:

  • Carousel slide dimensions: 1080 × 1350 (4:5) is the highest-reach Instagram feed slot in 2026. 1080 × 1080 (1:1) still works for both platforms but loses real estate on the IG feed. TikTok image posts accept either.
  • Video specs: MP4, H.264, 1080 × 1920 (9:16) for both platforms. 60s max for Instagram Reels; 10 minutes max for TikTok. The MCP will warn you if your file exceeds limits before consuming credits.
  • Carousel max: 10 slides on Instagram, 35 on TikTok. The MCP enforces the lower limit when publishing to both.
If you generate carousels in another ViralSpin tool (or any external one), drop the finished slides into a folder with the NN_name.png convention before publishing. Past-Allen who didn't number slides spent fifteen minutes hand-renaming during a launch. Don't be past-Allen.

Step 4 — Publish with a single sentence

Open Claude Code. Make sure the viralspin MCP server is connected (/mcp confirms). Then just type what you want to happen.

Publishing a single video to both platforms

publish ~/videos/launch-teaser.mp4 to instagram and tiktok with caption
"The thing nobody told you about AI image repurposing. Full breakdown in bio.
#aitools #marketing #creators"

Claude Code parses the intent, calls the ViralSpin MCP, uploads once, and pushes to both platforms in parallel. You'll see status updates as each post is accepted. Typical end-to-end time: 30–90 seconds depending on file size.

Let Claude write the caption for you

This is the part that makes Claude Code publishing meaningfully better than a web uploader: you don't have to write the caption. Claude will do it — and do it well — if you ask.

A handful of phrasings that all work:

publish C:/path/to/clip.mp4 to tiktok only  write a caption for it
publish C:/path/to/clip.mp4 to instagram and tiktok with a punchy caption
about [what the video is about]
watch C:/path/to/clip.mp4 and write a caption that hooks in the first 5
words, then publish it to tiktok

The third form is the best one, because Claude Code can actually see video content. It'll watch the file, infer the subject and beat, write a caption that matches it, then call publish_now with the caption baked in — all in one turn.

Brief Claude at the level of intent, not copy:

publish E:/AI test/news/01_ai_arms_race_2026/ to instagram. Write a caption
that:
- opens with a contrarian hook
- mentions OpenAI, Anthropic, and the China gap
- ends with "save this for later 👀"
- includes 3-5 hashtags

Claude assembles the caption to spec, then publishes. You're editing at the level of brief, not at the level of every word.

The voice-matched, fully autonomous version:

publish all videos in ~/this-weeks-batch/ to tiktok. For each one, watch the
file, write a caption in my voice (study my last 10 captions on @aitechproduct
first), and schedule them one per day starting tomorrow at 9am pacific.

One sentence: pull last 10 captions via list_posts, study the voice, watch each video, write voice-matched captions, schedule each, confirm the queue. The constraint is no longer the tooling — it's how clearly you describe what you want.

The one rule: if you want Claude to write the caption, say so explicitly. The caption parameter on publish_now is required, so a bare publish ~/clip.mp4 to tiktok with no caption guidance and no instruction to write one will sometimes cause Claude to pause and ask. Phrases like "write a caption", "with a caption about X", or "with a caption that does Y" tell Claude to fill it in itself.

Publishing a carousel

publish E:/AI test/news/01_ai_arms_race_2026/ to instagram with caption
"Billions spent. Nobody ahead. Five slides on the AI arms race nobody is
actually winning. Save for later — link in bio." and hashtags
"#ai #openai #anthropic #tech #creators #marketing"

The MCP detects the folder, sorts the slides, validates each file, and submits the carousel post. Instagram carousels arrive as a single multi-image post; TikTok photo posts handle them natively as well.

Specifying just one platform

publish ~/videos/clip.mp4 to tiktok only with caption "Day 27 of building in public"

Or:

post the carousel in ./day_38_avatar/ to instagram with caption "..." and pin
the first comment "Save this 👉"

The MCP supports first-comment pinning on Instagram, which is the standard way to tuck the long hashtag list out of the visible caption.


Step 5 — Scheduling for later

Scheduling is the same command structure with a time appended. Natural language works — the MCP parses dates and times against your local timezone.

schedule E:/AI test/news/01_ai_arms_race_2026/ to instagram and tiktok
tomorrow at 9am with caption "..."
schedule ~/videos/launch-teaser.mp4 to instagram next monday at 6pm pacific
with caption "Launch is live. Link in bio."
schedule the contents of ~/campaign/q2-rollout/ to instagram every weekday
at 9am for the next two weeks

The third form — recurring posting from a folder — is the one that pays back the setup time fastest. Drop ten carousels into a folder, fire one scheduling command, and the queue is built. Each post burns the per-post credit at publish time, not at schedule time, so you can rearrange or cancel anything in the queue without penalty.

Reviewing and editing the queue

From Claude Code:

list my scheduled posts

The MCP returns the queue as a structured list with post IDs, target platforms, scheduled times, and a preview of each caption. To change one:

reschedule post sp_abc123 to friday at 2pm
cancel post sp_abc123
update caption on post sp_abc123 to "..."

The queue is also visible in the browser at viralspin.ai/publish under the Scheduled tab if you want a visual view. Both surfaces edit the same underlying queue.


Step 6 — Captions, hashtags, and platform-aware formatting

Both platforms have different caption norms. The MCP can apply platform-specific formatting if you ask for it.

publish ~/videos/clip.mp4 to instagram and tiktok with platform-specific captions:
instagram: "The full breakdown is in the carousel above. Save this for later 👇
Comment 'GUIDE' and I'll DM you the PDF."
tiktok: "wait for slide 4 😳 #ai #creators"

If you give a single caption, the MCP uses it on both platforms. If you split them, each platform gets its native voice — short, punchy, comment-bait on TikTok; longer, value-led on Instagram. That's the formula most professional creators settle on after a month of testing.

Hashtag handling:

  • Instagram: put them in the caption or, better, in a pinned first comment. The MCP can do either: ... and pin first comment "<hashtags>".
  • TikTok: inline in the caption is standard. 3–5 hashtags is the current sweet spot.

Mentions: prefix with @. The MCP resolves them via each platform's API and will warn you if a handle doesn't exist before publishing.


Step 7 — The music question (and why your phone still matters)

This is the part that catches most creators off guard, so we'll be direct.

Both Instagram and TikTok reserve their commercial music libraries — the trending sounds with full licensing — for the mobile app only. API publishing (which is what every web uploader, every scheduler, and the ViralSpin MCP all use under the hood) cannot attach a track from either platform's licensed library. This is a licensing decision Meta and ByteDance made, not a tooling limitation. Every third-party publishing tool faces the same constraint — Buffer, Hootsuite, Later, Blotato, Publer, all of them.

What this means in practice:

  • You can publish from Claude Code with audio that's already part of your file. Voiceover baked into the MP4, royalty-free music you've embedded, original audio — all fine. The MCP uploads the file as-is and the audio plays.
  • You cannot, from any API, attach the Reels trending audio "drift away by Aretha Franklin" or the TikTok "of course, of course." That's a mobile-app-only privilege.

What ViralSpin's draft mode actually supports

The MCP supports a send_to_drafts tool that sends posts to platforms' draft surfaces where the platform's API exposes one:

Platform Draft via API? What "draft" means
TikTok ✅ Yes File lands in your TikTok inbox / drafts. Finish in the mobile app (add music, edit caption, publish).
YouTube ✅ Yes Video uploads as private. Publish from YouTube Studio or the mobile app whenever ready.
Instagram ❌ No Meta's Content Publishing API has no draft endpoint. IG drafts are stored locally on your phone only — no third-party tool can put a post into IG drafts.

So:

send ~/videos/clip.mp4 to my tiktok drafts with caption "..." i'll add music in the app

…works. Open TikTok mobile → tap the inbox → finish the post with trending audio → publish.

send ~/videos/clip.mp4 to my instagram drafts ...

…does not work. There's no Instagram drafts API. The MCP will return a clear error if you include instagram in a draft command.

The Instagram music workaround

For Instagram posts that need trending audio, the workflow is one step longer:

  1. Use Claude Code to generate, caption, and prepare the asset
  2. Get the file onto your phone (AirDrop, Google Drive sync, iCloud sync, or email it to yourself)
  3. Open Instagram → tap + → pick the file from Camera Roll → add audio from IG's library → publish

This isn't ViralSpin-specific; it's the only viable path on Instagram for any creator using any third-party tool. The MCP can prepare the file end-to-end, but the final upload-with-music step happens in the IG app.

Coming soon: a send_to_phone tool that uploads the file to a short-URL pickup page (viralspin.ai/p/<token>) with a QR code printed in your terminal. You scan, tap "Save to Camera Roll," and the file appears on your phone in one tap — ready for the IG-with-music workflow above. We're building it now because this is the highest-friction step.

The hybrid workflow that actually works today

For posts that don't need licensed music, the pure Claude Code flow is end-to-end:

publish ~/videos/clip.mp4 to instagram and tiktok with caption "..."

For posts that need a TikTok trending sound, the TikTok-drafts flow:

send ~/videos/clip.mp4 to my tiktok drafts with caption "..." i'll add music in the app

For posts that need an Instagram trending sound, the manual-handoff flow:

prepare ~/videos/clip.mp4 with caption "..." and save it to my downloads
folder  i'll AirDrop to phone and post from instagram with music

Claude writes the caption, you AirDrop, IG handles the rest. Most pro creators we work with use the right flow per post.


Step 8 — Putting it all together: the weekly ritual

The workflow that ten of our heaviest-publishing creators converged on, more or less independently:

Monday — Plan. In Claude Code, brainstorm the week's posts. Whatever your idea-generation flow looks like, end it with the assets in a clearly-named folder per post.

~/posts/2026-05-week-21/
├── monday_carousel/
├── tuesday_video.mp4
├── wednesday_carousel/
├── thursday_video.mp4
└── friday_drafts_for_music/

Tuesday — Schedule the music-free posts. One command per post, scheduled across the week:

schedule ~/posts/2026-05-week-21/monday_carousel/ to instagram and tiktok
monday at 9am with caption "..."

Repeat for Tue, Wed, Thu.

Friday morning — Music drafts. Push TikTok drafts via the MCP, IG-bound files to your phone:

send all videos in ~/posts/2026-05-week-21/friday_drafts_for_music/tiktok/
to my tiktok drafts with captions from drafts.yaml

prepare all videos in ~/posts/2026-05-week-21/friday_drafts_for_music/instagram/
into ~/Downloads/this-week-ig/ with captions  i'll AirDrop and finish in IG

Open TikTok → finish each draft with a trending sound. AirDrop the IG batch → finish each one in the IG app with audio.

Sunday — Review.

show me last week's performance across instagram and tiktok

The MCP pulls views, likes, shares, saves, comments, and follower deltas back into Claude Code. Whatever your AI workflow does next — extract winning hooks, draft next week's plan, brief a designer — happens with that data already in the context window.


Troubleshooting

The MCP server doesn't appear in Claude Code. Run /mcp and check the status line. If it's "failed," check the logs (~/.claude/logs/) for the npx invocation. Most common: stale Node (need 18+), or the JSON in ~/.claude.json has a syntax error somewhere else that broke parsing.

"403 Forbidden" when publishing. Your API key may have been revoked, or your TikTok/Instagram connection expired. Re-check both at viralspin.ai/settings and viralspin.ai/publish.

Carousel slides come out in the wrong order. The MCP sorts by filename. If your files are slide1.png, slide2.png, ... slide10.png, slide 10 will sort before slide 2. Always use zero-padded two-digit prefixes (01_, 02_, ...).

"Caption too long" warning. Instagram allows 2,200 characters in a caption. TikTok now allows ~4,000. If you're writing for both and want platform-tuned lengths, use the platform-specific-captions form from Step 6.

Scheduled post didn't publish. Open viralspin.ai/publish → Failed tab. The most common reasons are token expiration (re-connect at /publish) and platform-side spam filtering (rare; usually resolved by re-running the post 15 minutes later).


What you get back

Claude Code + ViralSpin MCP collapses what used to be "open three apps, log in to each, upload, type captions, screenshot for the queue" into one sentence. The economic argument is real — most creators we work with reclaim 4–8 hours per week from publishing alone — but the better argument is that posting stops being a context switch. You stay in the workspace where your ideas live, and shipping is a sentence away.

The setup is fifteen minutes one time. The workflow is one command per post. The only thing that still needs your phone is licensed music, and that's a platform constraint everyone shares.

If you publish more than three times a week to either platform, this pays for itself in week one.


Quick reference

Connect accounts: viralspin.ai/publish Generate MCP API key: viralspin.ai/settings Visual queue view: viralspin.ai/publish → Scheduled

Claude Desktop / claude.ai connector URL:

https://mcp.viralspin.ai/mcp?key=YOUR_API_KEY

Useful commands in Claude Desktop (URL-based — upload to viralspin.ai/publish first to get a URL):

list my connected social platforms
publish <url> to instagram and tiktok with caption "..."
schedule <url> to instagram tomorrow at 9am with caption "..."
send <url> to my tiktok drafts with caption "..."
list my scheduled posts
cancel post <id>

Useful commands in Claude Code (file-path-based — local files supported):

publish <file-or-folder> to instagram and tiktok with caption "..."
schedule <file-or-folder> to instagram tomorrow at 9am with caption "..."
send <file-or-folder> to my tiktok drafts with caption "..."   # IG drafts not API-supported
prepare <file-or-folder> with caption "..." into ~/Downloads/   # for AirDrop → IG-with-music
list my scheduled posts
reschedule post <id> to <time>
cancel post <id>
update caption on post <id> to "..."
show me last week's performance across instagram and tiktok