Skip to main content
Glama

postiz_create_post

Create, schedule, or immediately publish social media posts across multiple integrations. Specify content, images, and optional settings for each account. Choose between draft, scheduled, or instant publication.

Instructions

Create, schedule, or immediately publish one or more posts via POST /api/posts. PUBLIC SIDE EFFECT: with type='now' or a near-term schedule, this lands on real social accounts. Use postiz_get_provider_settings_schema first to construct valid settings blocks. Requires enableWrite.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
typeYesdraft / schedule / now. PUBLIC SIDE EFFECT for schedule + now.
dateYesISO-8601 timestamp.
postsYesOne entry per integration to post on.
shortLinkNo
tagsNo

Implementation Reference

  • The `createCreatePostTool` function returns the tool definition with name 'postiz_create_post'. The `execute` handler validates the write gate, maps params to `PostizCreatePostInput`, calls `client.createPost(body)`, and returns the result with rate-limit info.
    export function createCreatePostTool(
      getClient: () => PostizClient,
      config: PostizPluginConfig,
    ) {
      return {
        name: "postiz_create_post",
        label: "postiz: create post",
        description:
          "Create, schedule, or immediately publish one or more posts via POST /api/posts. PUBLIC SIDE EFFECT: with type='now' or a near-term schedule, this lands on real social accounts. Use postiz_get_provider_settings_schema first to construct valid `settings` blocks. Requires enableWrite.",
        parameters: Schema,
        execute: async (_id: string, raw: Record<string, unknown>) => {
          requireWriteGate(config, "postiz_create_post");
          const params = raw as {
            type: "draft" | "schedule" | "now";
            date: string;
            posts: Array<{
              integrationId: string;
              value: Array<{ content: string; image?: Array<{ id?: string; path?: string }> }>;
              settings?: Record<string, unknown>;
              group?: string;
            }>;
            shortLink?: boolean;
            tags?: Array<{ value: string; label: string }>;
          };
          const body: PostizCreatePostInput = {
            type: params.type,
            date: params.date,
            posts: params.posts.map((p) => ({
              integration: { id: p.integrationId },
              value: p.value,
              ...(p.settings ? { settings: p.settings } : {}),
              ...(p.group ? { group: p.group } : {}),
            })),
            ...(params.shortLink !== undefined ? { shortLink: params.shortLink } : {}),
            ...(params.tags ? { tags: params.tags } : {}),
          };
          const client = getClient();
          const res = await client.createPost(body);
          return jsonToolResult(
            withRate(client, {
              ok: true,
              action: "create_post",
              type: params.type,
              date: params.date,
              integrationCount: params.posts.length,
              response: res,
            }),
          );
        },
      };
  • TypeBox schema for the tool's `parameters`: defines `type` (draft/schedule/now), `date`, `posts` (array of integration posts with content, images, settings, group), `shortLink`, and `tags`.
    const Schema = Type.Object(
      {
        type: Type.Union(
          [Type.Literal("draft"), Type.Literal("schedule"), Type.Literal("now")],
          {
            description:
              "'draft' saves without scheduling. 'schedule' queues for the supplied date. 'now' publishes immediately on the platform side.",
          },
        ),
        date: Type.String({
          description:
            "ISO-8601 timestamp (e.g. '2026-05-01T14:00:00.000Z'). Required even for 'now' — Postiz expects the field. Use postiz_find_next_slot for a schedule-respecting default.",
        }),
        posts: Type.Array(
          Type.Object(
            {
              integrationId: Type.String({
                description:
                  "Integration id (from postiz_list_integrations) to post on.",
              }),
              value: Type.Array(
                Type.Object(
                  {
                    content: Type.String({
                      description:
                        "Post body. For threads (X, Bluesky), append more value entries — each entry is one post in the thread.",
                    }),
                    image: Type.Optional(
                      Type.Array(
                        Type.Object(
                          {
                            id: Type.Optional(Type.String()),
                            path: Type.Optional(Type.String()),
                          },
                          { additionalProperties: true },
                        ),
                        {
                          description:
                            "Attached media. Use postiz_upload_file or postiz_upload_from_url first to obtain { id, path }.",
                        },
                      ),
                    ),
                  },
                  { additionalProperties: true },
                ),
                { minItems: 1 },
              ),
              settings: Type.Optional(
                Type.Record(Type.String(), Type.Unknown(), {
                  description:
                    "Provider-specific settings block (must include `__type`). Use postiz_get_provider_settings_schema to discover fields and required values for the target provider.",
                }),
              ),
              group: Type.Optional(
                Type.String({
                  description:
                    "Optional group id to associate this post with an existing group (e.g. cross-posting the same thread to multiple integrations).",
                }),
              ),
            },
            { additionalProperties: false },
          ),
          {
            minItems: 1,
            description:
              "One entry per integration to post on. Each entry's `value` array is the post (or thread, for value.length > 1).",
          },
        ),
        shortLink: Type.Optional(
          Type.Boolean({
            description:
              "If true, Postiz shortens links in the post via its short-link service. Default false.",
          }),
        ),
        tags: Type.Optional(
          Type.Array(
            Type.Object(
              {
                value: Type.String(),
                label: Type.String(),
              },
              { additionalProperties: false },
            ),
            {
              description:
                "Optional grouping tags Postiz uses for filtering in its UI. NOT the same as platform-specific hashtags.",
            },
          ),
        ),
      },
      { additionalProperties: false },
    );
  • index.ts:54-58 (registration)
    Tool is registered via `api.registerTool(createCreatePostTool(getClient, config) as AnyAgentTool)` inside the `enableWrite` gate block (line 58).
    if (config.enableWrite) {
      api.registerTool(
        createConnectIntegrationTool(getClient, config) as AnyAgentTool,
      );
      api.registerTool(createCreatePostTool(getClient, config) as AnyAgentTool);
  • mcp-server.ts:171-198 (registration)
    Tool is also registered/bound in the standalone MCP server via `bind(server, createCreatePostTool(getClient, config), {...})` with Zod-based parameter schemas.
    bind(server, createCreatePostTool(getClient, config), {
      type: z.enum(["draft", "schedule", "now"]).describe(
        "draft / schedule / now. PUBLIC SIDE EFFECT for schedule + now.",
      ),
      date: z.string().describe("ISO-8601 timestamp."),
      posts: z.array(
        z.object({
          integrationId: z.string(),
          value: z.array(
            z.object({
              content: z.string(),
              image: z
                .array(
                  z.object({
                    id: z.string().optional(),
                    path: z.string().optional(),
                  }),
                )
                .optional(),
            }),
          ).min(1),
          settings: z.record(z.string(), z.unknown()).optional(),
          group: z.string().optional(),
        }),
      ).min(1).describe("One entry per integration to post on."),
      shortLink: z.boolean().optional(),
      tags: z.array(z.object({ value: z.string(), label: z.string() })).optional(),
    });
  • `PostizCreatePostInput` interface — the data shape sent to POST /api/public/v1/posts, used by the tool's execute handler to construct the request body.
    export interface PostizCreatePostInput {
      type: "draft" | "schedule" | "now";
      date: string;
      posts: Array<{
        integration: { id: string };
        value: Array<{
          content: string;
          id?: string;
          image?: Array<{ id?: string; path?: string }>;
        }>;
        settings?: Record<string, unknown>;
        group?: string;
      }>;
      shortLink?: boolean;
      tags?: Array<{ value: string; label: string }>;
    }
Behavior5/5

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

With no annotations, description fully discloses the public side effect for 'now' and near-term schedule, the dependency on provider settings schema, and the 'enableWrite' permission requirement. This is comprehensive for a write operation.

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

Conciseness5/5

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

Three sentences exactly: action, side-effect warning, prerequisite. Every sentence adds value; no redundancy or filler.

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

Completeness3/5

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

No output schema, yet description does not mention expected return value (e.g., post ID) or pagination. For a creation tool, this gap may hinder the agent from handling the response. Purpose and side effects are clear, but return details are missing.

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 60% (type, date, posts described in schema). Description adds the side-effect warning for type and the prerequisite for settings, but does not explain shortLink or tags parameters, which remain undocumented.

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?

Description clearly states the tool creates, schedules, or publishes posts, specifying the HTTP endpoint and the public side effect for 'now' or near-term schedule. This distinctly separates it from siblings like delete or update tools.

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?

Description advises using postiz_get_provider_settings_schema first to construct valid settings and mentions the 'enableWrite' requirement. It implies caution with type='now' but lacks explicit 'when not to use' guidance.

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

Install Server

Other Tools

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/solomonneas/postiz-mcp'

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