Skip to main content
These are the tools exposed by the VibeFlow MCP server. They’re available to any MCP-compatible client connected via Connect your agent. Read-only tools carry MCP readOnlyHint annotations, so clients like Claude run them without per-call confirmation; outward-facing tools (schedule_post, publish_post) always prompt.

Guides (call these first)

get_content_guide

Returns the content-operator workflow: the post lifecycle, the platform-first rule, writing in the user’s voice or a voice persona, the X, Instagram and TikTok rules, LinkedIn polls, gap tracking, review comments, the visual paths (photos, canvas graphics, and Video Lab videos), and the schedule/publish confirmation contract. No arguments. Call once per session before creating or editing posts.

get_canvas_guide

Returns the canvas workflow — how to brief the design agent, review frames, and deliver graphics. No arguments. Call once before creating graphics.

Workspace

list_organizations

Lists the workspaces your account belongs to. Every content tool takes one of these ids as organization_id. No arguments.

get_workspace_context

Loads the workspace’s content context in one call. Returns { business_context, memories, viral_formats: { linkedin, x }, platforms, capabilities: { instagram, tiktok, x_articles }, agent_canvas_id }. platforms lists where the workspace can post: always linkedin and x, plus instagram and tiktok when they’re enabled for the workspace. capabilities.x_articles is true when the workspace can write X Articles with create_x_article. agent_canvas_id is the canvas where designed post graphics live; use it for create_canvas_frame and set_post_graphic.

list_post_options

Lists the workspace’s publishing options: platforms, connected social accounts, and saved voice personas. Accounts resolve automatically when omitted from create_post, so this is only needed when the user names a specific account (“post as the company page”) or wants to write like someone else. Returns { platforms, accounts: [{ platform, integration_id, author_urn, label, kind }], voices: [{ voice_persona_id, name, platform, handle }] }.

Voice

Every post should be written in the voice from get_voice: the learned voice of whoever is posting, or a saved voice persona when the user wants to write like someone else.

get_voice

Loads the voice to write in. Call it before drafting. By default it returns the voice of the person or page posting for this user. Pass accounts when posting as a specific account so the voice matches that identity, or voice_persona_id to write like someone else. Returns { voice_kind, voice: { guides, patterns, example_posts }, workspace_voice, how_to_use, platforms, x_char_limit }, plus writing_as (the posting identity) or persona (the voice persona). example_posts holds up to 5 real posts to mirror for rhythm, length, openings and vocabulary; agents should never copy their sentences or claims. When the identity has no learned voice yet, how_to_use says so and the workspace brand voice applies.

learn_voice_persona

Learns how another person or brand writes from their public posts and saves it to the workspace voice library, so drafts can be written like them. Check list_post_options first: a persona that’s already saved only needs get_voice. Learning runs in the background and takes about a minute. Returns { voice_persona_id, name, platform, status: "learning", next_steps }. Call get_voice with the voice_persona_id; until learning finishes it returns a “still learning” message.
A persona is inspiration for the drafts the user asked for, never the user’s own voice. Facts still come from the workspace, not from the persona’s posts.

Posts

create_post

Creates a post as a draft: one post with one variant per platform, each carrying real copy written for that platform. Never publishes or schedules. The platform choice belongs to the user, so agents shouldn’t add platforms nobody asked for. Each variant: Returns { post_id, post_url, variants: [{ variant_id, platform, photo_suggestion? }], status: "draft", missing_info? }. post_url opens the draft in the VibeFlow studio. X copy is weighted-counted server-side (URLs 23 chars, emoji 2) against the connected account’s limit: 280, or 25k with X Premium. A too-long tweet fails the whole call with a clear message; shorten and retry.

Platform rules

TikTok posts also need a privacy level and compliance settings (comments, duet, stitch, commercial disclosure, AI-generated label) that only the user can choose, in the studio’s TikTok tab. schedule_post and publish_post refuse a TikTok variant until they’re set.

LinkedIn polls

Pass linkedin_poll on a LinkedIn variant to publish it as a native poll. The variant’s text is the body above the poll; don’t repeat the options in it. A poll post is text only (no photos or graphics, so no photo gap), and the poll locks once the post is live. Polls exist only on LinkedIn.

