Reply to Post or Comment
replyReply to any Reddit post or comment by providing its URL and your response text.
Instructions
Reply to a Reddit post or comment. Provide a full URL.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| url | Yes | Full Reddit URL of the post or comment to reply to | |
| body | Yes | Reply text content |
Implementation Reference
- src/tools/post.ts:17-312 (registration)The 'register' function in src/tools/post.ts registers the 'reply' tool alongside create_post, edit_content, and delete_content on the MCP server. This is where the tool name 'reply' is bound.
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, }; } } ); server.registerTool( "reply", { title: "Reply to Post or Comment", description: "Reply to a Reddit post or comment. Provide a full URL.", inputSchema: z.object({ url: z .string() .describe("Full Reddit URL of the post or comment to reply to"), body: z.string().describe("Reply text content"), }), }, async ({ url, body }) => { try { const thingId = extractThingId(url); if (!thingId) { return { content: [ { type: "text" as const, text: "Could not extract post/comment ID from URL.", }, ], isError: true, }; } const data = await client.post("/api/comment", { thing_id: thingId, text: body, }); 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, }; } const commentData = data?.json?.data?.things?.[0]?.data; return { content: [ { type: "text" as const, text: JSON.stringify( { success: true, id: commentData?.name || null, replied_to: thingId, }, null, 2 ), }, ], }; } catch (error) { return { content: [ { type: "text" as const, text: `Error replying: ${error instanceof Error ? error.message : String(error)}`, }, ], isError: true, }; } } ); server.registerTool( "edit_content", { title: "Edit Post or Comment", description: "Edit your own Reddit post or comment. Provide the URL of the content to edit.", inputSchema: z.object({ url: z .string() .describe("Full Reddit URL of your post or comment to edit"), new_body: z.string().describe("New text content"), }), }, async ({ url, new_body }) => { try { const thingId = extractThingId(url); if (!thingId) { return { content: [ { type: "text" as const, text: "Could not extract post/comment ID from URL.", }, ], isError: true, }; } const data = await client.post("/api/editusertext", { thing_id: thingId, text: new_body, }); 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, id: thingId, edited: true }, null, 2 ), }, ], }; } catch (error) { return { content: [ { type: "text" as const, text: `Error editing: ${error instanceof Error ? error.message : String(error)}`, }, ], isError: true, }; } } ); server.registerTool( "delete_content", { title: "Delete Post or Comment", description: "Delete your own Reddit post or comment.", inputSchema: z.object({ url: z .string() .describe("Full Reddit URL of your post or comment to delete"), }), }, async ({ url }) => { try { const thingId = extractThingId(url); if (!thingId) { return { content: [ { type: "text" as const, text: "Could not extract post/comment ID from URL.", }, ], isError: true, }; } await client.post("/api/del", { id: thingId }); return { content: [ { type: "text" as const, text: JSON.stringify( { success: true, id: thingId, deleted: true }, null, 2 ), }, ], }; } catch (error) { return { content: [ { type: "text" as const, text: `Error deleting: ${error instanceof Error ? error.message : String(error)}`, }, ], isError: true, }; } } ); } - src/tools/post.ts:104-182 (handler)The handler function for the 'reply' tool. It takes 'url' and 'body' parameters, extracts the Reddit thing ID (t3_ for post, t1_ for comment) from the URL using extractThingId, posts to /api/comment with the thing_id and text, then returns success/failure JSON.
server.registerTool( "reply", { title: "Reply to Post or Comment", description: "Reply to a Reddit post or comment. Provide a full URL.", inputSchema: z.object({ url: z .string() .describe("Full Reddit URL of the post or comment to reply to"), body: z.string().describe("Reply text content"), }), }, async ({ url, body }) => { try { const thingId = extractThingId(url); if (!thingId) { return { content: [ { type: "text" as const, text: "Could not extract post/comment ID from URL.", }, ], isError: true, }; } const data = await client.post("/api/comment", { thing_id: thingId, text: body, }); 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, }; } const commentData = data?.json?.data?.things?.[0]?.data; return { content: [ { type: "text" as const, text: JSON.stringify( { success: true, id: commentData?.name || null, replied_to: thingId, }, null, 2 ), }, ], }; } catch (error) { return { content: [ { type: "text" as const, text: `Error replying: ${error instanceof Error ? error.message : String(error)}`, }, ], isError: true, }; } } ); - src/tools/post.ts:110-115 (schema)Input schema for the 'reply' tool: requires a 'url' (string) and 'body' (string) using Zod validation.
inputSchema: z.object({ url: z .string() .describe("Full Reddit URL of the post or comment to reply to"), body: z.string().describe("Reply text content"), }), - src/tools/post.ts:5-15 (helper)Helper function extractThingId parses a Reddit URL to extract the thing ID. For post URLs (e.g., /r/sub/comments/abc123/...) it returns t3_<id>. For comment URLs (e.g., /r/sub/comments/postid/title/commentid/) it returns t1_<id>. Returns null if unparseable.
function extractThingId(url: string): string | null { // Extract thing ID from URL like /r/sub/comments/abc123/title/ const match = url.match(/\/comments\/([a-z0-9]+)/i); if (match) return `t3_${match[1]}`; // Or from a comment URL /r/sub/comments/postid/title/commentid/ const commentMatch = url.match( /\/comments\/[a-z0-9]+\/[^/]*\/([a-z0-9]+)/i ); if (commentMatch) return `t1_${commentMatch[1]}`; return null; } - src/reddit/client.ts:159-185 (helper)The RedditClient.post() method handles all write API calls including the reply tool's /api/comment endpoint. It ensures auth, sets Content-Type, appends 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(); }