get_posts
Retrieve Product Hunt posts filtered by topic, date, URL, or Twitter link, sorted by ranking, votes, or newest. Use pagination to explore additional results.
Instructions
Retrieve a list of Product Hunt posts with various filtering and sorting options.
Parameters:
- featured (bool, optional): Only return featured posts if True.
- topic (str, optional): Filter by topic slug.
- order (str, optional): Sorting order. Valid values: RANKING (default), NEWEST, VOTES, FEATURED_AT.
- count (int, optional): Number of posts to return (default: 10, max: 20).
- after (str, optional): Pagination cursor for next page.
- url (str, optional): Filter posts by URL.
- twitter_url (str, optional): Filter posts by Twitter URL.
- posted_before (str, optional): ISO datetime to filter posts posted before this date.
- posted_after (str, optional): ISO datetime to filter posts posted after this date.
Returns:
- success (bool)
- data (dict): If successful, contains:
- posts (list): List of post objects (id, name, description, etc.)
- pagination (dict): { end_cursor, has_next_page }
- error (dict, optional)
- rate_limits (dict)
Notes:
- This is not a keyword search; use filters to narrow results.
- If no posts match, `posts` will be an empty list.
- Invalid date formats return a user-friendly error.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| after | No | ||
| count | No | ||
| featured | No | ||
| order | No | RANKING | |
| posted_after | No | ||
| posted_before | No | ||
| topic | No | ||
| twitter_url | No | ||
| url | No |
Implementation Reference
- The core handler function for the 'get_posts' tool. It handles input parameters, builds GraphQL variables, executes the POSTS_QUERY, processes errors (including date format validation), and formats the response with posts list and pagination.@mcp.tool() @require_token @handle_errors @validate_with_schema(POSTS_SCHEMA) def get_posts( featured: bool = None, topic: str = None, order: str = "RANKING", count: int = 10, after: str = None, url: str = None, twitter_url: str = None, posted_before: str = None, posted_after: str = None, ) -> Dict[str, Any]: """ Retrieve a list of Product Hunt posts with various filtering and sorting options. Parameters: - featured (bool, optional): Only return featured posts if True. - topic (str, optional): Filter by topic slug. - order (str, optional): Sorting order. Valid values: RANKING (default), NEWEST, VOTES, FEATURED_AT. - count (int, optional): Number of posts to return (default: 10, max: 20). - after (str, optional): Pagination cursor for next page. - url (str, optional): Filter posts by URL. - twitter_url (str, optional): Filter posts by Twitter URL. - posted_before (str, optional): ISO datetime to filter posts posted before this date. - posted_after (str, optional): ISO datetime to filter posts posted after this date. Returns: - success (bool) - data (dict): If successful, contains: - posts (list): List of post objects (id, name, description, etc.) - pagination (dict): { end_cursor, has_next_page } - error (dict, optional) - rate_limits (dict) Notes: - This is not a keyword search; use filters to narrow results. - If no posts match, `posts` will be an empty list. - Invalid date formats return a user-friendly error. """ params = { k: v for k, v in { "featured": featured, "topic": topic, "order": order, "count": count, "after": after, "url": url, "twitter_url": twitter_url, "posted_before": posted_before, "posted_after": posted_after, }.items() if v is not None } logger.info("posts.get_posts called", extra=params) # Apply pagination defaults variables = apply_pagination_defaults(count, after) # Add order parameter variables["order"] = order # Add optional filters if featured is not None: variables["featured"] = featured if topic: variables["topic"] = topic if url: variables["url"] = url if twitter_url: variables["twitterUrl"] = twitter_url if posted_before: variables["postedBefore"] = posted_before if posted_after: variables["postedAfter"] = posted_after result, rate_limits, error = execute_graphql_query(POSTS_QUERY, variables) if error: # If there's a GraphQL error related to date format, provide a more user-friendly message if ( "code" in error and error["code"] == "GRAPHQL_ERROR" and any( "postedBefore" in str(e) or "postedAfter" in str(e) for e in error.get("details", []) ) ): return format_response( False, error={ "code": "INVALID_DATE_FORMAT", "message": "The provided date format is invalid. Please use ISO 8601 format (e.g., 2023-01-01T00:00:00Z)", }, rate_limits=rate_limits, ) return format_response(False, error=error, rate_limits=rate_limits) # Extract posts posts_data = result["data"]["posts"] return format_response( True, data={ "posts": posts_data["edges"], "pagination": extract_pagination(posts_data["pageInfo"]), }, rate_limits=rate_limits, )
- Input validation schema (POSTS_SCHEMA) for the get_posts tool parameters, used by @validate_with_schema decorator.POSTS_SCHEMA = { "featured": {"type": bool}, "topic": {"type": str}, "order": {"type": str, "valid_values": ["RANKING", "NEWEST", "VOTES", "FEATURED_AT"]}, "count": {"type": int, "min_value": 1, "max_value": 20}, "after": {"type": str}, "url": {"type": str}, "twitter_url": {"type": str}, "posted_before": {"type": str, "is_iso8601": True}, "posted_after": {"type": str, "is_iso8601": True}, }
- src/product_hunt_mcp/cli.py:35-35 (registration)Registration of post tools (including get_posts) by calling register_post_tools on the MCP server instance in the main CLI entrypoint.register_post_tools(mcp)