reddit-mcp

reddit-mcp

4.2

reddit-mcp is hosted online, so all tools can be tested directly either in theInspector tabor in theOnline Client.

If you are the rightful owner of reddit-mcp and would like to certify it and/or have it hosted online, please leave a comment on the right or send an email to henry@mcphub.com.

This repository contains a Model Context Protocol server implementation for Reddit that allows AI assistants to access and interact with Reddit content through PRAW (Python Reddit API Wrapper).

The Reddit MCP Server is a Model Context Protocol server implementation designed to facilitate AI assistants in accessing and interacting with Reddit content. By leveraging the Python Reddit API Wrapper (PRAW), this server allows for comprehensive engagement with Reddit's vast array of data. The server adheres to the MCP standard, enabling seamless integration with external services, tools, and data sources. It provides a robust set of features, including user engagement analysis, subreddit statistics, and AI-driven insights. The server supports both read-only and authenticated access, allowing for a wide range of operations from fetching public data to posting and commenting. With its intelligent analysis capabilities, the server offers strategic recommendations and performance metrics, making it a powerful tool for AI-driven Reddit interactions.

Features

  • Get detailed user information with engagement analysis
  • Fetch and analyze top posts from any subreddit
  • Get comprehensive subreddit statistics and health metrics
  • View trending subreddits with growth patterns
  • Create strategic posts with timing recommendations

