Skip to main content
Glama

Post Draft From Markdown

post_draft_from_markdown

Create or update a Substack draft from Markdown content, with optional tags, prepublish checks, and publishing controls for newsletter or post delivery.

Instructions

Create or update a Substack draft from Markdown.

This tool builds a Substack `Post` from markdown content and posts a draft.
It supports optional tag assignment, prepublish (setup check), and publishing.

Args:
    title: Draft title.
    markdown: Markdown body content.
    subtitle: Optional subtitle text.
    audience: One of `everyone`, `only_paid`, `founding`, `only_free`.
    write_comment_permissions: One of `none`, `only_paid`, `everyone`.
    search_engine_title: Optional title for search engine optimization.
    search_engine_description: Optional description for search engine optimization.
    slug: Optional URL slug for the post.
    draft_section_id: Optional section ID for the draft.
    tags: Tag or list of tags to attach to the post.
    prepublish: If true, calls `prepublish_draft` after creation.
    publish: If true, calls `publish_draft` after creation (and optionally prepublish).
    send: Passed to `publish_draft` for newsletter delivery.
    share_automatically: Passed to `publish_draft`.

Returns:
    dict containing drafted post (`draft`), optional `tags`, `prepublish`, `publish` results.

Examples:
    With the YAML structure from the README, a caller can map fields like:

    ```yaml
    title: "My Post Title"
    subtitle: "My Post Subtitle"
    audience: "everyone"
    write_comment_permissions: "everyone"
    markdown: |
      # Hello

      This is the body.

    tags:
      - python
      - substack
    prepublish: true
    publish: true
    send: false
    share_automatically: true
    ```

    Then invoke via MCP directly:

    ```python
    from substack_mcp.mcp_server import post_draft_from_markdown

    result = await post_draft_from_markdown(
        title='My Post Title',
        markdown='# Hello

This is the body.', subtitle='My Post Subtitle', audience='everyone', write_comment_permissions='everyone', tags=['python', 'substack'], prepublish=True, publish=False, # set true when ready ) print(result) ```

    A longer process with manual prepublish/publish calls:

    ```python
    from substack_mcp.mcp_server import (
        post_draft_from_markdown,
        prepublish_draft,
        publish_draft,
        add_tags,
    )

    d = await post_draft_from_markdown(
        title='Long flow',
        markdown='Content',
        tags=['a','b'],
        publish=False,
    )
    draft_id = d['draft']['id']

    await add_tags(draft_id, ['post-tag', 'news'])
    await prepublish_draft(draft_id)
    await publish_draft(draft_id, send=True, share_automatically=True)
    ```

    This docstring example is meant to mirror the YAML-driven workflow and show how to decompose the same operations into explicit tool calls.

Input Schema

NameRequiredDescriptionDefault
sendNo
slugNo
tagsNo
titleYes
publishNo
audienceNoeveryone
markdownYes
subtitleNo
prepublishNo
draft_section_idNo
search_engine_titleNo
share_automaticallyNo
search_engine_descriptionNo
write_comment_permissionsNoeveryone

Output Schema

NameRequiredDescriptionDefault

No arguments

Schema Changelog

Changes observed during successful MCP inspections.

  1. First observedv0.1.0

TDQS

A3.6/5.0
Behavior3/5

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

With no annotations at all, the description carries the full burden, and it does disclose meaningful behavior: chained side effects when prepublish/publish are true, newsletter delivery via send, and the shape of the return dict. It omits the highest-stakes facts — that publish=true makes the post publicly live, that send=true (the schema default!) emails subscribers, and any auth prerequisite. The 'create or update' claim is also unexplained since no identifier parameter controls which mode applies.

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?

The first sentence is well front-loaded and the Args block is scannable, but the description is bloated: a YAML block plus two full Python examples, a Returns section redundant with the output schema, and a meta-sentence explaining what the examples are for. Roughly half the text restates information an agent already has from the schema.

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

Completeness4/5

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

For a 14-parameter mutation tool with 0% schema coverage, the description covers most of what an agent needs: parameter listing, enums, chaining semantics, and return shape (redundant given the output schema). The remaining gaps are the create-vs-update mechanism and the risk profile of publish/send, which matter for a write tool with no annotations.

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

Parameters3/5

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

Schema coverage is 0% and there are 14 parameters, so the description must compensate — and it does list every one, including enum values for audience and write_comment_permissions that the schema lacks. But several entries are near-tautological ('subtitle: Optional subtitle text') and send/share_automatically are dismissed as 'Passed to publish_draft' with no explanation, and no defaults are stated despite the surprising send=true default.

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

Purpose4/5

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

The opening sentence gives a specific verb and resource ('Create or update a Substack draft from Markdown') and the body clarifies it builds a Post and posts a draft. It also names the sibling tools it can chain into (prepublish_draft, publish_draft), which helps distinguish it from those. It does not, however, differentiate itself from put_draft, the other draft-writing sibling.

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

Usage Guidelines4/5

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

The two worked examples implicitly establish when to use the combined call versus decomposing into add_tags/prepublish_draft/publish_draft manually, and the closing sentence states that intent explicitly. What is missing is a stated rule for choosing between the two approaches and any precondition ('the draft must not already be published').

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