MCP Server

DemandBird for Claude

Connect DemandBird to Claude Desktop or Claude Code and manage your social posts with plain English, no API calls needed.

← Also available: REST API Reference
Business

The MCP server and REST API are available on the Business and Agency plans. See plans & what's included.

What is MCP?

The Model Context Protocol (MCP) lets Claude connect to external tools and services. With the DemandBird MCP server connected, Claude can read your drafts, generate AI-written posts in your voice, schedule content, and manage your queue — all through natural conversation.

The DemandBird MCP server is hosted — no installation or Node.js required. MCP is available in Claude Desktop and Claude Code.

Setup

  1. Get your API token
    In DemandBird, go to Settings → API Tokens and create a token. Copy it — you'll need it in the next step. (What to scope it to.)The API Tokens page in DemandBird
  2. Configure your Claude app
    Follow the Claude Desktop or Claude Code instructions below.

Claude Desktop

Open (or create) ~/Library/Application Support/Claude/claude_desktop_config.jsonand add the demandbird server under mcpServers:

{
  "mcpServers": {
    "demandbird": {
      "type": "http",
      "url": "https://app.demandbird.com/mcp",
      "headers": {
        "Authorization": "Bearer your-token-here"
      }
    }
  }
}
Multiple accounts? Add an X-Account-Id header with your account ID to set a default account. You can find your account ID on the Settings page. If omitted, Claude will ask which account to use.
"headers": {
  "Authorization": "Bearer your-token-here",
  "X-Account-Id": "acct_your-account-id"
}
Restart Claude Desktop after saving — the server won't appear until you do. After restarting, you should see a DemandBird tool indicator in the toolbar when starting a new conversation.
On Windows, the config path is %APPDATA%\Claude\claude_desktop_config.json.

Claude Code

This works for Claude Code in the terminal, VS Code, JetBrains, and the desktop app.

Run this command in your terminal:

claude mcp add --transport http demandbird https://app.demandbird.com/mcp \
  --header "Authorization: Bearer your-token-here"

Or add it manually to ~/.claude.json:

{
  "mcpServers": {
    "demandbird": {
      "type": "http",
      "url": "https://app.demandbird.com/mcp",
      "headers": {
        "Authorization": "Bearer your-token-here"
      }
    }
  }
}
Multiple accounts? Add --header "X-Account-Id: acct_your-account-id" to set a default. If omitted, Claude will ask which account to use.
Start a new session after adding the server — it won't be picked up in an existing conversation.

Example prompts

Once connected, you can talk to DemandBird in plain English:

YouWrite a LinkedIn post about our new feature launch and save it as a draft.
ClaudeI'll generate a LinkedIn post in your voice and save it as a draft... [uses draft_post]