create_x_article

Creates a long-form X Article as a draft. Never publishes or schedules. Only works on workspaces where get_workspace_context reports capabilities.x_articles: true; elsewhere the call fails. Use it when the user asks for an article, not as an extra next to a regular X post. Returns { post_id, post_url, variant_id, platform: "x_article", article_title, status: "draft", photo_suggestion?, missing_info? }. The cover is the variant’s first visual: attach it with set_post_photos or set_post_graphic (X recommends 5:2; video isn’t supported). Inline images need hosted urls, so upload local files with request_upload_url first. Tweet character limits don’t apply. Edit the headline or body with update_post_variant (article_title, text), and schedule or publish with platforms: ["x_article"].

list_posts

Lists the workspace’s posts, newest first, with per-variant platform, lifecycle, schedule time, and whether a visual and connected account are set.

get_post

Reads one post in full: per-variant copy, visual_urls (photos), frame_ids (canvas graphics), media_layout, photo_suggestion, linkedin_poll, schedule state, missing_info gaps, and the post_url that opens it in the studio. Always call before editing, attaching visuals, scheduling, or publishing.

update_post_variant

Edits one variant of a draft or scheduled post: its copy, its photo_suggestion, its LinkedIn poll, or whether it’s enabled. Character limits are enforced server-side, and a too-long edit fails as a whole. Published variants only accept text edits. Visuals go through the two set_post_* tools instead. Send at least one change per call.

classify_posts

Labels posts with a content-strategy bucket (get-noticed, build-trust, selling, or customer), the labels shown on the workspace’s Drafts board. Omit assignments to auto-classify every unlabeled post in one batch; posts that already have a label are never touched. Returns { mode: "auto", classified, assignments, has_more } when auto-classifying (call again while has_more is true), or { mode: "explicit", updated, skipped } for explicit labels.

flag_post_gaps

Updates what an existing post still needs from the user, shown as an alert banner on the draft in the studio. New posts declare their gaps on create_post instead. Kinds: photo, data, other. Replace semantics: gaps becomes the post’s full open list; an empty array clears it. Photos attached via set_post_photos clear photo gaps automatically.

Review comments

Posts carry the same review comment threads teammates leave in the VibeFlow studio. Your agent can read them, leave its own feedback, reply, and resolve threads once the change is made. Comments never change the copy: edits go through update_post_variant.

get_post_comments

Reads the open review threads on a post. Each thread has a thread_id, its messages oldest first, and an optional anchor pointing at a passage of one variant’s copy. No anchor means the comment is about the whole post. Returns { post_id, post_url, open_threads: [{ thread_id, anchor?: { variant_id, platform, quoted_text, quote_still_in_copy }, messages: [{ author, from_vibeflow_staff, body, created_at }] }] }. quote_still_in_copy: false means the copy was rewritten after the comment, so it may be stale.

comment_on_post

Leaves feedback on a post as a review comment. Comments are posted under the connected user’s name and the whole workspace sees them. Three shapes:
  • body alone comments on the whole post.
  • body + variant_id + quoted_text anchors the comment to that exact passage, highlighted in the studio. quoted_text must be a verbatim substring of the variant’s copy as get_post returns it.
  • body + thread_id replies to an existing thread, and reopens it if it was resolved.
Returns { post_id, thread_id, is_reply, anchored }.

resolve_post_comments

Marks review threads as resolved. Call it after the change a thread asked for is saved, and only for the threads actually handled. Questions, discussions, and threads that need the user’s input stay open. Returns { post_id, resolved, not_found }.

Visuals

Three separate paths: real photos and videos (list_workspace_photos or request_upload_url → set_post_photos), designed canvas graphics (create_canvas_frame → set_post_graphic), and videos made by the Video Lab agent (create_video → set_post_photos with the render url, see Video). The last one applied wins.

list_workspace_photos

Lists the workspace photo library (the Assets page in VibeFlow), newest first: each photo or video’s url, name, kind, and a caption describing what it shows. When a library photo fits a post, attach its url with set_post_photos. Returns { photos: [{ url, name, kind, caption? }], total }. kind is image or video.

