Skip to main content
Glama
code-yeongyu

Perplexity Advanced MCP

ask_perplexity

Search the internet and get answers using Perplexity. Choose simple queries for quick facts or complex queries for deep analysis, with optional file attachments.

Instructions

Perplexity is fundamentally an LLM that can search the internet, gather information, and answer users' queries.

    For example, let's suppose we want to find out the latest version of Python.
    1. You would search on Google.
    2. Then read the top two or three results directly to verify.

    Perplexity does that work for you.

    To answer a user's query, Perplexity searches, opens the top search results, finds information on those websites, and then provides the answer.

    Perplexity can be used with two types of queries: simple and complex. Choosing the right query type to fulfill the user's request is most important.

    SIMPLE Query:
    - Cheap and fast (on average, 10x cheaper and 3x faster than complex queries).
    - Suitable for straightforward questions such as "What is the latest version of Python?"
    - Pricing: $1/M input tokens, $1/M output tokens.

    COMPLEX Query:
    - Slower and more expensive (on average, 10x more expensive and 3x slower).
    - Suitable for tasks requiring multiple steps of reasoning or deep analysis, such as "Analyze the attached code to examine the current status of a specific library and create a migration plan."
    - Pricing: $1/M input tokens, $5/M output tokens.

    Instructions:
    - When reviewing the user's request, if you find anything unexpected, uncertain, or questionable, do not hesitate to use the "ask_perplexity" tool to consult Perplexity.
    - Since Perplexity is also an LLM, prompt engineering techniques are paramount.
    - Remember the basics of prompt engineering, such as providing clear instructions, sufficient context, and examples.
    - Include as much context and relevant files as possible to smoothly fulfill the user's request.
    - IMPORTANT: When adding files as attachments, you MUST use absolute paths (e.g., '/absolute/path/to/file.py'). Relative paths will not work.

    Note: All queries must be in English for optimal results.
    

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
queryYesThe query to search for
query_typeYesType of query to determine model selection
attachment_pathsYesAn optional list of absolute file paths to attach as context for the search query

