One URL. Every agent you already talk to.
vibedraft runs as an MCP connector. Your own agent does the drafting, on your own subscription. vibedraft supplies the voice profile, the live signals, the queue, the scheduling and the metrics. It holds every post until you say yes.
https://vibedraft.app/api/mcpThe same URL in all four clients. Each one opens a vibedraft consent screen the first time; approving it issues a token scoped to your account, and you can revoke it from Settings at any time.
Claude Code
The terminal. One command, then one browser tab.
claude mcp add --transport http vibedraft https://vibedraft.app/api/mcpclaude/mcp/mcp finishes the OAuth handshake in your browser and shows vibedraft as connected. Add --scope user to the first command to make the connector available in every project instead of the current one.
Claude
claude.ai and the Claude desktop app. Custom connectors need a Pro or Max plan.
https://vibedraft.app/api/mcpThe desktop app and claude.ai read the same connector list, so adding it in one adds it in both. Revoke it from Settings at any time.
Codex
The Codex CLI and the Codex IDE extension.
[mcp_servers.vibedraft]
url = "https://vibedraft.app/api/mcp"
auth = "oauth"codex mcp login vibedraftA remote server goes in the config file rather than through codex mcp add, which takes a launch command for a local process. auth = "oauth" is what makes Codex open the sign-in instead of reporting a failed connection. In the Codex IDE extension, the same server is added from the gear menu under MCP servers → Add server.
ChatGPT
The ChatGPT desktop app, on a plan that allows custom MCP servers.
https://vibedraft.app/api/mcpvibedraft.~20 secChatGPT on the web reaches custom MCP servers only through developer mode, and what a server is allowed to expose there is narrower than in the desktop app. The desktop app is the path to use today.
Cron jobs skip OAuth.
For anything that runs without a browser, take a personal access token from Settings and call the REST API directly.
curl https://vibedraft.app/api/v1/scheduled-posts \
-H "Authorization: Bearer vd_pat_..."Tell it what happened.
Marketing events are things that happened to your product: a milestone crossed, a feature shipped, a customer won or churned, a theme in support. Record them as they happen and vibedraft has something real to write from later. Nothing posts, nothing is scheduled, and no credits are spent.
mark that we crossed 100 paying userscurl -X POST https://vibedraft.app/api/v1/events \
-H "Authorization: Bearer vd_pat_..." \
-H "Content-Type: application/json" \
-d '{"type":"feature.shipped","ref_id":"dark-mode","title":"Dark mode is live"}'title is required on these event types and body is optional. Write the title in plain words a stranger could read, “We crossed 100 paying users” rather than “milestone-100”. It is the only text later stages have to work with, so an event without it cannot be judged worth posting, cannot be checked against the topics you never want posted about, and cannot be read by you when vibedraft asks.
Types: milestone.crossed, feature.shipped, customer.won, customer.churned, support.theme.
ref_id is a stable id for the thing itself, so the same event recorded twice is recognisable.
What your agent can do.
A plain post costs 1 credit; a post containing a URL costs 13. Reading metrics is free.
get_onboarding_stateWhether your login can use VibeDraft yet and the one next thing to do about it — a tool to call, or a link to open when the step needs a browser.
start_intakeBegin or resume the onboarding interview. Returns the next thing to find out and how to ask it.
answer_intakeRecord what you said, in your own words, and get the next prompt, or that the interview is complete.
restart_intakeRun the interview again when something about you has changed. Your old answers stay as history; the questions get asked fresh.
get_intake_statusWhere the interview stands, and your 7-day activation plan once it's complete.
get_account_contextEverything VibeDraft knows about you and your business, as one block, plus the few things most worth learning next and why each matters.
capture_contextRecord things that came up in conversation: a fact, a number with its date, a preference, a correction, something a customer said. Vague values are sent back with what would make them specific.
import_contextPaste the memory another assistant kept about you (Claude, ChatGPT) and VibeDraft files what is durable under the right slots, marked imported, and proposes any goals it states.
note_turnHand VibeDraft what you just said, verbatim. It keeps the facts, numbers, preferences and corrections worth keeping, proposes any goal you stated, and tells the agent what it kept so you can undo it.
search_journalSearch everything you have said to any connected assistant or in Compose, kept whole with its date. The record under the memory summary: what you said about pricing, when you started something, what you decided.
confirm_contextMark lines the agent believed about you as confirmed, once you have agreed.
forget_contextRetire a line about you. Kept as history, no longer read.
list_accountsEvery account this login drives — X handles, Instagram and TikTok accounts — with id, channel, status and which one this connector is acting as.
switch_accountPoint this connector at a different account on either channel. Saved per connector, so your other clients are unaffected.
get_voice_contextYour voice, resolved for the active account's channel and format: profile, brand layer, channel conventions and limits, hard rules, drafting rules, and what is still missing. Can also carry what you said this chat.
update_voice_profileRewrite your voice profile from chat. Full replace, versioned, and free — the same document /voice edits. A document that omits sections you already have is rejected rather than applied.
get_signalsActive signal briefs: what's moving right now in your niches.
list_bookmark_foldersYour X bookmark folders, with the id analyze_bookmark_folder takes.
list_bookmarksEverything you have bookmarked on X, newest first, with each post's author, metrics, folders and link. Free in credits; a tenth of a cent per bookmark on X, once a day.
analyze_bookmark_folderRead a bookmark folder of posts you admire and get the evidence for why each did well and what they share: metrics, each post's multiple over its author's normal, what it quoted or answered, the replies under it on request, its trajectory over time, and the folder's structural features against a control group of tracked creators. Free in credits; posts are read from X once (about half a cent each), stored, and re-read daily while young.
get_goalThe handle's goal archetype, and whether a human has confirmed it. The archetype selects the ranker's weight vector.
set_goalSet the goal by picking an archetype or by classifying the user's own words.
confirm_goalRecord that the user agreed with a classified archetype.
add_objectiveRecord an account-wide goal in the user's words (e.g. more people trying vibedraft). Every agent reads these as context; the reply judge weighs posts against them.
create_short_linkMake a tracked short link (vibedraft.app/l/<slug>) for one place on X: clicks, the signups they become and the paid checkouts after are attributed to it.
get_link_reportEvery tracked link with clicks, visitors, signups and paid revenue, so the next link goes where the last one worked.
archive_objectiveRetire one account goal by id. Kept, not deleted.
list_tracked_handlesThe accounts Radar listens to for the active handle, whether each follows the handle back, and what tracking does and costs.
track_handleAdd an X account to the list Radar reads new posts from (about half a cent a post, a few cents a month). Nothing changes on X.
untrack_handleStop reading an account's posts. Posts already read stay.
get_engage_queueWho to reply to right now, ranked, with the reason each card ranked. Writes: every card returned is logged with the probability it was shown at.
record_engage_decisionRecord that a queue card was replied to or skipped. A skip is a training signal, not a discard.
take_planClaim a queue card's plan before drafting, so two agents never answer the same post.
get_daily_packVoice + signals + upcoming schedule as one bundle, so a session can start with a single call. Can also carry what you said this chat, so it is remembered.
get_pricingCredit costs, available plans, and your current balance.
get_post_metricsImpressions, likes, replies and bookmarks for posts you've published.
search_my_postsSearch your own published posts by keyword, so a draft does not repeat something you already said.
search_trending_postsWhat creators you track are posting on a topic, ranked by engagement — evidence of what lands, not phrasing to copy.
growth_postsThe posts that drove people to your profile, by rate rather than reach — the closest thing to a growth ranking.
top_postsYour best-performing posts, optionally per weekday — real exemplars to draft from, not a description of your style.
engagement_by_local_hourYour average engagement by hour of day, so an agent can place a post where your account actually performs.
engagement_by_dow_and_hourThe same, broken down per day of the week, with thin days flagged rather than guessed at.
list_scheduledEverything queued and not yet posted, each with a link that opens it in VibeDraft.
create_mediaRegister an image, GIF, or mp4 and get a signed URL to PUT the bytes to. Returns a media_id for preview_post or schedule_post, which verify the upload — there is no separate complete step. Needs a shell or HTTP client to upload the bytes; video must carry an audio track.
list_mediaMedia already uploaded and verified, newest first. The normal way to attach a file the user already has — no bytes move.
upload_mediaSend a TINY file's bytes inline (base64) when no network upload is possible — icons and cards, never video. You must generate every character yourself, so anything sizeable fails partway. Verifies on arrival.
import_mediaFetch a file from a public https link into the media library and verify it; returns a media_id. The route for a chat client that can only say where the file is. Nothing is posted.
get_capabilitiesThe formats an account accepts (X: post, thread; Instagram: image, carousel, reel, story; TikTok: video, photo) with the exact media, caption and pricing rules for each, read from the channel adapter. Nothing is written.
preview_postValidate a draft, X text or an Instagram or TikTok payload, and get its exact cost plus a short-lived confirmation nonce. For TikTok the reply also carries the creator name, the privacy options and the consent line to show the user. Media is checked against the channel's rules here, with the fix named when it fails. Pass sources to back a draft's numbers and links: every number must be in a quote and every URL is fetched live, so a removed post or an unsourced figure refuses the preview instead of shipping. Nothing is published by this call.
publish_postPost immediately. Requires the nonce from preview_post, and publishes the content stored on that preview — not content passed here — to the channel it was previewed for.
publish_instagramPublish a previewed Instagram image, carousel, reel or story now, by preview_id. Instagram processes reels before they appear; the reply says 'processing' when that outlasts the call and VibeDraft finishes it. Refunded if Instagram rejects it.
publish_tiktokPublish a previewed TikTok video or photo post now, by preview_id. The video is uploaded to TikTok in chunks and processed before it appears; the reply says 'processing' when that outlasts the call and VibeDraft finishes it. Refunded if TikTok rejects it.
cross_postQueue drafts across accounts and channels for one scheduled_for in a single call. Every draft is validated before anything is charged; charged per draft at that channel's price. Pass sources on a draft to back its numbers and links, same as preview_post. No preview, so show the user each draft first.
preview_articleConvert markdown into a long-form X Article and check it before anything is created. Returns a one-time preview_id. Nothing is sent to X by this call.
publish_articleRedeem an article preview. Creates a private draft you can still read and discard on X, and only publishes publicly when the preview was made with publish: true. Requires X Premium.
list_blog_targetsList the blogs a draft can be rendered for. Each has its own frontmatter schema and body dialect.
preview_blogValidate a blog draft against a target's schema and convert its body to that target's dialect. Returns a one-time preview_id. Publishes nothing.
publish_blogRedeem a blog preview. The default export mode returns the rendered file and writes nothing. Mode git commits it to your blog repo and opens a pull request it never merges. Mode api publishes to dev.to, Hashnode or Ghost, as a draft unless the preview said publish live. Free in every mode.
syndicate_blogPackage an already-published post for Medium or Substack: paste-ready body plus a checklist. Free — those platforms have no publishing API, so the human pastes.
schedule_postQueue a post, thread, or Instagram / TikTok payload for later and get the link that opens it in VibeDraft. Pass sources to back its numbers and links, same as preview_post. Credits are debited atomically with the write.
cancel_scheduledRemove something from the queue before it goes out.
emit_eventRecord something that happened to the product — a milestone crossed, a feature shipped, a customer won or churned, a theme in support — so it can be marketed later. Writes to VibeDraft only: nothing posts, nothing is scheduled, no credits are spent. A plain-words title is required.
Machine-readable pricing lives at /pricing.md.
Attaching a file you already have.
A hosted tool call carries text, so a file has to be typed out as base64 to ride inside one. upload_media exists for that and stops at 64 KB, which is an icon. A screenshot is usually 150-250 KB and a video is megabytes, so for anything real the bytes have to move some other way.
The way that works everywhere: register with create_media and PUT the bytes yourself. Any shell, any HTTP client, any language. preview_post then verifies the upload and shows you a link to watch or view it before anything publishes.
curl -X POST "https://vibedraft.app/api/v1/media/<id>/upload" \
-H "Authorization: Bearer vd_pat_..." \
-H "Content-Type: image/png" --data-binary @shot.pngNo terminal? Install the one-click extension instead. Double-click it, paste the same token, and your agent can attach any file on your machine without you touching a command line. Claude Desktop only, and it cannot work on a phone: a remote server has no filesystem to read, so mobile attaches from list_media instead.
Nothing posts without you.
Every publish path requires a confirmation step. Your agent calls preview_post first, which validates the draft, quotes its exact credit cost and returns a short-lived nonce. Publishing sends the text stored on that preview, not text supplied afterwards. An agent cannot draft something, change it, and post it in one move.