request_upload_url

Returns a short-lived signed URL to upload one photo or video into the workspace. HTTP PUT the raw bytes to upload_url with exactly the returned headers (Content-Type and Content-Length are part of the signature). After the PUT, public_url is the file’s permanent address. Returns { upload_url, method: "PUT", headers, key, public_url, expires_in_seconds }. The URL expires in 10 minutes; one call per file.

set_post_photos

Attaches real photos or videos to a post as its published visuals. Each url can be:
  • a photo from list_workspace_photos,
  • any public image or video link (downloaded and stored in the workspace),
  • a public_url from request_upload_url, after the file was PUT.
Urls that can’t be used come back in skipped_urls with the reason. A photo pasted into the chat has no url: the user can drop it on the draft in the studio (post_url) or add it on the Assets page. Replaces designed canvas visuals if the post had them, and clears open photo gaps. Returns { post_id, variants: [{ variant_id, platform, image_urls, replaced_canvas_visuals }], skipped_urls, remaining_gaps }.

set_post_graphic

Attaches designed canvas frames to a post. Exports the frames to PNG fresh on every call — re-call after a graphic is edited. canvas_id defaults to the workspace’s agent canvas.

Video

The Video Lab agent makes and edits videos: cutting and captioning footage, shorts, titles, motion graphics, music, and voiceover. These tools only work when Video Lab is enabled for the workspace; otherwise they return an error.

create_video

Starts an asynchronous agent job from a natural-language brief. Without project_id it creates a new Video Lab project, which counts toward the workspace’s video allowance. Pass the project_id of an earlier run to iterate on that video (“make the captions bigger”) instead of starting over. Consumes credits. Returns { job_id, status: "queued", project_id, new_project, next_steps } immediately. One run per project at a time: a call on a project that’s still working returns an error naming the running job_id.

get_video_creation

Polls a job started by create_video. Each call waits up to 20 seconds for progress. Keep polling until status is completed or failed; a run usually takes a few minutes. Returns { job_id, status, project_id, video_lab_url, final_text, failed_reason, renders: [{ render_id, kind, status, url, duration_seconds, poster_url }], running_jobs }. status is queued, running, completed, or failed, and kind is final, preview, or harness. Put a finished render on a post with set_post_photos.

list_video_projects

Lists the workspace’s Video Lab projects, newest first, with each one’s latest finished render. Use it to find the project_id to continue with create_video. Returns { projects: [{ project_id, name, width, height, for_post_id?, video_lab_url, latest_render: { render_id, kind, url, duration_seconds, poster_url } | null, created_at, updated_at }] }.

Publishing

schedule_post

Schedules a post for delivery at a specific time. Only after the user explicitly confirmed the exact post and time: the tool refuses without user_confirmed: true. Variants that are already live are never re-sent. Returns { post_id, post_url, title, variant_ids, scheduled_at, timezone }.

publish_post

Publishes a post right now (delivery starts within seconds). Same confirmation contract as schedule_post.
“Post the LinkedIn version now, X tomorrow morning”: publish_post with platforms: ["linkedin"], then schedule_post with platforms: ["x"].

unschedule_post

Cancels a scheduled delivery — the post returns to drafts. Safe and reversible.

Analytics

Read-only views over the workspace’s indexed social history (built by Index history in the app’s Analytics page) and its tracked competitors. Competitors are added and removed in the app.

get_content_analytics

Aggregated performance of the workspace’s indexed posts.

get_top_posts

The workspace’s real best-performing indexed posts — copy, engagement, category, media type, image urls — optionally filtered by category or media_type (image, video, carousel, document, poll, text). Takes organization_id, optional platform (linkedin, x, or instagram), and limit (1–20).

list_competitors

Lists tracked competitor companies and creators with company ids, enrichment state, and indexing progress. Takes organization_id. Resolve ids here before the two tools below.

get_competitor_analysis

Head-to-head comparison vs tracked competitors: share of voice, engagement share, monthly trend, category mix, frequency, authors, follower counts. Takes organization_id, optional competitor_company_id (self-vs-one; omit for aggregate), range_months, include_reposts.

