""" Google Gemini MCP Integration Natural language conversations about Hellenistic astrology """ import json from typing import Dict, List, Optional import os try: import google.generativeai as genai GEMINI_AVAILABLE = True except ImportError: GEMINI_AVAILABLE = False class GeminiMCP: """MCP Server for Google Gemini AI conversations about Hellenistic astrology""" def __init__(self, api_key: Optional[str] = None): """ Initialize Gemini MCP server Args: api_key: Google AI API key (or set GOOGLE_API_KEY environment variable) """ self.api_key = api_key or os.getenv("GOOGLE_API_KEY") self.model_name = "gemini-pro" self.conversation_history = [] if GEMINI_AVAILABLE and self.api_key: genai.configure(api_key=self.api_key) self.model = genai.GenerativeModel(self.model_name) self.chat = None self.is_configured = True else: self.model = None self.chat = None self.is_configured = False # Hellenistic astrology system prompt self.system_prompt = """You are an expert in Hellenistic astrology (1st-7th century CE). You specialize in: - Essential dignities (domicile, exaltation, triplicity, bound, decan) - Sect (day/night charts and benefic/malefic teams) - Whole Sign houses (traditional house system) - Traditional aspects with orbs - Lots/Parts (Fortune, Spirit, Eros, etc.) - Time-lord techniques (profections, zodiacal releasing, firdaria) - Classical texts (Vettius Valens, Ptolemy, Dorotheus, Paulus Alexandrinus) **Teaching Style:** - Explain concepts clearly for beginners - Reference primary sources when relevant - Distinguish traditional vs. modern techniques - Use examples from classical texts - Be precise about technical terminology **Always:** - Cite sources (ancient or modern) - Explain "why" behind techniques, not just "what" - Connect theory to practical interpretation - Note when techniques vary between authors - Encourage further study of primary texts **Never:** - Make predictions without chart data - Mix modern psychological astrology with traditional - Oversimplify complex techniques - Claim certainty about contested interpretations""" def ask_question( self, question: str, include_sources: bool = True ) -> Dict: """ Ask a question about Hellenistic astrology Args: question: User's question include_sources: Whether to request source citations Returns: AI response with explanation and sources """ if not self.is_configured: return { "error": "Gemini not configured", "message": "Please set GOOGLE_API_KEY environment variable or provide API key", "fallback": self._get_fallback_response(question) } try: # Start new chat if needed if not self.chat: self.chat = self.model.start_chat(history=[]) # Send system prompt as first message self.chat.send_message(self.system_prompt) # Add instruction for sources if requested if include_sources: full_question = f"{question}\n\n(Please include relevant classical sources in your answer.)" else: full_question = question # Send question response = self.chat.send_message(full_question) return { "question": question, "answer": response.text, "model": self.model_name, "conversation_turn": len(self.conversation_history) + 1, "source": "Google Gemini via HERMES MCP" } except Exception as e: return { "error": f"Gemini API error: {str(e)}", "question": question, "fallback": self._get_fallback_response(question) } def _get_fallback_response(self, question: str) -> str: """ Provide fallback responses when Gemini unavailable Returns basic information about common topics """ fallback_db = { "dignit": """**Essential Dignities** measure planetary strength by zodiacal position. The five levels are: 1. **Domicile** (+5): Planet in its home sign (e.g., Sun in Leo) 2. **Exaltation** (+4): Planet in its exaltation (e.g., Sun in Aries) 3. **Triplicity** (+3): Planet ruling the element 4. **Bound/Term** (+2): Planet ruling degree ranges within signs 5. **Decan/Face** (+1): Planet ruling 10-degree sections **Debilities** are opposites: - **Detriment** (-5): Opposite of domicile (e.g., Sun in Aquarius) - **Fall** (-4): Opposite of exaltation (e.g., Sun in Libra) *Source: Ptolemy's Tetrabiblos, Vettius Valens*""", "sect": """**Sect** divides charts into day and night teams. **Day Chart** (Sun above horizon): - Sun, Jupiter, Saturn = Day team (stronger) - Moon, Venus, Mars = Night team (weaker) - Jupiter = benefic, Saturn = malefic (but of the day team) **Night Chart** (Sun below horizon): - Moon, Venus, Mars = Night team (stronger) - Sun, Jupiter, Saturn = Day team (weaker) - Venus = benefic, Mars = malefic (but of the night team) Planets in-sect function better than out-of-sect planets. *Source: Vettius Valens, Anthology Book II*""", "profection": """**Annual Profections** move the Ascendant forward one house per year. **How it works:** 1. Start at Ascendant (age 0-1) 2. Move to 2nd house (age 1-2) 3. Continue advancing one house per year 4. At age 12, return to Ascendant (12-year cycle) The **profected house** shows the year's themes. The **ruler** of that house becomes **Lord of the Year**. Example: Age 35 profects to the 12th house (35 % 12 = 11, +1 = 12th). *Source: Vettius Valens, Paulus Alexandrinus*""", "whole sign": """**Whole Sign Houses** assign entire signs to houses. **How it works:** 1. Ascendant sign = entire 1st house (0-30°) 2. Next sign = entire 2nd house 3. Continue through all 12 signs This is the **original Hellenistic house system** (1st-7th century). **Benefits:** - Simple and clear - Each house is exactly 30° - Easy to determine house rulers - Used by Vettius Valens, Dorotheus Modern systems (Placidus, Koch) came later (16th-18th century). *Source: Chris Brennan, Hellenistic Astrology (2017)*""" } # Check for keywords question_lower = question.lower() for keyword, response in fallback_db.items(): if keyword in question_lower: return response # Default response return """**API Key Required** For AI-powered conversations, set your Google AI API key: ```python export GOOGLE_API_KEY="your-key-here" ``` Get a free API key at: https://makersuite.google.com/app/apikey **Meanwhile, try these resources:** - Chris Brennan: "Hellenistic Astrology: The Study of Fate and Fortune" (2017) - Vettius Valens: "Anthology" (Project Hindsight translation) - Demetra George: "Ancient Astrology in Theory and Practice" (2019) **Or ask specific questions like:** - "What are essential dignities?" - "How does sect work?" - "What are annual profections?" - "What are Whole Sign houses?" """ def explain_technique( self, technique: str, level: str = "beginner" ) -> Dict: """ Get detailed explanation of a traditional technique Args: technique: Name of technique (dignities, profections, lots, etc.) level: Explanation level (beginner, intermediate, advanced) Returns: Structured explanation tailored to level """ levels_prompt = { "beginner": "Explain this as if teaching someone new to astrology. Use simple language and clear examples.", "intermediate": "Provide a comprehensive explanation with examples and source citations.", "advanced": "Give an in-depth technical explanation including variant methods across classical authors." } question = f"""Please explain the technique of {technique} in Hellenistic astrology. Level: {levels_prompt.get(level, levels_prompt['beginner'])} Include: 1. What it is and why it's used 2. How to calculate or apply it 3. An example 4. Classical sources 5. Common mistakes to avoid""" return self.ask_question(question, include_sources=True) def interpret_placement( self, planet: str, sign: str, house: int, aspects: Optional[List[str]] = None, is_day_chart: bool = True ) -> Dict: """ Get AI interpretation of a planetary placement Args: planet: Planet name sign: Zodiac sign house: House number (1-12) aspects: List of aspects (e.g., ["square Mars", "trine Jupiter"]) is_day_chart: Whether it's a day chart (for sect analysis) Returns: Detailed interpretation using Hellenistic principles """ aspect_text = f"\nAspects: {', '.join(aspects)}" if aspects else "" chart_type = "day chart" if is_day_chart else "night chart" question = f"""Interpret this planetary placement using Hellenistic astrology: **Planet:** {planet} **Sign:** {sign} **House:** {house} **Chart Type:** {chart_type}{aspect_text} Please analyze: 1. Essential dignity (domicile, exaltation, detriment, fall) 2. Sect condition (in-sect or out-of-sect) 3. House signification 4. Aspects and their influence 5. Overall interpretation Use traditional Hellenistic principles and cite classical sources where relevant.""" return self.ask_question(question, include_sources=True) def compare_techniques( self, technique1: str, technique2: str ) -> Dict: """ Compare two astrological techniques Args: technique1: First technique technique2: Second technique Returns: Comparison with similarities, differences, and when to use each """ question = f"""Compare these two techniques in Hellenistic astrology: 1. {technique1} 2. {technique2} Please explain: - What each technique does - Similarities and differences - Historical origins - When to use each one - How they complement each other Include classical sources where relevant.""" return self.ask_question(question, include_sources=True) def reset_conversation(self): """Reset conversation history and start fresh""" self.conversation_history = [] if self.chat: self.chat = None return {"status": "Conversation reset", "ready": True} def get_mcp_tools() -> List[Dict]: """Return list of available Gemini MCP tools""" return [ { "name": "ask_question", "description": "Ask any question about Hellenistic astrology", "parameters": { "question": "string (your question)", "include_sources": "boolean (optional, default True)" }, "returns": "AI-generated answer with classical sources" }, { "name": "explain_technique", "description": "Get detailed explanation of a traditional technique", "parameters": { "technique": "string (dignities, profections, lots, etc.)", "level": "string (beginner, intermediate, advanced)" }, "returns": "Structured explanation tailored to experience level" }, { "name": "interpret_placement", "description": "Get interpretation of a planetary placement", "parameters": { "planet": "string", "sign": "string", "house": "integer (1-12)", "aspects": "list of strings (optional)", "is_day_chart": "boolean (optional, default True)" }, "returns": "Hellenistic interpretation with sect and dignity analysis" }, { "name": "compare_techniques", "description": "Compare two astrological techniques", "parameters": { "technique1": "string", "technique2": "string" }, "returns": "Comparison with when to use each" }, { "name": "reset_conversation", "description": "Reset conversation history", "parameters": {}, "returns": "Confirmation of reset" } ] # Main entry point if __name__ == "__main__": import sys if len(sys.argv) > 1 and sys.argv[1] == "tools": print(json.dumps(get_mcp_tools(), indent=2)) else: print("=" * 70) print("Google Gemini MCP Server") print("Natural Language Hellenistic Astrology Conversations") print("=" * 70) print("\nAvailable Tools:") print(json.dumps(get_mcp_tools(), indent=2)) # Test example print("\n" + "=" * 70) print("TEST: Ask Question (Fallback Mode)") print("=" * 70) server = GeminiMCP() result = server.ask_question("What are essential dignities?") print(json.dumps(result, indent=2)) if not GEMINI_AVAILABLE: print("\n⚠️ Note: google-generativeai package not installed") print(" Install with: pip install google-generativeai") if not server.api_key: print("\n⚠️ Note: GOOGLE_API_KEY not set") print(" Get free API key: https://makersuite.google.com/app/apikey") print(" Set with: export GOOGLE_API_KEY='your-key'")