Skip to main content
Glama
karanb192

Reddit Buddy MCP

by karanb192

user_analysis

Analyze Reddit user activity patterns, posting history, karma statistics, and top subreddits to understand behavior and engagement trends.

Instructions

Analyze a Reddit user's posting history, karma, and activity patterns. Returns posts, comments, and statistics.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
comments_limitNoNumber of recent comments to include (0-100, default: 10)
posts_limitNoNumber of recent posts to include (0-100, default: 10)
time_rangeNoPeriod to analyze: "day", "week", "month", "year", "all". Note: "all" returns newest content, others return top-scored content from that period
top_subreddits_limitNoNumber of most-active subreddits to list (1-50, default: 10)
usernameYesReddit username without u/ prefix (e.g., "spez", not "u/spez")

Implementation Reference

  • The core handler function implementing the user_analysis tool logic. Fetches user profile, posts, and comments from Reddit API, handles time-based filtering with fallbacks, and processes the data into a summary using ContentProcessor.processUserSummary.
    async userAnalysis(params: z.infer<typeof userAnalysisSchema>) {
      // Try to get posts within the specified time range first
      // If time_range is 'all', use 'new' sort; otherwise use 'top' to respect time filtering
      const sort = params.time_range === 'all' ? 'new' : 'top';
      
      let posts = null;
      let comments = null;
      let usedFallback = false;
      
      const user = await this.api.getUser(params.username);
      
      // Fetch posts
      if (params.posts_limit > 0) {
        posts = await this.api.getUserPosts(params.username, 'submitted', {
          limit: params.posts_limit,
          sort,
          time: params.time_range,
        });
        
        // If no results with time filter, fallback to getting recent posts
        if (posts.data.children.length === 0 && params.time_range !== 'all') {
          usedFallback = true;
          posts = await this.api.getUserPosts(params.username, 'submitted', {
            limit: params.posts_limit,
            sort: 'new',
            time: 'all',
          });
        }
      }
      
      // Fetch comments
      if (params.comments_limit > 0) {
        comments = await this.api.getUserPosts(params.username, 'comments', {
          limit: params.comments_limit,
          sort,
          time: params.time_range,
        });
        
        // If no results with time filter, fallback to getting recent comments
        if (comments.data.children.length === 0 && params.time_range !== 'all') {
          usedFallback = true;
          comments = await this.api.getUserPosts(params.username, 'comments', {
            limit: params.comments_limit,
            sort: 'new',
            time: 'all',
          });
        }
      }
    
      // Process summary
      let summary: any;
      if (posts) {
        summary = ContentProcessor.processUserSummary(user, posts, {
          maxTopSubreddits: params.top_subreddits_limit,
          comments: comments || undefined
        });
      } else {
        // Fallback when no posts - but still include comments if available
        summary = {
          username: user.name,
          accountAge: 'Unknown',
          karma: {
            link: user.link_karma,
            comment: user.comment_karma,
            total: user.link_karma + user.comment_karma,
          },
        };
    
        // Add comments even when there are no posts
        if (comments && comments.data.children.length > 0) {
          summary.recentComments = comments.data.children.map(child => {
            const comment = child.data as any;
            return {
              id: comment.id,
              body: comment.body?.substring(0, 200) + (comment.body?.length > 200 ? '...' : ''),
              score: comment.score,
              subreddit: comment.subreddit || 'unknown',
              postTitle: comment.link_title,
              created: new Date(comment.created_utc * 1000),
              url: `https://reddit.com${comment.permalink}`,
            };
          });
        }
      }
    
      // Add note if we used fallback data
      if (usedFallback && params.time_range !== 'all') {
        const timeRangeLabel = {
          'hour': 'hour',
          'day': 'day',
          'week': 'week', 
          'month': 'month',
          'year': 'year'
        }[params.time_range];
        
        summary.timeRangeNote = `No posts found in the last ${timeRangeLabel}, showing all recent posts instead`;
      }
    
      return summary;
    }
  • Zod schema defining the input parameters for the user_analysis tool, including username and optional limits for posts, comments, time range, and top subreddits.
    export const userAnalysisSchema = z.object({
      username: z.string().describe('Reddit username'),
      posts_limit: z.number().min(0).max(100).optional().default(10).describe('Default 10, range (0-100). Change ONLY IF user specifies.'),
      comments_limit: z.number().min(0).max(100).optional().default(10).describe('Default 10, range (0-100). Override ONLY IF user asks.'),
      time_range: z.enum(['day', 'week', 'month', 'year', 'all']).optional().default('month').describe('Time range for posts/comments (default: month). Note: When set to values other than "all", posts are sorted by top scores within that period. When set to "all", posts are sorted by newest'),
      top_subreddits_limit: z.number().min(1).max(50).optional().default(10).describe('Default 10, range (1-50). Change ONLY IF user requests.'),
    });
  • Registration of the user_analysis tool in the MCP server's toolDefinitions array, specifying name, description, input schema, and read-only hint.
      name: 'user_analysis',
      description: 'Analyze a Reddit user\'s posting history, karma, and activity patterns. Returns posts, comments, and statistics.',
      inputSchema: zodToJsonSchema(userAnalysisSchema) as any,
      readOnlyHint: true
    },
  • Dispatch logic in the MCP tool call handler that invokes the userAnalysis method with parsed arguments when 'user_analysis' is called.
    case 'user_analysis':
      result = await tools.userAnalysis(
        userAnalysisSchema.parse(args)
      );
      break;
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden of behavioral disclosure. It mentions the tool returns posts, comments, and statistics, but lacks details on permissions, rate limits, data freshness, or error handling. For a tool with 5 parameters and no annotations, this is a significant gap in transparency.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, efficient sentence that front-loads the core functionality and return values. Every word earns its place, with no redundant or vague phrasing. It's appropriately sized for the tool's complexity.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given 5 parameters with full schema coverage but no annotations or output schema, the description is minimally adequate. It covers the purpose and return types but lacks behavioral context and usage guidance. For a user analysis tool with no output schema, more detail on return structure would be beneficial.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents all parameters thoroughly. The description adds no additional parameter semantics beyond what's in the schema, such as explaining interactions between parameters or edge cases. Baseline 3 is appropriate when the schema does the heavy lifting.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool analyzes a Reddit user's posting history, karma, and activity patterns, which is a specific verb (analyze) and resource (Reddit user). It distinguishes from sibling tools like browse_subreddit or search_reddit by focusing on user analysis rather than content browsing or searching. However, it doesn't explicitly differentiate from reddit_explain, which might have overlapping functionality.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides no guidance on when to use this tool versus alternatives like search_reddit or reddit_explain. It mentions what the tool does but offers no context about appropriate use cases, prerequisites, or exclusions. Users must infer usage from the description alone.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Latest Blog Posts

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/karanb192/reddit-mcp-buddy'

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