get_competitor_evidence

Bounded evidence for one competitor: strategic profile, top posts, topics, formats, engagement. Takes organization_id, competitor_company_id, optional limit (1–15).

Performance and audience

The app’s Performance > Posts table and Audience Intelligence page. Read-only, and for business accounts only.

list_post_performance

Every published post for the connected accounts with impressions, likes, comments, shares, engagement, and engagement rate, plus window totals. Answers “how did my posts do this month” or “which post got the most impressions”. Returns { platform, window, total, offset, has_more, stats, accounts, posts: [{ text, url, published_date, account, impressions, likes, comments, shares, engagement, engagement_rate }] }.

get_follower_growth

Follower history per connected account: start and latest counts, net change, and a daily series. On LinkedIn it also returns the posts published in the window, so follower jumps can be lined up with specific posts. Returns { platform, window, accounts: [{ account, start, latest, change, change_pct, points }], posts_in_window? }.

get_audience_overview

Who engages with the workspace’s posts: total engagers, relevance split, engagement types, seniority, company sizes, follower bands, countries, industries, top companies and job titles, and repeat engagers. Also lists the tracked account names the other audience tools take as account.

search_engagers

Searches the people who liked, commented on, or reposted the workspace’s posts, with their enriched profile (company, title, industry, followers, location) and relevance verdicts. Pass post to list who engaged with one post, plus that post’s audience counts. Returns { platform, total, offset, has_more, post?, post_audience?, engagers: [{ engager_id, name, headline, company, job_title, followers, location, engagement_type, last_comment, account_relevance, person_relevance, relevance_why }] }.

get_engager

One engager’s full profile (about, company description, HQ, funding, role tenure, relevance reasoning) and every post they reacted to or commented on, newest first, with their comment text.

ask_audience

Answers a natural-language question about the engagers, engagements, and tracked posts (the Audience page’s Ask AI), for joins and counts the filters can’t express: “which VPs at fintech companies commented more than twice”. Unavailable while profiles are still being enriched. For simple filters, search_engagers and get_audience_overview are faster. Returns { platform, title, count, rows, truncated?, sql }: up to 50 answer rows and the read-only SQL that produced them.

Radar

The app’s Radar page: what’s moving on the topics the workspace watches, and in its space. Radar has three feeds: The feeds fill on their own schedules, so there’s nothing to trigger. search_radar is the instant path: it scans any topic right now. Radar tools are for business accounts only.

get_radar

The starting point for any Radar question: the watched topics, the topic limit, whether Trending on X is on, and which feeds are switched on, with their counts and last and next run. Returns { topics: [{ topic_id, topic, focus?, sources, subreddits?, cadence, enabled }], topic_limit, trending_on_x, for_you: { enabled, platforms, last_run_at, next_run_at, new_trends, posted_trends }, timeline: { enabled, platforms, last_run_at, next_run_at, new_posts, engaged_posts } }. A feed that’s off comes back as { enabled: false }.

list_radar_signals

The Your topics feed, newest first. Each signal has a summary, why it’s notable, a 0–100 relevance score for the business, and the angle to take. Returns { count, has_more, signals: [{ signal_id, topic_id, topic, source, title, url, summary, why_notable, relevance, angle, author, engagement, published_at, found_at, saved, idea_card_id? }] }. idea_card_id is set when Radar already turned the signal into an idea card.
To turn a signal into a post, write it in the user’s voice (get_voice) from what the signal actually says, then call create_post.

The For you feed: trends picked for the business, each with a summary, why it fits, a post angle, a suggested format, momentum, a 0–100 fit score, and up to 3 real posts as evidence. Returns { enabled, status, count, trends: [{ trend_id, platform, label, summary, why_for_you, angle, suggested_format, momentum, score, evidence: [{ url, author, text, engagement, posted_at }], found_at, status, used_post_id? }] }. When For you is off for the workspace, it returns enabled: false with a message.

list_radar_timeline

