Skip to main content
Glama

Reddit MCP Server

index.ts16.3 kB
#!/usr/bin/env node import { Server } from "@modelcontextprotocol/sdk/server/index.js"; import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; import { CallToolRequestSchema, ErrorCode, ListToolsRequestSchema, McpError, } from "@modelcontextprotocol/sdk/types.js"; import { initializeRedditClient } from "./client/reddit-client"; import * as tools from "./tools"; import dotenv from "dotenv"; // Load environment variables dotenv.config(); class RedditServer { private server: Server; constructor() { console.log("[Setup] Initializing Reddit Server..."); // Initialize the Reddit client this.initializeRedditClient(); this.server = new Server( { name: "reddit-mcp-server", version: "0.1.0", }, { capabilities: { tools: {}, }, } ); this.setupToolHandlers(); this.server.onerror = (error) => console.error("[Error] Server error:", error); process.on("SIGINT", async () => { await this.server.close(); process.exit(0); }); } private initializeRedditClient() { const clientId = process.env.REDDIT_CLIENT_ID; const clientSecret = process.env.REDDIT_CLIENT_SECRET; const userAgent = process.env.REDDIT_USER_AGENT || "RedditMCPServer/0.1.0"; const username = process.env.REDDIT_USERNAME; const password = process.env.REDDIT_PASSWORD; if (!clientId || !clientSecret) { console.error( "[Error] Missing required Reddit API credentials. Please set REDDIT_CLIENT_ID and REDDIT_CLIENT_SECRET environment variables." ); process.exit(1); } try { initializeRedditClient({ clientId, clientSecret, userAgent, username, password, }); console.log("[Setup] Reddit client initialized"); if (username && password) { console.log(`[Setup] Authenticated as user: ${username}`); } else { console.log( "[Setup] Running in read-only mode (no user authentication)" ); } } catch (error) { console.error("[Error] Failed to initialize Reddit client:", error); process.exit(1); } } private setupToolHandlers() { this.server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: [ { name: "test_reddit_mcp_server", description: "Test the Reddit MCP Server", inputSchema: { type: "object", properties: { // No input parameters, this will just return a test message }, }, }, { name: "get_reddit_post", description: "Get a Reddit post", inputSchema: { type: "object", properties: { subreddit: { type: "string", description: "The subreddit to fetch posts from", }, post_id: { type: "string", description: "The ID of the post to fetch", }, }, required: ["subreddit", "post_id"], }, }, { name: "get_top_posts", description: "Get top posts from a subreddit", inputSchema: { type: "object", properties: { subreddit: { type: "string", description: "Name of the subreddit", }, time_filter: { type: "string", description: "Time period to filter posts (e.g. 'day', 'week', 'month', 'year', 'all')", enum: ["day", "week", "month", "year", "all"], default: "week", }, limit: { type: "integer", description: "Number of posts to fetch", default: 10, }, }, required: ["subreddit"], }, }, { name: "get_user_info", description: "Get information about a Reddit user", inputSchema: { type: "object", properties: { username: { type: "string", description: "The username of the Reddit user to get info for", }, }, required: ["username"], }, }, { name: "get_subreddit_info", description: "Get information about a subreddit", inputSchema: { type: "object", properties: { subreddit_name: { type: "string", description: "Name of the subreddit", }, }, required: ["subreddit_name"], }, }, { name: "get_trending_subreddits", description: "Get currently trending subreddits", inputSchema: { type: "object", properties: {}, }, }, { name: "create_post", description: "Create a new post in a subreddit", inputSchema: { type: "object", properties: { subreddit: { type: "string", description: "Name of the subreddit to post in", }, title: { type: "string", description: "Title of the post", }, content: { type: "string", description: "Content of the post (text for self posts, URL for link posts)", }, is_self: { type: "boolean", description: "Whether this is a self (text) post (true) or link post (false)", default: true, }, }, required: ["subreddit", "title", "content"], }, }, { name: "reply_to_post", description: "Post a reply to an existing Reddit post", inputSchema: { type: "object", properties: { post_id: { type: "string", description: "The ID of the post to reply to", }, content: { type: "string", description: "The content of the reply", }, subreddit: { type: "string", description: "The subreddit name if known (for validation)", }, }, required: ["post_id", "content"], }, }, { name: "get_comment", description: "Accéder à un commentaire spécifique", inputSchema: { type: "object", properties: { comment_id: { type: "string", description: "L'ID du commentaire à récupérer", }, }, required: ["comment_id"], }, }, { name: "get_comments_by_submission", description: "Accéder aux commentaires d'une soumission", inputSchema: { type: "object", properties: { submission_id: { type: "string", description: "L'ID de la soumission", }, limit: { type: "integer", description: "Nombre de commentaires à récupérer", default: 20, }, }, required: ["submission_id"], }, }, { name: "get_submission", description: "Accéder à une soumission", inputSchema: { type: "object", properties: { submission_id: { type: "string", description: "L'ID de la soumission à récupérer", }, }, required: ["submission_id"], }, }, { name: "get_subreddit", description: "Accéder à un subreddit par nom", inputSchema: { type: "object", properties: { subreddit_name: { type: "string", description: "Le nom du subreddit", }, }, required: ["subreddit_name"], }, }, { name: "search_posts", description: "Rechercher des posts dans un subreddit", inputSchema: { type: "object", properties: { subreddit: { type: "string", description: "Le nom du subreddit dans lequel rechercher", }, query: { type: "string", description: "La requête de recherche", }, sort: { type: "string", description: "Méthode de tri (relevance, new, hot, top)", enum: ["relevance", "new", "hot", "top"], default: "relevance", }, limit: { type: "integer", description: "Nombre de résultats à retourner", default: 25, }, }, required: ["subreddit", "query"], }, }, { name: "search_subreddits", description: "Rechercher des subreddits par nom ou description", inputSchema: { type: "object", properties: { query: { type: "string", description: "La requête de recherche", }, limit: { type: "integer", description: "Nombre de résultats à retourner", default: 25, }, }, required: ["query"], }, }, { name: "get_user_posts", description: "Obtenir l'historique des posts d'un utilisateur", inputSchema: { type: "object", properties: { username: { type: "string", description: "Le nom d'utilisateur Reddit", }, sort: { type: "string", description: "Méthode de tri (new, top, hot)", enum: ["new", "top", "hot"], default: "new", }, limit: { type: "integer", description: "Nombre de posts à récupérer", default: 25, }, }, required: ["username"], }, }, { name: "get_user_comments", description: "Obtenir l'historique des commentaires d'un utilisateur", inputSchema: { type: "object", properties: { username: { type: "string", description: "Le nom d'utilisateur Reddit", }, sort: { type: "string", description: "Méthode de tri (new, top, hot)", enum: ["new", "top", "hot"], default: "new", }, limit: { type: "integer", description: "Nombre de commentaires à récupérer", default: 25, }, }, required: ["username"], }, }, { name: "get_user_activity", description: "Obtenir une analyse détaillée de l'activité d'un utilisateur", inputSchema: { type: "object", properties: { username: { type: "string", description: "Le nom d'utilisateur Reddit", }, limit: { type: "integer", description: "Nombre d'éléments d'activité à analyser", default: 50, }, }, required: ["username"], }, }, ], })); this.server.setRequestHandler(CallToolRequestSchema, async (request) => { try { const toolName = request.params.name; const toolParams = request.params.arguments || {}; console.log(`[Request] Tool call: ${toolName}`, toolParams); switch (toolName) { case "test_reddit_mcp_server": return { content: [ { type: "text", text: "Hello, world! The Reddit MCP Server is working correctly.", }, ], }; case "get_reddit_post": return await tools.getRedditPost( toolParams as { subreddit: string; post_id: string } ); case "get_top_posts": return await tools.getTopPosts( toolParams as { subreddit: string; time_filter?: string; limit?: number; } ); case "get_user_info": return await tools.getUserInfo(toolParams as { username: string }); case "get_subreddit_info": return await tools.getSubredditInfo( toolParams as { subreddit_name: string } ); case "get_trending_subreddits": return await tools.getTrendingSubreddits(); case "create_post": return await tools.createPost( toolParams as { subreddit: string; title: string; content: string; is_self?: boolean; } ); case "reply_to_post": return await tools.replyToPost( toolParams as { post_id: string; content: string; subreddit?: string; } ); case "get_comment": return await tools.getComment( toolParams as { comment_id: string } ); case "get_comments_by_submission": return await tools.getCommentsBySubmission( toolParams as { submission_id: string; limit?: number } ); case "get_submission": return await tools.getSubmission( toolParams as { submission_id: string } ); case "get_subreddit": return await tools.getSubreddit( toolParams as { subreddit_name: string } ); case "search_posts": return await tools.searchPosts( toolParams as { subreddit: string; query: string; sort?: string; limit?: number } ); case "search_subreddits": return await tools.searchSubreddits( toolParams as { query: string; limit?: number } ); case "get_user_posts": return await tools.getUserPosts( toolParams as { username: string; sort?: string; limit?: number } ); case "get_user_comments": return await tools.getUserComments( toolParams as { username: string; sort?: string; limit?: number } ); case "get_user_activity": return await tools.getUserActivity( toolParams as { username: string; limit?: number } ); default: throw new McpError( ErrorCode.MethodNotFound, `Tool with name ${toolName} not found` ); } } catch (error: unknown) { if (error instanceof Error) { console.error("[Error] Error calling tool:", error.message); throw new McpError( ErrorCode.InternalError, `Failed to fetch data: ${error.message}` ); } throw error; } }); } async run() { const transport = new StdioServerTransport(); await this.server.connect(transport); console.log("[Server] Server is running"); } } const server = new RedditServer(); server.run().catch(console.error);

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/samy-clivolt/reddit-mcp-server'

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