Skip to main content
Glama

Server Configuration

Describes the environment variables required to run the server.

NameRequiredDescriptionDefault
POSTKING_API_URLNoOverride the API base URLhttps://try.postking.app
POSTKING_API_TOKENNoSkip device login by providing a token directly

Instructions

Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.

This server publishes no instructions, or was last inspected before Glama recorded them.

Capabilities

Features and capabilities supported by this server

Protocol revision2025-11-25

CapabilityDetails
tools
{
  "listChanged": true
}
prompts
{
  "listChanged": true
}

Tools

Functions exposed to the LLM to take actions

NameDescription
login_startA

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.

login_completeA

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.

logoutA

Clear locally stored PostKing credentials.

whoamiA

Return the profile of the currently authenticated PostKing user (email, plan, credit balance, token source).

list_brandsA

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'.

set_active_brandA

Set the active brand for this session. All subsequent tools will use this brand by default.

get_brand_infoA

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.

create_brandA

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.

onboard_brandA

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.

set_brand_mediumsA

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.

get_brand_mediumsA

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'.

get_brand_membersA

List all active members of a brand with their role and user info (id, name, email).

get_onboarding_statusA

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.

list_themesA

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.

edit_themeA

Edit an existing content theme's title or content instructions.

delete_themeA

Delete a content theme from the active brand.

generate_themesA

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.

get_social_media_rulesA

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.

set_social_media_rulesA

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.

generate_postA

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).

generate_bulk_postsB

Generate and schedule multiple posts across a date range in the background.

create_postA

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.

list_postsA

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.

get_postA

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.

approve_postA

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'.

reschedule_postB

Move a scheduled post to a new time. Pass a future ISO 8601 UTC datetime.

schedule_postA

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'.

cancel_postA

Cancel a scheduled or approved post, reverting it to draft status without deleting it. Use delete_post to remove it entirely.

delete_postA

Cancel and delete a post regardless of its current status (draft, scheduled, or posted).

get_calendarA

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.

repurpose_contentA

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.

generate_textA

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.

list_voicesA

List all available voice profiles with their IDs. Lists default short; pass detail=medium/full for more fields.

rewrite_with_voiceC

Rewrite text using a specific voice profile.

rewrite_textB

Rewrite text using a voice profile or general writing rules.

humanize_textC

Apply LLM rewrite and BERT replacements to reduce AI detection signals in text.

check_ai_contentA

Check whether text is likely AI-generated. Returns a score and analysis.

check_social_accountsA

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.

generate_connect_linkA

Generate a secure browser link to connect a social media account. Share this URL with the user to complete OAuth.

disconnect_social_accountB

Disconnect a social account by its account ID.

list_domainsA

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.

add_domainA

Add a new custom domain to the active brand. After adding, call verify_domain to check DNS and activate it.

verify_domainA

Check DNS verification for a domain. Returns whether it's pointing to PostKing servers and what A record is needed if not.

delete_domainA

Remove a custom domain. Connected blogs and landing pages are unlinked but not deleted.

connect_domain_to_publicationA

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).

get_creditsA

Check your current PostKing credit balance and free-tier status.

healthA

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.

list_blogsA

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'.

create_publicationA

Create a new blog publication (the container that articles live under). Returns a publicationId needed for generate_blog_post.

update_publicationA

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.

delete_publicationA

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).

generate_blog_postA

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'.

get_blog_articleA

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.

update_blog_articleA

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.

schedule_blog_articleA

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'.

delete_blog_articleA

Permanently delete a blog article.

list_blog_authorsA

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.

list_blog_categoriesA

List all categories for a blog publication. Returns id+name+slug by default (short); use detail='medium' for description+articleCount.

create_blog_categoryB

Create a new category in a blog publication.

list_publishing_connectionsA

List external publishing connections for a blog publication (WordPress, Medium, Substack, etc.).

publish_blog_articleA