The Timeline feed: recent LinkedIn and X posts worth engaging with. Each one comes with why to engage, a drafted comment and quote post (one per connected account when there are several), its metrics, a digest of its comments, and anything already done on it. Posts from the watch list come first. Read-only: commenting, liking, and reposting happen in the app. Returns { enabled, status, count, posts: [{ timeline_post_id, platform, url, author, text, published_at, metrics, score, why_engage, suggested_comment, suggested_quote, drafts_by_account?, can_repost, watch?, comments?, your_engagement?, found_at, status }] }. When Timeline is off for the workspace, it returns enabled: false with a message.

search_radar

Scans a topic right now across web and news, LinkedIn, Hacker News, X, and Reddit, without waiting for a scheduled sweep. Results are raw: not saved to Radar and not scored for the business. Takes up to about a minute. Returns { topic, focus?, sources, count, items: [{ source, title, url, summary, author, engagement, published_at }] }, up to 24 items.

watch_radar_topic

Adds a topic to the workspace’s Radar so it keeps getting swept, and its strongest finds land in list_radar_signals and the chat bot digests. A workspace watches at most 5 topics. A topic it already watches comes back with already_watching: true. Returns { topic_id, topic, already_watching, note }. The first sweep is queued right away.

update_radar_topic

Pauses or resumes a watched topic, or changes its focus, sources, subreddits, or cadence. Pass only what changes: an empty focus clears it, and subreddits: [] means all of Reddit. Paused topics keep their signals. Returns { updated: true, topic }.

remove_radar_topic

Stops watching a topic and deletes the signals it collected. To keep the signals, pause the topic with update_radar_topic instead. Returns { removed: true, topic }.

Memory

remember

Saves a durable user preference for the workspace’s content (voice, wording, topics). Comes back via get_workspace_context. Takes organization_id, text, optional kind (style / wording / fact), importance (1–5), and supersedes_id.

forget

Deletes a saved preference by memory_id. Takes organization_id and memory_id.

Canvas (graphics engine)

list_canvases

Lists your canvases, most recent first. Paginated. Returns { canvases: [{ canvas_id, name, organization_id, preview_image_url, created_at, updated_at }], next_cursor, is_done }.

create_canvas

Creates a new canvas.

get_canvas

Returns one canvas’s metadata. Takes canvas_id.

list_canvas_frames

Lists every frame on a canvas (metadata, no HTML). Takes canvas_id, optional cursor and limit.

get_canvas_frame_code

Returns the raw HTML of one frame. Takes canvas_id and frame_id.

screenshot_canvas_frames

Renders 1–4 frames to images so the agent can see the actual result, not just its HTML. Takes canvas_id and frame_ids; returns the screenshots as inline images.

create_canvas_frame

Starts an asynchronous agent job: the VibeFlow design agent reads your natural-language brief, plans the frames, authors the HTML, and may create several frames in one run. Consumes credits. Also the edit path — brief it again on the same canvas, naming the frames to change. Returns { job_id } immediately.

get_canvas_frame_creation

Polls an agent job started by create_canvas_frame. Takes job_id; returns the job status (queued / running / completed / failed) and, once completed, the created_frames (frame_id, name, width, height), the agent’s final_text, and its credit usage.

Canvas exports

export_canvas

Starts an export job for a canvas. Takes canvas_id, format (png, jpg, pdf, pptx, or all), optional frame_ids. Returns { job_id }.

get_canvas_export

Polls an export job. Takes job_id; returns the status and, once completed, one result per format with its download_url, filename, mime_type, and size_bytes.

Auth + errors

Every tool requires auth — OAuth (default) or an API key bearer header; see the overview. Errors come back as actionable messages, not bare status codes: an over-limit X post explains the weighted count, a photo url that can’t be attached comes back with the reason, a TikTok post without its studio settings says where to set them, and an empty balance returns an “insufficient credits” message instead of running. The performance, audience, and Radar tools need a VibeFlow business account, and the video tools need Video Lab enabled for the workspace; otherwise they return a message saying so.

Next

Connect your agent

Claude, Claude Code, Cursor, Codex, OpenClaw, Hermes — step by step.

Credits

What each tool costs.