Skip to main content
Glama

mastodon_create_toot

Post text content to Mastodon with options for visibility, media attachments, scheduling, and content warnings.

Instructions

Create a new toot (status) on Mastodon, optionally with media attachments

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
contentYesThe text content of the toot
visibilityNoThe visibility level of the tootpublic
sensitiveNoMark the toot as sensitive content
spoiler_textNoText to be shown as a warning before the actual content
media_fileNoPath to a media file to attach (image, video, or audio)
media_descriptionNoAlt text / description for the attached media
scheduled_atNoOptional ISO 8601 datetime string to schedule the toot for a future time. Examples: 2024-01-01T10:00:00Z, 2024-01-01T10:00:00+01:00

Implementation Reference

  • The main handler function for the 'mastodon_create_toot' tool. It handles media upload if provided, calls the Mastodon API to create or schedule a toot, and formats a success response with link or schedule details.
    async (params: TootParams) => { let media_ids: string[] | undefined; if (params.media_file) { try { const fileData = await readFile(params.media_file); const media = await client.uploadMedia( fileData, params.media_file.split("/").pop() || "image", params.media_description ); media_ids = [media.id]; } catch (error: unknown) { const errorMessage = error instanceof Error ? error.message : "Unknown error"; throw new Error(`Failed to upload media: ${errorMessage}`); } } const result = await client.createStatus({ status: params.content, visibility: params.visibility, sensitive: params.sensitive, spoiler_text: params.spoiler_text, media_ids, scheduled_at: params.scheduled_at, }); let successMessage: string; // Check if 'url' property exists to differentiate MastodonStatus from ScheduledMastodonStatus if ('url' in result) { // It's a MastodonStatus (posted immediately) const mediaInfo = result.media_attachments.length > 0 ? `\nMedia: ${result.media_attachments.map((m) => m.url).join(", ")}` : ""; successMessage = `Successfully created toot! View it at: ${result.url}${mediaInfo}`; } else { // It's a ScheduledMastodonStatus const scheduledTime = new Date(result.scheduled_at).toLocaleString(); let mediaInfo = ""; if (result.media_attachments && result.media_attachments.length > 0) { mediaInfo = `\nMedia will be attached: ${result.media_attachments.length} item(s).`; } successMessage = `Successfully scheduled toot! ID: ${result.id}. It will be posted at: ${scheduledTime}.${mediaInfo}`; } return { content: [ { type: "text", text: successMessage, }, ], }; }
  • Zod schema defining the input parameters and validation for the 'mastodon_create_toot' tool.
    const TootSchema = z.object({ content: z.string().describe("The text content of the toot"), visibility: z .enum(["public", "unlisted", "private", "direct"]) .describe("The visibility level of the toot") .default("public"), sensitive: z .boolean() .describe("Mark the toot as sensitive content") .default(false), spoiler_text: z .string() .describe("Text to be shown as a warning before the actual content") .default(""), media_file: z .string() .describe("Path to a media file to attach (image, video, or audio)") .optional(), media_description: z .string() .describe("Alt text / description for the attached media") .optional(), scheduled_at: z .string() .datetime({ offset: true, message: "Invalid datetime string, expected ISO 8601 format (e.g., YYYY-MM-DDTHH:mm:ss.sssZ, YYYY-MM-DDTHH:mm:ss.sss+HH:MM)" }) .describe("Optional ISO 8601 datetime string to schedule the toot for a future time. Examples: 2024-01-01T10:00:00Z, 2024-01-01T10:00:00+01:00") .optional(), });
  • Registration of the 'mastodon_create_toot' tool using server.tool(), including name, description, input schema, and handler function.
    server.tool( "mastodon_create_toot", "Create a new toot (status) on Mastodon, optionally with media attachments", TootSchema.shape, async (params: TootParams) => { let media_ids: string[] | undefined; if (params.media_file) { try { const fileData = await readFile(params.media_file); const media = await client.uploadMedia( fileData, params.media_file.split("/").pop() || "image", params.media_description ); media_ids = [media.id]; } catch (error: unknown) { const errorMessage = error instanceof Error ? error.message : "Unknown error"; throw new Error(`Failed to upload media: ${errorMessage}`); } } const result = await client.createStatus({ status: params.content, visibility: params.visibility, sensitive: params.sensitive, spoiler_text: params.spoiler_text, media_ids, scheduled_at: params.scheduled_at, }); let successMessage: string; // Check if 'url' property exists to differentiate MastodonStatus from ScheduledMastodonStatus if ('url' in result) { // It's a MastodonStatus (posted immediately) const mediaInfo = result.media_attachments.length > 0 ? `\nMedia: ${result.media_attachments.map((m) => m.url).join(", ")}` : ""; successMessage = `Successfully created toot! View it at: ${result.url}${mediaInfo}`; } else { // It's a ScheduledMastodonStatus const scheduledTime = new Date(result.scheduled_at).toLocaleString(); let mediaInfo = ""; if (result.media_attachments && result.media_attachments.length > 0) { mediaInfo = `\nMedia will be attached: ${result.media_attachments.length} item(s).`; } successMessage = `Successfully scheduled toot! ID: ${result.id}. It will be posted at: ${scheduledTime}.${mediaInfo}`; } return { content: [ { type: "text", text: successMessage, }, ], }; } );

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/The-Focus-AI/mastodon-mcp'

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