search_bookmarks
Search recent bookmarks by query across titles, notes, and tags to quickly find saved web content. Use for focused retrieval of recently saved bookmarks.
Instructions
Search bookmarks by query string across titles, notes, and tags (recent focus).
Args:
query: Search query to match against bookmark titles, notes, and tags
limit: Maximum number of results to return (1-100, default 20)
Note: Searches recent bookmarks first, expands automatically if needed.
For comprehensive historical search, use search_bookmarks_extended.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | ||
| limit | No |
Implementation Reference
- src/pinboard_mcp_server/main.py:19-40 (handler)The main tool handler decorated with @mcp.tool. Performs input validation on limit, calls PinboardClient.search_bookmarks helper, and formats the response dictionary with bookmarks list, total count, and query.@mcp.tool async def search_bookmarks(query: str, limit: int = 20) -> dict[str, Any]: """Search bookmarks by query string across titles, notes, and tags (recent focus). Args: query: Search query to match against bookmark titles, notes, and tags limit: Maximum number of results to return (1-100, default 20) Note: Searches recent bookmarks first, expands automatically if needed. For comprehensive historical search, use search_bookmarks_extended. """ if not 1 <= limit <= 100: raise ValueError("Limit must be between 1 and 100") bookmarks = await client.search_bookmarks(query=query, limit=limit) return { "bookmarks": [bookmark.model_dump() for bookmark in bookmarks], "total": len(bookmarks), "query": query, }
- PinboardClient helper method implementing the core search logic: caches results, searches cached bookmarks (title/notes/tags), optimizes with exact tag search via Pinboard API, expands cache if needed, returns list of matching Bookmark objects.async def search_bookmarks(self, query: str, limit: int = 20) -> list[Bookmark]: """Search bookmarks by query string.""" # Check query cache first cache_key = f"search:{query}:{limit}" if cache_key in self._query_cache: return self._query_cache[cache_key] # First try with recent bookmarks bookmarks = await self.get_all_bookmarks() query_lower = query.lower() # Search in title, notes, and tags matches = [] for bookmark in bookmarks: if ( query_lower in bookmark.title.lower() or query_lower in bookmark.notes.lower() or any(query_lower in tag.lower() for tag in bookmark.tags) ): matches.append(bookmark) if len(matches) >= limit: break # If no matches found, try optimized strategies before full expansion if not matches: # First, check if the query matches a tag exactly - use direct tag search tags = await self.get_all_tags() exact_tag_match = next( (tag.tag for tag in tags if tag.tag.lower() == query_lower), None ) if exact_tag_match: # Use efficient tag-based search try: await self._search_by_tag_direct( exact_tag_match, matches, None, None, limit ) except Exception: pass # Fall through to expanded search if tag search fails # If still no matches and we haven't expanded yet, try with more data # This allows comprehensive free-text search but limits scope for safety if not matches and not self._has_expanded_data: bookmarks = await self.get_all_bookmarks(expand_if_needed=True) for bookmark in bookmarks: if ( query_lower in bookmark.title.lower() or query_lower in bookmark.notes.lower() or any(query_lower in tag.lower() for tag in bookmark.tags) ): matches.append(bookmark) if len(matches) >= limit: break # Cache the result self._query_cache[cache_key] = matches return matches