Skip to main content
Glama

Create Post

create_post

Create a draft post on the workspace blog. Never publishes or sends: publish_post and broadcast_post are separate, explicit acts.

The fields are not interchangeable blurbs — each feeds a different surface, and one left blank degrades that surface silently rather than failing.

list_posts is the only view of this blog, and it carries two things a new draft would otherwise lack:

  • The Author, AuthorURL and AuthorAvatarURL of the most recent post: the blog's established byline. A new author photo is hosted by upload_post_image.

  • The Tags and Categories already in use. Every distinct term generates its own public index page, so a near-duplicate splits one topic across two pages holding one post each.

The four text fields appear on different surfaces:

  • Title is the visible headline — the page heading, index-card/RSS title, and newsletter fallback subject.

  • SEO Title is an optional independent search/social title. When blank, search and social metadata fall back to Title.

  • Summary is the HUMAN line — the lede under the title, the index card, the RSS entry. For a reader who has already arrived; when Description is blank, its word-aware first 160 characters also supply the metadata fallback.

  • Description is an optional search/social override, never rendered on the page. Blank uses the Summary fallback, never the post body.

BODY. Markdown, rendered with raw HTML disabled. Tables and footnotes render; raw HTML, inline SVG and fenced mermaid blocks do not — they publish as visible literal text. A comparison renders as a markdown table; a diagram does not render.

IMAGES. A body image is a Markdown image whose URL upload_post_image returned. An external URL, an invented path or SVG does not render as a picture; a table or a structured list carries a comparison instead.

COVER. The post page, card, social metadata, and the newsletter email use the dedicated CoverImageURL field, never the first Markdown image. Set it to a URL upload_post_image returned for this workspace; omit it to publish with no cover. Setting the cover does not add anything to Markdown, and a Markdown image is never picked up as the cover automatically. CoverImageAlt supplies the cover's text alternative. An omitted alt text marks a purely decorative cover.

The result is a draft. publish_post puts it on the public blog; broadcast_post emails the list and takes its own inbox-specific Subject.

Tool call template

Replace each placeholder with a value matching the input schema. Only required parameters are included; add optional parameters as needed.

{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "tools/call",
  "params": {
    "arguments": {
      "Title": "<Title>"
    },
    "name": "create_post"
  }
}

Input Schema

NameRequiredDescriptionDefault
SlugNoOptional URL slug. When omitted, one is derived from the title and de-duplicated against the workspace. Format: lowercase words joined by hyphens.
TagsNoTopic terms. Each one generates its own public tag index page, so a term already used on this blog (listed by list_posts) keeps one page per topic, while near-duplicates - AI, ai and artificial-intelligence - become three pages holding one post each instead of one page holding three.
TitleYesPost headline and visible identity: the page heading, index-card title, RSS title and newsletter fallback subject. This is also the search/social title only when SEO Title is empty. Maximum 255 characters.
AuthorNoAuthor display name - the real person writing; the most recent post from list_posts carries the blog's current byline. Left blank, the post's structured data attributes it to the GoodSender organisation rather than to a person.
SummaryNoThe lede under the title on the post page, the preview blurb on the blog index card, the RSS entry, and the post's line in llms.txt.
MarkdownNoThe post body in Markdown, rendered by markdown-it with raw HTML DISABLED. Tables, lists, headings, links, blockquotes and footnote references such as [^1] all render. Raw HTML, inline SVG and fenced mermaid blocks do NOT - they are escaped and published as visible literal text; a comparison renders as a markdown table. Image URLs come from upload_post_image; the API does not restrict Markdown image URLs, and an external or invented one may not render.
SEOTitleNoOptional search/social title override, independent of the visible Title. Omit or send an empty string to use Title as the fallback. Maximum 255 characters.
AuthorURLNoAuthor profile URL matching Author - LinkedIn, GitHub or a personal site. MUST carry the scheme: a value that does not parse as http:// or https:// is silently DROPPED, so a bare handle or a scheme-less domain publishes as no link at all.
CategoriesNoBlog sections such as Guides, News or Engineering. Each generates its own public index page; list_posts shows the categories already in use. Categories group posts; Tags describe them.
ProvenanceNoOptional agent attribution recording that this post was machine-authored. All five fields are required together - a partial record is rejected - and the server stamps its own timestamp. It applies to a post written by an agent working in a code repository; omitted, no attribution is recorded.
DescriptionNoOptional search/social description override: the meta description, OG/Twitter description and JSON-LD description. No theme renders it on the post page. Omit or send an empty string to use the existing word-aware Summary fallback capped at 160 characters, never body text.
PublishedAtNoOptional RFC 3339 publish timestamp, for example 2026-08-30T09:00:00Z. Omit it on a normal draft: publish_post stamps the current time when this is still empty, and keeps a value that is already set. Set it only to back-date an imported post or to carry a specific public date.
CoverImageAltNoOptional text alternative for the cover image. Omission renders alt="". Ignored without CoverImageURL.
CoverImageURLNoOptional cover image URL, rendered on the post page, card, social metadata, and in the newsletter email - separate from any image inside Markdown. Only a URL upload_post_image returned for this workspace is valid; omit it to publish with no cover. Setting it does not add anything to Markdown, and an image already in Markdown is never picked up as the cover.
AuthorAvatarURLNoOptional author photo URL, shown beside the byline and as the author's image in structured data. Only a URL upload_post_image returned for this workspace is valid; omit it for no photo. The most recent post from list_posts carries the current author's AuthorAvatarURL.