Push a blog article to connected external platforms (WordPress, Medium, Substack, etc.). Get connection IDs from list_publishing_connections.

import_blog_articlesA

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.

get_blog_statusA

Poll the async generation status of a blog article. Use the articleId returned by generate_blog_post. Status: pending | running | completed | failed.

create_blog_authorA

Create a new author for blog articles. Returns an authorId that can be used in generate_blog_post and update_blog_article.

list_publicationsA

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.

get_seo_roadmapA

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.

seo_add_seedsA

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.

seo_generate_keywordsA

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.

seo_list_keywordsA

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.

seo_edit_keywordA

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"]}.

seo_delete_keywordA

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.

seo_bulk_delete_keywordsA

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.

seo_restore_keywordA

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.

seo_bulk_edit_keywordsA

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}.

seo_list_keyword_idsA

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.

seo_tag_geographyA

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.

seo_categorizeA

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.

seo_generate_clustersA

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.

seo_create_clusterA

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.

seo_edit_clusterA

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]}.

seo_merge_clustersA

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.

seo_delete_clusterA

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.

seo_list_clustersA

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).

seo_bulk_approve_clustersA

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).

seo_approve_clusterA

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).

seo_reject_clusterA

Reject a single cluster — marks it rejected and detaches its scored keywords. Use when a generated cluster isn't relevant.

seo_bulk_reject_clustersA

Bulk-reject N clusters in one call. Symmetric to seo_bulk_approve_clusters.

seo_unapprove_clusterA

Revert an approved cluster back to pending_review. Fails if briefs have already been generated for this cluster (cannot be reverted once briefs exist).

seo_restore_clusterA

Restore a rejected cluster back to pending_review so it can be approved again.

seo_generate_roadmapA

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.

seo_list_roadmapA

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.

seo_roadmap_getA

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}.

seo_roadmap_editA

Edit a roadmap item — update its title, status (suggested|in_progress|completed|ignored), or priority.

seo_roadmap_deleteA

Permanently delete a roadmap item. Pass confirm: true to proceed — this is irreversible.

seo_roadmap_statsB

Progress stats for the content roadmap (completed, in-progress, suggested counts).

seo_list_briefsA

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: [...] }.

seo_get_briefA

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.

seo_create_custom_briefA

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.

seo_edit_briefA

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.

seo_approve_briefsA

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}] }.

Prompts

Interactive templates invoked by user choice

NameDescription
getting_startedStep-by-step guide for first-time PostKing setup
connect_social_accountsGuide for connecting or checking social media accounts
repurpose_and_scheduleTurn a URL or text into scheduled social posts
manage_postsView, reschedule, or delete scheduled and draft posts
manage_themesView, edit, or generate content themes for your brand
blog_publishingGenerate, edit, and publish blog posts to WordPress, Medium, Substack and more
use_voice_profilesApply a voice profile to rewrite or generate content in a specific style
seo_end_to_endRun SEO / GEO from seed keywords to published articles using PostKing's agentic SEO / GEO pipeline
content_week_plannerPlan and approve a full week of social posts using smart-week + batch generation
blog_publishing_pipelineGenerate a blog article, iterate via MCP resources, then publish to internal or external platforms
landing_page_builderGenerate a landing page, iterate with AI edits, connect a domain, then publish
reddit_repurposeRepurpose brand content into Reddit-native posts: pool subreddits → suggest subreddits for content → rewrite → review
plan_storyline_campaignPlan and execute a full marketing storyline: clarify → brief → strategy → curate → execute
competitor_intelligenceBuild a competitive intelligence picture: probe → add → analyze → comparison → overview
manage_knowledge_baseBrowse, create, update, and delete brand knowledge base items
trends_to_postBrowse trending posts, extract or pick a content template, then generate a post
repurpose_and_schedule_v2Updated repurpose flow for /api/agent/v1/* endpoints with per-platform voice profiles

Resources

Contextual data attached and managed by the client

NameDescription

No resources

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/bitsandtea/postking-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server