Skip to main content
Glama
hmumixaM

USCardForum MCP Server

by hmumixaM

get_topic_posts

Fetch paginated posts from USCardForum topics to read discussions in batches, starting at a specified position with optional markdown source.

Instructions

Fetch a batch of posts from a topic starting at a specific position.

Args:
    topic_id: The numeric topic ID
    post_number: Which post number to start from (default: 1 = first post)
    include_raw: Include raw markdown source (default: False, returns HTML)

This fetches ~20 posts per call starting from post_number.
Use for paginated reading of topics.

Returns a list of Post objects with:
- post_number: Position in topic (1, 2, 3...)
- username: Author's username
- cooked: HTML content of the post
- raw: Markdown source (if include_raw=True)
- created_at: When posted
- updated_at: Last edit time
- like_count: Number of likes
- reply_count: Number of direct replies
- reply_to_post_number: Which post this replies to (if any)

Pagination example:
1. Call with post_number=1, get posts 1-20
2. Call with post_number=21, get posts 21-40
3. Continue until no posts returned

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
topic_idYesThe numeric topic ID
post_numberNoWhich post number to start from (default: 1 = first post)
include_rawNoInclude raw markdown source (default: False, returns HTML)

Implementation Reference

  • The primary handler function decorated with @mcp.tool(). It defines the input schema via Annotated Fields and executes the tool logic by delegating to the DiscourseClient.get_topic_posts method.
    @mcp.tool()
    def get_topic_posts(
        topic_id: Annotated[
            int,
            Field(description="The numeric topic ID"),
        ],
        post_number: Annotated[
            int,
            Field(default=1, description="Which post number to start from (default: 1 = first post)"),
        ] = 1,
        include_raw: Annotated[
            bool,
            Field(default=False, description="Include raw markdown source (default: False, returns HTML)"),
        ] = False,
    ) -> list[Post]:
        """
        Fetch a batch of posts from a topic starting at a specific position.
    
        Args:
            topic_id: The numeric topic ID
            post_number: Which post number to start from (default: 1 = first post)
            include_raw: Include raw markdown source (default: False, returns HTML)
    
        This fetches ~20 posts per call starting from post_number.
        Use for paginated reading of topics.
    
        Returns a list of Post objects with:
        - post_number: Position in topic (1, 2, 3...)
        - username: Author's username
        - cooked: HTML content of the post
        - raw: Markdown source (if include_raw=True)
        - created_at: When posted
        - updated_at: Last edit time
        - like_count: Number of likes
        - reply_count: Number of direct replies
        - reply_to_post_number: Which post this replies to (if any)
    
        Pagination example:
        1. Call with post_number=1, get posts 1-20
        2. Call with post_number=21, get posts 21-40
        3. Continue until no posts returned
        """
        return get_client().get_topic_posts(
            topic_id, post_number=post_number, include_raw=include_raw
        )
  • Imports all server tools including get_topic_posts from server_tools package. Importing the decorated function registers it with the global FastMCP instance.
    from uscardforum.server_tools import (
        analyze_user,
        bookmark_post,
        compare_cards,
        find_data_points,
        get_all_topic_posts,
        get_categories,
        get_current_session,
        get_hot_topics,
        get_new_topics,
        get_notifications,
        get_top_topics,
        get_topic_info,
        get_topic_posts,
        get_user_actions,
        get_user_badges,
        get_user_followers,
        get_user_following,
        get_user_reactions,
        get_user_replies,
        get_user_summary,
        get_user_topics,
        list_users_with_badge,
        login,
        research_topic,
        resource_categories,
        resource_hot_topics,
        resource_new_topics,
        search_forum,
        subscribe_topic,
    )
  • Re-exports the get_topic_posts tool from the topics module, enabling its import and registration via the server_tools package.
    from .topics import get_topic_info, get_topic_posts, get_all_topic_posts
  • Shared helper function get_client() that provides the DiscourseClient instance used by all tools, including automatic login if credentials are provided.
    def get_client() -> DiscourseClient:
        """Get or create the Discourse client instance."""
        global _client, _login_attempted
    
        if _client is None:
            base_url = os.environ.get("USCARDFORUM_URL", "https://www.uscardforum.com")
            timeout = float(os.environ.get("USCARDFORUM_TIMEOUT", "15.0"))
            _client = DiscourseClient(base_url=base_url, timeout_seconds=timeout)
    
            # Auto-login if credentials are provided
            if not _login_attempted:
                _login_attempted = True
                username = os.environ.get("NITAN_USERNAME")
                password = os.environ.get("NITAN_PASSWORD")
    
                if username and password:
                    try:
                        result = _client.login(username, password)
                        if result.success:
                            print(f"[uscardforum] Auto-login successful as '{result.username}'")
                        elif result.requires_2fa:
                            print(
                                "[uscardforum] Auto-login failed: 2FA required. Use login() tool with second_factor_token."
                            )
                        else:
                            print(
                                f"[uscardforum] Auto-login failed: {result.error or 'Unknown error'}"
                            )
                    except Exception as e:  # pragma: no cover - logging side effect
                        print(f"[uscardforum] Auto-login error: {e}")
    
        return _client
  • Imports the Post model used as return type for get_topic_posts, which defines the output schema.
    from uscardforum.models.topics import Post, TopicInfo, TopicSummary
    from uscardforum.server_core import get_client, mcp
    
    
    @mcp.tool()
    def get_hot_topics(
        page: Annotated[
            int | None,
            Field(default=None, description="Page number for pagination (0-indexed, default: 0)"),
        ] = None,
    ) -> list[TopicSummary]:
        """
        Fetch currently trending/hot topics from USCardForum.
    
        This returns the most actively discussed topics right now, ranked by
        engagement metrics like recent replies, views, and likes.
    
        Use this to:
        - See what the community is currently discussing
        - Find breaking news or time-sensitive opportunities
        - Discover popular ongoing discussions
    
        Args:
            page: Page number for pagination (0-indexed). Use page=1 to get more topics.
    
        Returns a list of TopicSummary objects with fields:
        - id: Topic ID (use with get_topic_posts)
        - title: Topic title
        - posts_count: Total replies
        - views: View count
        - like_count: Total likes
        - created_at: Creation timestamp
        - last_posted_at: Last activity timestamp
    
        Example response interpretation:
        A topic with high views but low posts may be informational.
        A topic with many recent posts is actively being discussed.
        """
        return get_client().get_hot_topics(page=page)
    
    
    @mcp.tool()
    def get_new_topics(
        page: Annotated[
            int | None,
            Field(default=None, description="Page number for pagination (0-indexed, default: 0)"),
        ] = None,
    ) -> list[TopicSummary]:
        """
        Fetch the latest/newest topics from USCardForum.
    
        Returns recently created topics sorted by creation time (newest first).
        These may have fewer replies but contain fresh information.
    
        Use this to:
        - Find newly posted deals or offers
        - See fresh questions from the community
        - Discover emerging discussions before they get popular
    
        Args:
            page: Page number for pagination (0-indexed). Use page=1 to get more topics.
    
        Returns a list of TopicSummary objects with:
        - id: Topic ID
        - title: Topic title
        - posts_count: Number of posts
        - created_at: When the topic was created
        - category_id: Which forum section it's in
    
        Tip: New topics with high view counts may indicate important news.
        """
        return get_client().get_new_topics(page=page)
    
    
    @mcp.tool()
    def get_top_topics(
        period: Annotated[
            str,
            Field(
                default="monthly",
                description="Time window for ranking: 'daily', 'weekly', 'monthly' (default), 'quarterly', or 'yearly'",
            ),
        ] = "monthly",
        page: Annotated[
            int | None,
            Field(default=None, description="Page number for pagination (0-indexed, default: 0)"),
        ] = None,
    ) -> list[TopicSummary]:
        """
        Fetch top-performing topics for a specific time period.
    
        Args:
            period: Time window for ranking. Must be one of:
                - "daily": Top topics from today
                - "weekly": Top topics this week
                - "monthly": Top topics this month (default)
                - "quarterly": Top topics this quarter
                - "yearly": Top topics this year
            page: Page number for pagination (0-indexed). Use page=1 to get more topics.
    
        Use this to:
        - Find the most valuable discussions in a time range
        - Research historically important threads
        - Identify evergreen popular content
    
        Returns TopicSummary objects sorted by engagement score.
    
        Example: Use "yearly" to find the most impactful discussions,
        or "daily" to see what's trending today.
        """
        return get_client().get_top_topics(period=period, page=page)
    
    
    @mcp.tool()
    def get_topic_info(
        topic_id: Annotated[
            int,
            Field(description="The numeric topic ID (from URLs like /t/slug/12345)"),
        ],
    ) -> TopicInfo:
        """
        Get metadata about a specific topic without fetching all posts.
    
        Args:
            topic_id: The numeric topic ID (from URLs like /t/slug/12345)
    
        Use this FIRST before reading a topic to:
        - Check how many posts it contains (for pagination planning)
        - Get the topic title and timestamps
        - Decide whether to fetch all posts or paginate
    
        Returns a TopicInfo object with:
        - topic_id: The topic ID
        - title: Full topic title
        - post_count: Total number of posts
        - highest_post_number: Last post number (may differ from count if posts deleted)
        - last_posted_at: When the last reply was made
    
        Strategy for large topics:
        - <50 posts: Safe to fetch all at once
        - 50-200 posts: Consider using max_posts parameter
        - >200 posts: Fetch in batches or summarize key posts
        """
        return get_client().get_topic_info(topic_id)
    
    
    @mcp.tool()
    def get_topic_posts(
        topic_id: Annotated[
            int,
            Field(description="The numeric topic ID"),
        ],
        post_number: Annotated[
            int,
            Field(default=1, description="Which post number to start from (default: 1 = first post)"),
        ] = 1,
        include_raw: Annotated[
            bool,
            Field(default=False, description="Include raw markdown source (default: False, returns HTML)"),
        ] = False,
    ) -> list[Post]:

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/hmumixaM/uscardforum-mcp4'

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