Done! Draft saved (post #124). Here's what I wrote: “We just shipped something that's been...”
YouShow me my current drafts.
Claude[uses list_drafts]

You have 3 drafts:
• Post #124: LinkedIn: “We just shipped something...”
• Post #121: Twitter, Threads: “The one thing I wish I knew...”
• Post #118: LinkedIn: “Hot take on AI in marketing...”
YouSchedule post 124 for LinkedIn at 9am tomorrow.
Claude[uses schedule_post]

Post #124 scheduled for 2026-03-03T09:00:00Z on LinkedIn.
YouAdd post 121 to the queue for Twitter and Threads.
Claude[uses queue_post]

Post #121 queued on Twitter and Threads.
Scheduled times:
• twitter: 2026-03-03T08:00:00Z
• threads: 2026-03-03T10:00:00Z

Tool reference

list_accounts

list_accounts
List all accounts you have access to. Shows account IDs, names, roles, and which one is currently selected.

No parameters required.

select_account

select_account
Switch to a different account for the current request. All subsequent tool calls in this conversation will use this account.
ParameterTypeDescription
account_idrequiredstringAccount prefix ID (e.g., acct_xxx) or numeric ID. Use list_accounts to find your IDs.

get_brand_voice

get_brand_voice
Get the active workspace's brand identity (positioning, audience, content pillars, current context) and your writing voice (how you sound, signature phrases, openers, what you avoid, recent feedback and edits). Read-only.
ParameterTypeDescription
platformoptionalstringAlso return recent before-and-after edits captured for this platform. Same values as draft_post.

draft_post and revise_draft already apply your voice and brand, so you don't need this for them. It is for when Claude writes the words itself and saves them with save_draft or update_draft, which store text exactly as given.

Each plan includes a monthly AI allowance: 90 drafts, 60 rewrites, 100 post ideas, and 2 voice re-trainings on Pro; 140 drafts, 110 rewrites, 200 ideas, and 4 re-trainings on Business; 450 drafts, 340 rewrites, 500 ideas, and 10 re-trainings on Agency. Plans & what's included.

draft_post

draft_post
Generate an AI-written social post using your writing style and voice, then save it as a draft. Uses your stored comments and posts to match your tone.
ParameterTypeDescription
promptrequiredstringWhat to write about. E.g., “a post about launching my new SaaS product”
platformoptionalstringTarget platform: linkedin, twitter, threads, bluesky, substack, youtube. Influences tone and length.
youtubeoptionalobjectYouTube-specific options: { title?, privacy_status?, thumbnail_url? }. title max 100 chars (auto-derived from the first line if omitted); privacy_status is public, unlisted, or private (defaults to public). A video must be attached via images before the post can be scheduled or published.

save_draft

save_draft
Save a piece of content you've written as a draft: no AI generation involved.
ParameterTypeDescription
contentrequiredstringThe post text to save.
platformsoptionalarray of stringsTarget platforms. Same values as draft_post.
youtubeoptionalobjectYouTube-specific options. Same shape as draft_post (title, privacy_status, thumbnail_url).

update_draft

update_draft
Replace an existing post's content and/or platforms with text you supply. Stored exactly as given, with no AI pass. Works on draft, scheduled and pending-review posts, and keeps the schedule.
ParameterTypeDescription
idrequirednumberPost ID to update.
contentoptionalstringNew post content. Replaces the existing text.
platformsoptionalarray of stringsUpdated target platforms. Replaces the existing selection.
youtubeoptionalobjectReplace the YouTube variant fields. Same shape as draft_post. Pass {} to clear them.
on_variant_conflictoptionalstringreplace or keep. When you change content, channel copies that still matched the draft are updated along with it. If a channel copy was edited separately, the call is refused and names those channels. Re-send with on_variant_conflict: "replace" to apply the new content there too, or "keep" to leave those channels as they are.

revise_draft

revise_draft
Apply feedback (“shorter”, “less salesy”, “add a call to action”) to an existing draft and save the rewrite onto the same post. It keeps the post's images, channel copies and schedule, and writes in your voice and brand.
ParameterTypeDescription
idrequirednumberPost ID of the draft to revise, as returned by draft_post, save_draft or list_drafts.
feedbackrequiredstringWhat you want changed, in your own words.
platformoptionalstringThe platform whose length limit the rewrite should fit. Defaults to the post's first platform. It does not change where the post publishes.
draft_anywayoptionalbooleanSet true to rewrite with what it has instead of asking for more context.
on_variant_conflictoptionalstringreplace or keep. Same as on update_draft: if a channel has its own tailored copy, the call is refused and names it until you choose.

Use this every time you react to a draft. Calling draft_post again creates a second, unrelated draft instead, and leaves the first one (and its images) where it was. Each call uses one AI rewrite from your monthly allowance.

attach_reference

attach_reference
Store source material (a call transcript, an article, notes) with a post. You and your reviewers can read it in the editor and on the approvals card. It is never published, and it does not change the post copy or reset an approval.
ParameterTypeDescription
post_idrequirednumberPost ID to attach the reference to.
textoptionalstringThe source material itself, stored as given. Up to 200,000 characters. Give exactly one of text or url.
urloptionalstringA link to the source. The page is fetched in the background, and the link is kept even if the fetch fails. Give exactly one of text or url.
titleoptionalstringA label. Taken from the first line of text when left out.

Never put source material in content. Whatever is in content on save_draft or update_draft gets published. A post holds up to 20 references. Attaching one makes no AI call.

list_drafts

list_drafts
List your posts filtered by status. Returns post IDs, content previews, platforms, and schedule info.
ParameterTypeDescription
statusoptionalstringOne of: draft, scheduled, posted, failed. Defaults to draft.
limitoptionalnumberMax posts to return (default 20, max 100).

get_post

get_post
Fetch full details of a specific post by ID, including all schedule statuses per platform.
ParameterTypeDescription
idrequirednumberPost ID.

Also lists the post's reference materials: title, url, kind, length and status. It does not return their text.

delete_post

delete_post
Permanently delete a post by ID. Works for drafts, scheduled, and already-published posts. For published posts: this removes the DemandBird record (and its analytics linkage); the live copy on the platform stays put. Cannot be undone.
ParameterTypeDescription
idrequirednumberPost ID to delete.

schedule_post

schedule_post
Schedule a draft for a specific date and time on one or more platforms.
ParameterTypeDescription
idrequirednumberPost ID to schedule.
scheduled_atrequiredstring (ISO 8601)When to publish. E.g., 2026-03-10T09:00:00Z. Must be in the future.
platformsoptionalarray of stringsPlatforms to schedule on. If omitted, uses platforms already set on the post.

queue_post

queue_post
Add a post to the next available time slot in your posting queue. Uses the schedule you've configured in DemandBird.
ParameterTypeDescription
idrequirednumberPost ID to queue.
platformsoptionalarray of stringsPlatforms to queue for. If omitted, uses platforms already set on the post.

Returns the exact scheduled time for each platform based on your posting queue. Use get_queue_slots first if you want to see available times before queueing.

get_queue_slots

get_queue_slots
Check the next available queue slot for one or more platforms without scheduling anything.
ParameterTypeDescription
platformsrequiredarray of stringsPlatforms to check. E.g., ["linkedin", "twitter"].

list_connected_accounts

list_connected_accounts
List the social accounts connected to the current DemandBird account. Useful when a platform has more than one connected account (e.g. two Twitter logins) and you need the numeric id to target a specific one.
ParameterTypeDescription
platformoptionalstringFilter to a single platform. Same values as draft_post.

Use the returned ids with platform_account_ids on schedule_post or queue_post to post from a specific account.

request_review

request_review
Send a draft to one or more teammates for approval. Required reviewers block publishing until every one approves; optional reviewers are FYI. The post must already exist as a draft.
ParameterTypeDescription
post_idrequiredstringID of the draft to send for review.
reviewersrequiredarray of objectsEach reviewer needs either email (their email on this account) oruser_id. Set required: false to make a reviewer optional; defaults to true.
noteoptionalstringA message to include when notifying the reviewers.
scheduled_atoptionalstring (ISO 8601)Pre-schedule the post. It will auto-publish at this time if every required reviewer has approved by then.

list_posts_awaiting_my_review

list_posts_awaiting_my_review
List posts that teammates have asked the authenticated user to review. Returns posts with a pending review assigned to the user.
ParameterTypeDescription
limitoptionalnumberMax posts to return (1–100, default 20).

upload_image

upload_image
Get a presigned S3 upload URL for an image or video. Use this for files too large to pass inline. Returns a curl command to run plus an s3_key to reference on draft_post, save_draft, or update_draft.
ParameterTypeDescription
filenamerequiredstringOriginal filename (e.g. photo.jpg).
content_typeoptionalstringMIME type. Inferred from the filename extension if omitted. Supports images (JPEG, PNG, GIF, WebP) and videos (MP4, MOV, AVI, WebM, MKV).

generate_image

generate_image
Create an original image with AI to go with a post. Your workspace's brand style is applied for you. Takes 10 to 30 seconds, uses one of your monthly image credits, and returns the credits left. The image is also saved to your media library.
ParameterTypeDescription
promptrequiredstringWhat the image should show. Describe the picture, not the post.
styleoptionalstringphoto, illustration, infographic or diagram. Defaults to illustration.
sizeoptionalstringsquare (1:1), portrait (2:3) or landscape (3:2). Defaults to square.

Returns an s3_key to pass to draft_post, save_draft or update_draft in images. If you already have a picture, use upload_image instead. See AI images.

Analytics tools

These tools are read-only. Every number comes from the same data as the Analytics tab. Reddit is not included.

platform takes one of twitter, bluesky, threads, facebook, instagram, mastodon, youtube, tiktok, pinterest or linkedin. period takes 7d, 30d or 90d, and defaults to 30d.

get_analytics_summary

get_analytics_summary
Followers, engagements, reach and engagement rate, each with the change from the previous period. Leave out platform for a roll-up across every connected network.
ParameterTypeDescription
platformoptionalstringFocus on one network. Omit for all of them.
periodoptionalstringTime window. Default 30d.

list_top_posts

list_top_posts
Rank your recent posts, best or worst, across all networks or one. Returns each post's id, stats, a snippet and a link.
ParameterTypeDescription
platformoptionalstringRank posts from one network. Omit for all of them.
metricoptionalstringengagement_rate, engagements, reach, likes, comments or shares. Default engagement_rate. Some platforms don't report reach or engagement rate.
orderoptionalstringtop (best) or bottom (worst). Default top.
periodoptionalstringTime window. Default 30d.
limitoptionalnumberHow many posts (default 5, max 20).

get_post_analytics

get_post_analytics
Full metrics for one post, including how its reach and engagement built up over time where the platform supports it. Pick the post by post_id, or by platform with latest: true.
ParameterTypeDescription
post_idoptionalnumberThe post's id, for example from list_top_posts.
platformoptionalstringThe network to take the latest post from. Use with latest.
latestoptionalbooleanSet true with platform to get that network's most recent post.

get_best_time_to_post

get_best_time_to_post
The days of the week and hours (in your timezone) when your posts on a platform have done best.
ParameterTypeDescription
platformrequiredstringThe network to look at.
periodoptionalstringTime window. Default 30d.
limitoptionalnumberHow many time slots (default 3, max 10).

get_format_performance

get_format_performance
Rank post formats (text, image, video and so on) on a platform by engagement.
ParameterTypeDescription
platformrequiredstringThe network to look at.
periodoptionalstringTime window. Default 30d.

get_audience_demographics

get_audience_demographics
Who your followers are. Instagram and Threads report country, age, gender and city. LinkedIn company pages report seniority, job function, industry, company size and location. Other platforms, and LinkedIn personal profiles, don't share this.
ParameterTypeDescription
platformrequiredstringThe network to look at.
periodoptionalstringTime window. Default 30d.