Skip to main content
Glama
james-livefront

Poetry MCP Server

search_poems

Find poems by searching titles, content, and notes with filters for states, forms, and tags to locate specific poetry matching your criteria.

Instructions

Search for poems matching criteria.

Args: query: Text to search for in titles, content, and notes states: Filter by states (e.g., ["completed", "fledgeling"]) forms: Filter by forms (e.g., ["free_verse", "prose_poem"]) tags: Filter by tags (poems must have all specified tags) limit: Maximum number of results to return include_content: Whether to include full poem text in results

Returns: SearchResult with matched poems and query metadata

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
queryYes
statesNo
formsNo
tagsNo
limitNo
include_contentNo

Implementation Reference

  • The core handler function for the 'search_poems' tool. It performs text search, applies filters for states, forms, and tags, sorts by relevance, limits results, and returns a SearchResult. Registered via @mcp.tool() decorator.
    @mcp.tool()
    async def search_poems(
        query: str,
        states: Optional[List[str]] = None,
        forms: Optional[List[str]] = None,
        tags: Optional[List[str]] = None,
        limit: int = 20,
        include_content: bool = False
    ) -> SearchResult:
        """
        Search for poems matching criteria.
    
        Args:
            query: Text to search for in titles, content, and notes
            states: Filter by states (e.g., ["completed", "fledgeling"])
            forms: Filter by forms (e.g., ["free_verse", "prose_poem"])
            tags: Filter by tags (poems must have all specified tags)
            limit: Maximum number of results to return
            include_content: Whether to include full poem text in results
    
        Returns:
            SearchResult with matched poems and query metadata
        """
        import time
        start_time = time.perf_counter()
    
        cat = get_catalog()
    
        # Start with text search if query provided
        if query:
            results = cat.index.search_content(query, case_sensitive=False)
        else:
            # No query, start with all poems
            results = cat.index.all_poems.copy()
    
        # Apply state filter
        if states:
            results = [p for p in results if p.state in states]
    
        # Apply form filter
        if forms:
            results = [p for p in results if p.form in forms]
    
        # Apply tag filter (must have all tags)
        if tags:
            results = [
                p for p in results
                if all(tag.lower() in [t.lower() for t in p.tags] for tag in tags)
            ]
    
        # Sort by relevance (poems with more tag matches first)
        if tags:
            def relevance_score(poem: Poem) -> int:
                return sum(1 for tag in tags if tag.lower() in [t.lower() for t in poem.tags])
            results.sort(key=relevance_score, reverse=True)
    
        # Limit results
        total_matches = len(results)
        results = results[:limit]
    
        # Remove content if not requested
        if not include_content:
            results = [
                Poem(**{**p.model_dump(), 'content': None})
                for p in results
            ]
    
        query_time_ms = (time.perf_counter() - start_time) * 1000
    
        return SearchResult(
            poems=results,
            total_matches=total_matches,
            query_time_ms=query_time_ms
        )
  • Pydantic model defining the output schema for the search_poems tool, including list of poems, total matches, and query time.
    class SearchResult(BaseModel):
        """
        Result from search_poems operation.
    
        Contains matched poems and query metadata.
        """
    
        poems: list[Poem] = Field(
            ...,
            description="List of poems matching search criteria"
        )
    
        total_matches: int = Field(
            ...,
            description="Total number of poems matching query (may be > len(poems) if limited)"
        )
    
        query_time_ms: float = Field(
            ...,
            description="Time taken to execute query in milliseconds"
        )
    
        class Config:
            """Pydantic configuration."""
            json_schema_extra = {
                "example": {
                    "poems": [
                        {
                            "id": "second-bridge",
                            "title": "Second Bridge Out Old Route 12",
                            "state": "completed",
                            "form": "free_verse",
                            "tags": ["water", "memory"]
                        }
                    ],
                    "total_matches": 23,
                    "query_time_ms": 45.2
                }
            }
  • The @mcp.tool() decorator registers the search_poems function as an MCP tool.
    @mcp.tool()

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/james-livefront/poetry-mcp'

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