Create Reddit Post
create_postPost text or link content to any subreddit by specifying title, body, and optional flair. Returns the permalink.
Instructions
Create a new text or link post in a subreddit. Returns the permalink of the created post.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| subreddit | Yes | Subreddit name without r/ prefix | |
| title | Yes | Post title | |
| type | No | Post type: text (self post) or link | text |
| body | No | Post body text (for text posts) or URL (for link posts) | |
| flair_text | No | Flair text to apply to the post |
Implementation Reference
- src/tools/post.ts:17-102 (registration)The tool 'create_post' is registered via server.registerTool() in the register() function of src/tools/post.ts. This is both the registration point and the handler implementation (the handler is the inline async function passed as the third argument).
export function register(server: McpServer, client: RedditClient): void { server.registerTool( "create_post", { title: "Create Reddit Post", description: "Create a new text or link post in a subreddit. Returns the permalink of the created post.", inputSchema: z.object({ subreddit: z.string().describe("Subreddit name without r/ prefix"), title: z.string().describe("Post title"), type: z .enum(["text", "link"]) .default("text") .describe("Post type: text (self post) or link"), body: z .string() .optional() .describe("Post body text (for text posts) or URL (for link posts)"), flair_text: z .string() .optional() .describe("Flair text to apply to the post"), }), }, async ({ subreddit, title, type, body, flair_text }) => { try { const params: Record<string, string> = { sr: subreddit, title, kind: type === "link" ? "link" : "self", }; if (body) { params[type === "link" ? "url" : "text"] = body; } if (flair_text) { params.flair_text = flair_text; } const data = await client.post("/api/submit", params); const result = data?.json?.data; const errors = data?.json?.errors; if (errors && errors.length > 0) { return { content: [ { type: "text" as const, text: JSON.stringify({ success: false, error: errors.map((e: string[]) => e.join(": ")).join("; "), }, null, 2), }, ], isError: true, }; } return { content: [ { type: "text" as const, text: JSON.stringify( { success: true, permalink: result?.url || null, id: result?.name || result?.id || null, }, null, 2 ), }, ], }; } catch (error) { return { content: [ { type: "text" as const, text: `Error creating post: ${error instanceof Error ? error.message : String(error)}`, }, ], isError: true, }; } } ); - src/tools/post.ts:19-40 (schema)Input schema for 'create_post' using Zod: requires subreddit (string), title (string), optional type (enum 'text'|'link' defaulting to 'text'), optional body (string), and optional flair_text (string).
"create_post", { title: "Create Reddit Post", description: "Create a new text or link post in a subreddit. Returns the permalink of the created post.", inputSchema: z.object({ subreddit: z.string().describe("Subreddit name without r/ prefix"), title: z.string().describe("Post title"), type: z .enum(["text", "link"]) .default("text") .describe("Post type: text (self post) or link"), body: z .string() .optional() .describe("Post body text (for text posts) or URL (for link posts)"), flair_text: z .string() .optional() .describe("Flair text to apply to the post"), }), }, - src/tools/post.ts:41-101 (handler)The handler function for 'create_post'. It builds params for the Reddit API (kind='self' or 'link'), calls client.post('/api/submit', params), handles errors from the API response, and returns success with permalink and id or error details.
async ({ subreddit, title, type, body, flair_text }) => { try { const params: Record<string, string> = { sr: subreddit, title, kind: type === "link" ? "link" : "self", }; if (body) { params[type === "link" ? "url" : "text"] = body; } if (flair_text) { params.flair_text = flair_text; } const data = await client.post("/api/submit", params); const result = data?.json?.data; const errors = data?.json?.errors; if (errors && errors.length > 0) { return { content: [ { type: "text" as const, text: JSON.stringify({ success: false, error: errors.map((e: string[]) => e.join(": ")).join("; "), }, null, 2), }, ], isError: true, }; } return { content: [ { type: "text" as const, text: JSON.stringify( { success: true, permalink: result?.url || null, id: result?.name || result?.id || null, }, null, 2 ), }, ], }; } catch (error) { return { content: [ { type: "text" as const, text: `Error creating post: ${error instanceof Error ? error.message : String(error)}`, }, ], isError: true, }; } } - src/index.ts:29-29 (registration)The registration function registerPostTools (imported from ./tools/post.js) is called here with server and client, which in turn registers all post-related tools including 'create_post'.
registerPostTools(server, client); - src/reddit/client.ts:159-185 (helper)Helper: RedditClient.post() method used by the 'create_post' handler to call the Reddit API. It ensures authentication, sends POST requests with URL-encoded params and api_type='json', and returns the JSON response.
async post( endpoint: string, body: Record<string, string> ): Promise<any> { await this.ensureToken(); if (!this.session?.username) { throw new Error( "Write operations require authentication. Run the 'authorize' tool first to connect your Reddit account (one-time browser authorization)." ); } const url = endpoint.startsWith("http") ? endpoint : `${OAUTH_BASE}${endpoint}`; const res = await fetch(url, { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded", Authorization: `Bearer ${this.session!.accessToken}`, "User-Agent": this.userAgent, }, body: new URLSearchParams({ ...body, api_type: "json", }), }); return res.json(); }