Skip to main content
Glama

mcp-otzaria-server

from mcp.server.models import InitializationOptions import mcp.types as types from mcp.server import NotificationOptions, Server import mcp.server.stdio import asyncio import os import logging import sys import json from .tantivy_search_agent import TantivySearchAgent # Configure logging logging.basicConfig( level=logging.ERROR, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', handlers=[ logging.StreamHandler(sys.stderr), logging.FileHandler('jewish_library.log', encoding='utf-8') ] ) logger = logging.getLogger('jewish_library') # Initialize TantivySearchAgent with the index path current_dir = os.path.dirname(os.path.abspath(__file__)) index_path = os.path.join(os.path.dirname(os.path.dirname(current_dir)), "index") try: search_agent = TantivySearchAgent(index_path) logger.info("Search agent initialized") except Exception as e: logger.error(f"Failed to initialize search agent: {e}") raise server = Server("jewish_library") @server.list_tools() async def handle_list_tools() -> list[types.Tool]: """ List available tools. Each tool specifies its arguments using JSON Schema validation. """ logger.debug("Handling list_tools request") return [ types.Tool( name="full_text_search", description="Full text searching in the jewish library", inputSchema={ "type": "object", "properties": { "query": { "type": "string", "description": """ Instructions for generating a query: 1. Boolean Operators: - AND: term1 AND term2 (both required) - OR: term1 OR term2 (either term) - Multiple words default to OR operation (cloud network = cloud OR network) - AND takes precedence over OR - Example: Shabath AND (walk OR go) 2. Field-specific Terms: - Field-specific terms: field:term - Example: text:אדם AND reference:בראשית - available fields: text, reference, topics - text contains the text of the document - reference contains the citation of the document, e.g. בראשית, פרק א - topics contains the topics of the document. available topics includes: תנך, הלכה, מדרש, etc. 3. Required/Excluded Terms: - Required (+): +term (must contain) - Excluded (-): -term (must not contain) - Example: +security cloud -deprecated - Equivalent to: security AND cloud AND NOT deprecated 4. Phrase Search: - Use quotes: "exact phrase" - Both single/double quotes work - Escape quotes with \\" - Slop operator: "term1 term2"~N - Example: "cloud security"~2 - the above will find "cloud framework and security " - Prefix matching: "start of phrase"* 5. Wildcards: - ? for single character - * for any number of characters - Example: sec?rity cloud* 6. Special Features: - All docs: * - Boost terms: term^2.0 (positive numbers only) - Example: security^2.0 cloud - the above will boost security by 2.0 Query Examples: 1. Basic: +שבת +חולה +אסור 2. Field-specific: text:סיני AND topics:תנך 3. Phrase with slop: "security framework"~2 4. Complex: +reference:בראשית +text:"הבל"^2.0 +(דמי OR דמים) -הבלים 6. Mixed: (text:"רבנו משה"^2.0 OR reference:"משנה תורה") AND topics:הלכה) AND text:"תורה המלך"~3 AND NOT topics:מדרש Tips: - Group complex expressions with parentheses - Use quotes for exact phrases - Add + for required terms, - for excluded terms - Boost important terms with ^N - use field-specific terms for better results. - the corpus to search in is an ancient Hebrew corpus: Tora and Talmud. so Try to use ancient Hebrew terms and or Talmudic expressions and prevent modern words that are not common in talmudic texts """ }, "num_results": { "type": "integer", "description": "The maximum number of results to return (default: 25)", "default": 25, }, }, "required": ["query"], }, ), ] @server.call_tool() async def handle_call_tool( name: str, arguments: dict | None ) -> list[types.TextContent | types.ImageContent | types.EmbeddedResource]: """ Handle tool execution requests. Tools can search the Jewish library and return formatted results. """ logger.debug(f"Handling call_tool request for {name} with arguments {arguments}") try: if not arguments: raise ValueError("Missing arguments") if name == "full_text_search": try: query = arguments.get("query") if not query: raise ValueError("Missing query parameter") num_results = arguments.get("num_results", 25) if not isinstance(num_results, int) or num_results <= 0: raise ValueError("Invalid num_results parameter") logger.info(f"Searching with query: {query}") # Now do the actual search logger.debug(f"Executing search with query: {query}") results = await search_agent.search(query, num_results = num_results) logger.debug(f"Search completed: {len(results)} results") if not results or len(results) == 0: logger.info("No results found") return [types.TextContent( type="text", text="No results found" )] formatted_results = [] for result in results: text = result.get('text', 'N/A') reference = result.get('reference', 'N/A') formatted_results.append(f"Reference: {reference}\nText: {text}\n") logger.info(f"Found {len(formatted_results)} results") response_text = "\n\n".join(formatted_results) logger.debug(f"Response text: {response_text}") return [ types.TextContent( type="text", text=response_text ) ] except Exception as err: logger.error(f"Search error: {err}", exc_info=True) return [types.TextContent( type="text", text=f"Error: {str(err)}" )] else: raise ValueError(f"Unknown tool: {name}") except Exception as e: logger.error(f"Tool execution error: {e}", exc_info=True) return [types.TextContent( type="text", text=f"Error: {str(e)}" )] async def main(): try: logger.info("Starting Jewish Library MCP server...") # Run the server using stdin/stdout streams async with mcp.server.stdio.stdio_server() as (read_stream, write_stream): await server.run( read_stream, write_stream, InitializationOptions( server_name="jewish_library", server_version="0.1.0", capabilities=server.get_capabilities( notification_options=NotificationOptions(), experimental_capabilities={}, ), ), ) except Exception as e: logger.error(f"Server error: {e}", exc_info=True) raise if __name__ == "__main__": try: asyncio.run(main()) except KeyboardInterrupt: logger.info("Server stopped by user") except Exception as e: logger.error(f"Fatal error: {e}", exc_info=True) raise

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/Sivan22/mcp-otzaria-server'

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