Tools

  1. get_user_info

    Get information about a Reddit user.

    Args:
        username: The username of the Reddit user to get info for
    
    Returns:
        Dictionary containing user information with the following structure:
        {
            'username': str,  # User's username
            'created_utc': float,  # Account creation timestamp
            'comment_karma': int,  # User's comment karma
            'link_karma': int,  # User's post/link karma
            'has_verified_email': bool,  # Whether email is verified
            'is_mod': bool,  # Whether user is a moderator
            'is_gold': bool,  # Whether user has Reddit premium
            'has_subscribed': bool,  # Whether user has subscribed to premium
            'is_employee': bool,  # Whether user is a Reddit employee
            'over_18': bool,  # Whether user is marked as NSFW
            'is_suspended': bool,  # Whether account is suspended
            'suspension_expiration_utc': Optional[float],  # When suspension ends if suspended
            'total_karma': int,  # Total karma (comments + posts)
            'subreddit': Optional[Dict],  # User's profile subreddit info if exists
        }
    
    Raises:
        ValueError: If the username is invalid or not found
        RuntimeError: For other errors during the operation
    
  2. get_top_posts

    Get top posts from a subreddit.

    Args:
        subreddit: Name of the subreddit (with or without 'r/' prefix)
        time_filter: Time period to filter posts (e.g. "day", "week", "month", "year", "all")
        limit: Number of posts to fetch (1-100)
    
    Returns:
        Dictionary containing structured post information with the following structure:
        {
            'subreddit': str,  # Subreddit name
            'time_filter': str,  # The time period used for filtering
            'posts': [  # List of posts, each with the following structure:
                {
                    'id': str,  # Post ID
                    'title': str,  # Post title
                    'author': str,  # Author's username
                    'score': int,  # Post score (upvotes - downvotes)
                    'upvote_ratio': float,  # Ratio of upvotes to total votes
                    'num_comments': int,  # Number of comments
                    'created_utc': float,  # Post creation timestamp
                    'url': str,  # URL to the post
                    'permalink': str,  # Relative URL to the post
                    'is_self': bool,  # Whether it's a self (text) post
                    'selftext': str,  # Content of self post (if any)
                    'link_url': str,  # URL for link posts (if any)
                    'over_18': bool,  # Whether marked as NSFW
                    'spoiler': bool,  # Whether marked as spoiler
                    'stickied': bool,  # Whether stickied in the subreddit
                    'locked': bool,  # Whether comments are locked
                    'distinguished': Optional[str],  # Distinguishing type (e.g., 'moderator')
                    'flair': Optional[Dict],  # Post flair information if any
                },
                ...
            ],
            'metadata': {
                'fetched_at': float,  # Timestamp when data was fetched
                'post_count': int,  # Number of posts returned
            }
        }
    
    Raises:
        ValueError: If subreddit is invalid or time_filter is not valid
        RuntimeError: For other errors during the operation
    
  3. get_subreddit_info

    Get information about a subreddit.

    Args:
        subreddit_name: Name of the subreddit (with or without 'r/' prefix)
    
    Returns:
        Dictionary containing subreddit information
    
    Raises:
        ValueError: If subreddit_name is invalid or subreddit not found
        RuntimeError: For other errors during the operation
    
  4. get_trending_subreddits

    Get currently trending subreddits.

    Args:
        limit: Maximum number of trending subreddits to return (1-50)
    
    Returns:
        Dictionary containing list of trending subreddits with their basic info
    
    Raises:
        ValueError: If limit is invalid
        RuntimeError: For errors during the operation
    
  5. get_subreddit_stats

    Get statistics and information about a subreddit.

    Args:
        subreddit: Name of the subreddit (with or without 'r/' prefix)
    
    Returns:
        Dictionary containing structured subreddit information with the following structure:
        {
            'id': str,  # Subreddit ID (e.g., '2qgzt')
            'display_name': str,  # Subreddit display name (without r/ prefix)
            'title': str,  # Subreddit title
            'public_description': str,  # Public description
            'description': str,  # Full description (can include markdown)
            'subscribers': int,  # Number of subscribers
            'active_user_count': Optional[int],  # Currently active users if available
            'created_utc': float,  # Creation timestamp (UTC)
            'over18': bool,  # Whether marked as NSFW
            'submission_type': str,  # Allowed submission types (any, link, self)
            'allow_images': bool,  # Whether image uploads are allowed
            'allow_videos': bool,  # Whether video uploads are allowed
            'allow_polls': bool,  # Whether polls are allowed
            'spoilers_enabled': bool,  # Whether spoiler tags are enabled
            'wikienabled': bool,  # Whether wiki is enabled
            'user_is_banned': bool,  # Whether current user is banned
            'user_is_moderator': bool,  # Whether current user is a moderator
            'user_is_subscriber': bool,  # Whether current user is a subscriber
            'mod_permissions': List[str],  # Moderator permissions if applicable
            'metadata': {
                'fetched_at': float,  # Timestamp when data was fetched
                'url': str,  # Full URL to the subreddit
                'moderators_count': int,  # Number of moderators
                'rules': List[Dict],  # Subreddit rules if available
                'features': Dict[str, bool],  # Enabled subreddit features
            }
        }
    
    Raises:
        ValueError: If subreddit is invalid or not found
        RuntimeError: For other errors during the operation
    
  6. create_post

    Create a new post in a subreddit.

    Args:
        subreddit: Name of the subreddit to post in (with or without 'r/' prefix)
        title: Title of the post (max 300 characters)
        content: Content of the post (text for self posts, URL for link posts)
        flair: Flair to add to the post. Must be an available flair in the subreddit
        is_self: Whether this is a self (text) post (True) or link post (False)
    
    Returns:
        Dictionary containing information about the created post
    
    Raises:
        ValueError: If input validation fails or flair is invalid
        RuntimeError: For other errors during post creation
    
  7. reply_to_post

    Post a reply to an existing Reddit post.

    Args:
        post_id: The ID of the post to reply to (can be full URL, permalink, or just ID)
        content: The content of the reply (1-10000 characters)
        subreddit: The subreddit name if known (for validation, with or without 'r/' prefix)
    
    Returns:
        Dictionary containing information about the created reply and parent post
    
    Raises:
        ValueError: If input validation fails or post is not found
        RuntimeError: For other errors during reply creation
    
  8. get_submission_by_url

    Get a Reddit submission by its URL.

    Args:
        url: The URL of the Reddit submission to retrieve
    
    Returns:
        Dictionary containing structured submission information with the following structure:
        {
            'id': str,  # Submission ID (e.g., 'abc123')
            'title': str,  # Submission title
            'author': str,  # Author's username or '[deleted]' if deleted
            'subreddit': str,  # Subreddit name
            'score': int,  # Post score (upvotes - downvotes)
            'upvote_ratio': float,  # Ratio of upvotes to total votes
            'num_comments': int,  # Number of comments
            'created_utc': float,  # Post creation timestamp (UTC)
            'url': str,  # Full URL to the post
            'permalink': str,  # Relative URL to the post
            'is_self': bool,  # Whether it's a self (text) post
            'selftext': str,  # Content of self post (if any)
            'selftext_html': Optional[str],  # HTML formatted content
            'link_url': str,  # URL for link posts (if any)
            'domain': str,  # Domain of the linked content
            'over_18': bool,  # Whether marked as NSFW
            'spoiler': bool,  # Whether marked as spoiler
            'stickied': bool,  # Whether stickied in the subreddit
            'locked': bool,  # Whether comments are locked
            'archived': bool,  # Whether the post is archived
            'distinguished': Optional[str],  # Distinguishing type (e.g., 'moderator')
            'flair': Optional[Dict],  # Post flair information if any
            'media': Optional[Dict],  # Media information if any
            'preview': Optional[Dict],  # Preview information if available
            'awards': List[Dict],  # List of awards received
            'metadata': {
                'fetched_at': float,  # Timestamp when data was fetched
                'subreddit_id': str,  # Subreddit full ID
                'author_id': str,  # Author's full ID if available
                'is_original_content': bool,  # Whether marked as OC
                'is_meta': bool,  # Whether marked as meta
                'is_crosspostable': bool,  # Whether can be crossposted
                'is_reddit_media_domain': bool,  # Whether media is hosted on Reddit
                'is_robot_indexable': bool,  # Whether search engines should index
                'is_created_from_ads_ui': bool,  # Whether created via ads UI
                'is_video': bool,  # Whether the post is a video
                'pinned': bool,  # Whether the post is pinned in the subreddit
                'gilded': int,  # Number of times gilded
                'total_awards_received': int,  # Total number of awards received
                'view_count': Optional[int],  # View count if available
                'visited': bool,  # Whether the current user has visited
            }
        }
    
    Raises:
        ValueError: If URL is invalid or submission not found
        RuntimeError: For other errors during the operation
    
  9. get_submission_by_id

    Get a Reddit submission by its ID.

    Args:
        submission_id: The ID of the Reddit submission to retrieve (can be full URL or just ID)
    
    Returns:
        Dictionary containing structured submission information with the following structure:
        {
            'id': str,  # Submission ID (e.g., 'abc123')
            'title': str,  # Submission title
            'author': str,  # Author's username or '[deleted]' if deleted
            'subreddit': str,  # Subreddit name
            'score': int,  # Post score (upvotes - downvotes)
            'upvote_ratio': float,  # Ratio of upvotes to total votes
            'num_comments': int,  # Number of comments
            'created_utc': float,  # Post creation timestamp (UTC)
            'url': str,  # Full URL to the post
            'permalink': str,  # Relative URL to the post
            'is_self': bool,  # Whether it's a self (text) post
            'selftext': str,  # Content of self post (if any)
            'selftext_html': Optional[str],  # HTML formatted content
            'link_url': str,  # URL for link posts (if any)
            'domain': str,  # Domain of the linked content
            'over_18': bool,  # Whether marked as NSFW
            'spoiler': bool,  # Whether marked as spoiler
            'stickied': bool,  # Whether stickied in the subreddit
            'locked': bool,  # Whether comments are locked
            'archived': bool,  # Whether the post is archived
            'distinguished': Optional[str],  # Distinguishing type (e.g., 'moderator')
            'flair': Optional[Dict],  # Post flair information if any
            'media': Optional[Dict],  # Media information if any
            'preview': Optional[Dict],  # Preview information if available
            'awards': List[Dict],  # List of awards received
            'metadata': {
                'fetched_at': float,  # Timestamp when data was fetched
                'subreddit_id': str,  # Subreddit full ID
                'author_id': str,  # Author's full ID if available
                'is_original_content': bool,  # Whether marked as OC
                'is_meta': bool,  # Whether marked as meta
                'is_crosspostable': bool,  # Whether can be crossposted
                'is_reddit_media_domain': bool,  # Whether media is hosted on Reddit
                'is_robot_indexable': bool,  # Whether search engines should index
                'is_created_from_ads_ui': bool,  # Whether created via ads UI
                'is_video': bool,  # Whether the post is a video
                'pinned': bool,  # Whether the post is pinned in the subreddit
                'gilded': int,  # Number of times gilded
                'total_awards_received': int,  # Total number of awards received
                'view_count': Optional[int],  # View count if available
                'visited': bool,  # Whether the current user has visited
            }
        }
    
    Raises:
        ValueError: If submission_id is invalid or submission not found
        RuntimeError: For other errors during the operation
    
  10. who_am_i

    Get information about the currently authenticated user.

    Returns:
        Dictionary containing structured user information with the following structure:
        {
            'id': str,  # Full user ID (e.g., 't2_abc123')
            'name': str,  # Username
            'created_utc': float,  # Account creation timestamp
            'comment_karma': int,  # Comment karma
            'link_karma': int,  # Post/link karma
            'total_karma': int,  # Total karma (comments + posts)
            'awardee_karma': int,  # Karma from awards received
            'awarder_karma': int,  # Karma from awards given
            'has_verified_email': bool,  # Whether email is verified
            'is_employee': bool,  # Whether user is a Reddit employee
            'is_friend': bool,  # Whether user is a friend
            'is_gold': bool,  # Whether user has Reddit Premium
            'is_mod': bool,  # Whether user is a moderator
            'is_suspended': bool,  # Whether account is suspended
            'verified': bool,  # Whether account is verified
            'has_subscribed': bool,  # Whether user has subscribed to Premium
            'snoovatar_img': str,  # URL to snoovatar image
            'icon_img': str,  # URL to user's icon
            'pref_show_snoovatar': bool,  # Whether to show snoovatar
            'snoovatar_size': Optional[List[int]],  # Snoovatar dimensions
            'subreddit': Optional[Dict],  # User's profile subreddit info
            'metadata': {
                'fetched_at': float,  # Timestamp when data was fetched
                'is_authenticated': bool,  # Whether user is authenticated
                'is_moderator': bool,  # Whether user is a moderator
                'has_verified_email': bool,  # Whether email is verified
                'has_mail': bool,  # Whether user has unread messages
                'has_mod_mail': bool,  # Whether user has mod mail
                'has_subscribed': bool,  # Whether user has subscribed to Premium
                'in_chat': bool,  # Whether user is in chat
                'in_redesign_beta': bool,  # Whether user is in redesign beta
                'new_modmail_exists': bool,  # Whether user has new modmail
                'pref_no_profanity': bool,  # Whether to filter profanity
                'suspension_expiration_utc': Optional[float],  # When suspension ends if suspended
            }
        }
    
    Raises:
        ValueError: If user authentication is not available
        RuntimeError: For other errors during the operation