Skip to main content
Glama

create_draft

Create a draft Substack post from markdown content without publishing. Converts markdown to Substack's format and saves as unpublished draft.

Instructions

Create a new draft post. Accepts markdown body which is converted to Substack's format. Does NOT publish — creates a draft only.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
titleYesPost title
bodyNoPost body in markdown format
subtitleNoPost subtitle
audienceNoWho can see this posteveryone

Implementation Reference

  • Handler function for 'create_draft' tool. Converts markdown body to ProseMirror format, calls client.createDraft() with title, body, subtitle, and audience parameters, and returns the draft ID and title.
    async ({ title, body, subtitle, audience }) => {
      const prosemirrorBody = body ? markdownToProseMirror(body) : undefined;
      const draft = await client.createDraft(
        title,
        prosemirrorBody,
        subtitle,
        audience,
      );
      return {
        content: [
          {
            type: "text",
            text: JSON.stringify(
              {
                id: draft.id,
                title: draft.draft_title,
                message: "Draft created successfully. Open Substack to review and publish.",
              },
              null,
              2,
            ),
          },
        ],
      };
    },
  • Zod schema defining input parameters for 'create_draft' tool: title (required string), body (optional markdown), subtitle (optional string), and audience (optional enum with default 'everyone').
    {
      title: z.string().describe("Post title"),
      body: z.string().optional().describe("Post body in markdown format"),
      subtitle: z.string().optional().describe("Post subtitle"),
      audience: z
        .enum(["everyone", "only_paid", "founding", "only_free"])
        .optional()
        .default("everyone")
        .describe("Who can see this post"),
    },
  • src/server.ts:167-205 (registration)
    Registration of 'create_draft' tool with MCP server. Includes tool name, description, schema, and handler function.
    server.tool(
      "create_draft",
      "Create a new draft post. Accepts markdown body which is converted to Substack's format. Does NOT publish — creates a draft only.",
      {
        title: z.string().describe("Post title"),
        body: z.string().optional().describe("Post body in markdown format"),
        subtitle: z.string().optional().describe("Post subtitle"),
        audience: z
          .enum(["everyone", "only_paid", "founding", "only_free"])
          .optional()
          .default("everyone")
          .describe("Who can see this post"),
      },
      async ({ title, body, subtitle, audience }) => {
        const prosemirrorBody = body ? markdownToProseMirror(body) : undefined;
        const draft = await client.createDraft(
          title,
          prosemirrorBody,
          subtitle,
          audience,
        );
        return {
          content: [
            {
              type: "text",
              text: JSON.stringify(
                {
                  id: draft.id,
                  title: draft.draft_title,
                  message: "Draft created successfully. Open Substack to review and publish.",
                },
                null,
                2,
              ),
            },
          ],
        };
      },
    );
  • createDraft method in SubstackClient that constructs the API payload and makes POST request to /api/v1/drafts endpoint to create a new draft.
    async createDraft(
      title: string,
      body?: string,
      subtitle?: string,
      audience: string = "everyone",
    ): Promise<SubstackDraft> {
      const payload: DraftCreatePayload = {
        draft_title: title,
        draft_bylines: [{ id: this.userId, is_guest: false }],
        audience: audience as DraftCreatePayload["audience"],
        type: "newsletter",
      };
    
      if (subtitle) payload.draft_subtitle = subtitle;
      if (body) payload.draft_body = body;
    
      return this.request<SubstackDraft>(
        `${this.publicationUrl}/api/v1/drafts`,
        {
          method: "POST",
          body: JSON.stringify(payload),
        },
      );
    }
  • DraftCreatePayload interface defining the structure for creating drafts: draft_title, draft_subtitle, draft_body, draft_bylines, audience, type, and section_id.
    export interface DraftCreatePayload {
      draft_title: string;
      draft_subtitle?: string;
      draft_body?: string;
      draft_bylines: Array<{ id: number; is_guest: boolean }>;
      audience?: "everyone" | "only_paid" | "founding" | "only_free";
      type?: "newsletter" | "podcast" | "thread";
      section_id?: number | null;
    }

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/conorbronsdon/substack-mcp'

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