Skip to content

Socifyr MCP tools reference ​

The Socifyr MCP server exposes 20 tools. Each one calls the TypeScript SDK, which calls the REST API with your API key. The remote server and the local stdio server register the same tool definitions, so they behave the same.

This page lists every tool with its input schema, a sample call and a sample result. For connecting a client, see MCP setup. For failures and their fixes, see MCP errors.

Which MCP tools does Socifyr have? ​

GroupTools
Accountslist_connections, refresh_connection, reconnect_connection
Postingpost_text, post_image, post_video
Schedulingschedule_post, schedule_posts
Managing postslist_posts, check_post_status, update_post, retry_post, publish_draft
Medialist_media, delete_media
Analyticsget_post_analytics, get_follower_growth, compare_accounts
Planget_usage
AIgenerate_caption

How does an MCP client call these tools? ​

A client sends a tools/call request with the tool name and an arguments object. The samples below show the name and arguments. Every tool returns a content array with one text item. When something goes wrong the result has isError: true and the text begins with Error: followed by the API message, so the model can read it and correct itself.

json
{
  "name": "post_text",
  "arguments": {
    "connections": ["linkedin-myhandle", "x-myhandle"],
    "caption": "Just shipped our new docs"
  }
}

Which tools can an API key with guardrails use? ​

An API key with a daily post limit, an X spend cap or requireApproval is deny-by-default. It can only call API routes on an allowlist. From the routes behind each tool:

Allowed for guarded keysNot allowed for guarded keys
list_connections, post_text, post_image, post_video, schedule_post, schedule_posts, list_posts, check_post_status, update_post, retry_post, list_media, get_post_analytics, get_follower_growth, compare_accounts, get_usage, generate_captionrefresh_connection, reconnect_connection, delete_media

publish_draft is allowed for a key with a post limit or spend cap, but a key with requireApproval gets a 403: This API key requires approval and cannot publish drafts directly — submit the post for approval and a teammate will review it. A guarded key calling a blocked tool gets This API key has guardrails and cannot call this endpoint — use a dashboard session or an unrestricted key. See API keys.


list_connections ​

Lists connected accounts with their slugs and health. Call it first: every posting tool needs slugs from here.

Input: none.

Sample call

json
{ "name": "list_connections", "arguments": {} }

Sample result

Connected accounts (3):

• instagram-mybrand — instagram / mybrand (expires 11/18/2026) ⚠ expiring — call refresh_connection
• x-myhandle — x / myhandle ⚠ NEEDS RECONNECT — call reconnect_connection
• linkedin-myhandle — linkedin / Madhav Poudel

Use these slugs in the "connections" field when posting.

Flags in the result come from the connection status: needs_reconnect shows NEEDS RECONNECT — call reconnect_connection. expiring shows expiring — call refresh_connection when the account can refresh, and expiring soon — call reconnect_connection when it cannot. active shows no flag. Disconnected accounts are left out. With no accounts the tool says so and points to the dashboard. See Connections and slugs.

refresh_connection ​

Renews an account's access token with its stored refresh token. No owner action is needed. Use it when list_connections shows expiring or a post failed with an expired or invalid token.

ParameterTypeRequiredDescription
connectionstringyesConnection slug, for example instagram-mybrand
json
{ "name": "refresh_connection", "arguments": { "connection": "instagram-mybrand" } }
Refreshed instagram-mybrand (instagram). Status: active. New expiry: 1/12/2027, 10:00:00 AM.

If the platform cannot refresh, the result is an error: Could not refresh "instagram-mybrand": <API message> followed by If it cannot be refreshed, call reconnect_connection to get a re-authorization link.

reconnect_connection ​

Returns a single-use link the account owner opens to re-authorize an account whose status is needs_reconnect, or whose post failed with reconnect_required.

ParameterTypeRequiredDescription
connectionstringyesConnection slug, for example x-myhandle
json
{ "name": "reconnect_connection", "arguments": { "connection": "x-myhandle" } }
Reconnect link for x-myhandle (x):
https://api.socifyr.com/api/oauth/x/connect-popup?code=...

Ask the account owner to open it and approve access with the SAME account (a different account creates a new connection instead). It works once and expires in 10 minutes. Afterwards, retry the failed post (retry_post) or run list_connections to confirm the status is active.

The slug and scheduled posts are kept when the same account is approved. Only the workspace owner can create the link; anyone else gets Only the workspace owner can connect accounts. An unknown slug gives Connection not found. The full flow is in Connections and slugs.

post_text ​

Publishes a text post to one or more accounts now.

ParameterTypeRequiredDescription
captionstringyesThe text to post
connectionsstring[] (at least 1)yesConnection slugs
firstCommentstringnoA first comment added after posting, for example hashtags
json
{
  "name": "post_text",
  "arguments": {
    "connections": ["linkedin-myhandle", "x-myhandle"],
    "caption": "Just shipped our new docs",
    "firstComment": "#buildinpublic"
  }
}
Post submitted successfully!
ID: 6a05033584584482ace13d72
Request ID: 9f2c7a1e-3d44-4b2a-8e1f-0a5c2d7e9f10

Check results with: check_post_status tool using ID "6a05033584584482ace13d72"

The tool returns as soon as the post is accepted. Publishing continues in the background, so follow with check_post_status. With an approval-required key the post waits in pending_approval even though the message says it was submitted.

post_image ​

Publishes one or more images, now or scheduled.

ParameterTypeRequiredDescription
connectionsstring[] (at least 1)yesConnection slugs
imagesstring[] (1 to 10)yesPublic image URLs or media library IDs (24-character hex)
textstringnoCaption
scheduledAtstringnoISO 8601 time. Omit to post now
firstCommentstringnoFirst comment
contentFormatphoto_single | photo_carousel | storynoFormat override
json
{
  "name": "post_image",
  "arguments": {
    "connections": ["instagram-mybrand"],
    "images": ["6a04f715d3d7d93575e65d13", "https://cdn.example.com/banner.png"],
    "text": "New product banner",
    "contentFormat": "photo_carousel"
  }
}
Submitted
ID: 6a05033584584482ace13d72
Images: 2
Connections: instagram-mybrand

With scheduledAt the first line reads Scheduled for <date and time>. The tool takes URLs and library IDs only; it cannot upload a file from your disk. Upload through the SDK, CLI or REST API first, then pass the ID.

post_video ​

Publishes one video, now or scheduled.

ParameterTypeRequiredDescription
connectionsstring[] (at least 1)yesConnection slugs
videostringyesPublic video URL or media library ID
textstringnoCaption
scheduledAtstringnoISO 8601 time. Omit to post now
firstCommentstringnoFirst comment
contentFormatshort_video | story | feed_videonoFormat override
json
{
  "name": "post_video",
  "arguments": {
    "connections": ["tiktok-mybrand", "instagram-mybrand"],
    "video": "6a04f715d3d7d93575e65d13",
    "text": "Behind the scenes",
    "contentFormat": "short_video"
  }
}
Submitted
ID: 6a05033584584482ace13d72
Connections: tiktok-mybrand, instagram-mybrand

schedule_post ​

Schedules a text post for a future time.

ParameterTypeRequiredDescription
captionstringyesThe text to post
connectionsstring[] (at least 1)yesConnection slugs
scheduledAtstringyesISO 8601 time, for example 2026-12-01T09:00:00Z
firstCommentstringnoFirst comment
json
{
  "name": "schedule_post",
  "arguments": {
    "connections": ["linkedin-myhandle"],
    "caption": "Tomorrow at 9",
    "scheduledAt": "2026-12-01T09:00:00Z"
  }
}
Post scheduled for 12/1/2026, 9:00:00 AM
ID: 6a05033584584482ace13d73
Connections: linkedin-myhandle

The displayed time uses the server's locale and timezone. For scheduled media use post_image or post_video with scheduledAt. The free plan does not include scheduling.

schedule_posts ​

Schedules many text posts in one call. Use it instead of repeating schedule_post.

ParameterTypeRequiredDescription
postsobject[] (1 to 500)yesThe posts to schedule
posts[].textstringyesPost text
posts[].connectionsstring[] (at least 1)yesConnection slugs
posts[].scheduledAtstringyesISO 8601 future time
posts[].titlestringnoOptional title
json
{
  "name": "schedule_posts",
  "arguments": {
    "posts": [
      { "text": "Monday tip", "connections": ["x-myhandle"], "scheduledAt": "2026-12-07T09:00:00Z" },
      { "text": "Friday recap", "connections": ["x-myhandle", "linkedin-myhandle"], "scheduledAt": "2026-12-11T16:00:00Z", "title": "Weekly recap" }
    ]
  }
}
Scheduled 1 of 2 posts.

1 failed:
  • Row 1: scheduledAt must be in the future

Rows are numbered from 1 in the order you sent them. A failed row does not stop the others. Same behavior as the CLI schedule command.

list_posts ​

Lists posts with their IDs, so you can find one to edit, publish or check.

ParameterTypeRequiredDefaultDescription
statusdraft | scheduled | queued | publishing | completed | partial_failure | failednoallFilter by status. scheduled is an alias the tool maps to the stored pending status
limitinteger 1 to 50no20Maximum results
json
{ "name": "list_posts", "arguments": { "status": "scheduled", "limit": 10 } }
Posts (2 total):

• 6a05033584584482ace13d73 — [pending] text "Tomorrow at 9" | scheduled 12/1/2026, 9:00:00 AM
    → linkedin/Madhav Poudel
• 6a05032a84584482ace13d5f — [pending] photo "New product banner" | scheduled 12/3/2026, 5:30:00 PM
    → instagram/mybrand, x/myhandle

Use a post ID with update_post, publish_draft, check_post_status, or get_post_analytics.

Each entry shows the ID, status, type, a preview of up to 60 characters of the title or text, the schedule time and the target accounts. The tool has no filter for pending-approval posts.

check_post_status ​

Returns the status and per-platform result of a post.

ParameterTypeRequiredDescription
postIdstringyesThe ID from a posting tool, or a request ID
json
{ "name": "check_post_status", "arguments": { "postId": "6a05032a84584482ace13d5f" } }
Post 6a05032a84584482ace13d5f
Status: partial_failure

  ✓ linkedin → https://linkedin.com/feed/update/...
  ✗ x (rate limit exceeded)

A · marks a channel that has not finished. With no channel results yet the text says No channel results yet. Statuses are explained in post lifecycle.

update_post ​

Edits a draft or a scheduled post that has not published.

ParameterTypeRequiredDescription
postIdstringyesDraft or scheduled post ID, from list_posts
connectionsstring[] (at least 1)noThe full set of slugs. Replaces the current accounts, it is not a delta
textstringnoNew caption or body
titlestringnoNew title
descriptionstringnoNew description
firstCommentstringnoFirst comment text
mediaIdsstring[]noMedia library IDs. Replaces the current media
scheduledAtstringnoNew ISO 8601 time. For a scheduled post it must be in the future
contentFormatstringnoContent format override
json
{
  "name": "update_post",
  "arguments": {
    "postId": "6a05032a84584482ace13d5f",
    "connections": ["instagram-mybrand", "x-mybrand", "linkedin-mybrand"],
    "scheduledAt": "2026-12-01T09:00:00Z"
  }
}
Post 6a05032a84584482ace13d5f updated.
Connections now: instagram-mybrand, x-mybrand, linkedin-mybrand
Scheduled for: 12/1/2026, 9:00:00 AM
Check it with: check_post_status tool using ID "6a05032a84584482ace13d5f"

Passing only postId returns an error: Nothing to update — provide at least one field (connections, text, scheduledAt, …).

retry_post ​

Re-queues the failed channels of a partial_failure or failed post. Channels that published are skipped.

ParameterTypeRequiredDescription
postIdstringyesThe post ID
json
{ "name": "retry_post", "arguments": { "postId": "6a05032a84584482ace13d5f" } }
Retry queued
ID: 6a05032a84584482ace13d5f
Retried channels: 1

Check results with: check_post_status tool using ID "6a05032a84584482ace13d5f"

If a channel failed because the account needs reconnecting, run reconnect_connection first.

publish_draft ​

Publishes a saved draft now.

ParameterTypeRequiredDescription
postIdstringyesThe draft ID
json
{ "name": "publish_draft", "arguments": { "postId": "6a05032a84584482ace13d5f" } }
Draft published
ID: 6a05032a84584482ace13d5f
Request ID: 9f2c7a1e-3d44-4b2a-8e1f-0a5c2d7e9f10

Check results with: check_post_status tool using ID "6a05032a84584482ace13d5f"

The MCP server cannot create a draft or submit one for approval. Create drafts with the dashboard, CLI --draft, or the SDK, and submit for approval via the SDK or REST. See feature parity.

list_media ​

Lists media library items. The IDs work in post_image and post_video without re-uploading.

ParameterTypeRequiredDefaultDescription
typeimage | video | documentnoallFilter by type
searchstringnononeSearch by filename
limitinteger 1 to 100no20Maximum results
json
{ "name": "list_media", "arguments": { "type": "video", "limit": 10 } }
Media library (2 total):

• 6a93a4bfaa1135c3d8dd3df5 — launch-teaser.mp4 (video, 8.4MB)
• 6a93b7c2d1e0f3a4b5c6d7e8 — demo-full.mp4 (video, 156.2MB)

Use these IDs in post_image or post_video "images"/"video" fields.

delete_media ​

Deletes one or more media items.

ParameterTypeRequiredDescription
idsstring[] (at least 1)yesMedia IDs
json
{ "name": "delete_media", "arguments": { "ids": ["6a93a4bfaa1135c3d8dd3df5"] } }
Deleted 1 media item: 6a93a4bfaa1135c3d8dd3df5

Not available to API keys with guardrails.

get_post_analytics ​

Per-platform results and engagement for one post.

ParameterTypeRequiredDescription
postIdstringyesPost ID or request ID
json
{ "name": "get_post_analytics", "arguments": { "postId": "6a05032a84584482ace13d5f" } }
Post analytics: 6a05032a84584482ace13d5f
Status: completed

  ✓ youtube → https://youtube.com/shorts/6zaztTmk3Ck | likes: 12, comments: 3, impressions: 480

get_follower_growth ​

Follower or subscriber growth per connected account. Counts are captured once a day. LinkedIn and TikTok cannot report followers.

ParameterTypeRequiredDefaultDescription
periodlast_day | last_week | last_month | last_3months | last_yearnolast 30 daysTime window
connectionstringnoallOnly this account, by slug
platformstringnoallOnly accounts on this platform
json
{ "name": "get_follower_growth", "arguments": { "period": "last_3months" } }
Follower growth 2026-08-14 → 2026-11-13
Total: 5340 followers, +212

  · x-mybrand: 4200 followers, +180 (+4.48%)
  · bluesky-mybrand: 1140 followers, +32 (+2.89%)
  · linkedin-me: follower count not available on linkedin

A new account shows first daily snapshot pending until its first snapshot.

compare_accounts ​

Compares accounts for a window: followers and change, posts, total engagement, engagement per post, engagement rate and per-follower rate. Sorted by engagement. Inputs are the same as get_follower_growth.

json
{ "name": "compare_accounts", "arguments": { "period": "last_month" } }
Account comparison 2026-10-14 → 2026-11-13

  · x-mybrand [x]: 4200 followers (+180), 12 posts, 424 engagement (35.33/post), 2.02% rate, 0.84% per follower
  · bluesky-mybrand [bluesky]: 1140 followers (+32), 9 posts, 150 engagement (16.67/post), 0% rate, 1.46% per follower

Engagement is likes plus comments plus shares plus saves; rate is engagement divided by impressions.

get_usage ​

Shows usage against plan limits: posts this month, X posts, connected accounts and storage. Check it before connecting accounts or posting in bulk.

Input: none.

json
{ "name": "get_usage", "arguments": {} }
Usage (free plan):

Posts this month: 12 / 30 (18 left)
X posts this month: 2 / 5 (3 left) (~$0.00 X spend)
Connected accounts: 2 / 3 (1 left)
Storage: 120MB / 1.0GB (904MB left)

An unlimited dimension reads <used> / unlimited.

generate_caption ​

Generates captions with AI from a description, a URL or a brief.

ParameterTypeRequiredDescription
descriptionstringyesWhat to post about, or the raw content to work from
platformsstring[] (at least 1)yesPlatform types for tone, for example ["linkedin", "x"]. These are platform names, not connection slugs
toneprofessional | casual | humorous | inspirational | informativenoWriting tone
json
{
  "name": "generate_caption",
  "arguments": {
    "description": "Launch of our new analytics dashboard",
    "platforms": ["linkedin", "x"],
    "tone": "professional"
  }
}
Generated captions:

[linkedin]
<caption text>

---

[x]
<caption text>

The workspace needs its own AI provider key. Without one the result is Error: No AI provider key set for this workspace. Add your own key in Settings → AI to use AI features. AI endpoints allow 10 requests per minute. See AI composer and BYOK. The tool generates text only; hashtag suggestions exist in the REST API but not as an MCP tool.

FAQ ​

Can the MCP server upload a file from my computer? ​

No. post_image and post_video take public URLs or media library IDs. Upload first with the SDK, CLI or REST API, or reuse an ID from list_media.

Why does the tool say "submitted" but nothing is live yet? ​

Posting tools return when the post is accepted. Publishing runs in the background. Call check_post_status with the returned ID. A key with requireApproval leaves the post in pending_approval until a teammate approves it.

Which tools change data? ​

post_text, post_image, post_video, schedule_post, schedule_posts, update_post, retry_post, publish_draft, delete_media, refresh_connection and reconnect_connection change state. The rest only read, or generate text.

Next steps ​