Skip to main content
Glama
ronantakizawa

Search History MCP Server

get_most_visited

Retrieve frequently visited websites from browser history to identify browsing patterns and top destinations across multiple browsers.

Instructions

Get the most frequently visited sites from browser history.

Args: limit: Maximum number of results to return (default: 20, max: 100) browser: Which browser to query ("brave", "safari", "chrome", "firefox", "edge", "arc", "opera", or "duckduckgo")

Returns: Formatted list of most visited sites with visit counts

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
limitNo
browserNobrave

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
resultYes

Implementation Reference

  • The @mcp.tool decorator registers the tool, and the function implements the logic to retrieve the most frequently visited sites from the browser's history database. It handles different browsers (Brave, Safari, Chrome, Firefox, Edge, Arc, Opera, DuckDuckGo) with specific SQL queries, decryption for DuckDuckGo on macOS, timestamp conversions, and formats the output.
    @mcp.tool
    def get_most_visited(limit: int = 20, browser: Literal["brave", "safari", "chrome", "firefox", "edge", "arc", "opera", "duckduckgo"] = "brave") -> str:
        """
        Get the most frequently visited sites from browser history.
    
        Args:
            limit: Maximum number of results to return (default: 20, max: 100)
            browser: Which browser to query ("brave", "safari", "chrome", "firefox", "edge", "arc", "opera", or "duckduckgo")
    
        Returns:
            Formatted list of most visited sites with visit counts
        """
        if limit > 100:
            limit = 100
    
        if browser == "duckduckgo":
            if is_duckduckgo_encrypted():
                # DuckDuckGo macOS - encrypted database schema
                query = """
                    SELECT
                        ZURLENCRYPTED,
                        ZTITLEENCRYPTED,
                        ZNUMBEROFTOTALVISITS,
                        ZNUMBEROFTRACKERSBLOCKED,
                        ZLASTVISIT
                    FROM ZHISTORYENTRYMANAGEDOBJECT
                    WHERE ZURLENCRYPTED IS NOT NULL AND ZNUMBEROFTOTALVISITS > 1
                    ORDER BY ZNUMBEROFTOTALVISITS DESC
                    LIMIT ?
                """
                results = query_duckduckgo_db(query, (limit,))
            else:
                # DuckDuckGo Windows - Chromium-based
                query = """
                SELECT url, title, visit_count, last_visit_time
                FROM urls
                WHERE visit_count > 1
                AND url NOT LIKE 'https://static.ddg.local/%'
                ORDER BY visit_count DESC
                LIMIT ?
                """
                results = query_history_db(query, (limit,), browser)
    
        elif browser == "safari":
            # Safari database schema
            query = """
            SELECT
                history_items.url as url,
                history_visits.title as title,
                COUNT(history_visits.id) as visit_count,
                MAX(history_visits.visit_time) as last_visit_time
            FROM history_items
            JOIN history_visits ON history_items.id = history_visits.history_item
            GROUP BY history_items.url
            HAVING visit_count > 1
            ORDER BY visit_count DESC
            LIMIT ?
            """
        elif browser == "firefox":
            # Firefox database schema (places.sqlite)
            query = """
            SELECT
                url, title, visit_count,
                last_visit_date as last_visit_time
            FROM moz_places
            WHERE hidden = 0 AND visit_count > 1
            ORDER BY visit_count DESC
            LIMIT ?
            """
        else:
            # Chromium-based browsers (Brave/Chrome/Edge) database schema
            query = """
            SELECT url, title, visit_count, last_visit_time
            FROM urls
            WHERE visit_count > 1
            ORDER BY visit_count DESC
            LIMIT ?
            """
    
        # Query databases (DuckDuckGo already queried above)
        if browser != "duckduckgo":
            results = query_history_db(query, (limit,), browser)
    
        if not results:
            return f"No frequently visited sites found in {browser.capitalize()}"
    
        output = [f"Top {len(results)} most visited {browser.capitalize()} sites:\n"]
    
        for i, entry in enumerate(results, 1):
            title = entry['title'] or "No title"
            url = entry['url']
            visit_count = entry['visit_count']
    
            if browser == "duckduckgo":
                if is_duckduckgo_encrypted():
                    # macOS encrypted version has trackers blocked
                    last_visit = cocoa_timestamp_to_datetime(entry['last_visit_time'])
                    trackers_blocked = entry.get('trackers_blocked', 0)
                    output.append(f"{i}. {title}")
                    output.append(f"   URL: {url}")
                    output.append(f"   Visits: {visit_count} | Trackers blocked: {trackers_blocked} | Last visited: {last_visit}")
                    output.append("")
                else:
                    # Windows Chromium version
                    last_visit = chrome_timestamp_to_datetime(entry['last_visit_time'])
                    output.append(f"{i}. {title}")
                    output.append(f"   URL: {url}")
                    output.append(f"   Visits: {visit_count} | Last visited: {last_visit}")
                    output.append("")
            elif browser == "safari":
                last_visit = safari_timestamp_to_datetime(entry['last_visit_time'])
                output.append(f"{i}. {title}")
                output.append(f"   URL: {url}")
                output.append(f"   Visits: {visit_count} | Last visited: {last_visit}")
                output.append("")
            elif browser == "firefox":
                last_visit = firefox_timestamp_to_datetime(entry['last_visit_time'])
                output.append(f"{i}. {title}")
                output.append(f"   URL: {url}")
                output.append(f"   Visits: {visit_count} | Last visited: {last_visit}")
                output.append("")
            else:
                last_visit = chrome_timestamp_to_datetime(entry['last_visit_time'])
                output.append(f"{i}. {title}")
                output.append(f"   URL: {url}")
                output.append(f"   Visits: {visit_count} | Last visited: {last_visit}")
                output.append("")
    
        return "\n".join(output)
Behavior3/5

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

No annotations are provided, so the description carries the full burden of behavioral disclosure. It mentions the tool retrieves data from browser history, implying a read-only operation, but does not specify permissions required, data privacy implications, rate limits, or error handling. The description adds basic context but lacks detailed behavioral traits beyond the core functionality.

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

Conciseness5/5

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

The description is well-structured and front-loaded with the core purpose, followed by clear sections for arguments and returns. Every sentence earns its place by providing essential information without redundancy. It is appropriately sized for a tool with two parameters and an output schema.

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?

Given the tool's moderate complexity (2 parameters, no annotations, but with an output schema), the description is mostly complete. It covers purpose, parameters, and return format. However, it lacks details on behavioral aspects like permissions or errors, which are important for a tool accessing browser history. The output schema existence reduces the need to explain return values, but some gaps remain.

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 description coverage is 0%, so the description must compensate. It fully documents both parameters: 'limit' with its default and maximum values, and 'browser' with its enum values and default. This adds complete semantic meaning beyond the bare schema, effectively compensating for the lack of schema descriptions.

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?

The description clearly states the specific action ('Get') and resource ('most frequently visited sites from browser history'), distinguishing it from sibling tools like 'get_recent_history' (which would presumably return recent visits rather than most frequent) and 'search_history' (which would search rather than aggregate by frequency). The verb+resource combination is precise and unambiguous.

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

Usage Guidelines4/5

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

The description implies usage context by specifying it retrieves 'most frequently visited sites,' which suggests aggregation by visit count rather than recency or search. However, it does not explicitly state when to use this tool versus alternatives like 'get_recent_history' or 'search_history,' nor does it provide exclusions or prerequisites. The context is clear but lacks explicit comparative guidance.

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/ronantakizawa/search-history-mcp'

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