Save Post or Comment
save_itemSave any Reddit post or comment to your saved items by providing its full URL.
Instructions
Save a Reddit post or comment to your saved items list.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| url | Yes | Full Reddit URL of the post or comment to save |
Implementation Reference
- src/tools/save.ts:16-53 (registration)The tool 'save_item' is registered via server.registerTool() with name 'save_item', including schema and handler in one call.
export function register(server: McpServer, client: RedditClient): void { server.registerTool( "save_item", { title: "Save Post or Comment", description: "Save a Reddit post or comment to your saved items list.", inputSchema: z.object({ url: z.string().describe("Full Reddit URL of the post or comment to save"), }), }, async ({ url }) => { try { const thingId = extractThingId(url); if (!thingId) { return { content: [{ type: "text" as const, text: "Could not extract ID from URL." }], isError: true, }; } await client.post("/api/save", { id: thingId }); return { content: [ { type: "text" as const, text: JSON.stringify({ success: true, id: thingId, saved: true }, null, 2), }, ], }; } catch (error) { return { content: [ { type: "text" as const, text: `Error saving: ${error instanceof Error ? error.message : String(error)}` }, ], isError: true, }; } } ); - src/tools/save.ts:26-52 (handler)The handler function for 'save_item' that extracts a Reddit thing ID from a URL and calls client.post('/api/save', {id}) to save the item.
async ({ url }) => { try { const thingId = extractThingId(url); if (!thingId) { return { content: [{ type: "text" as const, text: "Could not extract ID from URL." }], isError: true, }; } await client.post("/api/save", { id: thingId }); return { content: [ { type: "text" as const, text: JSON.stringify({ success: true, id: thingId, saved: true }, null, 2), }, ], }; } catch (error) { return { content: [ { type: "text" as const, text: `Error saving: ${error instanceof Error ? error.message : String(error)}` }, ], isError: true, }; } } - src/tools/save.ts:22-24 (schema)Input schema for 'save_item' defines a single required string parameter 'url' (the full Reddit URL of the post or comment to save).
inputSchema: z.object({ url: z.string().describe("Full Reddit URL of the post or comment to save"), }), - src/tools/save.ts:6-14 (helper)Helper function extractThingId() that parses a Reddit URL to extract the thing ID (t1_ for comments, t3_ for posts) used in the save API call.
function extractThingId(url: string): string | null { const commentMatch = url.match( /\/comments\/[a-z0-9]+\/[^/]*\/([a-z0-9]+)/i ); if (commentMatch) return `t1_${commentMatch[1]}`; const postMatch = url.match(/\/comments\/([a-z0-9]+)/i); if (postMatch) return `t3_${postMatch[1]}`; return null; } - src/reddit/client.ts:159-185 (helper)The RedditClient.post() method called by the save_item handler. It sends a POST request to /api/save on the Reddit OAuth API with Bearer token authentication.
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(); }