get_subreddit_posts
Fetch posts from any Reddit subreddit with sorting options like hot, new, or top. Specify the subreddit name to retrieve formatted results including title, author, score, comments, date, and link.
Instructions
📖 Get posts from a subreddit 🎯 What it does: Fetches posts from any Reddit subreddit with sorting options 📝 Required: subreddit name (e.g., 'programming', 'AskReddit', 'MachineLearning') ⚙️ Optional: sort ('hot', 'new', 'top') 💡 Examples: • Get hot posts: {"subreddit": "programming"} • Get new posts: {"subreddit": "AskReddit", "sort": "new"} • Get top posts: {"subreddit": "MachineLearning", "sort": "top"} 🔍 Output: Formatted list with title, author, score, comments, date, and Reddit link
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| sort | No | Sort order (default: hot) | hot |
| subreddit | Yes | Subreddit name (e.g., 'programming', 'AskReddit') |
Implementation Reference
- src/services/reddit-api.ts:335-350 (handler)Core handler function that executes the Reddit API request for subreddit posts using makeRequest method.async getSubredditPosts( subreddit: string, sort: "hot" | "new" | "top" | "rising" | "controversial" = "hot", limit: number = 25, time?: "hour" | "day" | "week" | "month" | "year" | "all", ): Promise<ApiCallResult> { const params: Record<string, any> = { limit }; if (time && (sort === "top" || sort === "controversial")) { params.t = time; } return this.makeRequest<{ data: { children: Array<{ data: RedditPost }> } }>( `/r/${subreddit}/${sort}.json`, params, ); }
- src/index.ts:426-467 (registration)MCP tool registration for 'get_subreddit_posts' including description, schema reference, and handler wrapper.server.tool( "get_subreddit_posts", "📖 Get posts from a subreddit\n" + "🎯 What it does: Fetches posts from any Reddit subreddit with sorting options\n" + "📝 Required: subreddit name (e.g., 'programming', 'AskReddit', 'MachineLearning')\n" + "⚙️ Optional: sort ('hot', 'new', 'top')\n" + "💡 Examples:\n" + " • Get hot posts: {\"subreddit\": \"programming\"}\n" + " • Get new posts: {\"subreddit\": \"AskReddit\", \"sort\": \"new\"}\n" + " • Get top posts: {\"subreddit\": \"MachineLearning\", \"sort\": \"top\"}\n" + "🔍 Output: Formatted list with title, author, score, comments, date, and Reddit link", SimpleSubredditPostsSchema.shape, createToolHandler(async (params: z.infer<typeof SimpleSubredditPostsSchema>) => { const { subreddit, sort } = params; // 🧠 Smart defaults for missing parameters const smartDefaults = getSmartDefaults(params, 'subreddit_posts'); const finalParams = { ...smartDefaults, subreddit, sort: sort || smartDefaults.sort }; const result = await redditAPI.getSubredditPosts( finalParams.subreddit, finalParams.sort, finalParams.limit, finalParams.time as any ); // ✅ DRY: Sử dụng validateApiResponse helper const posts = validateApiResponse(result, "posts"); if (posts.length === 0) { return createSuccessResponse(`No posts found in r/${subreddit}`); } const summary = `📊 Found ${posts.length} posts from r/${subreddit} (sorted by ${sort})`; // ✅ DRY: Sử dụng formatDataList helper const postDetails = formatDataList(posts, formatRedditPost, POST_PREVIEW_LIMIT, "posts"); const resultText = `${summary}\n\n${postDetails}`; return createSuccessResponse(resultText); }) );
- src/types/index.ts:96-98 (schema)Zod input schema defining parameters: subreddit (required string) and sort (optional enum: hot/new/top).export const SimpleSubredditPostsSchema = z.object({ subreddit: z.string().describe("Subreddit name (e.g., 'programming', 'AskReddit')"), sort: z.enum(["hot", "new", "top"]).default("hot").describe("Sort order (default: hot)")
- src/index.ts:78-112 (helper)Helper function to format individual Reddit post data into readable markdown text with emojis and details, used in tool output.function formatRedditPost(post: RedditPost): string { const title = post.title || 'No title'; const author = post.author || 'Unknown'; const subreddit = post.subreddit || 'Unknown'; const score = post.score || 0; const comments = post.num_comments || 0; const upvoteRatio = post.upvote_ratio ? `${(post.upvote_ratio * 100).toFixed(1)}%` : 'N/A'; // Format creation date const createdDate = post.created_utc ? new Date(post.created_utc * 1000).toLocaleDateString() : 'Unknown'; // Format score with emoji const scoreEmoji = score > HIGH_SCORE_THRESHOLD ? '🔥' : score > MEDIUM_SCORE_THRESHOLD ? '👍' : score > 0 ? '⬆️' : '➡️'; let result = `📝 **${title}**\n`; result += `👤 by u/${author} in r/${subreddit}\n`; result += `${scoreEmoji} Score: ${score.toLocaleString()} | 💬 Comments: ${comments.toLocaleString()} | ⬆️ Upvote Ratio: ${upvoteRatio}\n`; result += `📅 Created: ${createdDate}\n`; // Add post content preview if available if (post.selftext && post.selftext.length > 0) { const preview = post.selftext.length > 200 ? post.selftext.substring(0, 200) + '...' : post.selftext; result += `📄 Content: ${preview}\n`; } // Add URL if it's a link post if (!post.is_self && post.url) { result += `🔗 Link: ${post.url}\n`; } // Add permalink result += `🔗 Reddit: https://reddit.com${post.permalink}\n`; return result; }
- src/services/reddit-api.ts:251-330 (helper)Core helper method for making authenticated GET requests to Reddit API, handles OAuth, rate limiting, and returns standardized ApiCallResult.private async makeRequest<T>( endpoint: string, params: Record<string, any> = {}, ): Promise<ApiCallResult> { try { const accessToken = await this.getAccessToken(); // Build URL with parameters const url = new URL(`https://oauth.reddit.com${endpoint}`); Object.entries(params).forEach(([key, value]) => { if (value !== undefined && value !== null) { url.searchParams.append(key, value.toString()); } }); // Make the request const response = await fetch(url.toString(), { method: "GET", headers: { "Authorization": `Bearer ${accessToken}`, "User-Agent": this.userAgent, }, signal: AbortSignal.timeout(this.timeout), }); // Handle rate limiting const remaining = response.headers.get('x-ratelimit-remaining'); const reset = response.headers.get('x-ratelimit-reset'); if (remaining) { this.rateLimitRemaining = parseInt(remaining); } if (reset) { this.rateLimitReset = parseInt(reset); } // Check if we're approaching rate limit if (this.rateLimitRemaining < 5) { // Rate limit warning: ${this.rateLimitRemaining} requests remaining } if (!response.ok) { const errorText = await response.text(); // Handle rate limit exceeded if (response.status === 429) { const waitTime = this.rateLimitReset > 0 ? this.rateLimitReset : 60; return { success: false, error: `Rate limit exceeded. Please wait ${waitTime} seconds before trying again.`, endpoint, timestamp: Date.now(), }; } return { success: false, error: `Reddit API Error ${response.status}: ${errorText}`, endpoint, timestamp: Date.now(), }; } const data = await response.json(); return { success: true, data, endpoint, timestamp: Date.now(), }; } catch (error) { return { success: false, error: error instanceof Error ? error.message : "Unknown error", endpoint, timestamp: Date.now(), }; } }