aamanlamba commited on
Commit
9e59094
·
verified ·
1 Parent(s): 8e283f0

Add 3 new MCP server integrations: Local HERMES, Astro.com, Gemini AI

Browse files
Files changed (1) hide show
  1. astrodienst_mcp.py +365 -0
astrodienst_mcp.py ADDED
@@ -0,0 +1,365 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Astro.com (AstroDienst) MCP Integration
3
+ Fetches classical Hellenistic charts from astro.com
4
+ """
5
+
6
+ import requests
7
+ from typing import Dict, List, Optional
8
+ import time
9
+ from urllib.parse import urlencode
10
+ from bs4 import BeautifulSoup
11
+ import json
12
+ import re
13
+
14
+ class AstroDienstMCP:
15
+ """MCP Server for Astro.com integration"""
16
+
17
+ BASE_URL = "https://www.astro.com"
18
+ RATE_LIMIT = 2.0 # seconds between requests (be respectful)
19
+
20
+ def __init__(self):
21
+ self.last_request_time = 0
22
+ self.session = requests.Session()
23
+ self.session.headers.update({
24
+ 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'
25
+ })
26
+
27
+ def _rate_limit(self):
28
+ """Enforce rate limiting"""
29
+ elapsed = time.time() - self.last_request_time
30
+ if elapsed < self.RATE_LIMIT:
31
+ time.sleep(self.RATE_LIMIT - elapsed)
32
+ self.last_request_time = time.time()
33
+
34
+ def generate_chart(
35
+ self,
36
+ birth_date: str, # Format: "DD.MM.YYYY"
37
+ birth_time: str, # Format: "HH:MM"
38
+ city: str,
39
+ country: str = "",
40
+ house_system: str = "W" # W = Whole Sign, P = Placidus, K = Koch, etc.
41
+ ) -> Dict:
42
+ """
43
+ Generate classical chart from Astro.com
44
+
45
+ Args:
46
+ birth_date: Birth date in DD.MM.YYYY format
47
+ birth_time: Birth time in HH:MM format
48
+ city: City name
49
+ country: Country name (optional)
50
+ house_system: House system (W=Whole Sign, P=Placidus, K=Koch, E=Equal)
51
+
52
+ Returns:
53
+ Chart data including planet positions, houses, aspects
54
+ """
55
+ self._rate_limit()
56
+
57
+ # Astro.com guest chart URL
58
+ # Note: This is a simplified version - actual implementation would need
59
+ # to handle astro.com's location database and chart generation properly
60
+
61
+ return {
62
+ "service": "Astro.com Chart Generator",
63
+ "birth_date": birth_date,
64
+ "birth_time": birth_time,
65
+ "location": f"{city}, {country}" if country else city,
66
+ "house_system": self._get_house_system_name(house_system),
67
+ "chart_url": self._build_chart_url(birth_date, birth_time, city, house_system),
68
+ "note": "For full chart data, please visit astro.com directly. This integration provides chart URL generation.",
69
+ "instructions": [
70
+ "1. Visit the generated chart URL",
71
+ "2. Chart will be displayed with classical aspects",
72
+ "3. Use Whole Sign houses (W) for Hellenistic astrology",
73
+ "4. Planet positions shown in traditional format"
74
+ ],
75
+ "hellenistic_features": {
76
+ "whole_sign_houses": house_system == "W",
77
+ "traditional_aspects": True,
78
+ "sect_aware": "Manual calculation needed",
79
+ "essential_dignities": "Available in extended chart"
80
+ },
81
+ "source": "AstroDienst MCP Integration"
82
+ }
83
+
84
+ def _get_house_system_name(self, code: str) -> str:
85
+ """Convert house system code to name"""
86
+ systems = {
87
+ "W": "Whole Sign (Hellenistic)",
88
+ "P": "Placidus",
89
+ "K": "Koch",
90
+ "E": "Equal House",
91
+ "R": "Regiomontanus",
92
+ "C": "Campanus",
93
+ "B": "Alcabitius"
94
+ }
95
+ return systems.get(code, "Unknown")
96
+
97
+ def _build_chart_url(self, birth_date: str, birth_time: str, city: str, house_system: str) -> str:
98
+ """
99
+ Build astro.com chart URL
100
+
101
+ Note: This is a simplified version. Astro.com requires proper location codes
102
+ and has a complex URL structure. For production, use their API or manual entry.
103
+ """
104
+ # Simplified URL - users would need to fill in details manually
105
+ return f"{self.BASE_URL}/cgi/genchart.cgi?btyp=w2gw&rs=3&usechpref=1&hsy={house_system}"
106
+
107
+ def get_chart_interpretation(
108
+ self,
109
+ chart_data: Dict,
110
+ focus: str = "general"
111
+ ) -> Dict:
112
+ """
113
+ Get classical Hellenistic interpretation guidance
114
+
115
+ Args:
116
+ chart_data: Chart data from generate_chart()
117
+ focus: Interpretation focus (general, career, relationships, health)
118
+
119
+ Returns:
120
+ Interpretation guidance based on Hellenistic principles
121
+ """
122
+ interpretations = {
123
+ "general": {
124
+ "steps": [
125
+ "1. **Identify the Sect**: Determine if day or night chart (Sun above/below horizon)",
126
+ "2. **Assess Sect Light**: Evaluate Sun (day) or Moon (night) as primary luminary",
127
+ "3. **Find Benefics/Malefics**: Identify Jupiter/Venus (benefic) and Saturn/Mars (malefic)",
128
+ "4. **Check Essential Dignities**: Evaluate planetary strength by sign placement",
129
+ "5. **Examine House Rulers**: Note which planets rule key houses (1st, 10th, 7th, 4th)",
130
+ "6. **Analyze Aspects**: Traditional aspects (conjunction, sextile, square, trine, opposition)",
131
+ "7. **Consider Lots**: Calculate Lot of Fortune and Lot of Spirit"
132
+ ],
133
+ "key_principles": [
134
+ "Sect determines benefic/malefic team alignment",
135
+ "Stronger planet (by dignity) wins conflicting testimonies",
136
+ "House rulers show life area conditions",
137
+ "Aspects by degree and sign, with orbs"
138
+ ]
139
+ },
140
+ "career": {
141
+ "focus_points": [
142
+ "**10th House**: Career, reputation, public life",
143
+ "**10th Ruler**: Shows career significations",
144
+ "**MC Sign**: Public image and recognition",
145
+ "**Lot of Fortune**: Material success indicators",
146
+ "**Sun** (day) or **Moon** (night): Overall life direction"
147
+ ]
148
+ },
149
+ "relationships": {
150
+ "focus_points": [
151
+ "**7th House**: Marriage and partnerships",
152
+ "**7th Ruler**: Partner characteristics",
153
+ "**Venus**: Love, beauty, harmony",
154
+ "**Lot of Eros**: Romantic desires",
155
+ "**Moon**: Emotional connections"
156
+ ]
157
+ },
158
+ "health": {
159
+ "focus_points": [
160
+ "**6th House**: Illness and obstacles",
161
+ "**1st House**: Physical body and vitality",
162
+ "**Lot of Fortune**: Physical health",
163
+ "**Malefics**: Areas of potential difficulty",
164
+ "**Moon**: Bodily fluctuations"
165
+ ]
166
+ }
167
+ }
168
+
169
+ result = interpretations.get(focus, interpretations["general"])
170
+ result["focus"] = focus
171
+ result["methodology"] = "Classical Hellenistic Astrology (1st-7th century CE)"
172
+ result["sources"] = [
173
+ "Vettius Valens - Anthology",
174
+ "Claudius Ptolemy - Tetrabiblos",
175
+ "Dorotheus of Sidon - Carmen Astrologicum",
176
+ "Paulus Alexandrinus - Introductory Matters"
177
+ ]
178
+ result["modern_reference"] = "Chris Brennan - Hellenistic Astrology: The Study of Fate and Fortune (2017)"
179
+
180
+ return result
181
+
182
+ def calculate_hellenistic_aspects(
183
+ self,
184
+ planet_positions: Dict[str, float]
185
+ ) -> List[Dict]:
186
+ """
187
+ Calculate traditional Hellenistic aspects
188
+
189
+ Traditional aspects in Hellenistic astrology:
190
+ - Conjunction (0°): Same sign, close degrees
191
+ - Sextile (60°): 2-3 signs apart
192
+ - Square (90°): 3-4 signs apart
193
+ - Trine (120°): 4-5 signs apart
194
+ - Opposition (180°): 6-7 signs apart
195
+
196
+ Args:
197
+ planet_positions: Dict of planet names to absolute degrees (0-360)
198
+
199
+ Returns:
200
+ List of aspects with orbs and interpretations
201
+ """
202
+ aspects = []
203
+ aspect_types = {
204
+ 0: {"name": "Conjunction", "nature": "Blending", "orb": 8},
205
+ 60: {"name": "Sextile", "nature": "Harmonious", "orb": 6},
206
+ 90: {"name": "Square", "nature": "Tension", "orb": 7},
207
+ 120: {"name": "Trine", "nature": "Flowing", "orb": 8},
208
+ 180: {"name": "Opposition", "nature": "Polarity", "orb": 8}
209
+ }
210
+
211
+ planets = list(planet_positions.keys())
212
+ for i, planet1 in enumerate(planets):
213
+ for planet2 in planets[i+1:]:
214
+ angle = abs(planet_positions[planet1] - planet_positions[planet2])
215
+ if angle > 180:
216
+ angle = 360 - angle
217
+
218
+ for aspect_angle, aspect_info in aspect_types.items():
219
+ if abs(angle - aspect_angle) <= aspect_info["orb"]:
220
+ aspects.append({
221
+ "planet1": planet1,
222
+ "planet2": planet2,
223
+ "aspect": aspect_info["name"],
224
+ "angle": round(angle, 2),
225
+ "orb": round(abs(angle - aspect_angle), 2),
226
+ "nature": aspect_info["nature"],
227
+ "interpretation": f"{planet1} {aspect_info['name'].lower()} {planet2}: {aspect_info['nature']} connection"
228
+ })
229
+
230
+ return aspects
231
+
232
+ def get_whole_sign_houses(
233
+ self,
234
+ ascendant_sign: str,
235
+ ascendant_degree: float = 0
236
+ ) -> Dict:
237
+ """
238
+ Calculate Whole Sign house system (traditional Hellenistic)
239
+
240
+ In Whole Sign houses:
241
+ - Ascendant sign = entire 1st house
242
+ - Next sign = entire 2nd house
243
+ - And so on...
244
+
245
+ Args:
246
+ ascendant_sign: Rising sign
247
+ ascendant_degree: Degree of ascendant (for reference, not used in house calculation)
248
+
249
+ Returns:
250
+ Complete house system with signs
251
+ """
252
+ signs = ["Aries", "Taurus", "Gemini", "Cancer", "Leo", "Virgo",
253
+ "Libra", "Scorpio", "Sagittarius", "Capricorn", "Aquarius", "Pisces"]
254
+
255
+ try:
256
+ start_index = signs.index(ascendant_sign)
257
+ except ValueError:
258
+ return {"error": f"Invalid sign: {ascendant_sign}"}
259
+
260
+ houses = {}
261
+ for house_num in range(1, 13):
262
+ sign_index = (start_index + house_num - 1) % 12
263
+ houses[house_num] = {
264
+ "sign": signs[sign_index],
265
+ "start_degree": 0,
266
+ "end_degree": 30,
267
+ "system": "Whole Sign"
268
+ }
269
+
270
+ return {
271
+ "ascendant": ascendant_sign,
272
+ "ascendant_degree": ascendant_degree,
273
+ "house_system": "Whole Sign (Hellenistic)",
274
+ "houses": houses,
275
+ "note": "In Whole Sign houses, each house occupies an entire sign. This is the original house system used by Hellenistic astrologers.",
276
+ "source": "Classical Hellenistic tradition"
277
+ }
278
+
279
+
280
+ def get_mcp_tools() -> List[Dict]:
281
+ """Return list of available AstroDienst MCP tools"""
282
+ return [
283
+ {
284
+ "name": "generate_chart",
285
+ "description": "Generate classical Hellenistic chart from Astro.com",
286
+ "parameters": {
287
+ "birth_date": "string (DD.MM.YYYY)",
288
+ "birth_time": "string (HH:MM)",
289
+ "city": "string",
290
+ "country": "string (optional)",
291
+ "house_system": "string (W=Whole Sign, P=Placidus, K=Koch, E=Equal)"
292
+ },
293
+ "returns": "Chart URL and configuration for astro.com"
294
+ },
295
+ {
296
+ "name": "get_chart_interpretation",
297
+ "description": "Get Hellenistic interpretation guidance",
298
+ "parameters": {
299
+ "chart_data": "dict (from generate_chart)",
300
+ "focus": "string (general, career, relationships, health)"
301
+ },
302
+ "returns": "Step-by-step interpretation guide with classical principles"
303
+ },
304
+ {
305
+ "name": "calculate_hellenistic_aspects",
306
+ "description": "Calculate traditional aspects with orbs",
307
+ "parameters": {
308
+ "planet_positions": "dict {planet_name: degree_0_to_360}"
309
+ },
310
+ "returns": "List of aspects with interpretations"
311
+ },
312
+ {
313
+ "name": "get_whole_sign_houses",
314
+ "description": "Calculate Whole Sign house system (Hellenistic)",
315
+ "parameters": {
316
+ "ascendant_sign": "string (zodiac sign)",
317
+ "ascendant_degree": "float (optional, for reference)"
318
+ },
319
+ "returns": "Complete 12-house layout in Whole Sign system"
320
+ }
321
+ ]
322
+
323
+
324
+ # Main entry point
325
+ if __name__ == "__main__":
326
+ import sys
327
+
328
+ if len(sys.argv) > 1 and sys.argv[1] == "tools":
329
+ print(json.dumps(get_mcp_tools(), indent=2))
330
+ else:
331
+ print("=" * 70)
332
+ print("AstroDienst (Astro.com) MCP Server")
333
+ print("Classical Hellenistic Chart Integration")
334
+ print("=" * 70)
335
+ print("\nAvailable Tools:")
336
+ print(json.dumps(get_mcp_tools(), indent=2))
337
+
338
+ # Test example
339
+ print("\n" + "=" * 70)
340
+ print("TEST: Generate Chart")
341
+ print("=" * 70)
342
+
343
+ server = AstroDienstMCP()
344
+ result = server.generate_chart(
345
+ birth_date="15.01.1990",
346
+ birth_time="12:00",
347
+ city="New York",
348
+ country="USA",
349
+ house_system="W"
350
+ )
351
+ print(json.dumps(result, indent=2))
352
+
353
+ print("\n" + "=" * 70)
354
+ print("TEST: Whole Sign Houses")
355
+ print("=" * 70)
356
+
357
+ result = server.get_whole_sign_houses("Leo", 15.5)
358
+ print(json.dumps(result, indent=2))
359
+
360
+ print("\n" + "=" * 70)
361
+ print("TEST: Interpretation Guide")
362
+ print("=" * 70)
363
+
364
+ result = server.get_chart_interpretation({}, "general")
365
+ print(json.dumps(result, indent=2))