MCP
MCP
The Model Context Protocol (MCP) is an open standard that lets an AI assistant work with an outside service through a set of tools it can call. Buffer runs a remote MCP server at https://mcp.buffer.com/mcp, which enables AI assistants to read your channels, browse your queue and drafts, schedule and edit posts, capture ideas and pull post analytics, all without leaving the conversation.
Any MCP-compatible AI tool can connect. If yours doesn't have a Buffer integration guide of its own, follow the setup instructions below.
Setup
Get Your API Key
You need an API key to integrate Buffer with MCP.
Your key is shared with the API Explorer and will prefill the configuration steps below.
Configure Your MCP Client
LLM clients that support MCP and headers can connect to Buffer by adding an HTTP MCP server with the following settings:
-
Server URL:
https://mcp.buffer.com/mcp -
Authorization Header:
Authorization: Bearer YOUR_API_KEY
Supported tools
The Buffer MCP server exposes a large list of tools. Most of them cover a specific job, like listing channels or scheduling a post. Two generic tools let an assistant reach the rest of the GraphQL API when no specific tool fits.
A few conventions apply across the tools:
- Every ID is a 24-character hex string.
- Every date and time is an ISO 8601 string with a UTC offset, such as
2026-08-11T17:00:00-05:00.get_accountreturns the account timezone and its current local time, which is what an assistant should use to turn "tomorrow at 5pm" into a real timestamp. - Tools that return lists page with
firstandafter, returning 20 items by default and up to 100 per page. create_post,edit_post,delete_post,create_idea, the template write tools andexecute_mutationchange your data. Most MCP clients ask you to approve those before they run.
Account tools
get_account
get_accountReturns the signed-in account and the organizations it belongs to: email, name, timezone, the current time in that timezone, and for each organization its ID, name, plan limits and member count.
If you belong to more than one organization, an assistant will name them and ask which one you mean before going further.
Takes no parameters.
Example prompt: "Which Buffer organizations do I have access to?"
Channel tools
list_channels
list_channelsLists the social accounts connected to an organization, with each channel's ID, name, display name, service, type, avatar and connection status.
| Parameter | Type | Required | Description |
|---|---|---|---|
organizationId |
string | Yes | The organization to list channels for |
Example prompt: "List all my connected Buffer channels."
get_channel
get_channelReturns the detail that list_channels leaves out for a single channel: its posting schedule, posting goals, queue status, timezone, link shortening settings, and service-specific data such as Pinterest boards, a Mastodon server URL or Instagram reminder settings.
| Parameter | Type | Required | Description |
|---|---|---|---|
channelId |
string | Yes | The channel to read |
Example prompt: "What times does my LinkedIn channel post at?"
Post tools
list_posts
list_postsLists posts in an organization. Returns each post's ID, status, text, scheduled and sent times, channel, tags, assets and any publishing error.
| Parameter | Type | Required | Description |
|---|---|---|---|
organizationId |
string | Yes | The organization to list posts for |
channelIds |
string[] | No | Only return posts on these channels |
status |
string[] | No | Any of draft, needs_approval, scheduled, sending, sent, error |
tagIds |
string[] | No | Only return posts carrying any of these tags |
dueAt |
object | No | start and end bounds on the scheduled time |
createdAt |
object | No | start and end bounds on the creation time |
sort |
object[] | No | Sort by dueAt or createdAt, asc or desc |
first |
integer | No | Page size, 20 by default and 100 at most |
after |
string | No | Pagination cursor |
includeMetrics |
boolean | No | Also return per-post analytics. Off by default, since it makes the response much larger |
Example prompt: "Show me all my draft posts in Buffer so I can review what's pending."
get_post
get_postReads one post in full: status, content, author, channel, tags, notes, assets and the actions you are allowed to take on it. The metadata field carries service-specific data such as Instagram geolocation, a Twitter thread or YouTube privacy settings. A post with the error status carries the failure message.
| Parameter | Type | Required | Description |
|---|---|---|---|
postId |
string | Yes | The post to read |
includeMetrics |
boolean | No | Also return this post's analytics and the time they were last refreshed |
Example prompt: "Why did my Instagram post from yesterday fail?"
create_post
create_postSchedules or publishes a post on one channel. Works for Instagram, Facebook, Twitter, LinkedIn, Pinterest, YouTube, Google Business, Mastodon, TikTok, Threads, Bluesky and Start Page.
What each service needs as a minimum:
- Twitter, Mastodon, Threads and Bluesky: text only.
- Instagram and TikTok: an image or a video.
- Pinterest: an image, plus the board to pin to in
metadata.pinterest. - YouTube: a video, plus a title and category in
metadata.youtube.
| Parameter | Type | Required | Description |
|---|---|---|---|
channelId |
string | Yes | The channel to post to, taken from list_channels |
schedulingType |
string | Yes | automatic to publish for you, or notification to send you a reminder to post manually |
mode |
string | No | addToQueue (the default), shareNow, shareNext, or customScheduled, which needs dueAt |
text |
string | No | The body of the post |
dueAt |
string | No | When to publish, required for customScheduled and always in the future |
tagIds |
string[] | No | Tags to file the post under |
assets |
object[] | No | Media to attach, each one an image, a video, or a document on LinkedIn |
metadata |
object | No | Service-specific settings, keyed by service |
saveToDraft |
boolean | No | Save as a draft instead of scheduling it |
ideaId |
string | No | The idea this post is being created from |
draftId |
string | No | The draft this post is being created from |
Example prompt: "Add a post to my Buffer queue that says 'Excited to share our latest update!' for next Monday."
edit_post
edit_postChanges an existing post. Every edit is validated as a whole post, the same way a new one is, rather than being merged into the stored version. So an assistant should read the post with get_post first and carry the current assets and metadata forward, changing only what you asked for. Dropping a field the post needs will make the edit fail.
Leaving schedulingType out keeps the post publishing the way it already does, and leaving mode and dueAt out keeps it in its current slot.
| Parameter | Type | Required | Description |
|---|---|---|---|
postId |
string | Yes | The post to change |
schedulingType |
string | No | automatic or notification |
mode |
string | No | addToQueue, shareNow, shareNext, or customScheduled |
text |
string | No | The body of the post |
dueAt |
string | No | A new publishing time, only valid with customScheduled |
tagIds |
string[] | No | Tags to file the post under |
assets |
object[] | No | Media to attach. Leave it out to keep the stored media, send an empty array to clear it |
metadata |
object | No | Service-specific settings, keyed by service |
saveToDraft |
boolean | No | Move the post back to a draft |
ideaId |
string | No | The idea this post is being created from |
draftId |
string | No | The draft this post is being created from |
Example prompt: "Move my Thursday LinkedIn post to Friday at 9am and shorten the opening line."
delete_post
delete_postDeletes a post for good. Not every post can be deleted, so an assistant should check that deletePost appears in the post's allowedActions first.
| Parameter | Type | Required | Description |
|---|---|---|---|
postId |
string | Yes | The post to delete |
Example prompt: "Delete the draft I made this morning about the pricing update."
get_aggregated_post_metrics
get_aggregated_post_metricsAdds up analytics across many posts over a date range and returns the totals and averages, rather than making an assistant pull every post and do the arithmetic itself.
The response always carries post count, reactions and comments. Other metrics, such as reach, impressions and engagement rate, appear only when every channel in the filter supports them. Metrics refresh once a day, so values can lag the social network by up to a day. The date range can cover at most 365 days.
| Parameter | Type | Required | Description |
|---|---|---|---|
organizationId |
string | Yes | The organization to aggregate metrics for |
startDateTime |
string | Yes | Start of the window, inclusive |
endDateTime |
string | Yes | End of the window, inclusive |
channelIds |
string[] | No | Channels to include. Leave it out to cover every channel you can see insights for |
tags |
object | No | in limits the aggregate to posts carrying any of these tags, isEmpty also counts untagged posts |
Example prompt: "How did my LinkedIn posts perform last month?"
Idea tools
list_ideas
list_ideasLists the ideas in an organization. Ideas capture a concept for a future post before it belongs to a channel. Each one returns its title, text, media, tags, target services, target date, board column and timestamps.
| Parameter | Type | Required | Description |
|---|---|---|---|
organizationId |
string | Yes | The organization to list ideas for |
tagIds |
string[] | No | Only return ideas carrying any of these tags |
includeUntagged |
boolean | No | Also return ideas with no tags. Off by default |
first |
integer | No | Page size, 20 by default and 100 at most |
after |
string | No | Pagination cursor |
Example prompt: "What ideas do I have saved that are tagged for the product launch?"
list_idea_groups
list_idea_groupsLists the columns on the ideas board, with each column's ID, name and lock status.
| Parameter | Type | Required | Description |
|---|---|---|---|
organizationId |
string | Yes | The organization to list idea groups for |
Example prompt: "What columns does my Buffer ideas board have?"
create_idea
create_ideaSaves a new idea. This captures content for later. It does not schedule or publish anything.
| Parameter | Type | Required | Description |
|---|---|---|---|
organizationId |
string | Yes | The organization to create the idea in |
content |
object | Yes | The idea itself: title, text, media, tags, target services and a target date, all optional |
Example prompt: "Save an idea for a post about our new integration, tagged for Instagram and LinkedIn."
Post template tools
Post templates are reusable starting points for content. A template body can hold {{placeholders}} to fill in later. Each template is public, internal or private: public templates are curated by Buffer, internal ones are shared with everyone in your organization, and private ones are yours alone.
list_post_templates
list_post_templatesLists the templates you can use in an organization. With no filter this returns all three kinds together: the public templates, your organization's internal ones, and your own private ones.
| Parameter | Type | Required | Description |
|---|---|---|---|
organizationId |
string | Yes | The organization whose templates to list |
visibility |
string | No | Narrow to private, internal or public |
first |
integer | No | Page size, 20 by default and 100 at most |
after |
string | No | Pagination cursor |
Example prompt: "What post templates can I use?"
get_post_template
get_post_templateReads one template: its body, title, description, emoji, visibility and timestamps.
| Parameter | Type | Required | Description |
|---|---|---|---|
postTemplateId |
string | Yes | The template to read |
Example prompt: "Show me the full text of my product announcement template."
create_post_template
create_post_templateCreates a template in an organization. You can set it to private or internal. Public is curated by Buffer and cannot be set here.
| Parameter | Type | Required | Description |
|---|---|---|---|
organizationId |
string | Yes | The organization the template belongs to |
title |
string | Yes | The name of the template |
body |
string | Yes | The content, which may contain {{placeholders}} |
description |
string | Yes | A short description of what the template is for |
emoji |
string | No | An emoji to show alongside the template |
visibility |
string | No | private, the default, or internal |
Example prompt: "Turn this post into a template my whole team can reuse."
update_post_template
update_post_templateChanges a template. Only the fields you send are changed. You can edit templates you own, and internal templates in your organization if you are an admin or owner.
| Parameter | Type | Required | Description |
|---|---|---|---|
postTemplateId |
string | Yes | The template to change |
title |
string | No | The name of the template |
body |
string | No | The content, which may contain {{placeholders}} |
description |
string | No | A short description of what the template is for |
emoji |
string | No | An emoji to show alongside the template |
visibility |
string | No | private or internal |
Example prompt: "Add a call to action line to my weekly recap template."
delete_post_template
delete_post_templateDeletes a template for good. You can delete templates you own, and internal templates in your organization if you are an admin or owner.
| Parameter | Type | Required | Description |
|---|---|---|---|
postTemplateId |
string | Yes | The template to delete |
Example prompt: "Delete the old holiday sale template."
Advanced tools
These three cover anything the tools above do not. An assistant should read the schema first and then run an operation from it, rather than guessing at field names.
introspect_schema
introspect_schemaReturns the complete GraphQL schema for the Buffer API: every query, mutation, type and argument. This is only worth calling before execute_query or execute_mutation, since the tools above already cover the common jobs.
Takes no parameters.
execute_query
execute_queryRuns a read-only GraphQL query against the Buffer API.
| Parameter | Type | Required | Description |
|---|---|---|---|
summary |
string | Yes | A short, plain description of what the operation does, shown to you in the approval prompt |
query |
string | Yes | The GraphQL query, using names from the schema |
variables |
object | No | Variables for the query |
operationName |
string | No | Which query to run, if the document defines several |
execute_mutation
execute_mutationRuns a GraphQL mutation against the Buffer API. This changes your data, so most clients will ask you to approve it.
| Parameter | Type | Required | Description |
|---|---|---|---|
summary |
string | Yes | A short, plain description of what the operation does, shown to you in the approval prompt |
mutation |
string | Yes | The GraphQL mutation, using names from the schema |
variables |
object | No | Variables for the mutation |
operationName |
string | No | Which mutation to run, if the document defines several |
Beyond the tools
The GraphQL schema is available as a resource at buffer://schema, which is the same content introspect_schema returns. Clients that support resources can attach it to a conversation instead of spending a tool call on it.
There is also one prompt, review_weekly_posts, which reviews the posts you have scheduled for the current week and groups them by channel. Clients that support prompts usually list it as a command you can pick.
Rate limits
Requests made through the MCP server count against the same rate limits as any other client: a rolling 15-minute, 24-hour and 30-day window, with quotas that depend on your plan. The limits are per client and shared across every request rather than counted per tool, so one conversation that lists your posts, reads a few of them and then edits one has spent several requests from the same budget.
When a window drops below a tenth of its quota, a successful tool response carries a note naming the window that is running low and when it resets. Treat it as a signal to slow down: ask for less in one go, and wait for the reset it names before carrying on. Past the limit the call fails with 429 Too Many Requests, and the error the assistant sees carries the Retry-After value from the API, in seconds. That is how long to wait before asking for anything else.
Most of what keeps an assistant inside these limits is how you prompt it. Check out the prompts for AI agents section of the Efficient API Usage guide for best practices and example prompts.
Security considerations
Connecting a client to the MCP server gives it the same reach over your content as you have, so it is worth knowing what that covers before you connect one.
- The connection covers your whole account. An API key acts for your account and reaches every organization and channel in it. There is no per-organization scoping, so you cannot open one workspace to an assistant while holding another back. See key permissions and scope for what a key can do.
- Treat the key like a password. MCP clients keep it in a config file, often in plain text, and some sync that file between machines. Keep it out of anything you share or commit, and generate a fresh key in Settings → API if you think it has leaked.
- Check the server URL. The only Buffer MCP endpoint is
https://mcp.buffer.com/mcp. A one-click install from a third-party list is worth opening and reading before you trust it. - Leave the approval prompts on.
create_postcan publish immediately, anddelete_postcannot be undone. Most clients ask before they run a tool that writes, and that prompt is your last chance to catch a misread instruction.
Try It Out
Copy any of these example prompts to get started with MCP: