SkedCast
Read, schedule and publish social media posts across connected accounts, and read analytics, from any MCP client.
Что умеет
- List Scheduled Posts: List the workspace’s composed posts (queue / drafts / published), most recently CREATED first, with optional status / client / platform / free-text filters and a creation-date wi
- List Post Targets: List individual post DESTINATIONS — one row per platform account a post goes to — with optional status / statuses / client / account / platform / free-text filters and a SCHEDULE-ti
- Get Capabilities: The per-platform composing rulebook: caption and hashtag limits, whether text-only is allowed, media rules per kind (allowed, whether OUR adapter can publish it, min/max count, accep
Какие данные видит
Нужен ли аккаунт
Не нужен: сервер работает без входа
Read, schedule and publish social media posts across connected accounts, and read analytics, from any MCP client. Built for agencies managing many clients. Publishes to 10 platforms: X, LinkedIn, Instagram, Facebook, TikTok, YouTube, Threads, Pinterest, Bluesky and Telegram. OAuth 2.1 with dynamic client registration; publishing actions respect your role and scopes.
Как подключить
Как подключить SkedCast к Claude
Адрес сервера, который нужно вставить в настройках Claude:
https://skedcast--hello-qv9y.run.tools
- Откройте Claude (сайт claude.ai или приложение для компьютера).
- Перейдите в Настройки → Коннекторы (в английском интерфейсе: Settings → Connectors).
- Нажмите Добавить пользовательский коннектор (Add custom connector).
- Вставьте адрес сервера, скопированный ниже, в поле URL удалённого MCP-сервера и нажмите Добавить.
- В чате нажмите + → Коннекторы и включите новый коннектор.
Пользовательские коннекторы доступны на тарифах Free, Pro, Max, Team и Enterprise. На Free можно добавить только один. В Team и Enterprise коннектор сначала добавляет владелец организации в Настройки организации → Коннекторы.
Авторизация
После нажатия Добавить откроется окно входа в сервис. Войдите под своим аккаунтом и подтвердите доступ. Пароль Claude не видит.
Как подключить SkedCast к ChatGPT
Адрес сервера, который нужно вставить в настройках ChatGPT:
https://skedcast--hello-qv9y.run.tools
- Откройте ChatGPT в браузере (chatgpt.com). Нужен тариф Plus, Pro, Business, Enterprise или Edu.
- Один раз включите режим разработчика: Настройки → Приложения → Дополнительные настройки → Режим разработчика (Settings → Apps → Advanced settings → Developer mode).
- Откройте Настройки → Коннекторы и нажмите Создать (Create).
- Заполните форму: Название (любое), Описание (одна фраза, что делает сервис), URL MCP-сервера (скопируйте ниже).
- В поле Аутентификация выберите OAuth, если сервис требует вход, иначе Нет. Нажмите Создать.
- В новом чате откройте + → Приложения/Коннекторы и включите коннектор.
Название раздела у OpenAI менялось (Connectors → Apps/Plugins). Если пункт называется иначе, ищите «режим разработчика» в настройках. В рабочих пространствах Business/Enterprise администратор должен разрешить пользовательские коннекторы.
Авторизация
При первом использовании ChatGPT откроет окно входа в сервис. Войдите и подтвердите доступ.
Как подключить SkedCast к Cursor
Адрес сервера, который нужно вставить в настройках Cursor:
https://skedcast--hello-qv9y.run.tools
Быстрый способ: нажмите кнопку Открыть в Cursor ниже, Cursor сам предложит добавить сервер.
Вручную:
- В Cursor откройте Settings → Cursor Settings → MCP и нажмите Add new global MCP server.
- Вставьте JSON, скопированный ниже, в открывшийся файл
~/.cursor/mcp.json(для одного проекта:.cursor/mcp.jsonв корне проекта). - Сохраните файл. Сервер появится в списке MCP; при необходимости пройдите авторизацию по кнопке рядом с ним.
Авторизация
Если сервис требует вход, рядом с сервером в списке MCP появится кнопка авторизации.
Список инструментов сервера (58)
Технические названия из tools/list. Нужны только разработчикам.
| list_scheduled_posts | List the workspace’s composed posts (queue / drafts / published), most recently CREATED first, with optional status / client / platform / free-text filters and a creation-date window. Keyset-paginated: pass the returned nextCursor to page. Note the ordering and the from/to window are both on when a post was AUTHORED, not when it publishes — to reason about publish times, read each post’s targets. |
| list_post_targets | List individual post DESTINATIONS — one row per platform account a post goes to — with optional status / statuses / client / account / platform / free-text filters and a SCHEDULE-time window. This is the tool to ask "what publishes on this date": unlike list_scheduled_posts, from/to and sort=scheduled_at are about when a target GOES OUT, not when its post was authored. The page carries `total` (matching targets) and `totalPosts` (distinct parent posts) alongside `nextCursor`, so a caller can tell a full page from a complete set instead of assuming the default 25 rows are everything. Keyset-paginated: pass the returned nextCursor to page. |
| get_capabilities | The per-platform composing rulebook: caption and hashtag limits, whether text-only is allowed, media rules per kind (allowed, whether OUR adapter can publish it, min/max count, accepted formats, file-size ceiling, duration bounds, aspect-ratio range), post types, native-scheduling window, default cadence, first-comment support, and the `variants[].overrides` keys each platform REQUIRES or accepts. Read this before composing instead of discovering a limit by failing a publish. Omit `platform` for all of them. |
| get_post | Get a single post with its per-platform variants and resolved targets. |
| list_clients | List the workspace’s client groups (brands / influencers), newest first. Keyset-paginated: pass the returned nextCursor to page. |
| list_accounts | List connected social accounts (with token health), optionally filtered by client / platform. Keyset-paginated: pass the returned nextCursor to page. |
| get_analytics_overview | Get the analytics overview over an optional date window and client / account filter. Returns `summary` (postsPublished, failed, rateLimited, reach, impressions, clicks, likes, comments, shares, saves, engagementRate as a 0-1 fraction, costUsd, followers, followersGained, followersLost), `summary.audience` when the platform reports profile-level activity (profileViews, accountsEngaged, profileLinkTaps, videoViews, videoWatchTimeMinutes, contentPlays), `platforms[]` (the same totals per platform, plus a daily impressions sparkline), `accounts[]` (per connected channel, with profileStats), and `series[]` (one entry per day). A metric a platform does not expose is omitted or null, never a fabricated 0. Use get_post_analytics for per-post grain. |
| get_post_analytics | Per-post performance — complements get_analytics_overview with post grain. With postId: that post’s lifetime metrics broken down by target. Without: one keyset page of per-post rows (newest-first) over an optional date window and client / account / platform filter; pass the returned nextCursor to page. Every row carries impressions, reach, likes, comments, shares, saves, clicks, engagementRate and permalink. Where the platform reports them it also carries reactionsByType (Facebook: like/love/wow/haha/sad/angry), clicksByType, profileActivity, navigation (Instagram Stories: forward/back/exit), follows, profileVisits, reposts, quotes, linkClicks, totalInteractions, videoViews, videoCompletions, skipRate, watchTimeMinutes, avgViewDurationSeconds, avgViewPercentage, subscribersGained/Lost, audienceRetention, trafficSources and audienceBreakdown. null means the platform does not report that metric for this post — it never means zero. platformRemovedAt is set when the post was deleted on the platform; its figures are then final. |
| get_account_analytics | Analytics for ONE connected channel over an optional date window — the account grain that sits between get_analytics_overview (whole workspace) and get_post_analytics (one post). Returns `totals` and a daily `series`, plus two things available nowhere else: `audience` (profile-level activity the platform reports about the PROFILE rather than any post — profileViews, accountsEngaged, profileLinkTaps, videoViews, videoWatchTimeMinutes, contentPlays), and `demographics` (follower demographics as dimension → label → count, e.g. { country: { US: 120 }, age: { '25-34': 90 } }). demographics is a snapshot of the audience TODAY, not a window aggregate, and Meta suppresses it entirely below 100 followers — absent means not reported, never zero. Use list_accounts first to get a socialAccountId. |
| list_library_assets | List media assets in the content library (DAM), with optional kind / folder / label / client / status / search filters. Newest-uploaded first. Keyset-paginated: pass the returned nextCursor to page. |
| get_agency | Get the current workspace (agency) profile — name, plan, app mode, settings, and the caller’s role. |
| list_reports | List the workspace’s saved analytics report definitions (CSV/PDF), newest first. Keyset-paginated: pass the returned nextCursor to page. |
| get_best_times | Get the worker-derived best posting times (strongest-first slots), optionally filtered by client / platform. |
| list_approvals | List the workspace's approval queue (pending and decided requests), newest-first, with optional status / post filters. Each row carries a preview of the gated post. |
| get_posting_limits | Anti-ban posting limits (cadence): pass socialAccountId for one account’s view (effective daily cap / spacing, used-today, reset instant), or omit it for the whole-tenant overview of every active channel plus the tenant bypass flag. |
| get_quota | Read your adaptive-quota-pool budget for every scarce channel (today: YouTube uploads) BEFORE planning a batch: guaranteed slice, used, best-effort burst headroom, tomorrow’s guarantee tonight, and the window reset (ISO-8601 UTC; null for rolling windows). Read-only. |
| list_campaigns | List the workspace's campaigns (named post groupings), alphabetically, optionally filtered by client / status. Requires the campaigns.read scope. |
| create_post | Compose a post and fan it out across the selected accounts (or save a draft with saveDraft:true). This creates real outbound content — confirm with the user before calling. Retry-safe: retrying with IDENTICAL arguments replays the original result instead of creating a duplicate post (the idempotency key is derived from the arguments). Requires the posts.compose scope. |
| validate_post | Dry-run a compose request and get the per-platform verdict WITHOUT writing anything: same arguments as create_post, same validation gate, no post row, no draft, no idempotency record. Returns `{ valid, platforms[], estimatedCostUsd, verdicts? }`, where each platform carries its own `valid` plus the `issues` that would block it. Use this instead of creating a far-future post and cancelling it. Note it does NOT run cadence or quota admission, so `valid: true` means the SHAPE is acceptable, not that a publish cannot later be deferred. Requires the posts.compose scope. |
| revise_post | Change the CONTENT of an already-scheduled post — caption, media, cover, alt text, per-platform overrides — without disturbing its destinations. Nothing about the fan-out is rewritten: the publisher reads content at publish time, so every destination picks the change up on its own schedule. Send only the fields you are changing; an omitted field is left alone, and `variants` are merged by platform. Destinations and schedule are NOT editable here — use reschedule_post / cancel_post / bulk_post_target_action for those. REFUSES, naming the destinations that blocked it, when any has already published or has been handed to the publisher. If the post was already APPROVED, the edit returns the whole post to review and nothing publishes until it is approved again — the result's `reGated` says so. A write action — confirm with the user before calling. Requires the posts.compose scope. |
| update_post | Replace a DRAFT post in place — its content, media, targets, and schedule. Only draft posts can be updated (a scheduled or published post returns a conflict). This rewrites a real draft — confirm with the user before calling. Requires the posts.compose scope. |
| import_media | Ingest an external image/video into the content library by URL — the file must already be reachable at a public URL. For bytes you already hold (an image your client just rendered, or a file on the caller’s own machine) use `upload_media` instead; this tool cannot accept file contents. This creates a real library asset — confirm with the user before calling. Requires the media.manage scope. |
| upload_media | Upload an image or video from your own machine into the content library, and get back a media id usable as `create_post`'s mediaIds. Three phases: `inline` sends the file base64 in this call (≤18 MiB, works in any client); `start` returns a presigned URL your client PUTs the bytes to directly (any size, needs a client that can make HTTP requests — e.g. a shell); `finish` registers what `start` uploaded. For a file already on the public internet use `import_media` instead. This creates a real library asset — confirm with the user before calling. Requires the media.manage scope. |
| reschedule_post | Move a pending post target to a new time — provide an absolute scheduledAt (ISO-8601 with offset) or a relative shiftMinutes. This changes a real scheduled post — confirm with the user before calling. Requires the posts.compose scope. |
| cancel_post | Cancel a still-pending post target (draft / queued / rate-limited / failed) before it publishes; an already-published target cannot be canceled. This stops a real scheduled post — confirm with the user before calling. Requires the posts.compose scope. |
| bulk_post_target_action | Reschedule, retry or cancel up to 5000 post TARGETS in one call — the batch form of reschedule_post / retry_post / cancel_post. `action` is `reschedule` | `retry` | `cancel`. For `reschedule`, pass either `params.scheduledAt` (an absolute instant) or `params.shiftMinutes` (relative), optionally with `params.respectCadence`; a relative shift is all-or-nothing across the batch. Returns `{ jobId, accepted, skipped, skippedReasons? }` — a skipped target is reported, never silently dropped. This changes real scheduled content — confirm with the user before calling. Requires the posts.compose scope. |
| retry_post | Re-queue a failed or rate-limited post target so it publishes again immediately; only a failed / rate-limited target can be retried. This re-publishes a real post — confirm with the user before calling. Requires the posts.compose scope. |
| set_post_recycle | Set, update, or disable a post's evergreen recycle settings (enabled / intervalDays / times / endDate / maxRecycles) — the shared recycle-config contract. Pass enabled:false to pause recycling without losing the settings. This changes how a real post republishes — confirm with the user before calling. Requires the posts.compose scope. |
| shift_campaign | Move a whole campaign's still-pending schedule by a relative shiftMinutes (non-zero, ±1 year) — delegates to the existing reschedule engine and returns the accepted / skipped counts. This moves real scheduled posts in bulk — confirm with the user before calling. Requires the campaigns.manage scope. |
| decide_approval | Approve, reject, or request changes on a PENDING approval request, with an optional reviewer note. Approving releases the gated post for publishing; an already-decided request returns a conflict. This gates real outbound content — confirm with the user before calling. Requires the approvals.decide scope. |
| list_webhooks | List the workspace's outbound webhook endpoints (url, subscribed events, active flag; signing secret masked), newest-first. Requires the webhooks.read scope. |
| create_webhook | Register an outbound webhook endpoint to receive HMAC-signed event deliveries (post.scheduled, post.published, post.failed, target.rate_limited, account.disconnected, account.token_expiring, approval.requested, approval.decided, media.ready, report.completed). The signing secret is returned ONCE. This creates a real subscription — confirm with the user before calling. Requires the webhooks.manage scope. |
| delete_webhook | Delete an outbound webhook endpoint by id (its delivery history cascades). Idempotent. This removes a real subscription — confirm with the user before calling. Requires the webhooks.delete scope. |
| get_webhook | Read one webhook endpoint: its URL, subscribed events, active state, consecutive-failure count and, when it has been auto-disabled, when and why. The signing secret is NEVER returned here — it is shown once at creation and once on rotation. Requires the webhooks.read scope. |
| list_webhook_deliveries | Read the delivery log for one endpoint — each attempt with its event type, response status, error and timing. This is how you find out WHY an endpoint stopped receiving: a 401 from your server, a timeout, or an auto-disable after repeated failures. Keyset-paginated: pass the returned nextCursor to page. Requires the webhooks.read scope. |
| update_webhook | Change an endpoint’s URL, its subscribed event list, or whether it is active. Re-enabling an endpoint that was auto-disabled after repeated failures is done here. The event list REPLACES the previous one — send the full set, not a delta. A write action — confirm with the user before calling. Requires the webhooks.manage scope and the webhooks feature. |
| test_webhook | Send a `webhook.test` delivery to one endpoint and report the outcome, so you can prove an endpoint is reachable and correctly verifying signatures WITHOUT waiting for a real event. This performs a real outbound HTTP request to the customer’s URL — confirm with the user before calling. Requires the webhooks.manage scope and the webhooks feature. |
| rotate_webhook_secret | Mint a NEW signing secret for one endpoint and return it. THE SECRET IS SHOWN ONCE and is not readable again — hand it to the user, and do not repeat it in summaries, logs or files. The previous secret keeps verifying for a short overlap so the customer can redeploy without dropping deliveries. A write action — confirm with the user before calling. Requires the webhooks.manage scope and the webhooks feature. |
| create_client | Create a new client group (a brand or influencer whose accounts are managed together). This adds a real client to the workspace — confirm with the user before calling. Requires the clients.manage scope. |
| get_campaign | Read one campaign with its detail view — name, description, status, colour, date range, owning client, and its post counts. Requires the campaigns.read scope. |
| create_campaign | Create a campaign — a named group of posts with an optional client, colour and date range. Posts are added with assign_to_campaign. A write action — confirm with the user before calling. Requires the campaigns.manage scope. |
| update_campaign | Change a campaign’s name, description, status, colour or date range. At least one field is required. A write action — confirm with the user before calling. Requires the campaigns.manage scope. |
| delete_campaign | Delete a campaign. The POSTS in it are not deleted — they lose their campaign grouping and keep their own schedules. A write action — confirm with the user before calling. Requires the campaigns.manage scope. |
| assign_to_campaign | Add up to 500 existing posts to a campaign. Grouping only — nothing about a post’s content or schedule changes. A write action — confirm with the user before calling. Requires the campaigns.manage scope. |
| unassign_from_campaign | Remove posts from a campaign. Grouping only — the posts themselves and their schedules are untouched. A write action — confirm with the user before calling. Requires the campaigns.manage scope. |
| get_client | Read one client group in full — its name, type, approval policy, posting rules, brand voice and default timezone. Requires the clients.read scope. |
| update_client | Change a client’s name, type, approval policy, posting rules, brand voice or default timezone. A write action — confirm with the user before calling. Requires the clients.manage scope. |
| delete_client | Archive a client group. OWNER ONLY — a Manager holding the clients.manage scope cannot do this. A write action — confirm with the user before calling. |
| get_post_recycle | Read one post’s evergreen re-posting configuration — interval, times, end date, remaining recycles — plus the worker’s bookkeeping (when it last recycled, how many times). Returns null when the post is not enrolled. Requires the posts.read scope. |
| clear_post_recycle | Turn OFF evergreen re-posting for a post. Idempotent — clearing a post that was not enrolled succeeds. Already-scheduled recycled copies are not retracted by this; cancel those with cancel_post or bulk_post_target_action. A write action — confirm with the user before calling. Requires the posts.compose scope. |
| get_post_target | Read a single fan-out destination in full — its status, scheduled time, platform, account, published permalink and external id, and its failure reason when it failed. Requires the posts.read scope. |
| get_account | Read one connected social account in full — platform, handle, display name, avatar, status (including whether it needs re-authorisation), owning client and connection metadata. Requires the accounts.read scope. |
| get_approval | Read one approval request with the gated post’s preview and roll-up, so a reviewer can see WHAT they are deciding on before calling decide_approval. Requires the approvals.read scope. |
| get_media_asset | Read one content-library asset in full — filename, kind, size, dimensions, duration, folder, labels, alt text, pipeline status, and the `publishable` / `ready` flags plus the per-platform readiness map. Requires the media.read scope. |
| get_client_analytics | One client group’s analytics — totals, a per-platform breakdown and a time series. A different projection from get_analytics_overview filtered by client: this is the client rollup the console renders. Requires the analytics.read scope. |
| get_report | Read one report definition with its run history — each run’s status, window, and whether an export is available to download. Requires the reports.read scope. |
| download_report_export | Get a time-limited download URL for one completed report run’s export file. The URL expires, so fetch it when you are ready to use it rather than storing it. Requires the reports.read scope. |
| create_connect_invite | Mint a shareable self-connect link so a client can connect the requested platforms themselves. Returns the link + expiry; share it with the client. This creates a real invite — confirm with the user before calling. Requires the accounts.connect scope. |