Skip to main content
Glama
GodisinHisHeaven

USCardForum MCP Server

get_topic_posts

Fetch batches of forum posts from specific topics for paginated reading, starting at any position to retrieve content in manageable segments.

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 core MCP tool handler for 'get_topic_posts'. Decorated with @mcp.tool(), defines input schema via Annotated Fields, detailed docstring, and delegates execution to the DiscourseClient via get_client().
    @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 the get_topic_posts tool function to register it with the MCP server via module import (FastMCP auto-registers decorated tools).
        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,
    )
    
    __all__ = [
        "MCP_HOST",
        "MCP_PORT",
        "MCP_TRANSPORT",
        "NITAN_TOKEN",
        "SERVER_INSTRUCTIONS",
        "get_client",
        "main",
        "mcp",
        "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",
  • Shared helper get_client() that provides the DiscourseClient instance used by all tools, including get_topic_posts.
    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
  • Client wrapper method that delegates to TopicsAPI.
    def get_topic_posts(
        self,
        topic_id: int,
        *,
        post_number: int = 1,
        include_raw: bool = False,
    ) -> list[Post]:
        """Fetch a batch of posts starting at a specific post number.
    
        Args:
            topic_id: Topic ID
            post_number: Starting post number (default: 1)
            include_raw: Include raw markdown (default: False)
    
        Returns:
            List of posts sorted by post_number
        """
        return self._topics.get_topic_posts(
            topic_id, post_number=post_number, include_raw=include_raw
        )
  • Low-level API handler in TopicsAPI that makes the HTTP request to Discourse and parses the response into Post models.
    def get_topic_posts(
        self,
        topic_id: int,
        *,
        post_number: int = 1,
        include_raw: bool = False,
    ) -> list[Post]:
        """Fetch a batch of posts starting at a specific post number.
    
        Args:
            topic_id: Topic ID
            post_number: Starting post number (default: 1)
            include_raw: Include raw markdown (default: False)
    
        Returns:
            List of posts sorted by post_number
        """
        params_list: list[tuple[str, Any]] = [
            ("post_number", int(post_number)),
            ("asc", "true"),
            ("include_suggested", "false"),
            ("include_raw", str(include_raw).lower()),
        ]
        payload = self._get(f"t/topic/{int(topic_id)}.json", params=params_list)
        raw_posts = payload.get("post_stream", {}).get("posts", [])
    
        posts = []
        for p in raw_posts:
            post = Post(
                id=p.get("id", 0),
                post_number=p.get("post_number", 0),
                username=p.get("username", ""),
                cooked=p.get("cooked"),
                raw=p.get("raw") if include_raw else None,
                created_at=p.get("created_at"),
                updated_at=p.get("updated_at"),
                like_count=p.get("like_count", 0),
                reply_count=p.get("reply_count", 0),
                reply_to_post_number=p.get("reply_to_post_number"),
            )
            posts.append(post)
    
        posts.sort(key=lambda p: p.post_number)
        return posts

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/GodisinHisHeaven/uscardforum-mcp'

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