Implementation Reference

  • The main handler function for the ask_perplexity tool. It accepts a query, query_type, and optional attachment_paths, processes file attachments, wraps complex queries with reasoning instructions, and calls the appropriate provider API (OpenRouter or Perplexity). Returns the answer with optional reasoning in XML format.
    async def ask_perplexity(
        query: str = Field(description="The query to search for"),
        query_type: Literal["simple", "complex"] = Field(description="Type of query to determine model selection"),
        attachment_paths: list[str] = Field(
            description="An optional list of absolute file paths to attach as context for the search query",
        ),
    ) -> str:
        """
        Performs an advanced search using the appropriate API provider and model.
    
        This function processes any attached files by reading their contents and formatting them
        into XML before appending them to the original query. The combined query is then sent
        to either OpenRouter or Perplexity API based on the available configuration.
    
        Args:
            query: The search query text
            query_type: Query complexity type ('simple' or 'complex')
            attachment_paths: Optional list of files to include as context
    
        Returns:
            str: XML-formatted result containing reasoning (if available) and answer
    
        Raises:
            ValueError: If the query is empty or attachments cannot be processed
            APIKeyError: If no API provider is configured
        """
        if not query:
            raise ValueError("Query must not be empty")
    
        # Process any file attachments and get the XML string
        attachments_xml = ""
        if attachment_paths:
            attachments_xml = process_attachments(attachment_paths)
    
        # Combine the original query with the attachment contents
        if query_type == "complex":
            query = textwrap.dedent(
                f"""
                <system>
                Think or reason about the user's words in as much detail as possible. Summarize everything thoroughly.
                List all the elements that need to be considered regarding the user's question or prompt.
    
                    <idea-reflection>
                    Form your opinions about these elements from an objective standpoint, avoiding an overly pessimistic or overly optimistic view. Opinions should be specific and realistic.
                    Then logically verify these opinions once more. If they hold up, proceed to the next thought; if not, re-examine them.
                    </idea-reflection>
    
                By carrying out this reflection process, you can accumulate opinions that have been logically reviewed and verified.
                Finally, combine these logically validated pieces of reasoning to form your answer. By doing this way, provide responses that are verifiable and logically sound.
                </system>
    
                <user-request>
                {query}
                </user-request>
                """[1:]
            )
        query_with_attachments = query + attachments_xml
    
        # Retrieve available providers
        available_providers: list[ProviderType] = [p for p, cfg in PROVIDER_CONFIG.items() if cfg["key"]]
        if not available_providers:
            raise APIKeyError("No API key available")
        provider: ProviderType = available_providers[0]
        config: ModelConfig = PROVIDER_CONFIG[provider]
    
        # Map query_type from string to QueryType enum
        match query_type:
            case "simple":
                query_type_enum = QueryType.SIMPLE
            case "complex":
                query_type_enum = QueryType.COMPLEX
            case _:
                raise ValueError(f"Invalid query type: {query_type}")
    
        model: str = config["models"][query_type_enum]
        include_reasoning = provider == "openrouter" and query_type_enum == QueryType.COMPLEX
    
        # Call the provider with the combined query
        response = await call_provider(
            provider, model, [{"role": "user", "content": query_with_attachments}], include_reasoning
        )
        # Format the result as raw text with XML-like tags
        result = ""
    
        # Add reasoning if available
        reasoning = response.get("reasoning")
        answer = response.get("content", "")
    
        reasoning_text = f"<think>\n{reasoning}\n</think>\n\n" if reasoning else ""
        answer_text = f"<answer>\n{answer}\n</answer>"
    
        result += reasoning_text + answer_text
        return result
  • The function signature and Pydantic Field definitions for the three parameters: query (str), query_type (Literal['simple','complex']), and attachment_paths (list[str]).
    async def ask_perplexity(
        query: str = Field(description="The query to search for"),
        query_type: Literal["simple", "complex"] = Field(description="Type of query to determine model selection"),
        attachment_paths: list[str] = Field(
            description="An optional list of absolute file paths to attach as context for the search query",
        ),
  • The @mcp.tool decorator registering 'ask_perplexity' with FastMCP, including a detailed description explaining the tool's purpose, query types (simple vs complex), pricing, and usage instructions.
    @mcp.tool(
        name="ask_perplexity",
        description=(
            """Perplexity is fundamentally an LLM that can search the internet, gather information, and answer users' queries.
    
            For example, let's suppose we want to find out the latest version of Python.
            1. You would search on Google.
            2. Then read the top two or three results directly to verify.
    
            Perplexity does that work for you.
    
            To answer a user's query, Perplexity searches, opens the top search results, finds information on those websites, and then provides the answer.
    
            Perplexity can be used with two types of queries: simple and complex. Choosing the right query type to fulfill the user's request is most important.
    
            SIMPLE Query:
            - Cheap and fast (on average, 10x cheaper and 3x faster than complex queries).
            - Suitable for straightforward questions such as "What is the latest version of Python?"
            - Pricing: $1/M input tokens, $1/M output tokens.
    
            COMPLEX Query:
            - Slower and more expensive (on average, 10x more expensive and 3x slower).
            - Suitable for tasks requiring multiple steps of reasoning or deep analysis, such as "Analyze the attached code to examine the current status of a specific library and create a migration plan."
            - Pricing: $1/M input tokens, $5/M output tokens.
    
            Instructions:
            - When reviewing the user's request, if you find anything unexpected, uncertain, or questionable, do not hesitate to use the "ask_perplexity" tool to consult Perplexity.
            - Since Perplexity is also an LLM, prompt engineering techniques are paramount.
            - Remember the basics of prompt engineering, such as providing clear instructions, sufficient context, and examples.
            - Include as much context and relevant files as possible to smoothly fulfill the user's request.
            - IMPORTANT: When adding files as attachments, you MUST use absolute paths (e.g., '/absolute/path/to/file.py'). Relative paths will not work.
    
            Note: All queries must be in English for optimal results.
            """
        ),
    )
  • The process_attachments helper function used by ask_perplexity to read file contents and format them into an XML string wrapped in <files>/<file> tags.
    def process_attachments(attachment_paths: list[str]) -> str:
        """
        Processes file attachments and formats them into an XML string.
    
        Reads the contents of each file and wraps them in XML tags with the following structure:
        <files>
            <file path="/absolute/path/to/file1">
                [file1 contents]
            </file>
            <file path="/absolute/path/to/file2">
                [file2 contents]
            </file>
        </files>
    
        Args:
            attachment_paths: List of absolute file paths to process
    
        Returns:
            str: XML-formatted string containing file contents
    
        Raises:
            ValueError: If a file is not found, is invalid, or cannot be read
        """
        if not attachment_paths:
            return ""
    
        result = ["<files>"]
    
        # Process each file
        for file_path in attachment_paths:
            try:
                abs_path = Path(file_path).resolve(strict=True)
                if not abs_path.is_file():
                    raise ValueError(f"'{abs_path}' is not a valid file")
    
                # Read file content
                with abs_path.open(encoding="utf-8") as f:
                    file_content = f.read()
    
                # Add file content with proper indentation
                result.append(f'\t<file path="{abs_path}">')
                # Indent each line of the content
                content_lines = file_content.splitlines()
                result.extend(f"\t\t{line}" for line in content_lines)
                result.append("\t</file>")
    
            except FileNotFoundError:
                raise ValueError(f"File not found: {file_path}")
            except Exception as e:
                raise ValueError(f"Error processing file '{file_path}': {e}") from e
    
        result.append("</files>")
        formatted_xml = "\n".join(result)
        return formatted_xml
  • Package-level re-export of ask_perplexity from the search_tool module.
    from .search_tool import ask_perplexity as ask_perplexity
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations provided, so description carries full burden. It explains that Perplexity is an LLM that searches, opens results, finds info, and answers. Details query types and file attachment behavior. Lacks mention of potential inaccuracies or response format, but overall sufficiently transparent.

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?

Description is lengthy but well-structured with sections, examples, and bullet points. Front-loaded with core purpose. Could be slightly more concise, but each section serves a purpose in guiding usage.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Covers main use cases, query types, file attachments, language requirement, and prompt engineering. No output schema, but output is implied to be an answer. Adequate for an LLM-based search tool.

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

Parameters5/5

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

Schema coverage is 100%, but description adds significant value: explains the 'simple' vs 'complex' enum with cost/speed implications, and clarifies that 'attachment_paths' must be absolute paths. Provides context for 'query' via examples.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Description clearly states that Perplexity searches the internet and answers queries, with explicit differentiation between simple and complex queries. The verb 'ask' and resource 'perplexity' are well-defined, and no sibling tools exist to cause confusion.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides explicit guidance on when to use simple vs complex queries, including cost and speed trade-offs. Includes instructions to use the tool for uncertain queries and emphasizes English-only queries. Offers prompt engineering tips and absolute path requirements for attachments.

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/code-yeongyu/perplexity-advanced-mcp'

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