Skip to main content
Glama

create_note

Publish short-form content to Substack using markdown format. This tool creates notes that are published immediately without a draft state.

Instructions

Create a Substack Note (short-form content). Accepts markdown text. Publishes immediately — there is no draft state for notes.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
bodyYesNote content in markdown format

Implementation Reference

  • Tool registration and handler for 'create_note'. Registers the tool with Zod schema validation (body: string), then handles the request by converting markdown to ProseMirror format, calling client.createNote(), and returning the created note details.
    server.tool(
      "create_note",
      "Create a Substack Note (short-form content). Accepts markdown text. Publishes immediately — there is no draft state for notes.",
      {
        body: z.string().describe("Note content in markdown format"),
      },
      async ({ body }) => {
        const bodyJson = {
          type: "doc" as const,
          attrs: { schemaVersion: "v1" as const },
          content: markdownToProseMirrorContent(body),
        };
        const note = await client.createNote(bodyJson);
        return {
          content: [
            {
              type: "text",
              text: JSON.stringify(
                {
                  id: note.id,
                  body: note.body,
                  date: note.date,
                  message: "Note published successfully.",
                },
                null,
                2,
              ),
            },
          ],
        };
      },
  • API client method that creates a note by constructing the payload with bodyJson, tabId, surface, and replyMinimumRole, then makes a POST request to the Substack API endpoint /api/v1/comment/feed.
    async createNote(
      bodyJson: NoteCreatePayload["bodyJson"],
      attachmentIds?: string[],
    ): Promise<SubstackNote> {
      const payload: NoteCreatePayload = {
        bodyJson,
        tabId: "for-you",
        surface: "feed",
        replyMinimumRole: "everyone",
      };
      if (attachmentIds?.length) {
        payload.attachmentIds = attachmentIds;
      }
      return this.request<SubstackNote>(
        `${this.publicationUrl}/api/v1/comment/feed`,
        {
          method: "POST",
          body: JSON.stringify(payload),
        },
      );
    }
  • Type definitions for the note creation payload (NoteCreatePayload) with bodyJson structure, and the response type (SubstackNote) with id, body, date, and other metadata fields.
    export interface NoteCreatePayload {
      bodyJson: {
        type: "doc";
        attrs: { schemaVersion: "v1" };
        content: unknown[];
      };
      tabId: string;
      surface: string;
      replyMinimumRole: string;
      attachmentIds?: string[];
    }
    
    export interface SubstackNote {
      id: number;
      body: string;
      body_json?: unknown;
      date: string;
      name: string;
      reaction_count: number;
      restacks: number;
      children_count: number;
      attachments: unknown[];
    }
  • Helper function that converts markdown text to ProseMirror content array format, used by the create_note handler to format the note body before sending to the API.
    /**
     * Returns the raw ProseMirror content array (for Notes, which wrap it in their own doc envelope).
     */
    export function markdownToProseMirrorContent(markdown: string): PMNode[] {
      const doc = JSON.parse(markdownToProseMirror(markdown));
      return doc.content;
    }

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