Skip to main content
Glama
fegizii

Semantic Scholar MCP Server

by fegizii

search_snippets

Find specific text passages within academic papers using search queries to locate relevant research content.

Instructions

Search for text snippets across academic papers.

Args:
    query: Search query for text snippets
    limit: Maximum number of results (default: 10, max: 100)
    offset: Number of results to skip (default: 0)

Returns:
    Text snippets from papers

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
queryYes
limitNo
offsetNo

Implementation Reference

  • The core handler function for the 'search_snippets' MCP tool. The @mcp.tool() decorator registers the tool, defines its input schema from the type hints and docstring, and this function implements the logic: it calls the Semantic Scholar snippet/search API, formats the results, and returns a formatted string of snippets with paper titles and years.
    @mcp.tool()
    async def search_snippets(query: str, limit: int = 10, offset: int = 0) -> str:
        """
        Search for text snippets across academic papers.
    
        Args:
            query: Search query for text snippets
            limit: Maximum number of results (default: 10, max: 100)
            offset: Number of results to skip (default: 0)
    
        Returns:
            Text snippets from papers
        """
        params = {"query": query, "limit": min(limit, 100), "offset": offset}
    
        result = await make_api_request("snippet/search", params)
    
        if result is None:
            return "Error: Failed to fetch snippets"
    
        if "error" in result:
            return f"Error: {result['error']}"
    
        snippets = result.get("data", [])
        total = result.get("total", 0)
    
        if not snippets:
            return "No snippets found matching your query."
    
        formatted_snippets = []
        for i, snippet in enumerate(snippets, 1):
            paper = snippet.get("paper", {})
            title = paper.get("title", "Unknown Title")
            year = paper.get("year", "Unknown")
            text = snippet.get("text", "No text available")
    
            formatted_snippets.append(f"{i}. From: {title} ({year})\nSnippet: {text}")
    
        result_text = f"Found {total} total snippets (showing {len(snippets)}):\n\n"
        result_text += "\n\n".join(formatted_snippets)
    
        return result_text
  • Supporting helper function that makes HTTP requests to the Semantic Scholar API, handles errors like rate limits, and is called by search_snippets to fetch the snippet search results.
    async def make_api_request(
        endpoint: str, params: Optional[Dict[str, Any]] = None, method: str = "GET"
    ) -> Optional[Dict[str, Any]]:
        """Make a request to the Semantic Scholar API."""
        url = f"{BASE_URL}/{endpoint.lstrip('/')}"
    
        headers = {
            "Accept": "application/json",
            "User-Agent": f"semantic-scholar-mcp/{USER_AGENT_VERSION}",
        }
    
        if API_KEY:
            headers["x-api-key"] = API_KEY
    
        try:
            async with httpx.AsyncClient(timeout=API_TIMEOUT) as client:
                if method == "GET":
                    response = await client.get(url, headers=headers, params=params)
                elif method == "POST":
                    response = await client.post(url, headers=headers, json=params)
                else:
                    raise ValueError(f"Unsupported HTTP method: {method}")
    
                response.raise_for_status()
                return response.json()
    
        except httpx.HTTPStatusError as e:
            if e.response.status_code == 403:
                if not API_KEY:
                    return {
                        "error": "Rate limit exceeded. The shared public rate limit (1000 req/sec) may be exceeded. Get a free API key from https://www.semanticscholar.org/product/api for dedicated limits."
                    }
                else:
                    return {
                        "error": f"API key may be invalid or rate limit exceeded: {str(e)}"
                    }
            elif e.response.status_code == 429:
                return {
                    "error": "Rate limit exceeded. Please wait a moment and try again, or get an API key for dedicated higher limits."
                }
            else:
                return {"error": f"HTTP error: {str(e)}"}
        except httpx.HTTPError as e:
            return {"error": f"HTTP error: {str(e)}"}
        except Exception as e:
            return {"error": f"Request failed: {str(e)}"}

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/fegizii/SemanticScholarMCP'

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