Skip to main content
Glama
jkingsman

https://github.com/jkingsman/qanon-mcp-server

search_posts

Search for QAnon posts containing specific keywords or phrases to support sociological research and analysis.

Instructions

Search for posts/drops containing a specific keyword or phrase.

Args:
    query: The keyword or phrase to search for
    limit: Maximum number of results to return (default: 10)

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
queryYes
limitNo

Implementation Reference

  • The handler function for the 'search_posts' tool. It is registered via the @mcp.tool() decorator, which also serves as the schema via type hints and docstring. Searches posts using the helper function and formats output.
    @mcp.tool()
    def search_posts(query: str, limit: int = 10) -> str:
        """
        Search for posts/drops containing a specific keyword or phrase.
    
        Args:
            query: The keyword or phrase to search for
            limit: Maximum number of results to return (default: 10)
        """
        if not query:
            return "Please provide a search query."
    
        results = search_posts_by_keyword(query)
    
        if not results:
            return f"No posts found containing '{query}'."
    
        total_found = len(results)
        results = results[:limit]
    
        output = f"Found {total_found} posts containing '{query}'. Showing top {len(results)} results:\n\n"
    
        for i, post in enumerate(results, 1):
            output += f"Result {i}:\n{format_post(post)}\n\n" + "-" * 40 + "\n\n"
    
        if total_found > limit:
            output += f"... and {total_found - limit} more posts."
    
        return output
  • Helper function that performs the actual keyword search on the loaded posts data, returning matching posts.
    def search_posts_by_keyword(keyword: str) -> List[Dict]:
        """Search posts containing a keyword."""
        keyword = keyword.lower()
        results = []
        for post in posts:
            text = post.get("text", "").lower()
            if keyword in text:
                results.append(post)
        return results
  • Supporting function used by search_posts to format individual post results for display.
    def format_post(post: Dict) -> str:
        """Format a post for display."""
        metadata = post.get("post_metadata", {})
        post_id = metadata.get("id", "Unknown")
        author = metadata.get("author", "Unknown")
        author_id = metadata.get("author_id", "Unknown")
        tripcode = metadata.get("tripcode", "Unknown")
    
        source = metadata.get("source", {})
        board = source.get("board", "Unknown")
        site = source.get("site", "Unknown")
    
        timestamp = metadata.get("time", 0)
        date_str = (
            datetime.fromtimestamp(timestamp).strftime("%Y-%m-%d %H:%M:%S")
            if timestamp
            else "Unknown"
        )
    
        text = post.get("text", "")
        if text:
            # Replace '\n' string literals with actual newlines
            text = text.replace("\\n", "\n")
    
        # Format images
        images_section = ""
        images = post.get("images", [])
        if images:
            images_section = "\nImages:\n"
            for img in images:
                images_section += f"- File: {img.get('file', 'Unknown')}, Name: {img.get('name', 'Unknown')}\n"
    
        # Format referenced posts
        refs_section = ""
        refs = post.get("referenced_posts", [])
        if refs:
            refs_section = "\nReferenced Posts:\n"
            for ref in refs:
                ref_text = ref.get("text", "No text")
                if ref_text:
                    ref_text = ref_text.replace("\\n", "\n")
                ref_author_id = ref.get("author_id", "Unknown")
                refs_section += f"- Reference: {ref.get('reference', 'Unknown')}\n"
                refs_section += f"  Author ID: {ref_author_id}\n"
                refs_section += f"  Text: {ref_text}\n"
    
        # Assemble the formatted post
        formatted = f"""
    Post ID: {post_id}
    Author: {author} (ID: {author_id}, tripcode: {tripcode})
    Source: {board} on {site}
    Date: {date_str}
    Text:
    {text}
    {images_section}
    {refs_section}
    """
        return formatted.strip()
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 searches for posts/drops but doesn't describe how results are returned (e.g., format, ordering, pagination), whether there are rate limits, authentication requirements, or what happens if no matches are found. For a search tool with zero annotation coverage, this is a significant gap in behavioral context.

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

Conciseness4/5

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

The description is appropriately sized and front-loaded, starting with the core purpose followed by parameter explanations. Each sentence adds value: the first defines the tool's function, and the next two clarify parameters. There's no redundant or wasted text, making it efficient for quick comprehension.

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 the tool's moderate complexity (2 parameters, no output schema, no annotations), the description is minimally adequate. It covers the basic purpose and parameters but lacks details on behavioral aspects like result formatting, error handling, or usage context relative to siblings. Without annotations or output schema, more completeness would be beneficial for effective agent use.

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

Parameters4/5

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

The description adds meaningful context for both parameters beyond the input schema, which has 0% description coverage. It explains that 'query' is 'The keyword or phrase to search for' and 'limit' is 'Maximum number of results to return (default: 10)', providing clear semantic understanding. This compensates well for the lack of schema descriptions, though it doesn't detail constraints like query syntax or limit ranges.

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's purpose: 'Search for posts/drops containing a specific keyword or phrase.' It specifies the verb ('search') and resource ('posts/drops'), making it easy to understand what the tool does. However, it doesn't explicitly differentiate from sibling tools like 'get_posts_by_author_id' or 'get_posts_by_date', which are more specific retrieval methods rather than keyword searches.

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. It doesn't mention sibling tools like 'analyze_post' or 'word_cloud_by_date_range', nor does it specify scenarios where keyword searching is preferred over other filtering methods (e.g., by author or date). This lack of comparative context leaves the agent without clear usage direction.

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/jkingsman/qanon-mcp-server'

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