PostKing MCP Server
One line summary: PostKing MCP server connects Claude or any MCP client to a PostKing account, letting you generate, schedule, publish, and analyze content across social media, blogs, landing pages, and SEO through natural conversation.
Authentication & account: device login (
login_start/login_complete),logout,whoami, credit balance (get_credits), API health, API key managementBrands: list/get/create brands, website onboarding crawl, set active brand, publishing mediums, onboarding status, members, per-platform social media rules
Social posts: AI-generate posts (single or bulk), create drafts, approve/schedule/reschedule/cancel/delete, view calendar, repurpose URLs/text/blogs into social or blog content
Writing tools: voice profiles, rewrite with voice, humanize text, AI-detection scoring, general text generation (emails, cover letters), content themes and content templates
Social accounts: check connected platforms, generate OAuth connect links, disconnect accounts
Blog: publications, generate/edit/publish/schedule/delete articles, authors, categories, RSS/Blogger import, CTAs, publishing to WordPress/Medium/Substack/Webflow
SEO / GEO pipeline: seeds → keywords → categorization → clusters → roadmap → briefs → approve auto-generates articles; plus keyword housekeeping, geo tagging, gap and competitor analysis, side pages
Landing & side pages: generate, section/layout edits, natural-language "vibe edit" with review/apply, version history and restore, publish, import bundles
Assets & visuals: asset library (upload/import CSV/URL/tags), stock image search, AI-suggested visuals, card templates and carousel rendering
Scheduling: weekly posting schedule get/set/enable/disable, run a single day on demand
Marketing intelligence: storylines (brief → strategy → execute), competitor tracking/comparison/overview, knowledge base, brand truths, audience ICP editing, trends
Analytics & ops: search performance, AI-answer-engine visibility and citations, ranked SEO/GEO worklist, async job polling (
get_job), dashboard deep links, domains and DNS verification, billing (credit packs and subscriptions)
Allows importing blog articles from Blogger via PostKing.
Allows publishing blog articles to Medium via PostKing.
Allows generating and rewriting content for Reddit posts, including subreddit discovery and suggestion.
Allows importing blog articles from RSS feeds via PostKing.
Allows publishing blog articles to Substack via PostKing.
Allows publishing blog articles to WordPress via PostKing.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@PostKing MCP Server generate a LinkedIn post about our new blog article"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
PostKing MCP Server
The official Model Context Protocol server for PostKing — an AI-powered content platform for social media scheduling, blog publishing, and brand management.
Connect Claude (Desktop, Cursor, or any MCP client) to your PostKing account and manage your entire content operation through conversation — generate posts, schedule them, repurpose URLs into social content, write and publish blog articles, generate landing pages and side pages, run SEO / GEO research and drafting, manage your asset library and weekly posting schedule, handle domains and API keys, and more.
The server exposes 291 tools across 33 modules — full parity with the postking-cli.
Transport note: All 291 tools are registered on both transports, including on the remote HTTP transport (
mcp.postking.app). The 4 authentication tools (login_start,login_complete,logout,whoami) stay registered there too — they just explain the OAuth bearer-token model instead of running a device-code flow, since that transport is already authenticated before any tool call happens.
Quick start
Claude Desktop
Option A — Via the GUI:
Open Claude Desktop → Settings (gear icon) → Developer → Edit Config
This opens
claude_desktop_config.jsonin your default editorPaste the following and save:
{
"mcpServers": {
"postking": {
"command": "npx",
"args": ["-y", "postking-mcp"]
}
}
}Restart Claude Desktop
Option B — Edit the config file directly:
Open ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or %APPDATA%\Claude\claude_desktop_config.json (Windows) in any text editor, paste the same JSON above, and save.
Once restarted, tell Claude: "Login to PostKing"
Claude Code (CLI)
claude mcp add postking -- npx -y postking-mcpHermes
npm i -g postking-mcp
hermes mcp add postking --command postking-mcpThen in Hermes: "Login to PostKing".
Cursor / other MCP clients
Use the same npx -y postking-mcp command in your client's MCP server config.
Related MCP server: social0-mcp
Login flow
No API keys to copy. PostKing uses a device login flow:
Tell Claude: "Login to PostKing"
Claude calls
login_start→ shows a URL and short codeVisit the URL in your browser, log in, approve
Tell Claude: "Done"
Claude calls
login_complete→ saves your token to~/.postking/credentials.json
You never need to log in again. The token is permanent.
What you can do
Authentication
Available on stdio/local transport only. Remote HTTP transport authenticates via OAuth bearer token before the session is created.
Tool | Description |
| Begin device login — get a URL and code to approve in browser |
| Finish login and save token after browser approval |
| Clear locally stored credentials |
| Return the profile of the currently authenticated user (email, plan, credit balance) |
Brands
Tool | Description |
| List all brands on your account |
| Set the default brand for this session |
| View brand profile — tone, audience, themes |
| Create a brand manually (step 1 of manual onboarding) |
| Crawl a website and auto-generate a brand profile + 10 themes (step 1 of website onboarding) |
| Save the list of platforms the brand publishes on (step 2 of onboarding) |
| Read which publishing platforms a brand posts to |
| Read the language a brand's AI-generated content is written in, plus the supported set |
| Set the generation language for all future content — |
| Poll background audience analysis + theme generation (step 3 of onboarding) |
Content themes
Tool | Description |
| List all content themes with IDs |
| AI-generate new themes (uses credits) |
| Update a theme's title or instructions |
| Remove a theme |
Social posts
Tool | Description |
| AI-generate a post for a platform |
| Save a manual post draft to one or more platforms |
| List posts filtered by status or platform |
| View a single post |
| Approve and schedule a draft post |
| Set a scheduled time on an existing post |
| Move a scheduled post to a new time |
| Replace a draft or scheduled post's text |
| Reply to an X (Twitter) post from the brand's account (PRO plan and above) |
| Cancel a scheduled post without deleting it |
| Cancel and delete a post |
| View upcoming scheduled content |
| Fill a date range with AI-generated posts |
Repurpose
Tool | Description |
| Turn a URL, text, or existing post into new social or blog content |
Voice profiles
Tool | Description |
| List available voice profiles |
| Rewrite text in a specific voice |
Social accounts
Tool | Description |
| List connected and disconnected platforms |
| Get a secure OAuth link to connect a platform |
| Disconnect a social account |
Reddit is a repurpose-to-Reddit workflow, not a scheduled publishing medium. Flow: reddit_generate_pool → reddit_get_pool → reddit_suggest → reddit_rewrite → reddit_list_posts.
Tool | Description |
| View the brand's saved pool of relevant subreddits, sorted by relevance score |
| Async: discover and score relevant subreddits for the brand by crawling Reddit |
| Return stats on the global subreddit dataset (informational only) |
| Sync: search Reddit for subreddits by user-directed queries (with free-text disambiguation context), ranked by subscribers and flagged against the brand pool — 15 credits per call |
| Add subreddits to the brand's pool by name (resolves live from Reddit; partial success reported per name) — free |
| Remove subreddits from the brand's pool by name (brand-scoped only; never touches the global cache) — free |
| Sync: suggest up to 8 best-fit subreddits for a specific piece of content, each with 2-3 posting angles, promotion mode, and buyer intent |
| Async: rewrite a blog article or raw content as a native Reddit post for a target subreddit |
| List saved Reddit posts (outputs of |
Blog
Tool | Description |
| List publications and articles (filterable by status) |
| List publications only |
| Create a new blog publication |
| Update an existing publication's title, description, domain/routing, or layout (partial update) |
| AI-generate a full blog article with optional voice |
| Fetch full article content, including the featured/header image ( |
| Poll generation/publish status for an article |
| Edit title, content, SEO fields, author, category, status, or the featured/header image ( |
| Permanently delete an article |
| List every CTA on an article individually, with raw anchor data — find a ctaId or an open anchor slot |
| Append a new CTA to an article without touching the existing ones |
| Edit one CTA by id (url/label/headline/body/style/anchor/sidePageId/slug) without touching the others |
| Remove one CTA by id without touching the others |
| Push to WordPress, Medium, Substack, etc. |
| List external platform connections |
| Import from RSS feed or Blogger URL |
| List blog authors |
| Create a new blog author |
| List categories for a publication |
| Create a new category |
| View SEO / GEO topic suggestions and completion stats |
SEO / GEO
Canonical flow: seo_add_seeds → seo_generate_keywords → seo_categorize → seo_generate_clusters → approve clusters → seo_generate_roadmap → review briefs → seo_approve_briefs (auto-fires article generation) → poll get_job → audit & publish.
Tool | Description |
| Seed SEO / GEO research with 3–10 topic keywords |
| Async: expand seeds into a full keyword universe (poll via |
| List researched keywords with intent, priority, and volume |
| Edit a keyword — override intent, adjust priority, set user tags, or exclude from clustering |
| Soft-delete a single keyword from the research set |
| Tag keywords by search intent and/or user tags |
| Async: group keywords into topic clusters (poll via |
| List keyword clusters with brief-generation status |
| Bulk-approve N clusters in one call, kicking off async brief generation for each |
| Approve a single cluster, gating brief generation for it |
| Reject a single cluster — marks it rejected and detaches its keywords |
| Bulk-reject N clusters in one call |
| Revert an approved cluster back to pending_review |
| Restore a rejected cluster back to pending_review |
| Turn one or more clusters into a prioritized content roadmap |
| List roadmap items (blog topics queued for writing) |
| Fetch a single roadmap item |
| Edit a roadmap item's title, status, or priority |
| Permanently delete a roadmap item |
| Roadmap completion stats |
| List content briefs across all clusters and statuses |
| Fetch a single brief including its full structured outline |
| Edit a brief's structured outline or approve/reject it |
| Bulk-approve briefs and auto-fire article generation |
| Re-run brief generation for a single brief |
| Re-resolve the brand truths a brief's page is written from |
| List generated results (blog articles, side pages, comparisons) from the SEO pipeline |
| Manual path: draft a blog article from a roadmap item (use only when not going through |
| Find keyword / topic gaps vs. existing content |
| Compare keyword coverage against a competitor domain |
| Publish or schedule an SEO-drafted article to a publication |
| Auto-suggest and assign side-page CTAs to published blog articles |
| Generate a side page optionally linked to an SEO cluster |
Landing pages
Tool | Description |
| List all landing pages for a brand |
| Create and AI-generate a new landing page (async; poll via |
| Import a static-build bundle (entry HTML + assets) hosted at URLs — for a local folder, use the |
| View a landing page including full section content |
| View the current unpublished draft |
| Edit landing page title or instructions (metadata only — does not touch page content) |
| Set one field (dot-path) or replace a whole section on a landing page's draft |
| Re-generate a landing page's content using AI (async; poll via |
| Apply a natural-language AI edit to a landing page (async; propose → review → apply flow) |
| Poll vibe-edit session status and review the field-level |
| Apply a completed vibe edit (all or a subset) to the draft as one new version |
| Reorder and/or toggle visibility of landing page sections |
| Publish the current draft |
| Permanently delete a landing page |
| List historical versions of a landing page |
| View a specific historical version |
| Roll the draft back to a prior version |
| Permanently delete a historical version |
| List side pages attached to a landing page |
| AI-generate a side page under a parent landing page (async; poll via |
| View a side page including sections and rendered HTML |
| Update the instructions or metadata of a side page |
| Update the content of a specific section within a side page |
| Publish or unpublish a side page |
| Delete a side page |
Weekly schedule
Tool | Description |
| Fetch the active weekly posting schedule |
| Configure platforms, times, and themes per day |
| Turn the weekly auto-generator on |
| Turn the weekly auto-generator off |
| Remove the schedule entirely |
| Generate a single day's posts on demand |
Visuals (asset library)
Tool | Description |
| List brand assets (images/videos) with filters |
| Fetch a single asset's metadata and URL |
| Upload an image/video (base64) |
| Pull an asset from a remote URL |
| Batch-import up to 50 assets from a list of public URLs |
| Add or remove tags on an asset |
| Remove an asset (requires confirm) |
| List all tags used across assets |
| Get AI-suggested assets for a specific post |
| Search stock-photo libraries |
Post visuals (cards & carousels)
Tool | Description |
| Fetch available visual options for a post (card templates, library matches, stock photos) |
| Refresh stock photos and quote/card templates for a post (does not re-match library assets) |
| Select a template/stock visual, or attach one or more of your own library assets, for a post on a given platform |
| Remove the selected visual from a post |
| List the carousel cards attached to a post |
| Edit a single carousel card by 1-based index |
| Bulk-replace all carousel cards for a post |
| Render a carousel PDF from the current cards |
Jobs (async poller)
Tool | Description |
| List recent async jobs for the active brand |
| List recent Operations (the newer async-op system) with kind and state filters |
| Poll a specific operation by ID or pollUrl; supports |
| Cancel a pending or running job/operation by operationId |
API keys (self-service)
Tool | Description |
| List your PostKing API keys |
| Mint a new API key |
| Revoke an API key (requires confirm) |
Domains
Tool | Description |
| List domains with verification and SSL status |
| Add a new custom domain |
| Check DNS and activate a domain |
| Remove a domain (content is preserved) |
| Wire a verified domain to a blog publication |
Writing tools
Tool | Description |
| Rewrite text using a voice profile or brand rules |
| Reduce AI detection signals in text |
| Score text for AI detection likelihood |
| Check your current credit balance and free-tier status |
| Check PostKing API health and version (no authentication required) |
Storylines (marketing plans)
Canonical flow: storyline_create → storyline_clarify (loop) → storyline_generate_brief (poll) → storyline_get → storyline_edit_brief → storyline_confirm_brief → storyline_generate_strategy (poll) → curate line items → storyline_estimate → storyline_execute (poll).
Tool | Description |
| List the brand's storylines (marketing plans) |
| Create a new storyline with a campaign goal or intent prompt |
| Fetch a single storyline with full state (brief, strategy, line items, status) |
| Update storyline metadata: title, live status, or start/end/launch dates |
| Archive (soft-delete) a storyline — reversible via |
| Restore an archived storyline back to active state |
| Run the intake/clarification step (iterative Q&A until system has enough context) |
| Async: generate the marketing brief — positioning, key messages, audience, timing (poll via |
| Manually set (replace) the full brief for a storyline |
| AI-edit the brief using natural-language instructions |
| Confirm the brief and gate strategy generation |
| Fetch the generated strategy and its line items |
| Async: generate the execution strategy and line item set (poll via |
| AI-edit the strategy using natural-language instructions |
| Dry-run credit estimate for executing the storyline |
| Add a new content line item to the strategy |
| Edit an existing line item (channel, type, title, selected flag, etc.) |
| Permanently remove a line item from the strategy (confirm: true required) |
| Async: regenerate a single strategy line item (poll via |
| Async: generate all selected drafts from the strategy (poll via |
Competitors (intelligence)
Canonical flow: competitor_probe → competitor_probe_status → competitor_probe_classify → competitor_add (poll) → competitor_analyze (poll) → competitor_list → competitor_get_comparison/recompute → competitor_get_overview/generate_overview (poll). Namespace: competitor_* (distinct from seo_competitor/seo_gap).
Tool | Description |
| List tracked competitors with status, analysis state, and a dashboard deep-link |
| Async: batch-add 1–20 competitor domains and trigger crawl + profile analysis (poll via |
| Update competitor settings — e.g. toggle |
| Soft-delete a tracked competitor (restorable via |
| Async: re-analyze pending or failed competitor rows (poll via |
| Async: refresh all active competitors — re-crawl + re-profile (poll via |
| Get the brand's head-to-head competitive comparison |
| Trigger a fresh comparison recompute (call after adding/analyzing competitors) |
| Get the saved competitive landscape overview |
| Async: generate a fresh AI-synthesized landscape overview (poll via |
| List SEO keyword sources that feed the competitive comparison |
| Async: discover and surface rival domain candidates based on the brand (poll via |
| Check the status of a probe run and list discovered candidates |
| Classify a probe candidate as add, skip, or blacklist |
Knowledge base
Canonical flow: knowledge_list → knowledge_get → knowledge_create (poll get_job) → knowledge_update → knowledge_delete.
Tool | Description |
| List knowledge base items — filter by tag, active status, or global flag |
| Async: create a knowledge base item with optional AI enrichment (poll via |
| Fetch a single knowledge base item with full content and metadata |
| Update a knowledge base item's name, description, content, or tags |
| Soft-delete a knowledge base item |
Brand truth
Atomic facts/observations about a brand (hard facts, audience truths, strategy notes, negative space, content insights, topics) used to ground generation. Brand truths are maintained by PostKing's own model — callers never write name/description/content/type/tags/personaScope directly. Canonical flow: brand_truth_list → brand_truth_get → brand_truth_create (LLM extraction decides what to store) → brand_truth_update (LLM-mediated correction, or pin toggle) → brand_truth_delete (soft) → brand_truth_restore if needed.
Tool | Description |
| List stored brand truths — filter by type, personaScope, tags, or free-text query; |
| Fetch a single brand truth with full content and metadata |
| Describe facts in plain language; an LLM extraction pipeline decides which atomic truths to store vs skip (returns |
| Describe a correction in plain language and/or toggle |
| Soft-delete a truth (undoable) and record rejection memory so it stops being re-suggested |
| Undo a |
Audience / ICP
The brand's audience intelligence (ideal customer profile) mined from its website + onboarding. Canonical flow: get_audience → preview_audience_edit (discover valid sections) → edit_audience (async LLM ai-edit; poll get_job).
Tool | Description |
| Fetch the brand's ICP — structured |
| Read-only: discover which |
| Async LLM ai-edit of the audience/ICP ( |
Trends and content templates
Canonical flow: trends_list → template_extract OR (template_list + template_pick) → template_create → existing post-generation tools. Note: trends_list is account-scoped (no brand required).
Tool | Description |
| List trending posts by niche and platform — account-scoped, no brand required |
| List saved content templates for the brand |
| Save or build a new content template |
| Update a template's title, content, or favorite flag |
| Delete a saved content template |
| AI: deconstruct a trending post into a reusable content template |
| AI: score and rank existing templates for a given theme or content goal |
Billing (agent wallet + subscription)
Canonical flow (one-off): billing_list_packs → billing_topup → (Stripe Link or browser) → billing_wallet (poll until balance rises). Subscription: billing_list_tiers → billing_subscribe → (human or first-invoice Link) → subscription activates automatically.
Tool | Description |
| List available agent credit packs with SKU, price, and credit amount |
| Create a Stripe Checkout session to top up the agent wallet with a one-off credit pack |
| Fetch the agent's prepaid credit balance and recent ledger entries |
| List available PostKing subscription tiers with pricing and monthly credits |
| Create a Stripe Checkout session for a GROWTH, PRO, or ENTERPRISE subscription |
Search performance & AI visibility
Canonical flow: search_sources (is a connector even live?) → search_performance (SEO clicks/impressions/CTR/position) → search_ai_visibility / search_ai_citations (AI-answer-engine visibility) → search_worklist ("do this next", synthesized from all of the above).
Tool | Description |
| List the brand's connected search-performance sources (Google Search Console, Bing Webmaster, Google Analytics) with status and last sync time |
| Search Console (Google/Bing) + GA4 performance readout — clicks, impressions, CTR, position; section-selectable (summary/queries/pages/timeseries) |
| Deep AI Dive (GEO) visibility readout — mention/citation coverage vs. competitors across AI answer engines (Google AI Overview, ChatGPT, Perplexity, Claude), by topic. Requires PRO+ tier |
| Bing "AI Performance" citation readout — daily citation counts plus the latest grounding-query and cited-page snapshots from an imported CSV export |
| Ranked "do this next" SEO + GEO worklist synthesized from the tools above |
Dashboard
Tool | Description |
| Get a clickable browser URL to any section of the PostKing dashboard (overview, SEO, posts, blogs, landing pages, reddit, storylines, knowledge, trends, competitors, search performance, jobs, etc.) |
Guided prompts
The server ships with built-in prompts accessible from the prompt picker in Claude Desktop:
Prompt | Description |
| First-time setup: login → brand → connect → first post |
| URL/text → repurpose → draft → approve → calendar |
| Check and connect LinkedIn, X, Instagram, Threads, Facebook |
| View, reschedule, and delete posts |
| Generate, edit, and organize content themes |
| Generate, edit, and publish blog posts |
| Apply a voice style to generated or rewritten content |
| Full marketing storyline: clarify → brief → strategy → curate → execute |
| Build competitive intelligence: probe → add → analyze → comparison → overview |
| Browse, create, update, and soft-delete brand knowledge base items |
| Browse trending posts, extract/pick a template, then generate a post |
Example workflows
Repurpose a blog post to LinkedIn and X:
"Repurpose https://myblog.com/my-article for LinkedIn and X, using my brand voice"
Generate and schedule a week of content:
"Generate 7 LinkedIn posts using my growth themes, schedule them daily at 9am starting Monday"
Write and publish a blog post:
"Write a 1500-word post about AI productivity tools, publish it to my blog"
Import and repurpose existing content:
"Import the last 20 posts from https://myblog.com/feed and convert the top 5 into LinkedIn posts"
Requirements
Node.js 18 or later
A PostKing account — sign up free at postking.app
Publishing to external platforms
PostKing supports publishing blog articles directly to:
WordPress (via REST API)
Medium
Substack
Webflow
Any platform with a publishing connection
Set up connections in your PostKing dashboard under Blog → Publishing Connections, then use publish_blog_article from Claude.
Development
git clone https://github.com/bitsandtea/postking-mcp
cd postking-mcp
npm install
npm run buildTest locally by pointing Claude Desktop at the built file:
{
"mcpServers": {
"postking": {
"command": "node",
"args": ["/absolute/path/to/postking-mcp/dist/index.js"]
}
}
}Environment variables
Variable | Default | Description |
|
| Override the API base URL |
| — | Skip device login by providing a token directly |
Contributing
Issues and pull requests are welcome. This repo is the MCP client layer only — it calls the PostKing API and exposes tools to any MCP-compatible AI client. If you find a bug, want to add a tool, or improve the prompts, open an issue or PR.
License
MIT
Available Tools
243 toolsadd_domainAInspect
Add a new custom domain to the active brand. After adding, call verify_domain to check DNS and activate it.
Inputs: domain (required), brandId, isPrimary, primaryContentType.
apply_vibe_editAInspect
Applies a completed vibe edit (from vibe_edit_landing_page) to the DRAFT as ONE new version. Pass exactly one of: all=true (accept every change), indices (subset by their index from get_vibe_edit_status), or paths (subset by their path). This does NOT publish — call publish_landing_page next to go live. Can be undone via restore_lp_version using the returned previousVersionId. If the draft has moved on since the edit was proposed (stale session), this returns a structured { error: 'stale_session', ... } payload instead of applying — either re-run vibe_edit_landing_page against the current draft, or retry this call with force=true to layer the selected changes onto the current draft.
Inputs: slug (required), operationId (required), all, name, +4 more.
approve_postAInspect
Approve and schedule a draft post. Requires a future datetime. The scheduledAt must be an ISO 8601 UTC datetime, e.g. 2026-03-11T09:00:00Z. After approving, the post status becomes 'scheduled'.
Inputs: postId (required), scheduledAt (required), timezone.
assign_asset_to_slotAInspect
Assign, reassign, or clear the asset in a landing-page or side-page slot. slotKey is a dotted key like 'hero.backgroundVideo' or 'cta.image' (discover valid keys with list_asset_slots). For array slots pass assetIds; for single slots pass assetId. The asset must already be in the brand's library (see list_assets / upload_asset / import_asset_from_url) and match the slot's media type. Pass sidePageSlug to target a side page. Set clear:true (or assetId:null) to empty the slot. Synchronous — the change applies immediately, no polling. Main-LP changes create a new draft version.
Inputs: slug (required), slotKey (required), clear, assetId, +3 more.
billing_list_packsAInspect
List available credit packs for one-off top-ups. Returns all packs with their SKU, price in USD, and credit amount. Call this tool first to show the user their options, then ask which pack they want. Only after the user explicitly chooses a pack, call billing_topup with that packSku.
Inputs: no named parameters.
billing_list_tiersAInspect
List available PostKing subscription tiers (GROWTH, PRO, ENTERPRISE). Returns each tier's name, price in USD, monthly credits, and billing interval options. Use billing_subscribe to create a subscription Checkout session for a chosen tier.
Inputs: no named parameters.
billing_subscribeAInspect
Create a Stripe Checkout session for a PostKing subscription. Returns { checkoutUrl, sessionId, tier, interval, amountUsd }. Subscription credits refill User.credits each billing period. The subscription Checkout is best completed by a human; the Link virtual card covers the first invoice only (renewals need a durable payment method).
Inputs: tier (required), interval.
billing_topupAInspect
Top up credits by charging the account's card on file (Stripe off-session). Prefers the headless path — no checkout link required. IMPORTANT: Only call this tool after the USER has explicitly chosen a specific pack — it triggers a real charge. To show the user their options first, call billing_list_packs and present the results; do NOT pick a pack on the user's behalf. The response is ONE OF two shapes: (1) Headless success (default when a card is on file): { status: 'paid', paymentIntentId, amountUsd, credits, balance, packSku, cardLast4/receiptUrl when available }. When you receive status === 'paid', the payment has already completed and the credits are in the wallet NOW. Announce to the user: payment ID, last-4 card digits, credits added, and new balance. You are DONE — do NOT call billing_wallet to poll. (2) Checkout fallback (only when there is no card on file): { checkoutUrl, sessionId, amountUsd, credits, packSku }. When you receive checkoutUrl, hand that link to the user so they can complete payment in their browser. Valid skus: agent_4 ($4 / 160 credits), agent_5 ($5 / 220 credits), agent_25 ($25 / 1200 credits), agent_50 ($50 / 2600 credits).
Inputs: packSku (required).
billing_walletAInspect
Fetch the user's credit balance and recent usage entries. Returns { credits, recent } where recent is the last ~10 usage rows. Poll this to confirm a top-up landed ONLY after a billing_topup CHECKOUT result (one that returned a checkoutUrl), until credits rise. Do NOT poll after a status:'paid' headless top-up — those credits are already applied and the new balance is in the topup response.
Inputs: no named parameters.
brand_truth_createAInspect
Capture brand truths from plain natural-language text. Describe facts/observations about the brand in ordinary prose — a sentence or short paragraph (≤8000 chars). Do NOT pre-classify, pre-format, or guess the taxonomy: PostKing's LLM extraction pipeline reads the text and decides which atomic 'brand truths' to persist and which to skip (duplicates, too vague, or previously rejected facts). Returns { addedCount, skippedCount, added, skipped }: 'added' are the truths that were stored; 'skipped' lists each rejected quote with a reason. Review both — the skipped reasons tell you what didn't make it in and why.
Inputs: text (required), brandId.
brand_truth_deleteAInspect
Delete a brand truth by ID. This also records rejection memory: the system learns to stop re-suggesting that fact during future extractions. Use it deliberately — deleting a truth teaches PostKing that the fact should not come back.
Inputs: id (required), brandId.
brand_truth_getAInspect
Fetch a single brand truth by ID. short {id,name,type,pinned}; medium adds personaScope+tags+summary+timestamps; full = raw (includes full content). Use detail='full' to retrieve the complete content body.
Inputs: id (required), detail, brandId.
brand_truth_listAInspect
List the brand's stored brand truths (atomic facts/observations used to ground generation). short {id,name,type,pinned}; medium adds personaScope+tags+summary+timestamps; full = raw. Filter by type, personaScope, tags (array or comma-separated), or a free-text query.
Inputs: tags, type, limit, query, +3 more.
brand_truth_updateAInspect
Targeted edit of an existing, known brand truth (by ID). This does NOT re-run the LLM extraction pipeline — it writes the provided fields directly. Use it to correct wording (name/description/content), fix the type/personaScope, adjust tags, or pin/unpin. To capture NEW facts from prose, use brand_truth_create instead.
Inputs: id (required), name, tags, type, +5 more.
cancel_jobAInspect
Cancel a pending or running job/operation. Flips it to cancelled and stops it from being polled. Note: work already in flight may still finish server-side, but its result is discarded. Already-finished jobs cannot be cancelled. Pass the operationId (from list_jobs pollUrl / get_job).
Inputs: operationId (required), brandId.
cancel_postAInspect
Cancel a scheduled or approved post, reverting it to draft status without deleting it. Use delete_post to remove it entirely.
Inputs: postId (required).
check_ai_contentAInspect
Check whether text is likely AI-generated. Returns a score and analysis.
Inputs: text (required), brandId.
check_social_accountsAInspect
List all connected and disconnected social accounts for the active brand. Lists default short; pass detail=medium/full for more fields. Run before posting to confirm platform availability.
Inputs: detail, brandId.
clear_post_visualCInspect
Remove the selected visual from a post for a specific platform. Includes editInVisualEditor: a direct URL to edit the post in the visual editor (when active brand is set).
Inputs: postId (required), platform (required).
competitor_addAInspect
Async. Batch-add competitor domains (1–20) to the brand. Returns { operationId, status } — poll get_job until state=completed. Each domain triggers crawl + profile analysis. Typically takes ~2–5 min.
Inputs: domains (required), brandId.
competitor_analyzeAInspect
Async. Trigger analysis for existing BrandCompetitor rows that are pending or failed. Use competitor_add to create new rows; use this to retry failed ones. Returns { operationId, status } — poll get_job until state=completed. Typically takes ~2–5 min.
Inputs: brandCompetitorIds (required), brandId.
competitor_comparison_sourcesAInspect
List the data sources used to build the brand's competitive comparison. Returns raw source records (URLs, snippets, timestamps) — useful for auditing comparison accuracy.
Inputs: brandId.
competitor_deleteAInspect
Soft-delete a tracked competitor from the brand. No credits are refunded. Use competitor_update (empty body) to restore.
Inputs: competitorId (required), brandId.
competitor_generate_overviewAInspect
Async. Generate the competitive landscape overview (uses ~20 credits). Returns { operationId, status } — poll get_job until state=completed. Typically takes ~2–5 min.
Inputs: brandId.
competitor_get_comparisonAInspect
Get the brand's head-to-head competitive comparison. short {id,status,generatedAt,competitorCount}; medium adds summary+strengths+weaknesses; full = raw. Returns null when no comparison has been generated yet — use competitor_recompute_comparison to generate.
Inputs: detail, brandId.
competitor_get_overviewAInspect
Get the brand's competitive landscape overview. short {id,status,generatedAt}; medium adds summary excerpt; full = raw. Returns null when no overview exists — use competitor_generate_overview to create one.
Inputs: detail, brandId.
competitor_listAInspect
List the brand's tracked competitors. short {id,domain,analysisState}; medium adds source,creditsCharged,lastError,addedAt,lastCrawledAt,cacheSource; full = raw. Also returns a dashboard link to the Competitors tab.
Inputs: detail, brandId.
competitor_probeAInspect
Start a competitor discovery probe. PostKing crawls the web to find rival domains automatically. Returns { started: true } when kicked off, or { alreadyRan, status } when a probe result already exists. Poll competitor_probe_status to check readiness, then use competitor_probe_classify to accept/reject candidates.
Inputs: brandId.
competitor_probe_classifyAInspect
Classify a discovered (or manually added) competitor candidate. 'direct' seeds a BrandCompetitor row; 'similar' and 'not_relevant' update the probe JSON only. Call once per domain. Probe must be in completed state first. Returns { candidates } — the updated full candidate list.
Inputs: domain (required), classification (required), name, brandId.
competitor_probe_statusAInspect
Check the status of the competitor discovery probe. Returns { status, candidates? } — status is one of: pending | running | completed | failed. When completed, candidates contains the discovered domains ready for classification.
Inputs: brandId.
competitor_recompute_comparisonAInspect
Trigger a fresh head-to-head comparison recompute. Use after adding or re-analyzing competitors to get an up-to-date comparison.
Inputs: brandId.
competitor_refreshAInspect
Async. Refresh all active competitors for the brand (re-crawl + re-profile). Returns { operationId, status } — poll get_job until state=completed. Typically takes ~2–5 min.
Inputs: brandId.
competitor_updateAInspect
Update a competitor's settings. Currently supports toggling excludeFromSeoPull (removes the domain from keyword-gap pull without deleting it). Send an empty body to restore a soft-deleted competitor.
Inputs: competitorId (required), brandId, excludeFromSeoPull.
connect_domain_to_publicationAInspect
Connect a verified domain to a blog publication so articles are served from that domain. Supports three routingType modes: 'path' ({domain}/blog), 'root' (bare {domain}), and 'subdomain' (blog.{domain} — provisions a separate Domain row that needs its own DNS verification before it resolves).
Inputs: domainId (required), publicationId (required), brandId, pathPrefix, +1 more.
create_api_keyAInspect
Create a new PostKing API key. The raw token (pk_live_*) is returned ONCE in this response and never shown again. Store it immediately — treat it like a password. Scope: 'write' (default) or 'read'.
Inputs: name, scope.
create_blog_authorAInspect
Create a new author for blog articles. Returns an authorId that can be used in generate_blog_post and update_blog_article.
Inputs: lastName (required), firstName (required), email, brandId.
create_blog_categoryBInspect
Create a new category in a blog publication.
Inputs: name (required), slug (required), publicationId (required), brandId, +1 more.
create_brandAInspect
STEP 1 of brand onboarding (manual path — no website crawl). Creates a new brand from user-supplied name/description, sets it as active, then RETURNS a nextStep payload telling you to ask the user which platforms they publish on. After the user answers, call set_brand_mediums with their picks. Ask the user for a description if they did not provide one — onboarding will fail without it.
Inputs: name (required), tone, website, audience, +1 more.
create_comparison_pageAInspect
Create a comparison / 'X vs Y' / 'best ' page for the brand WITHOUT going through the full SEO cluster → brief flow. One call kicks off generation and returns quickly with an operationId and a 'still_generating' or 'completed' status — it does NOT block until the page is fully built. mode controls the engine: 'research' crawls the named competitors + live SERP results before writing — slower (can take several minutes) but produces the strongest, best-grounded page; 'simple' skips all crawling and lets the LLM author from what you provide — fast, best when you already have the facts or just want a quick draft. When your inputs are sparse (few/no options, no domains, no seedData), prefer 'research' — it will discover and ground the comparison for you and yield a far stronger page than 'simple'. seedData (simple mode): paste your own raw facts/notes/competitor details here and the LLM writes from them instead of crawling — this is how you feed your own data and avoid a crawl. Async — fires the create, then waits only a short grace window before responding. On success returns { briefId, sidePageId, sidePageSlug, landingPageSlug, webUrl, warnings }. If it is still running past the grace window, returns { status: 'still_generating', operationId } — poll get_job with that operationId until state is 'completed'; do NOT fabricate the page yourself, and do NOT call create_comparison_page again for the same request while it's pending. Any warnings are surfaced verbatim — relay them to the user (e.g. sparse-input notes such as 'research mode would produce a stronger page').
Inputs: mode (required), primaryKeyword (required), preset, brandId, +8 more.
create_postAInspect
Save a post draft with custom content to one or more platforms. Supported platforms: x, linkedin, instagram, threads, facebook. After creating, call approve_post with a future ISO 8601 datetime to schedule it. To check which platforms are connected first, call check_social_accounts. Each created post includes editInVisualEditor: a direct URL to edit it in the visual editor.
Inputs: content (required), platforms (required), brandId, scheduledAt.
create_publicationAInspect
Create a new blog publication (the container that articles live under). Returns a publicationId needed for generate_blog_post.
Inputs: title (required), layout, brandId, description.
dashboard_linkAInspect
Return a clickable browser link to a PostKing dashboard page. ALWAYS use this instead of guessing dashboard URLs. The SEO roadmap / content plan is section 'seo_briefs' (or 'seo' for the overview) — there is NO '/seo/roadmap' page.
Inputs: brandId, section.
delete_assetAInspect
Soft-delete an asset from the brand library. Pass confirm: true to proceed.
Inputs: assetId (required), confirm (required), brandId.
delete_blog_articleAInspect
Permanently delete a blog article.
Inputs: articleId (required), brandId.
delete_domainAInspect
Remove a custom domain. Connected blogs and landing pages are unlinked but not deleted.
Inputs: domainId (required).
delete_landing_pageAInspect
Permanently delete a landing page. Pass confirm: true to proceed — this is irreversible.
Inputs: slug (required), confirm (required).
delete_lp_versionAInspect
Permanently delete a historical landing page version. Cannot delete the published version or the only remaining version (the server will reject those). Pass confirm: true to proceed.
Inputs: slug (required), confirm (required), versionId (required).
delete_postAInspect
Cancel and delete a post regardless of its current status (draft, scheduled, or posted).
Inputs: postId (required).
delete_publicationAInspect
Permanently delete a blog publication. Only allowed when it has zero articles and no connected domain/external sync/publishing connections — otherwise the API refuses with an explanation of what's still attached (remove/disconnect those first, e.g. delete_blog_article for every article under it).
Inputs: publicationId (required), brandId.
delete_side_pageBInspect
Delete a side page. Pass confirm: true to proceed.
Inputs: slug (required), confirm (required), sideKey (required).
delete_side_page_versionAInspect
Permanently delete a historical side-page version. Deleting the current (draft) version is allowed and repoints the draft to the newest remaining version. Cannot delete the published (live) version or the only remaining version — the server will reject those and the rejection reason is returned as-is. Pass confirm: true to proceed.
Inputs: slug (required), confirm (required), sideKey (required), versionId (required).
delete_themeAInspect
Delete a content theme from the active brand.
Inputs: themeId (required), brandId.
delete_weekly_scheduleAInspect
Permanently remove the weekly schedule for the active brand. Pass confirm: true to proceed.
Inputs: confirm (required), brandId.
disable_weekly_scheduleAInspect
Pause the weekly content schedule without deleting it. Re-enable later with enable_weekly_schedule.
Inputs: brandId.
disconnect_social_accountBInspect
Disconnect a social account by its account ID.
Inputs: accountId (required), brandId.
edit_audienceAInspect
Async LLM ai-edit of the brand's audience/ICP. Describe the change in prompt (natural language). sections is REQUIRED — the audience section(s) to edit (e.g. 'demographics', 'painPoints', 'positioning'). If unsure which sections are valid for this brand, call preview_audience_edit first and use the section keys it returns. Returns { operationId, status } — poll get_job(operationId) until state is 'completed' (or 'failed'/'cancelled' on error). Only one audience edit can run at a time; a second call returns an 'already_running' notice. Typically takes ~30–90 s.
Inputs: prompt (required), sections (required), brandId, subsections.
edit_landing_pageAInspect
Update METADATA ONLY — title and/or instructions — of a landing page. Does NOT touch page content. For content changes, use set_landing_page_section (targeted field/section writes) or vibe_edit_landing_page (AI-powered edits).
Inputs: slug (required), title, instructions.
edit_post_cardAInspect
Edit a single carousel card on a post by its 1-based index. Provide title and/or body to update. Set rerender=true to regenerate the visual asset.
Inputs: postId (required), cardIndex (required), body, title, +2 more.
edit_side_pageAInspect
Update a side page's page-level metadata and, for type:"text" pages only, its content. Metadata (any side-page type): name (display title, shown in auto-generated footer/nav 'Solutions' links and breadcrumbs), newKey (rename the URL-slug fragment; old URL 404s, no redirect; internal references are rewritten in the background), and instructions (stored as an annotation for future context — does NOT trigger an AI edit). Content — type:"text" pages ONLY: title and/or htmlContent. Text side pages store a flat {title, htmlContent} document, not per-section overrides, so this is the direct way to write their content — landing/comparison pages have no title/htmlContent fields and must use set_side_page_section (or set_side_page_section with instructions-only for an AI rewrite of a text page's whole document) instead. Passing only one of title/htmlContent fetches and preserves the other automatically, so a partial write never clobbers the unset field. Every edit creates a new draft version (see list_side_page_versions / restore_side_page_version) — nothing here is destructive, any write (including a bad title/htmlContent edit) can be undone by restoring a prior version. On a published page, edits stay draft-only until set_side_page_state({published:true}) publishes them. When newKey triggers a reference rewrite, the response includes slugRewriteOperationId — poll it to confirm the cascade finished.
Inputs: slug (required), sideKey (required), name, title, +4 more.
edit_themeAInspect
Edit an existing content theme's title or content instructions.
Inputs: themeId (required), title, brandId, content.
enable_weekly_scheduleAInspect
Enable the weekly content schedule without changing its configuration. The schedule must already be created with set_weekly_schedule.
Inputs: brandId.
generate_blog_postAInspect
Generate a full AI blog article. Requires a publicationId (from list_blogs or create_publication). Pass a voiceProfileId to write in a specific person's style (IDs from list_voices). Returns an articleId + operationId; generation is async — poll get_blog_status until completed, then get_blog_article. Use update_blog_article to edit, or publish_blog_article to push to external platforms. To make it live on your PostKing blog, call update_blog_article with status: 'published'.
Inputs: topic (required), publicationId (required), brandId, targetLength, +9 more.
generate_bulk_postsBInspect
Generate and schedule multiple posts across a date range in the background.
Inputs: days (required), platform (required), times, voice, +3 more.
generate_connect_linkAInspect
Generate a secure browser link to connect a social media account. Share this URL with the user to complete OAuth.
Inputs: brandId, platform.
generate_landing_pageAInspect
Create and AI-generate a new landing page for the brand. Step 1: Creates the LP record with the given slug. Step 2: Kicks off async AI content generation immediately. Returns { slug, operationId, pollUrl } — poll with get_job(operationId) until state is 'completed' (or 'failed'/'partially_failed'/'cancelled' on error). For targeted edits to an existing page, prefer vibe_edit_landing_page.
Inputs: topic (required), slug, brandId, voiceProfileId.
generate_postAInspect
Generate AI content for a platform. Returns quickly with a postId and a 'generating' or 'completed' status — it does NOT block until generation fully finishes. Deducts 10 credits per variation. To control what the post is about, pass theme with a free-text brief (any topic/angle/facts/tone). If you omit theme, the topic is RANDOM — so always pass it when the user wants specific content. When variations > 1, ALL variations are returned under a SINGLE postId in the variations array — it does NOT create one post per variation. content is variation 1 (the primary, already saved on the post). Never call generate_post again to 'get the other variations' — they're all in the response. originalContent (if seen elsewhere) is the pre-voice-rewrite draft, not a separate variation. After generating, use create_post to save a chosen variation, then approve_post to schedule it. To repurpose: call repurpose_content first, then create_post with the result, then approve_post. Generation can take 1-5 minutes (longer with multiple variations or voice rewrite). This tool only waits a short grace period so fast generations can return inline content; if it returns status 'generating', the job is still running server-side — poll get_post with the returned postId until operationStatus is 'completed', then use that content. Do NOT call generate_post again for the same request while it's pending — retrying creates a duplicate draft and wastes credits. After generation, brand visual options (quote/card templates, brand images, stock photos) are prepared but NOT attached — share viewInBrowser for the visual picker, or call pick_post_visual to attach one. Do not attach a visual unless the user chooses it. The response includes editInVisualEditor: a direct URL to edit the post in the visual editor (once completed).
Inputs: platform (required), theme, voice, brandId, +2 more.
generate_post_carouselAInspect
Generate a carousel PDF for a LinkedIn (or other) post from the post's cards. Returns an asset ID and download URL for the PDF. Requires cards to be set first via set_post_cards or edit_post_card.
Inputs: postId (required), style, title, variant.
generate_post_visual_optionsAInspect
Fetch available visual options for a post — card templates, library matches, stock photos. Returns a bestPick recommendation plus categorized options per platform. Use pick_post_visual to apply one of the returned options. Returns slim option list with pickArgs by default (medium). Use detail='short' for counts only, 'full' for raw catalog. Includes editInVisualEditor: a direct URL to edit the post in the visual editor (when active brand is set).
Inputs: postId (required), detail, category, platform.
generate_side_pageAInspect
AI-generates a side page under a parent landing page. Async — kicks off the side-page generator and returns { success, operationId, operationRowId, pollUrl, sidePageId }. This is the GENERATOR (POST /side-pages/generate) — NOT a row creator. Comparison-type briefs may run synchronously and return sidePageId directly with no operationId. Two body modes: • freeform: pass key + prompt (+ optional keywords, selectedSections, voiceProfileId, sidePageType). Freeform now writes real section-level content (hero/features/showcase/faq/cta), not just metadata. • brief: pass key + brief (structured outline) + optional briefId and roadmapItemId. Poll get_job with the returned operationId until state is completed (or failed/partially_failed/cancelled on error); the generated page's sections will be populated once complete.
Inputs: key (required), slug (required), brief, prompt, +7 more.
generate_textAInspect
Generate or rewrite general-purpose, email-style/formal text — follow-up emails, cover letters, outreach messages, formal notes, etc. Returns quickly with an operationId and a 'still_generating' or 'completed' status — it does NOT block until generation fully finishes. This is NOT for social media posts — use generate_post for those. This is also NOT for a simple voice-only rewrite of existing text with no other options — for that, use rewrite_with_voice or rewrite_text instead. Reach for generate_text when you need mode selection (generate vs rewrite), a stated purpose, a target length, or when there's no source text at all (mode='generate'). mode='generate' writes new text from a prompt (what to write, e.g. 'a follow-up email after a sales call, polite but direct'). mode='rewrite' rewrites existing sourceText into a new form/tone. purpose is optional free text describing the goal, e.g. 'win-back email' or 'job application cover letter'. length can be short | medium | long, or a specific target word count (20-5000). Supports detail param: short=status+wordCount only, medium=truncated content (500 chars)+wordCount (default), full=raw result including content, aiDetectionScore, burstinessScore, promptLogId, wordCount. If it returns status 'still_generating', the job is still running server-side — poll get_job with the returned operationId (wait:true) until state is 'completed', then read the text from the operation's result. Do NOT call generate_text again for the same request while it's pending — retrying wastes effort and may create duplicate work.
Inputs: mode (required), detail, length, prompt, +4 more.
generate_themesAInspect
Generate new content themes using AI. Waits a short grace window for generation to finish; if it's still running server-side after that, returns a 'generating' status instead of blocking — call list_themes a few seconds later to retrieve the new themes. Deducts credits.
Inputs: count, input, brandId, instructions.
get_audienceAInspect
Fetch the brand's audience intelligence / ICP (ideal customer profile). short = compact summary (name + primaryRoles + top painPoints + persona.role); medium adds positioning + fuller demographics; full = the raw payload (audienceData + positioning + persona + contentModulation). persona is the ghostwriter persona ({ role, styleNotes, ... }) and may be null. If the brand has no audience data yet, run website/audience analysis (onboarding) first.
Inputs: detail, brandId.
get_blog_articleAInspect
Fetch a blog article by ID. detail='short' returns id/title/slug/status; detail='medium' adds excerpt+wordCount+previewUrl+editUrl; detail='full' (default) returns the COMPLETE content plus previewUrl (GUI preview link) and editUrl (dashboard editor link). Pass maxContentChars only if you need to bound the body size; omit it to get the whole article.
Inputs: articleId (required), detail, brandId, maxContentChars.
get_blog_statusAInspect
Poll the async generation status of a blog article. Use the articleId returned by generate_blog_post. Status: pending | running | completed | failed.
Inputs: articleId (required), brandId.
get_brand_infoAInspect
Get a brand's profile. Returns core identity fields plus slim summaries: themes as [{id,title}], voiceProfiles as [{id,name,isActive,optimizedMedium}], blogAuthors as [{id,firstName,lastName}], and postCount/memberCount as numbers. Use list_themes, list_voices, list_blog_authors, list_posts, or get_brand_members for full detail on each.
Inputs: detail, brandId.
get_brand_mediumsAInspect
Read which publishing platforms (mediums) a brand posts to. Read-only counterpart to set_brand_mediums. NOTE: Reddit is NOT a medium — Reddit is a separate repurpose module; use the reddit_* tools or dashboard_link section 'reddit'.
Inputs: brandId.
get_brand_membersAInspect
List all active members of a brand with their role and user info (id, name, email).
Inputs: brandId.
get_calendarAInspect
View upcoming scheduled posts sorted by date. Returns id+status+scheduledAt by default; use detail='medium' or 'full' for more fields. For a single post use get_post.
Inputs: days, detail, brandId.
get_creditsAInspect
Check your current PostKing credit balance and free-tier status.
Inputs: detail.
get_jobAInspect
To check whether ONE specific operation you started is finished, pending, or failed, call this with its operationId (the pollUrl param accepts a bare operationId + brandId). Do NOT use list_operations to check a specific op. Poll the status of any background Operation by its operationId or pollUrl. Returns the Operation row: { id, kind, state (pending|running|completed|partially_failed|failed|cancelled), brandId, scopeType, scopeId, progress, result, errors, startedAt, finishedAt, createdAt, updatedAt }. Call repeatedly until state is 'completed' or 'failed' (or 'cancelled'). When completed, the payload you want is in result; on failure, see errors. Pass wait:true to block until the job is done (polls every 3s, capped at ~30s per call) — preferred over calling repeatedly. For longer-running jobs, call get_job again with wait:true to keep polling until it completes. Most generate_* and vibe_edit_* tools (including seo_generate_clusters and seo_generate_keywords) return an operationId — use this to poll them. Supports detail param: short=id+kind+state+progress, medium=adds timestamps+resultRef (key IDs from result, no full payload), full=raw including complete result JSONB.
Inputs: pollUrl (required), wait, detail, brandId, +1 more.
get_onboarding_statusAInspect
STEP 3 of brand onboarding. Polls background analysis + theme generation. detail='short' returns status only; detail='medium' (default) adds audienceSummary+themeCount; detail='full' returns raw data. Poll every ~15s. When done, surface the audience review + themes to the user.
Inputs: detail, brandId.
get_postAInspect
View the full content and status of a single post. Use detail='short'|'medium'|'full' to control verbosity (default full). Multi-variation posts expose a variations array (all variations live on one postId). Output shows the final voice-rewritten content by default; pass includeOriginal=true to also see the pre-rewrite draft. Includes contentReviewUrl: a direct link to read and approve the generated body, and editInVisualEditor: a direct URL to edit the post in the visual editor.
Inputs: postId (required), detail, includeOriginal.
get_seo_roadmapAInspect
View the SEO / GEO content roadmap — suggested blog topics, keywords, and completion status. detail='short' returns stats only; detail='medium' adds slim item list (id+title+status+keyword); detail='full' (default) returns raw response.
Inputs: detail, status, brandId.
get_social_media_rulesAInspect
Read a brand's per-platform social media content rules (the same rules editable in dashboard Settings → Social media rules). Covers content/structure/engagement/visual-strategy guidance plus secrets, guidelines, content types, things to avoid, and core principles. Call this BEFORE set_social_media_rules so you only change the fields you intend to.
Inputs: brandId, platform.
get_vibe_edit_statusAInspect
Poll vibe (AI) edit session status. detail='medium' (default) is the REVIEW view: { status, progress, stale, baseVersionId, currentVersionId, changesCount, credits, changes, error } where each changes entry is { index, path, before, after } (before/after truncated to 200 chars) — use these index/path values to select a subset in apply_vibe_edit. 'short' returns just { status, progress, error }. 'full' returns the raw payload including the untruncated editedData. error is populated when status is 'failed' and carries the failure reason — surface it to the user instead of just reporting 'failed'. When status is 'completed', call apply_vibe_edit next (this tool never applies anything).
Inputs: slug (required), operationId (required), detail.
get_weekly_scheduleAInspect
Retrieve the current weekly content schedule for the active brand. Returns enabled status, lead time, timezone, and per-day platform configs. If no schedule is configured yet, returns suggested defaults. Includes a viewInBrowser link to open the calendar page in the app.
Inputs: detail, brandId.
healthAInspect
Check PostKing API health and local auth state. No authentication required — safe to call first thing in a session to see whether you're logged in and what to do next.
Inputs: no named parameters.
humanize_textCInspect
Apply LLM rewrite and BERT replacements to reduce AI detection signals in text.
Inputs: text (required), brandId, platform.
import_asset_from_urlAInspect
Import an asset into the brand library from a public URL. The server fetches and stores the file. Set assetType (e.g. 'google-image') when importing a result surfaced by search_web_images — it is recorded as a tag on the asset to preserve provenance.
Inputs: url (required), name, tags, brandId, +1 more.
import_assets_csvAInspect
Batch-import up to 50 assets by providing an array of public URLs. All are added to the brand library. Supports detail param for the returned asset list.
Inputs: urls (required), detail, brandId.
import_blog_articlesAInspect
Import articles from an external blog, RSS feed, or Blogger URL into a PostKing publication as drafts. Returns id+title+slug by default (short); use detail='medium' for wordCount. Inspect individual articles with get_blog_article.
Inputs: sourceUrl (required), publicationId (required), limit, detail, +1 more.
import_landing_page_htmlAInspect
Bring-your-own-HTML: import an existing landing page from pasted HTML or a live URL. Synchronous — no polling needed. Pass exactly one of html (paste the full page source) or url (fetch and import from a live page). By default creates a brand-new landing page (optionally with name; the slug is always auto-generated). Pass convertExistingSlug instead to overwrite an existing landing page's content with the imported HTML. Set createMissingSidePages to true to auto-create stub side pages for internal links discovered in the HTML that don't already exist. Returns { landingPage: {id, slug}, report } where report audits the import: externalHosts (third-party domains referenced), relativeAssetPaths (local asset paths that may need re-hosting), placeholders (unresolved template tokens found), internalLinks (each { href, slug, existingSidePage }), themeExtracted (whether a theme was inferred from the HTML), truncated (whether the source HTML was cut down to fit limits), and extractability ({ verdict: 'ok'|'warn', reasons } — 'warn' means framework hydration scripts won't load post-import but static content still renders). If the source is a client-rendered app shell whose content depends entirely on framework scripts that can't be hosted here (e.g. a bare Next.js/React app shell), the import is refused before anything is persisted — this tool returns a non-throwing result { error: 'not_extractable', message, reasons } instead. Relay the reasons to the user and suggest pasting a static/exported HTML instead, or publishing directly from their site builder. Example: import_landing_page_html({ url: 'https://example.com/pricing', name: 'Pricing' }).
Inputs: url, html, name, brandId, +2 more.
knowledge_createAInspect
Async. Create a new knowledge-base item for the brand. Returns { operationId, status } — poll get_job until state=completed. If description or tags are omitted, PostKing auto-generates them from the content. For contentType='json', content must be valid JSON — this tool validates client-side before calling the API. Typically takes ~15–30 s.
Inputs: name (required), content (required), contentType (required), tags, +3 more.
knowledge_deleteAInspect
Soft-delete a knowledge-base item. The item is deactivated (isActive=false) and no longer appears in knowledge_list. This action is not reversible via the API.
Inputs: itemId (required), brandId.
knowledge_getAInspect
Fetch a single knowledge-base item by ID. short {id,name,contentType}; medium adds tags+summary+timestamps; full = raw (includes full content). Use detail='full' to retrieve the complete content body.
Inputs: itemId (required), detail, brandId.
knowledge_listAInspect
List the brand's knowledge-base items. short {id,name,contentType}; medium adds tags+summary+timestamps; full = raw. Filter by tag, active status, or global scope.
Inputs: tag, detail, global, brandId, +1 more.
knowledge_updateAInspect
Update a knowledge-base item. Minor edits (name, tags, description) return the updated item synchronously. When content changes significantly, PostKing queues an AI description regeneration and returns { operationId, status } — poll get_job until state=completed. For contentType='json', content must be valid JSON — this tool validates client-side before calling the API. Typically takes ~15–30 s.
Inputs: itemId (required), name, tags, brandId, +3 more.
list_api_keysAInspect
List all API keys on the account. Shows prefix, scope, and revocation status. Does NOT show raw tokens. Lists default short; pass detail=medium/full for more fields.
Inputs: detail.
list_assetsAInspect
List assets in the brand's visual library. Filter by type (IMAGE|DOCUMENT|VIDEO|LINK|LOTTIE), tags, or search text. Supports detail param: short=id+type+name, medium=key fields, full=raw.
Inputs: tags, type, limit, detail, +2 more.
list_asset_slotsAInspect
List the asset slots (image/video placeholders) for a landing page or side page, with each slot's current asset assignment. Use this to discover valid slotKeys before calling assign_asset_to_slot. Pass sidePageSlug to inspect a side page's slots.
Inputs: slug (required), pageKey, sidePageSlug.
list_asset_tagsAInspect
List all unique tags used across the brand's asset library.
Inputs: brandId.
list_blog_authorsAInspect
List all blog authors for the active brand. Returns id+name by default (short); use detail='medium' for email/social links. Author IDs can be passed to generate_blog_post or update_blog_article.
Inputs: detail, brandId.
list_blog_categoriesAInspect
List all categories for a blog publication. Returns id+name+slug by default (short); use detail='medium' for description+articleCount.
Inputs: publicationId (required), detail, brandId.
list_blogsAInspect
LIST tool. Even detail='full' OMITS article bodies (kept bounded) — to read an article's content, call get_blog_article. The number of rows is controlled by limit (default 50, max 200), NOT by detail; for a 'full list' of titles, raise limit and keep detail='short'.
Inputs: limit, detail, status, brandId.
list_brandsAInspect
List all brands on your PostKing account. Returns id+name+website by default (short). Use detail='medium' for description, 'full' for all raw fields. To zoom into one brand call get_brand_info with detail='full'.
Inputs: detail.
list_domainsAInspect
List all custom domains for the active brand. Lists default short; pass detail=medium/full for more fields including SSL status, verification, and connected blogs or landing pages.
Inputs: detail, brandId.
list_jobsAInspect
To check a SPECIFIC operation's status, call get_job with its operationId — this list only returns the most recent ops and may omit a just-started one. List background jobs for the active brand. Use status='pending' to see in-flight ops, 'completed' to see finished ones. Use get_job with an operationId to poll a specific job — most async tools return an operationId. Supports detail param: short=id+kind+state, medium=6 key fields, full=raw.
Inputs: limit, detail, status, brandId.
list_landing_pagesAInspect
Lists landing pages. Default detail='short' (id/slug/name/status). Use view_landing_page for full content.
Inputs: detail, brandId.
list_lp_versionsAInspect
List all saved versions of a landing page. Default detail='short'. Each version includes previewUrl (public GUI preview link — the published version's form when that version is the live one, otherwise the ?version= form); the top-level previewUrl is for the current draft. Use view_lp_version to see section content.
Inputs: slug (required), detail.
list_operationsAInspect
To check a SPECIFIC operation's status, call get_job with its operationId — this list only returns the most recent ops and may omit a just-started one. List recent Operations (the newer async-op system) for the active brand. Each operation has: id, kind, state (pending|running|completed|partially_failed|failed|cancelled), progress, result, errors. Use get_job with an operationId to poll a specific one. Filters: kind (e.g. seo_keyword_generate, seo_cluster_generate, lp_generate), state. Supports detail param: short=id+kind+state, medium=adds scopeId+progress+timestamps (no result/errors), full=raw including result.
Inputs: kind, limit, state, detail, +1 more.
list_post_cardsAInspect
List the carousel cards attached to a post. Cards are used for LinkedIn carousel / PDF generation. Returns {index,title} by default; use detail='medium' for truncated body, 'full' for all fields.
Inputs: postId (required), detail.
list_postsAInspect
List recent posts and drafts. Filter by status or platform. Use status='created' to find unscheduled drafts. Returns id+status+scheduledAt by default; use detail='medium' or 'full' for more fields. For a single post use get_post.
Inputs: limit, detail, status, brandId, +1 more.
list_publicationsAInspect
List all blog publications (the containers that blog articles live under). detail='short' returns id+name; detail='full' returns raw rows. Distinct from list_publishing_connections which lists external platforms like WordPress.
Inputs: detail, brandId.
list_publishing_connectionsAInspect
List external publishing connections for a blog publication (WordPress, Medium, Substack, etc.).
Inputs: publicationId (required), brandId.
list_side_pagesAInspect
List side pages attached to a landing page. Default detail='short'. Heavy JSONB (overrides/config) only at full via view_side_page. medium/full include currentVersionId (the draft) and publishedVersionId (the live version) per row — compare them to spot pages with unpublished draft edits without a second call.
Inputs: slug (required), detail.
list_side_page_versionsAInspect
List all saved versions of a side page. Default detail='short'. Always includes top-level currentVersionId (the draft) and publishedVersionId (the live version) so an agent can tell draft vs. live without a second call. Use view_side_page_version to see section content.
Inputs: slug (required), sideKey (required), detail.
list_themesAInspect
List all content themes for the active brand with their IDs. detail='short' (default) returns id+title; detail='medium' adds content preview; detail='full' returns raw content.
Inputs: detail, brandId.
list_voicesAInspect
List all available voice profiles with their IDs. Lists default short; pass detail=medium/full for more fields.
Inputs: detail.
login_completeAInspect
Wait for the user to approve the PostKing login code in their browser and then save the token. Polls automatically; call this immediately after login_start.
Inputs: no named parameters.
login_startAInspect
Start the PostKing login flow. Returns a URL and short code for the user to visit in their browser. IMPORTANT: Immediately after this tool returns, show the URL + code to the user and then call login_complete — it will wait (polling in the background) until the user approves the request in their browser, so there is no need to ask the user to tell you when they are done.
Inputs: no named parameters.
onboard_brandAInspect
STEP 1 of brand onboarding (website path). Crawls the site in the background and kicks off audience analysis + 10 themes. Sets the new brand as active and RETURNS a nextStep payload. IMMEDIATELY after this returns, ask the user which social platforms they publish on, then call set_brand_mediums. Do not call get_onboarding_status until mediums are set.
Inputs: websiteUrl (required), name.
pick_post_visualAInspect
Select a visual for a post on a given platform. Use the chosen option's pickArgs from generate_post_visual_options VERBATIM — for card/quote templates that means passing kind + style + variant together; for a library/smart asset or a stock photo, pass the assetId or slot from its pickArgs. Do not invent style names. variant is a 1-based template variant index. Includes editInVisualEditor: a direct URL to edit the post in the visual editor (when active brand is set).
Inputs: postId (required), platform (required), kind, slot, +3 more.
preview_audience_editAInspect
Read-only helper. Call this BEFORE edit_audience to discover which sections/subsections values are valid for this brand. Pass the natural-language change you intend to make; returns the available sections/subsections (computed from the brand's current audience data) plus a preview. Use the returned section keys (e.g. 'demographics', 'painPoints', 'positioning') as the required sections array for edit_audience.
Inputs: prompt (required), brandId.
publish_blog_articleAInspect
Push a blog article to connected external platforms (WordPress, Medium, Substack, etc.). Get connection IDs from list_publishing_connections.
Inputs: articleId (required), connectionIds (required), brandId.
publish_landing_pageAInspect
Publish a landing page, making it publicly accessible at its URL.
Inputs: slug (required).
reddit_generate_poolAInspect
Kick off async generation of a subreddit pool for the brand — finds relevant subreddits by crawling Reddit. Typically takes ~1–3 min. Returns { operationId, status }. Poll get_job with the operationId until state=completed, then call reddit_get_pool to see results. Reddit is a repurpose-to-Reddit workflow, NOT a scheduled publishing medium.
Inputs: brandId.
reddit_get_poolAInspect
Returns the brand's pool of relevant subreddits — THIS IS the brand-level subreddit match (each scored). Use it to answer 'which/what/top N subreddits should my brand post in?' — NO content needed; results are sorted most-relevant first; pass top for a top-N list. (reddit_suggest is a different, content-specific step.) Reddit is a repurpose-to-Reddit workflow, NOT a scheduled publishing medium.
Inputs: top, brandId.
reddit_global_poolAInspect
Return stats on the global subreddit dataset (count of known subreddits available for matching). Informational only — no DB writes.
Inputs: brandId.
reddit_list_postsAInspect
List saved Reddit posts (outputs of reddit_rewrite). Cursor-paginated. Returns { posts: [{ id, platform, content, outputData, sessionId, voiceId, createdAt }], nextCursor }. outputData contains: redditTitle, body, notes, wordCount, angle, length, subreddit, variationIndex. Flow step 4 of 4: pool → suggest → rewrite → LIST_POSTS.
Inputs: limit, cursor, brandId.
reddit_rewriteAInspect
Async. Rewrite a blog article (or raw content) into a Reddit-native post for a specific subreddit. Typically takes ~30–90 sec per variation. Returns quickly — if generation finishes within a short grace window, the finished Reddit post is returned inline; otherwise it returns a postId and a 'still in progress' status. Poll get_post with that postId until operationStatus is COMPLETED. Do NOT call reddit_rewrite again for the same request while it's pending. The subreddit does NOT need to be in the brand's pool — if it isn't, the rewrite still proceeds using general Reddit best-practices, and the result includes a subredditNotice string flagging that this subreddit hasn't been onboarded yet. Flow step 3 of 4: pool → suggest → REWRITE → list_posts.
Inputs: subreddit (required), angle, length, brandId, +5 more.
reddit_suggestAInspect
Given a brand's content (a blog post by id, or pasted title+text), return up to 8 best-fit subreddits from the brand's pool, each with 2-3 distinct posting angles (angle type + tailored title + framing hook), plus promotion mode, buyer intent, match score, and the key rule to watch. Use an angle's title/hook to then draft a native post via reddit_rewrite. short {subreddit,match_score,promotion_mode,buyer_intent,angle} (angle = first angle only); medium adds reason,rule_to_watch,angles (all angles); full = raw. Synchronous, 0 credits. Requires the brand pool to exist — call reddit_generate_pool first if it doesn't. Flow step 2 of 4: pool → SUGGEST → rewrite → list_posts.
Inputs: title, detail, postId, brandId, +1 more.
regenerate_landing_pageAInspect
Re-generate a landing page's content using AI. Optionally restrict to specific sections. Returns an operationId — poll with get_job to track progress. For targeted edits to an existing page, prefer vibe_edit_landing_page.
Inputs: slug (required), sections, instructions, voiceProfileId.
regenerate_post_visualAInspect
Regenerate the visual option set for a post — refreshes stock photo results and re-scores library assets. Returns slim option list with pickArgs by default (medium). Use detail='short' for counts only, 'full' for raw catalog. Includes editInVisualEditor: a direct URL to edit the post in the visual editor (when active brand is set).
Inputs: postId (required), detail, platform, loadExternal.
repurpose_contentAInspect
Turn a URL, text, blog post, or existing PostKing post into new content for social media or blogs. IMPORTANT: When the source is a URL, pass it directly to this tool via sourceUrl — do NOT fetch or crawl the URL yourself first. PostKing handles all crawling internally. Source types: url | text | blog | social_post. Target types: social (LinkedIn, X, etc.) | blog | text. Supports detail param: short=ids only, medium=key fields (default), full=raw response.
Inputs: sourceType (required), targetType (required), angle, detail, +11 more.
reschedule_postBInspect
Move a scheduled post to a new time. Pass a future ISO 8601 UTC datetime.
Inputs: postId (required), scheduledAt (required).
restore_lp_versionAInspect
Undo/rollback the draft to a prior version. Find valid version IDs via list_lp_versions. This does not touch the published version.
Inputs: slug (required), versionId (required).
restore_side_page_versionAInspect
Restore a side page's draft to a prior version. Find valid version IDs via list_side_page_versions. This only changes the DRAFT — it moves currentVersionId forward to a new version copied from the target (forward history is never deleted). The live/public page is unaffected until you publish again via set_side_page_state({ published: true }).
Inputs: slug (required), sideKey (required), versionId (required).
revoke_api_keyAInspect
Permanently revoke an API key. Pass confirm: true to proceed — this is irreversible and any clients using this key will stop working immediately.
Inputs: keyId (required), confirm (required).
rewrite_textBInspect
Rewrite text using a voice profile or general writing rules.
Inputs: text (required), voice, brandId, platform.
rewrite_with_voiceCInspect
Rewrite text using a specific voice profile.
Inputs: text (required), profileId (required), brandId, platform.
run_weekly_schedule_dayAInspect
Trigger the smart-week content generation engine for a specific date. This immediately queues posts for that day's schedule configuration. Use YYYY-MM-DD format for the date. Returns postsCreated count.
Inputs: date (required), brandId.
schedule_blog_articleAInspect
Schedule an existing blog article to auto-publish at a future date/time. scheduledAt must be a future ISO 8601 datetime. When the time arrives, the article publishes to the PostKing blog and auto-pushes to any connected external platforms flagged autoPublish. To publish immediately instead, use update_blog_article with status='published'.
Inputs: articleId (required), scheduledAt (required), brandId.
schedule_postAInspect
Schedule a draft or approved post for a specific time. Equivalent to approve_post but named to match 'pking posts schedule'. Pass a future ISO 8601 UTC datetime. After scheduling the post status becomes 'scheduled'.
Inputs: postId (required), scheduledAt (required), timezone.
search_stock_imagesAInspect
Search stock photo/video libraries for images matching a query. Returns URLs and descriptions. Use import_asset_from_url to add a result to the library. Supports detail param: short=url+thumbnail, medium=adds description+credit, full=raw.
Inputs: query (required), detail, brandId, platform.
search_web_imagesAInspect
Search Google Images across the whole web for a query — broader than search_stock_images, which only searches licensed stock photo/video libraries. Returns image URLs, the source site, and a link back to the source page. openLicensedOnly is a best-effort source filter, not a legal license guarantee — agents and users should still verify usage rights before publishing any result. Use import_asset_from_url to add a chosen result to the library. Supports detail param: short=url+source, medium=adds sourceUrl+alt+dimensions, full=raw.
Inputs: query (required), gl, hl, detail, +3 more.
seo_add_seedsAInspect
Step 1 of the SEO / GEO flow. Add 3–10 seed keywords that describe what the brand wants to rank for. After this, call seo_generate_keywords to expand them into the full keyword universe.
Inputs: seeds (required), brandId.
seo_approve_briefsAInspect
Approves one or more SeoBriefs and AUTO-fires L4 article/comparison generation immediately — do NOT call seo_write_article after this. Typically takes ~3–8 min per article. After approval, poll each returned operationId with get_job until state is completed (or failed/partially_failed/cancelled on error). A brief in status writing means generation is already in progress — poll the existing operation, do not re-submit. Body: briefIds (array, max 200). Response: { approved, failed: [{briefId, reason}], operationIds, operations: [{briefId, operationId, type}] }.
Inputs: briefIds (required), brandId, generateHeroImage.
seo_approve_clusterAInspect
Approve a single cluster. Gates brief generation — only approved clusters get briefs drafted. Position in flow: after seo_generate_clusters + seo_list_clusters, before seo_generate_roadmap / brief review. Typically takes ~2–5 min per cluster. Returns { cluster, operationId } — the operationId is for the async brief-generation job kicked off by approval. Poll get_job with the operationId until state is completed (or failed/partially_failed/cancelled on error).
Inputs: clusterId (required), brandId.
seo_auto_assign_ctaAInspect
Optional capstone step — runs AFTER blog articles are published. Auto-suggests a published side-page CTA for each blog article in the batch by matching the article's keywords (cluster + tags + title) against the brand's published side pages, then writes the result to BlogArticle.sidePageInfo (header + ctaText + ctaButtonText + ctaHref). Defaults are safe to re-run: skips blogs that already have a CTA (overwriteExisting=false) and skips Webflow-synced blogs (skipWebflowSynced=true) since CTA edits don't push back to Webflow. Synchronous — returns { updated, skipped, errors, total, results: [{blogId, status, sidePageId?, sidePageSlug?}] } directly; no polling needed. Pass blogIds: "all" to process every blog for the brand, or a list of up to 50 blog IDs. Hard cap of 50 blogs per call. For brands with more uncovered blogs, batch your blogIds arrays in groups of 50. The matcher uses keywords today; reusing an existing CTA header/ctaText body as a matching signal is a planned enhancement.
Inputs: blogIds (required), brandId, overwriteExisting, skipWebflowSynced.
seo_bulk_approve_clustersAInspect
Step 5b — bulk-approve N clusters in one call. Recommended path when an agent wants to move multiple clusters forward. Approving a cluster fires an async seo_brief_generate Operation per cluster; brief generation only runs on approved clusters. Typically takes ~2–5 min per cluster. Response includes operations: [{ clusterId, operationId }] and operationIds: string[] — Poll get_job with the operationId until state is completed (or failed/partially_failed/cancelled on error).
Inputs: clusterIds (required), brandId.
seo_bulk_delete_keywordsAInspect
Soft-delete N SeoScoredKeyword rows in one call (sets deletedAt; rows stay in the DB but are filtered out of all queries). Housekeeping op — not part of the main flow. Pass confirm: true to proceed. Use to clear out a batch of junk/irrelevant keywords the auto-pipeline missed, e.g. after filtering seo_list_keywords by relevanceMax.
Inputs: confirm (required), keywordIds (required), brandId.
seo_bulk_edit_keywordsAInspect
Edit userTags, intent, priority, and/or excludedFromClustering across N SeoScoredKeyword rows in one call — the same values are applied to every id in keywordIds. Housekeeping op — not part of the main flow. Pass confirm: true to proceed (this can silently overwrite tags/intent/priority for many keywords at once). At least one of intent, userTags, priority, or excludedFromClustering must be supplied. Typical flow: call seo_list_keyword_ids with a filter to get the target ids, then pass them here. Example: {"keywordIds":["kw_1","kw_2"],"excludedFromClustering":true,"confirm":true}.
Inputs: confirm (required), keywordIds (required), intent, brandId, +3 more.
seo_bulk_reject_clustersAInspect
Bulk-reject N clusters in one call. Symmetric to seo_bulk_approve_clusters.
Inputs: clusterIds (required), brandId.
seo_categorizeAInspect
Step 3 of the SEO / GEO flow. Tag keywords by search intent and/or user tags. Pass updates: an array of {keywordId, intent?, userTags?} (intent ∈ informational | commercial | navigational | transactional). Example: {"updates":[{"keywordId":"kw_123","intent":"commercial"}]}. After this, call seo_generate_clusters.
Inputs: updates (required), brandId.
seo_competitorAInspect
Compare the brand's keyword coverage against a competitor domain. Returns short detail by default: bucket totals only {overlapping: {total}, brandUnique: {total}, competitorOnly: {total}}. Use detail="medium" for capped keyword lists (up to 50 per bucket) or detail="full" for the raw API response.
Inputs: competitorDomain (required), detail, brandId.
seo_create_clusterAInspect
Create a real, named SEO cluster by hand — bypasses the auto-clustering pipeline entirely (no LLM call). The cluster starts empty; use seo_create_custom_brief with the returned id as clusterId to add its first brief. Manual clusters are tagged origin: "manual" so the dashboard can distinguish them from pipeline-generated clusters, and are created already approved (no separate approval step needed). Cluster names must be unique per brand — if the name is already taken, this returns a clear cluster_name_taken error instead of creating a duplicate; pick a different name or reuse the existing cluster via seo_list_clusters.
Inputs: name (required), brandId, description, pillarKeyword.
seo_create_custom_briefAInspect
Create a single custom SEO brief on demand — the MCP entry point for the 'generate-one' custom-brief flow (previously only reachable via raw agent-v1 REST). Pass clusterId (from seo_create_cluster or seo_list_clusters) to add this brief into an EXISTING named cluster. Omit clusterId to fall back to the legacy behavior: a throwaway single-brief cluster is minted automatically (tagged origin="manual"). Async — returns { operationId, status }. Poll get_job with the operationId until state is 'completed' (or 'failed'/'partially_failed'/'cancelled' on error), then call seo_get_brief with the briefId from the completed operation's result to read the generated outline. Typically takes ~2–5 min per cluster.
Inputs: type (required), pillarKeyword (required), intent, brandId, +4 more.
seo_delete_clusterAInspect
Hard-delete a cluster. This CASCADES: every SeoRoadmap item under this cluster is deleted, along with its brief. Blog articles and keywords that pointed at this cluster are NOT deleted but have their cluster link cleared. This is NOT UNDOABLE — there is no soft-delete for clusters (unlike keywords). Housekeeping op — not part of the main flow. Pass confirm: true to proceed. Prefer seo_reject_cluster if you just want to remove a cluster from the active pipeline without destroying its roadmap items and briefs — reject is reversible via seo_restore_cluster, delete is not.
Inputs: confirm (required), clusterId (required), brandId.
seo_delete_keywordAInspect
Soft-delete a single SeoScoredKeyword (sets deletedAt; the row stays in the DB but is filtered out of all queries). Housekeeping op — not part of the main flow. Pass confirm: true to proceed. Use for obvious junk keywords the auto-pipeline missed. Prefer seo_edit_keyword with excludedFromClustering=true when you only want to hold a keyword out of the next clustering pass.
Inputs: confirm (required), keywordId (required), brandId.
seo_edit_briefAInspect
Edit an SeoBrief before approval. The inner route does NOT accept free-text 'instructions' — refinement is structured. Pass briefData (the full replacement JSON for the brief outline — H2s, FAQs, keyword targets, etc.) and/or status ('approved' | 'rejected'). Approving via this tool fires L4 article/comparison generation immediately and returns { brief, operationId } — prefer seo_approve_briefs for the canonical approval step. Typical refinement loop: seo_get_brief → mutate briefData locally → seo_edit_brief with the new briefData (status omitted) → seo_approve_briefs.
Inputs: briefId (required), status, brandId, briefData, +4 more.
seo_edit_clusterAInspect
Edit a cluster's name, pillarKeyword, description, keywordsMeta, contentMix, and/or briefAssignments. Housekeeping op — not part of the main flow. At least one field must be supplied. MEMBERSHIP: there is no separate add/remove-member endpoint. Cluster membership is entirely controlled by keywordsMeta — it is a REPLACEMENT array, not a delta/patch. To add a keyword to the cluster, fetch the cluster's current keywordsMeta (seo_list_clusters with detail="full"), append a new entry {keyword, id, volume, kd, intent, relevance, priority, excluded?} (use the SeoScoredKeyword id from seo_list_keywords / seo_list_keyword_ids), and send the WHOLE array back. To remove a keyword, send the array with that entry omitted. Sending a partial array will drop the missing members from the cluster. contentMix must be an object with blog/tool/comparison/landing fractions summing to 1.0 (the server normalizes small rounding drift). briefAssignments is an array of {keyword, type, ...} entries (type ∈ hub|blog|comparison|tool|landing|skip); duplicate keywords are rejected. Example (rename): {"clusterId":"kwc_123","name":"Better cluster name"}. Example (remove a member): fetch full keywordsMeta, filter out the unwanted keyword, then {"clusterId":"kwc_123","keywordsMeta":[...remaining members]}.
Inputs: clusterId (required), name, brandId, contentMix, +4 more.
seo_edit_keywordAInspect
Edit a single SeoScoredKeyword. Housekeeping op — not part of the main flow. At least one of intent, userTags, priority, or excludedFromClustering must be supplied. Use to override the auto-detected intent label, attach user tags, manually nudge priority (0..1), or exclude a noisy keyword from clustering. Example: {"keywordId":"kw_123","intent":"commercial","userTags":["enterprise"]}.
Inputs: keywordId (required), intent, brandId, priority, +2 more.
seo_gapAInspect
Identify content gaps — topics the brand's competitors cover but the brand doesn't. Returns short detail by default: {id?, topic?, keyword?} labels only per gap. Use detail="medium" for compact gaps (+ searchVolume, difficulty, competitorDomains) or detail="full" for the raw API response.
Inputs: detail, brandId.
seo_generate_clustersAInspect
Step 4 of the SEO / GEO flow — async cluster-generation step. Groups related keywords into topic clusters that become candidate pillar topics. Typically takes ~1–2 min. Returns {operationId, status} — Poll get_job with the operationId until state is completed (or failed/partially_failed/cancelled on error). After completion, call seo_list_clusters to pick a target, then seo_generate_roadmap.
Inputs: brandId.
seo_generate_keywordsAInspect
Step 2 of the SEO / GEO flow. Async — expands seed keywords into the full keyword universe. Typically takes ~1–3 min. Uses credits. Returns {operationId, status} — Poll get_job with the operationId until state is completed (or failed/partially_failed/cancelled on error). By default the server auto-derives 30-40 seed concepts from the brand's own context (products, ICP, positioning) and expands those. Pass seeds to steer expansion yourself instead — e.g. to target specific topics or geographies the brand context wouldn't surface on its own ("California", "Texas", "Nashville plumbers"). Supplying seeds REPLACES the automatic brand-derived seed generation for this call — it does not add to it. 3-20 short phrases, the kind of thing someone would actually type into Google (2-4 words, no jargon). The only other thing the agent can tweak is autoScore (defaults to true server-side — set false to skip volume/difficulty scoring). After completion, call seo_categorize.
Inputs: seeds, brandId, autoScore.
seo_generate_roadmapAInspect
Step 6. Turn one or more clusters into a prioritized content roadmap of blog articles to write. Pass clusterId (single) or clusterIds (array of cluster IDs from seo_list_clusters) — omit both to roadmap all clusters. After this, call seo_write_article.
Inputs: brandId, clusterId, clusterIds.
seo_generate_side_pageAInspect
Generates a side page for a brand's landing page, optionally linked to an SEO cluster (clusterId). When linked, the side page surfaces in cluster-context queries and inherits the cluster's keyword targeting — strengthening topical authority that feeds GEO citation patterns. Two body modes: • freeform: pass key + prompt (+ optional keywords, selectedSections, voiceProfileId, sidePageType). Freeform now writes real section-level content (hero/features/showcase/faq/cta), not just metadata. • brief: pass key + brief (structured outline) + optional briefId and roadmapItemId. Typically takes ~2–5 min. Async — returns { success, operationId, operationRowId, pollUrl, sidePageId }. Poll get_job with the returned operationId until state is completed (or failed/partially_failed/cancelled on error); the generated page's sections will be populated once complete. Comparison-type briefs run synchronously and return sidePageId directly. slug is the PARENT landing page slug under which the side page is created.
Inputs: key (required), slug (required), brief, prompt, +8 more.
seo_get_briefAInspect
Fetch a single SeoBrief by id, including its briefData outline, status, roadmap item, and cluster. Returns full detail by default (complete brief incl briefData). Use detail="medium" for {id, type, status, title, clusterName, briefSummary, sidePageUrl} or detail="short" for {id, type, status}. Use to inspect a brief before refining it with seo_edit_brief or approving it with seo_approve_briefs.
Inputs: briefId (required), detail, brandId.
seo_list_briefsAInspect
Returns ALL briefs across EVERY status by default — do NOT add a status filter unless the user explicitly asks. statusBreakdown gives the per-status counts (match these to the dashboard's brief count). NOTE: briefs whose generation is still in-flight may not appear here yet — check list_operations / get_job for in-progress generation. Returns short detail by default: {id, type, status, title} per brief. Use detail="medium" for compact summary (clusterId, clusterName, briefSummary, sidePageUrl, generationError, blogArticleId, generatedAt, approvedAt) or detail="full" for raw briefs including briefData outline. To inspect a single brief's full outline, call seo_get_brief with detail="full". Filters: status (CSV — e.g. 'pending_review,approved'), type (CSV — e.g. 'blog,comparison,landing'), clusterId, roadmapItemId, q (cluster-name fuzzy match), limit (default 50, max 200), cursor. Response shape: { count, total, nextCursor, statusBreakdown, detail, briefs: [...] }.
Inputs: q, type, limit, cursor, +5 more.
seo_list_clustersAInspect
Step 5. List clusters so the agent can pick one (or several) to approve before brief and roadmap generation. Returns short detail by default: {id, name, status} per cluster. Use detail="medium" for the full compact summary (pillarKeyword, briefGenerationStatus, briefCount, keywordCount, topKeywords, firstBriefId, description, productFit, relevanceScore) or detail="full" for raw cluster objects. Full keyword detail (keywordsMeta, contentMix, briefAssignments) is intentionally omitted at short/medium to keep context small — use cluster IDs with approve/reject tools directly. Supports server-side filtering: status (CSV of pending_review/approved/rejected), productFit (core/adjacent/out_of_scope), archetype (competitor), origin (CSV of pipeline/manual), q (text search over name/description/pillarKeyword).
Inputs: q, detail, origin, status, +3 more.
seo_list_keyword_idsAInspect
Return just the ids of every SeoScoredKeyword matching a filter — unpaginated, no keyword data attached. Housekeeping op — not part of the main flow. Accepts the same filter set as seo_list_keywords: source, intent, clusterId, q, hasTag, volumeMin/volumeMax, kdMin/kdMax, relevanceMin/relevanceMax, priorityMin/priorityMax, includeDeleted, excludedFromClustering. Use to select "all keywords matching filter X" in one call, then feed the returned ids into seo_bulk_delete_keywords or seo_bulk_edit_keywords. Example: filter relevanceMax=0.2 to find low-relevance keywords, then bulk-delete or bulk-edit them. Or hasTag="geo:us-mn" to select every Minnesota-tagged keyword after seo_tag_geography.
Inputs: q, kdMax, kdMin, hasTag, +12 more.
seo_list_keywordsAInspect
List generated keywords for the brand. Useful for auditing between steps. Returns short detail by default: {id, keyword, intent} per keyword. Use detail="medium" for the full compact summary (priority, searchVolume, difficulty, relevance, clusterId, excludedFromClustering, userTags) or detail="full" for raw keyword objects. Supports server-side filtering: source, intent, clusterId, q (substring search), hasTag, volumeMin/volumeMax, kdMin/kdMax, relevanceMin/relevanceMax, priorityMin/priorityMax, includeDeleted, excludedFromClustering. hasTag filters on userTags (OR match) — use it to find geo-tagged keywords after seo_tag_geography, e.g. hasTag="geo:us-mn" or hasTag="geo:us-mn,geo:us-tx" for multiple regions. Use cursor (from a previous call's response) to page through results beyond limit.
Inputs: q, kdMax, kdMin, limit, +15 more.
seo_list_resultsAInspect
List the 'Generated Results' (blog articles + side pages + comparisons) the SEO/GEO pipeline has produced — mirrors the dashboard Results tab. Includes BOTH draft and published items. Use kind to filter. This is the canonical 'what content has been generated' list — prefer it over reconstructing results from briefs.
Inputs: kind, limit, cursor, detail, +2 more.
seo_list_roadmapAInspect
List roadmap items (blog topics queued for writing). Returns short detail by default: {id, title, status} per item. Use detail="medium" for the compact summary (priority, primaryKeywords, clusterId) or detail="full" for raw objects. Call seo_roadmap_get with detail="full" for a single item's complete detail.
Inputs: detail, status, brandId.
seo_merge_clustersAInspect
Merge one cluster into another: reassigns the source cluster's keywords, roadmap items (and their briefs, which follow transitively), and any linked blog articles to the target cluster, then deletes the source cluster. Not undoable. Housekeeping op — not part of the main flow. Use when seo_list_clusters or a rescan report shows near-duplicate clusters that should be consolidated. The target cluster's own name/description/keywordsMeta/contentMix are NOT changed by the merge — only the FK relations (keyword.clusterId, roadmap.clusterId, blogArticle.clusterId) move over. Use seo_edit_cluster afterward if the target's keywordsMeta needs updating to include the newly reassigned keywords.
Inputs: clusterId (required), sourceClusterId (required), brandId.
seo_publish_articleAInspect
Step 10. Publish or schedule a roadmap-generated article to a publication. Free-tier choke point — may return FREE_CAP_REACHED with a checkoutUrl.
Inputs: articleId (required), brandId, scheduledAt, connectionIds, +1 more.
seo_regenerate_briefAInspect
Re-runs L3 brief generation for a single brief (scoped to its cluster). Typically takes ~2–5 min. Async — returns {operationId, status}. Poll get_job with the operationId until state is completed (or failed/partially_failed/cancelled on error), then re-fetch with seo_get_brief to see the refreshed briefData. Use when the existing brief's outline is unusable and a structured seo_edit_brief won't recover it.
Inputs: briefId (required), brandId.
seo_reject_clusterAInspect
Reject a single cluster — marks it rejected and detaches its scored keywords. Use when a generated cluster isn't relevant.
Inputs: clusterId (required), brandId.
seo_restore_clusterAInspect
Restore a rejected cluster back to pending_review so it can be approved again.
Inputs: clusterId (required), brandId.
seo_restore_keywordAInspect
Undo a soft-delete: clears deletedAt on the given SeoScoredKeyword ids so they reappear in seo_list_keywords / seo_list_keyword_ids. Housekeeping op — not part of the main flow. Use after seo_delete_keyword or seo_bulk_delete_keywords removed something that shouldn't have been removed. IDs that are not currently soft-deleted are silently no-ops (the response's restored count only reflects rows that actually changed). Find deleted ids with seo_list_keyword_ids using includeDeleted=true.
Inputs: keywordIds (required), brandId.
seo_roadmap_deleteAInspect
Permanently delete a roadmap item. Pass confirm: true to proceed — this is irreversible.
Inputs: itemId (required), confirm (required), brandId.
seo_roadmap_editAInspect
Edit a roadmap item — update its title, status (suggested|in_progress|completed|ignored), or priority.
Inputs: itemId (required), title, status, brandId, +1 more.
seo_roadmap_getAInspect
View a single roadmap item by ID. Returns full detail by default (raw object). Use detail="medium" for {id, title, status, primaryKeywords, clusterId} or detail="short" for {id, title, status}.
Inputs: itemId (required), detail, brandId.
seo_roadmap_statsBInspect
Progress stats for the content roadmap (completed, in-progress, suggested counts).
Inputs: brandId.
seo_tag_geographyAInspect
Geo pivot Stage 1. Async — classifies every keyword's geographic intent and writes a geo:* tag into userTags. Tags: geo:<country>-<subdivision> (e.g. "geo:us-mn") for a place that resolves to one region, geo:<country> (e.g. "geo:us") for country-only intent, geo:none for no geographic intent, geo:ambiguous for a place name that maps to multiple regions with no way to resolve it. Typically takes ~1–2 min. Uses credits (unless dryRun is true). Returns {operationId, status} — poll get_job with the operationId until state is completed (or failed/partially_failed/cancelled on error). The job result includes tagCounts (tag -> count), ambiguousKeywords (needs human review), and costUsd. Idempotent by default: keywords that already carry any geo:* tag are skipped on a re-run — pass retag:true to force re-classification of everything. Pass dryRun:true to get the full classification breakdown WITHOUT writing any tags — use this first to review tagCounts and ambiguousKeywords before committing. After completion, use seo_list_keywords or seo_list_keyword_ids with hasTag="geo:us-mn" (etc.) to select the tagged keywords for further action.
Inputs: retag, dryRun, brandId.
seo_unapprove_clusterAInspect
Revert an approved cluster back to pending_review. Fails if briefs have already been generated for this cluster (cannot be reverted once briefs exist).
Inputs: clusterId (required), brandId.
seo_write_articleAInspect
ALTERNATIVE write path — only call this when a brief was NOT approved via seo_approve_briefs (which already auto-generates). If the brief status is writing, generation is already in progress — poll the existing operationId with get_job until state is completed rather than calling this again. Step 7 (manual path). Draft a full blog article for a roadmap item. Uses credits. Typically takes ~3–8 min per article. Precondition: the brief for this roadmap item must be in status approved. If the brief is still drafted or pending_review, review with seo_list_briefs / seo_get_brief, refine with seo_edit_brief, then approve with seo_approve_briefs (which will auto-generate). Returns an articleId that can be reviewed, edited, or published.
Inputs: roadmapItemId (required), count, brandId, voiceProfileId.
set_active_brandAInspect
Set the active brand for this session. All subsequent tools will use this brand by default.
Inputs: brandId (required).
set_brand_mediumsAInspect
STEP 2 of brand onboarding. Saves the list of platforms the brand publishes on. Call this immediately after create_brand or onboard_brand and the user has picked platforms. After this, call get_onboarding_status every ~15 seconds until it reports done.
Inputs: mediums (required), brandId.
set_landing_page_sectionAInspect
Set one field on a landing page section (dot-paths in field supported, e.g. 'plans.0.ctaUrl'), or replace a whole section with replaceSection=true. Pass the bare content-section key (e.g. 'hero', 'features', 'pricing') — the server maps it into the page's content tree. Top-level roots like slotMap, config, navigation, siteMetadata are also accepted as-is. Each call creates a new draft version — for many related changes across a page, prefer vibe_edit_landing_page instead. Example: section='hero', field='title', value='New headline'.
Inputs: slug (required), value (required), section (required), name, +3 more.
set_lp_section_layoutAInspect
Reorder and/or toggle visibility of a landing page's sections. Pass at least one of sectionOrder/sectionVisibility. Valid section-order keys (all 11): hero, features, pricing, cta, faq, howItWorks, showcase, categoryExplorer, replacesStack, comparisonMatrix, roiCalculator. sectionVisibility keys are the toggleable subset of the above. When both are given, order is attempted first, then visibility — each is applied independently, so one can succeed while the other fails. The result always reports both outcomes: { order: |{error}, visibility: |{error}, partialFailure: true } if only one part failed. This tool only throws if every requested part fails (or if a single requested part fails).
Inputs: slug (required), sectionOrder, sectionVisibility.
set_post_cardsAInspect
Bulk-replace all carousel cards for a post. Provide a full array of card objects with title, body, and optional number.
Inputs: cards (required), postId (required), rerender.
set_side_page_sectionAInspect
Update one section of a side page with STRUCTURED, typed fields (not a content string). The write must match the section's real shape or it is rejected with a 400 validation error. Landing sections use typed objects, e.g. hero → { title: { prefix, suffix }, description, testimonials: [...] }; comparison sections (matrix, verdict, scorecard, decisionTree, priceCalculator, competitorClaims, ...) use their comparison-schema shape. Use view_side_page(detail:'full') first to see the current section shape, then send the same shape back with your edits. Pass EITHER fields (a partial section object merged onto the current section) OR field (a dot-path) + value for a single nested change, OR instructions alone for a natural-language edit (the server runs an AI pass scoped to this section). type:"text" pages: there is no per-section nesting — the whole page is one flat {title, htmlContent} document. sectionId is accepted for symmetry (e.g. "content"/"htmlContent"/"title") but every edit applies to the whole document: pass fields:{title,htmlContent}, field:"title"|"htmlContent"+value, or instructions alone for an AI rewrite of the whole page. edit_side_page's title/htmlContent params are a simpler direct-write shortcut for the same document. Every edit creates a new draft version (like landing-page section edits) — see list_side_page_versions / restore_side_page_version; on a published page, edits stay draft-only until set_side_page_state({published:true}) publishes them.
Inputs: slug (required), sideKey (required), sectionId (required), field, +3 more.
set_side_page_stateAInspect
Publish or unpublish a side page. published:true publishes the CURRENT DRAFT — it sets the published pointer to the latest draft version, which is how you make draft edits (from edit_side_page / set_side_page_section) live. published:false hides the page publicly but keeps the last-published version marker, so re-publishing with no further edits restores it instantly. The response includes publishedVersionId — the version now live (unchanged from before on unpublish) — so you know exactly which version is public without a follow-up view_side_page call.
Inputs: slug (required), sideKey (required), published (required).
set_social_media_rulesAInspect
Update a brand's social media content rules for ONE platform. By default this MERGES your provided fields into the existing rules (send only what you want to change — other fields are preserved; arrays you provide replace the old array). Set replace=true to overwrite the entire platform ruleset. Valid platforms: linkedin, x/twitter, facebook, instagram, threads, general. Tip: call get_social_media_rules first to see current values.
Inputs: rules (required), platform (required), brandId, replace.
set_weekly_scheduleAInspect
Create or replace the weekly content schedule for the active brand. dayConfigs: array of { dayOfWeek (0=Sun…6=Sat), mediums: [{ medium, postsPerDay }] }. Mediums: x/twitter | linkedin | instagram | facebook | threads | blog. After setting, call enable_weekly_schedule to activate it.
Inputs: dayConfigs (required), brandId, enabled, timezone, +2 more.
storyline_add_line_itemAInspect
Add a new line item (deliverable) to a storyline's strategy. Specify the channel, type, title, description, and a config map (pass {} if no extra config).
Inputs: type (required), title (required), config (required), channel (required), +5 more.
storyline_clarifyAInspect
Run the intake/clarification step for a storyline. The API returns follow-up questions or a readiness signal; call iteratively until the system has enough context. After clarification is complete, call storyline_generate_brief.
Inputs: storylineId (required), brandId, userMessage.
storyline_confirm_briefAInspect
Confirm (lock) the brief for a storyline, advancing it to the strategy phase. After confirmation, call storyline_generate_strategy.
Inputs: storylineId (required), brandId.
storyline_createAInspect
Create a new storyline (marketing plan) for the brand. Pass a prompt describing the campaign goal; optionally provide a title. After creation, call storyline_clarify to gather context, then storyline_generate_brief.
Inputs: prompt (required), title, brandId.
storyline_deleteAInspect
Archive (soft-delete) a storyline. Pass confirm: true to proceed. Use storyline_restore to reverse this.
Inputs: confirm (required), storylineId (required), brandId.
storyline_delete_line_itemAInspect
Permanently remove a line item from a storyline's strategy. Pass confirm: true to proceed.
Inputs: itemId (required), confirm (required), storylineId (required), brandId.
storyline_edit_briefAInspect
Apply an AI-driven edit to the current brief using a natural-language instruction. Examples: 'Make the tone more casual', 'Add a proof point about our 99% uptime SLA'. Optionally pass expectedVersion for optimistic concurrency.
Inputs: instruction (required), storylineId (required), brandId, expectedVersion.
storyline_edit_strategyAInspect
Apply an AI-driven edit to the current strategy using a natural-language instruction. Examples: 'Add a LinkedIn video post for launch week', 'Remove the influencer outreach line items'.
Inputs: instruction (required), storylineId (required), brandId.
storyline_estimateAInspect
Read-only dry-run. Estimate the credits required to execute the storyline without actually running it. Use before storyline_execute to surface the cost to the user for approval. Returns { estimatedCredits, lineItemBreakdown } or similar.
Inputs: storylineId (required), brandId.
storyline_executeAInspect
Async. Execute a storyline — generates content drafts for all selected line items. Returns { operationId, status } — poll get_job with the operationId until state=completed. Typically takes ~3–8 min. Call storyline_estimate first to surface the credit cost before execution.
Inputs: storylineId (required), brandId.
storyline_generate_briefAInspect
Async. Generate the marketing brief for a storyline (positioning, key messages, audience, timing, tone notes). Returns { operationId, status } — poll get_job with the operationId until state=completed. Typically takes ~1–3 min. After completion, review the brief with storyline_get, then call storyline_confirm_brief to advance to strategy.
Inputs: storylineId (required), brandId.
storyline_generate_strategyAInspect
Async. Generate the strategy and line-items for a storyline based on its confirmed brief. Returns { operationId, status } — poll get_job with the operationId until state=completed. Typically takes ~2–5 min. After completion, review with storyline_get_strategy, then optionally edit with storyline_edit_strategy or add/remove line items.
Inputs: storylineId (required), brandId.
storyline_getAInspect
Fetch a single storyline by ID with its full state (brief, strategy, line items, status). Returns full detail by default. Use detail="medium" for a compact summary or detail="short" for {id,title,status}.
Inputs: storylineId (required), detail, brandId.
storyline_get_strategyAInspect
Fetch the strategy and line items for a storyline. Returns full detail by default (raw strategy + all line items). Use detail="medium" for a compact summary or detail="short" for {id,status} + line-item count.
Inputs: storylineId (required), detail, brandId.
storyline_listAInspect
List the brand's storylines (marketing plans). short detail {id,title,status}; medium adds isLive, dates, promptSummary; full = raw.
Inputs: detail, brandId.
storyline_regenerate_line_itemAInspect
Async. Re-generate a single line item's content draft. Returns { operationId, status } — poll get_job with the operationId until state=completed. Typically takes ~1–3 min.
Inputs: itemId (required), storylineId (required), brandId.
storyline_restoreAInspect
Restore an archived storyline back to active state.
Inputs: storylineId (required), brandId.
storyline_set_briefAInspect
Manually set (replace) the full brief for a storyline. Use to provide a human-authored brief or to push back an edited version retrieved via storyline_get. Pass the complete brief object and the current expectedVersion (use 0 when setting from scratch). After setting, call storyline_confirm_brief to advance to strategy generation.
Inputs: brief (required), storylineId (required), expectedVersion (required), brandId.
storyline_updateAInspect
Update metadata on a storyline: title, live status, or start/end/launch dates. Pass at least one field to change.
Inputs: storylineId (required), title, isLive, brandId, +3 more.
storyline_update_line_itemAInspect
Update a line item on a storyline — select/deselect, retitle, change description, targetDate, or config. Pass only the fields to change.
Inputs: itemId (required), storylineId (required), title, config, +4 more.
suggest_assets_for_postAInspect
Get AI-suggested assets from the brand library that match a given post context or topic.
Inputs: context (required), limit, brandId.
tag_assetAInspect
Add or remove tags on an asset. Provide addTags and/or removeTags as arrays.
Inputs: assetId (required), addTags, brandId, removeTags.
template_createAInspect
Create one or more content templates for the brand. Pass a single template object, or pass the 'templates' array param for bulk creation. If both are supplied, 'templates' (bulk) takes precedence. Returns the created template record(s).
Inputs: body, title, brandId, example, +5 more.
template_deleteAInspect
Permanently delete a content template from the brand. This action is irreversible.
Inputs: templateId (required), brandId.
template_extractAInspect
AI extracts a reusable content template from a pasted post text. Synchronous (seconds) — no polling needed. Pass save=true to also persist the template to the brand's library. Returns the extracted template object; if saved, includes the new template id.
Inputs: postText (required), save, brandId.
template_listAInspect
List the brand's saved content templates. short {id,title,category}; medium adds platforms,isFavorite,bodyPreview (160 chars); full = raw. Pass category to filter (e.g. 'hook', 'cta', 'thread'). Results are ordered by isFavorite desc, then usageCount desc.
Inputs: detail, brandId, category.
template_pickAInspect
RE-RANKER: AI scores a caller-supplied list of candidate templates and picks the N best-fitting ones for a given theme or topic. This tool does NOT read stored templates server-side — the caller must supply the candidates explicitly (e.g. call template_list first, then pass the results here). Synchronous — no polling needed. Pass the templates array from template_list (full detail) as candidates. Returns { templateIds } — an ordered array of the winning template IDs.
Inputs: count (required), theme (required), templates (required), brandId.
template_updateAInspect
Update an existing content template. All fields are optional — only supplied fields are changed. Use isFavorite=true/false to toggle favorite status.
Inputs: templateId (required), body, title, brandId, +5 more.
trends_listAInspect
Browse top-trending posts (with deconstructions) for a niche + platform. Account/niche-scoped — NOT tied to a specific brand. Each post includes hook, template, pattern, and virality reason from the deconstruction. The crawler runs every 3 days; use days=3 (default) for the freshest batch. Supported niches: ai-saas, marketing, web3. Supported platforms: x.
Inputs: days, sort, limit, niche, +1 more.
update_blog_articleAInspect
Edit a blog article — title, content, excerpt, SEO fields, status, author, category, featured/header image, or CTA. Set status='published' to make it live on your PostKing blog. CTA (call-to-action) is structured data, NOT part of the article body — never write CTA markup into content. Use cta: { url, label, headline, body } to set it (url is required when enabling), or cta: { enabled: false } to remove it. cta and sidePageInfo are mutually exclusive — pass sidePageInfo only if you need to link to an existing side page by id/slug (from list_side_pages) instead of a raw url; either way, malformed CTA shapes are now rejected by the server rather than silently persisted, so pass exactly the documented fields.
Inputs: articleId (required), cta, title, status, +11 more.
update_publicationAInspect
Update an existing blog publication's metadata — title, description, domain/routing config, or layout. Only the fields you pass are changed (partial update). Distinct from create_publication (which creates a new one). publicationId comes from list_publications or list_blogs.
Inputs: publicationId (required), title, layout, brandId, +4 more.
upload_assetAInspect
Upload an asset to the brand library from a local file path or base64-encoded content. Prefer filePath for local files: the server reads and base64-encodes the file itself, avoiding truncation of large base64 strings over the tool_call boundary. fileBase64 is still supported for remote/inline use where no local path is available. For large files over the remote/HTTP transport, a single fileBase64 string can get truncated crossing the LLM→tool_call boundary — use the chunked flow instead: upload_asset_begin → upload_asset_chunk (× N) → upload_asset_finish. Provide exactly one of filePath or fileBase64. Returns the new asset ID and URL.
Inputs: name, tags, brandId, fileName, +4 more.
upload_asset_abortAInspect
Cancel a chunked asset upload in progress and discard any buffered chunks.
Inputs: uploadId (required).
upload_asset_beginAInspect
Start a chunked asset upload. Use this instead of upload_asset's fileBase64 param for large files over the remote/HTTP transport, where a single large base64 string can get truncated crossing the LLM→tool_call boundary. Flow: upload_asset_begin (once) → upload_asset_chunk (once per chunk, in order) → upload_asset_finish (once). Returns an uploadId that expires after 10 minutes of inactivity.
Inputs: fileName (required), name, tags, sha256, +4 more.
upload_asset_chunkAInspect
Send one chunk of a base64-encoded file previously started with upload_asset_begin. Chunks must be sent in order, index starting at 0, with no gaps.
Inputs: index (required), uploadId (required), fileBase64Chunk (required).
upload_asset_finishAInspect
Finalize a chunked asset upload: reassembles the buffered chunks, verifies integrity, and uploads the asset to the brand library. Returns the new asset ID and URL.
Inputs: uploadId (required).
verify_domainAInspect
Check DNS verification for a domain. Returns whether it's pointing to PostKing servers and what A record is needed if not.
Inputs: domainId (required).
vibe_edit_landing_pageAInspect
Use AI to propose an edit to a landing page based on natural-language instructions. This is step 1 of a propose → review → apply flow — it does NOT change anything by itself: 1) Call this tool. Returns { operationId } — nothing is applied yet. 2) Poll get_vibe_edit_status(slug, operationId) — NOT get_job — until status is 'completed'. Vibe-edit sessions live in a separate store from the generic job/operation queue, so get_job will not find them. 3) Review the changes array returned by get_vibe_edit_status: field-level before/after entries, each with an index and a path. 4) Call apply_vibe_edit with all=true (accept everything) or a subset via indices/paths. 5) Call publish_landing_page to make the applied changes live. scope='full' edits the whole page; scope='section' restricts the edit to one section — sectionId is REQUIRED when scope='section'. Example section keys: hero, features, pricing, cta, faq, howItWorks, showcase, categoryExplorer, replacesStack, comparisonMatrix, roiCalculator.
Inputs: slug (required), instructions (required), scope, sectionId.
view_assetAInspect
View details of a single asset by ID. Supports detail param: short=id+type+name, medium=key fields, full=raw.
Inputs: assetId (required), detail, brandId.
view_landing_pageAInspect
Fetch a landing page by slug. detail='full' (default) returns full data JSONB plus previewUrl (public GUI preview link) and webUrl (dashboard editor link); 'medium' returns summary + sectionKeys/sectionWordCounts + previewUrl + webUrl; 'short' returns id/slug/name/status. Section bodies and rendered HTML appear only at full.
Inputs: slug (required), detail.
view_lp_draftAInspect
View the unpublished draft of a landing page. detail='full' (default) includes full versionData plus previewUrl (public GUI preview link, ?version= form); 'medium' adds sectionKeys/sectionWordCounts + previewUrl; 'short' is id/slug/name/status only.
Inputs: slug (required), detail.
view_lp_versionAInspect
View a specific LP version. detail='full' (default) returns full data plus previewUrl (public GUI preview link — the published form if this is the live version, otherwise the ?version= form); 'medium' adds sectionKeys/sectionWordCounts + previewUrl.
Inputs: slug (required), versionId (required), detail.
view_side_pageAInspect
View a side page including sections and rendered HTML. detail='full' (default) includes rendered HTML and full overrides (use this to read a section's typed shape before editing it with set_side_page_section); 'medium' gives summary + overrideSectionKeys (the section ids you can pass to set_side_page_section); 'short' gives id/slug/name/type/isPublished. Rendered HTML appears only at full. medium/full also include currentVersionId (the draft) and publishedVersionId (the live version) — a mismatch means there are unpublished draft edits.
Inputs: slug (required), sideKey (required), detail.
view_side_page_versionAInspect
View a specific side-page version snapshot. detail='full' (default) returns the complete snapshot { type, overrides, siteMetadata, slotMap, config } plus _meta { versionId, isCurrent, isPublished, createdAt }; 'medium' gives type + _meta + overrideSectionKeys (section ids only, no content); 'short' gives just _meta.
Inputs: slug (required), sideKey (required), versionId (required), detail.
web_searchAInspect
Perform a live, real-time web search and get back a raw answer with sources — for questions like 'find me the top 10 places to share/index my MCP', 'what's the latest on X', or 'where can I find Y'. Distinct from search_web_images, which only returns images — this tool returns a synthesized text answer plus the sources it drew from (each with title, url, and optional description), and optionally related follow-up prompts. Results are returned as-is (unsummarized) — pass the answer and sources straight through to the user.
Inputs: prompt (required), brandId.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 243 tools
Despite detailed descriptions, many tools occupy overlapping roles: generate_side_page and seo_generate_side_page are near-duplicates, list_jobs/list_operations/get_job offer three ways to inspect async work, and upload_asset overlaps with the upload_asset_begin/chunk/finish flow. An agent selecting from 243 tools will frequently face ambiguous choices.
Names are mostly snake_case verb_noun, but conventions shift across and within domains: seo_roadmap_get vs seo_list_roadmap vs get_seo_roadmap, list_blogs vs list_publications, and unprefixed tools like whoami and health break the pattern. It is readable but not a coherent naming system.
243 tools is far beyond a reasonable MCP surface, forcing massive context consumption and making it hard for an agent to even notice the right tool. This is an extreme scope mismatch for a single server regardless of how many features PostKing has.
Coverage is remarkably broad: posts, blogs, SEO pipeline, landing pages, side pages, assets, competitors, storylines, knowledge, and billing all have lifecycle support. Minor gaps exist, such as no direct update-post-content tool and asymmetries between soft-delete/restore flows, but they are workarounds rather than dead ends.
Related MCP Connectors
PostHero MCP server — schedule and publish social media posts from any MCP-compatible AI tool
MCP server for QPost — lets AI agents publish video and image posts to YouTube, TikTok, Instagram.
Hosted MCP server for AI agents to post to LinkedIn profiles and X and upload to YouTube.
MCP server for building and testing AI agents with multi-model experimentation and insights.
Related MCP Servers
- AlicenseAqualityDmaintenanceAn MCP server that automatically generates technical blog posts using AI (Gemini and Claude), supporting various input types, styles, and collaborative workflow.10MIT
- AlicenseAqualityCmaintenanceMCP server to manage social media accounts from AI assistants, enabling post creation, scheduling, publishing, and media uploads across multiple platforms.1311 npm1MIT
- AlicenseNot gradedqualityFmaintenanceMCP server for managing social media posts across multiple platforms using the Postiz API. Supports creating, updating, deleting posts, and generating videos.38 npm3MIT
- AlicenseAqualityCmaintenanceMCP server for QPost that lets AI agents schedule and publish video/image posts to YouTube, TikTok, and Instagram via QPost's REST API.782 npmMIT