Output Schema

NameRequiredDescriptionDefault
SlugYesURL slug.
TagsYesTags.
TitleYesVisible post headline; also the search/social title fallback when SEO Title is empty.
AuthorYesAuthor display name if set.
PostIDYesPost id.
StatusYesdraft or published.
SummaryYesHuman-facing lede; also the word-aware metadata-description fallback when Description is empty.
MarkdownYesMarkdown body.
SEOTitleYesStored optional search/social title override, or empty when Title supplies the fallback.
AuthorURLYesAuthor URL if set.
CreatedAtYesISO-8601 created time.
UpdatedAtYesISO-8601 updated time.
CategoriesYesCategories.
ProvenanceYesAgent attribution, absent on a human-authored post.
DescriptionYesStored optional search/social description override, or empty when the word-aware Summary fallback supplies metadata.
PublishedAtYesISO-8601 publish time if set.
CoverImageAltYesCover image alt text, or empty when unset. (FR-020)
CoverImageURLYesCover image URL, or empty when unset. Rendered on the post page, card, social metadata, and in the newsletter email - distinct from any image inside Markdown. CoverImageAlt describes it.
AuthorAvatarURLYesAuthor photo URL if set — shown beside the byline and as the author's image in structured data.
LastBroadcastAtYesISO-8601 broadcast time if set.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed12 schema fields changed
    • changedInput schema / properties / Author / description
      Previous value: -"Author display name - the real person writing. Take it from conversation context, or reuse the Author of the most recent post from list_posts. Left blank, the post's structured data attributes it to the GoodSender organisation rather than to a person, which is rarely what the author wants. Ask if you genuinely cannot tell."New value: +"Author display name - the real person writing; the most recent post from list_posts carries the blog's current byline. Left blank, the post's structured data attributes it to the GoodSender organisation rather than to a person."
    • changedInput schema / properties / AuthorAvatarURL / description
      Previous value: -"Optional author photo URL, shown beside the byline and as the author's image in structured data. Only a URL upload_post_image returned for this workspace is valid; omit it for no photo. Reuse the AuthorAvatarURL of the most recent post from list_posts when the author is the same person."New value: +"Optional author photo URL, shown beside the byline and as the author's image in structured data. Only a URL upload_post_image returned for this workspace is valid; omit it for no photo. The most recent post from list_posts carries the current author's AuthorAvatarURL."
    • changedInput schema / properties / Categories / description
      Previous value: -"Broad sections, usually 1-2, drawn from a small set reused across the whole blog such as Guides, News or Engineering. Each generates its own public index page, so consistency matters more than precision: reuse what list_posts shows before inventing one. Categories group posts; Tags describe them."New value: +"Blog sections such as Guides, News or Engineering. Each generates its own public index page; list_posts shows the categories already in use. Categories group posts; Tags describe them."
    • changedInput schema / properties / CoverImageAlt / description
      Previous value: -"Optional alt text for the cover: what the picture SHOWS, for a reader who cannot see it; one sentence, never a repeat of the title. Omit it when the cover only decorates the title (that renders alt=\"\"). Ignored without CoverImageURL."New value: +"Optional text alternative for the cover image. Omission renders alt=\"\". Ignored without CoverImageURL."
    • changedInput schema / properties / Description / description
      Previous value: -"Optional search/social description override: the meta description, OG/Twitter description and JSON-LD description. No theme renders it on the post page, so it must stand alone for a stranger who has NOT read the post. Omit or send an empty string to use the existing word-aware Summary fallback capped at 160 characters, never body text. Aim for 120-160 characters; one sentence, active voice, carrying the words someone would actually search for."New value: +"Optional search/social description override: the meta description, OG/Twitter description and JSON-LD description. No theme renders it on the post page. Omit or send an empty string to use the existing word-aware Summary fallback capped at 160 characters, never body text."
    • changedInput schema / properties / Markdown / description
      Previous value: -"The post body in Markdown, rendered by markdown-it with raw HTML DISABLED. Tables, lists, headings, links, blockquotes and footnote references such as [^1] all render. Raw HTML, inline SVG and fenced mermaid blocks do NOT - they are escaped and published as visible literal text, so never emit them; express a comparison as a markdown table instead. Open with the substance rather than a preamble restating the title. Image URLs come from upload_post_image; the API does not restrict Markdown image URLs, and an external or invented one may not render."New value: +"The post body in Markdown, rendered by markdown-it with raw HTML DISABLED. Tables, lists, headings, links, blockquotes and footnote references such as [^1] all render. Raw HTML, inline SVG and fenced mermaid blocks do NOT - they are escaped and published as visible literal text; a comparison renders as a markdown table. Image URLs come from upload_post_image; the API does not restrict Markdown image URLs, and an external or invented one may not render."
    • changedInput schema / properties / Provenance / description
      Previous value: -"Optional agent attribution recording that this post was machine-authored. All five fields are required together - a partial record is rejected - and the server stamps its own timestamp. Fill it when you are an agent working in a repository; omit it entirely otherwise."New value: +"Optional agent attribution recording that this post was machine-authored. All five fields are required together - a partial record is rejected - and the server stamps its own timestamp. It applies to a post written by an agent working in a code repository; omitted, no attribution is recorded."
    • changedInput schema / properties / SEOTitle / description
      Previous value: -"Optional search/social title override, independent of the visible Title. Omit or send an empty string to use Title as the fallback. Otherwise write a stand-alone search result title; aim for about 50-60 characters, with 255 as the hard limit."New value: +"Optional search/social title override, independent of the visible Title. Omit or send an empty string to use Title as the fallback. Maximum 255 characters."
    • changedInput schema / properties / Slug / description
      Previous value: -"Optional URL slug. Omit it and one is derived from the title and de-duplicated against the workspace - the right choice almost always. Set it only to keep a URL stable across a title change, or to shorten an unwieldy title. Lowercase words joined by hyphens; no dates, no stop words."New value: +"Optional URL slug. When omitted, one is derived from the title and de-duplicated against the workspace. Format: lowercase words joined by hyphens."
    • changedInput schema / properties / Summary / description
      Previous value: -"The HUMAN line: the lede under the title on the post page, the preview blurb on the blog index card, the RSS entry, and the post's line in llms.txt. Written for a reader who has already arrived, so it continues from the title instead of restating it. One or two sentences, aim for up to 300 characters. Must NOT repeat the Description sentence - that one is written for a different reader on a different surface."New value: +"The lede under the title on the post page, the preview blurb on the blog index card, the RSS entry, and the post's line in llms.txt."
    • changedInput schema / properties / Tags / description
      Previous value: -"Specific topic terms, roughly 3-6. Each one generates its own public tag index page, so reuse terms already used on this blog (listed by list_posts) rather than coining near-duplicates - AI, ai and artificial-intelligence become three pages holding one post each instead of one page holding three. Lowercase, singular where natural."New value: +"Topic terms. Each one generates its own public tag index page, so a term already used on this blog (listed by list_posts) keeps one page per topic, while near-duplicates - AI, ai and artificial-intelligence - become three pages holding one post each instead of one page holding three."
    • changedInput schema / properties / Title / description
      Previous value: -"Post headline and visible identity: the page heading, index-card title, RSS title and newsletter fallback subject. Write a specific claim rather than a topic label - prefer 'Why our retry queue drops 3% of jobs' over 'On retry queues'. This is also the search/social title only when SEO Title is empty. Keep it under 255 characters. Sentence case, no trailing period."New value: +"Post headline and visible identity: the page heading, index-card title, RSS title and newsletter fallback subject. This is also the search/social title only when SEO Title is empty. Maximum 255 characters."
  2. First observed

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only tell the agent this is a non-destructive, non-idempotent write; the description adds the behaviors that actually matter: the output is a draft, blank fields degrade a surface silently instead of failing, raw HTML/SVG/mermaid are escaped as visible literal text, and a Markdown image is never auto-picked as the cover. It also discloses the PublishedAt default (publish_post stamps the time) — none of which is inferable from the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Purpose and the publish/broadcast boundary are correctly front-loaded, but the body is long and re-states schema content almost verbatim (the Cover paragraph duplicates CoverImageURL's description, and the BODY/IMAGES sections overlap with Markdown's schema text). For 15 parameters the length is defensible, but a tighter draft would drop the redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present, the description only needs to close behavioral gaps, and it does: it explains the draft result, the handoff to publish_post and broadcast_post, the field-to-surface mapping, image sourcing, and date handling. Nothing an agent needs in order to call this correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, but the description still earns its place by explaining what each field feeds: Title vs SEOTitle vs Summary vs Description are mapped to distinct surfaces with explicit fallback chains, the Cover/Markdown image relationship is clarified, and a blank Author is disclosed as attributing to the organisation. This is meaning well beyond the schema's per-property text.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The opening sentence gives a specific verb, resource and scope: "Create a draft post on the workspace blog." The very next line draws the boundary against publish_post and broadcast_post, so an agent can separate this from its two nearest siblings without opening any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It states explicitly what this tool never does (publish or send) and names the alternatives that do it. It also routes the agent to list_posts for the established byline and existing tags/categories, and to upload_post_image for valid image URLs — concrete when-to-use guidance rather than implied usage.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.