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

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

Browse files
Files changed (1) hide show
  1. hermes_local_mcp.py +407 -0
hermes_local_mcp.py ADDED
@@ -0,0 +1,407 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Local HERMES MCP Server
3
+ Demonstrates MCP integration with core HERMES features
4
+ """
5
+
6
+ import json
7
+ from typing import Dict, List, Optional
8
+ from datetime import datetime
9
+ import sys
10
+
11
+ class HermesLocalMCP:
12
+ """Local MCP Server for HERMES core features"""
13
+
14
+ def __init__(self):
15
+ self.server_name = "HERMES Local MCP"
16
+ self.version = "1.0.0"
17
+
18
+ # Essential Dignities Data (from app.py)
19
+ DOMICILES = {
20
+ "Sun": ["Leo"],
21
+ "Moon": ["Cancer"],
22
+ "Mercury": ["Gemini", "Virgo"],
23
+ "Venus": ["Taurus", "Libra"],
24
+ "Mars": ["Aries", "Scorpio"],
25
+ "Jupiter": ["Sagittarius", "Pisces"],
26
+ "Saturn": ["Capricorn", "Aquarius"]
27
+ }
28
+
29
+ EXALTATIONS = {
30
+ "Sun": "Aries",
31
+ "Moon": "Taurus",
32
+ "Mercury": "Virgo",
33
+ "Venus": "Pisces",
34
+ "Mars": "Capricorn",
35
+ "Jupiter": "Cancer",
36
+ "Saturn": "Libra"
37
+ }
38
+
39
+ DETRIMENTS = {
40
+ "Sun": ["Aquarius"],
41
+ "Moon": ["Capricorn"],
42
+ "Mercury": ["Sagittarius", "Pisces"],
43
+ "Venus": ["Aries", "Scorpio"],
44
+ "Mars": ["Taurus", "Libra"],
45
+ "Jupiter": ["Gemini", "Virgo"],
46
+ "Saturn": ["Cancer", "Leo"]
47
+ }
48
+
49
+ FALLS = {
50
+ "Sun": ["Libra"],
51
+ "Moon": ["Scorpio"],
52
+ "Mercury": ["Pisces"],
53
+ "Venus": ["Virgo"],
54
+ "Mars": ["Cancer"],
55
+ "Jupiter": ["Capricorn"],
56
+ "Saturn": ["Aries"]
57
+ }
58
+
59
+ BOUNDS = {
60
+ "Aries": [
61
+ {"start": 0, "end": 6, "ruler": "Jupiter"},
62
+ {"start": 6, "end": 12, "ruler": "Venus"},
63
+ {"start": 12, "end": 20, "ruler": "Mercury"},
64
+ {"start": 20, "end": 25, "ruler": "Mars"},
65
+ {"start": 25, "end": 30, "ruler": "Saturn"}
66
+ ],
67
+ "Taurus": [
68
+ {"start": 0, "end": 8, "ruler": "Venus"},
69
+ {"start": 8, "end": 14, "ruler": "Mercury"},
70
+ {"start": 14, "end": 22, "ruler": "Jupiter"},
71
+ {"start": 22, "end": 27, "ruler": "Saturn"},
72
+ {"start": 27, "end": 30, "ruler": "Mars"}
73
+ ],
74
+ # Add remaining signs...
75
+ }
76
+
77
+ def calculate_essential_dignity(
78
+ self,
79
+ planet: str,
80
+ sign: str,
81
+ degree: float,
82
+ is_day_chart: bool = True
83
+ ) -> Dict:
84
+ """
85
+ Calculate essential dignity for a planet
86
+
87
+ Args:
88
+ planet: Planet name (Sun, Moon, Mercury, Venus, Mars, Jupiter, Saturn)
89
+ sign: Zodiac sign
90
+ degree: Degree within sign (0-30)
91
+ is_day_chart: Whether it's a day or night chart
92
+
93
+ Returns:
94
+ Complete dignity assessment with score and interpretation
95
+ """
96
+ dignity_score = 0
97
+ dignities = []
98
+ debilities = []
99
+
100
+ # Check domicile (+5)
101
+ if sign in self.DOMICILES.get(planet, []):
102
+ dignity_score += 5
103
+ dignities.append("Domicile (+5)")
104
+
105
+ # Check exaltation (+4)
106
+ if sign == self.EXALTATIONS.get(planet):
107
+ dignity_score += 4
108
+ dignities.append("Exaltation (+4)")
109
+
110
+ # Check detriment (-5)
111
+ if sign in self.DETRIMENTS.get(planet, []):
112
+ dignity_score -= 5
113
+ debilities.append("Detriment (-5)")
114
+
115
+ # Check fall (-4)
116
+ if sign in self.FALLS.get(planet, []):
117
+ dignity_score -= 4
118
+ debilities.append("Fall (-4)")
119
+
120
+ # Determine planetary condition
121
+ if dignity_score >= 4:
122
+ condition = "Very Strong"
123
+ elif dignity_score >= 2:
124
+ condition = "Strong"
125
+ elif dignity_score >= -1:
126
+ condition = "Moderate/Peregrine"
127
+ elif dignity_score >= -4:
128
+ condition = "Weak/Debilitated"
129
+ else:
130
+ condition = "Very Weak"
131
+
132
+ return {
133
+ "planet": planet,
134
+ "sign": sign,
135
+ "degree": degree,
136
+ "chart_type": "Day Chart" if is_day_chart else "Night Chart",
137
+ "dignity_score": dignity_score,
138
+ "dignities": dignities,
139
+ "debilities": debilities,
140
+ "condition": condition,
141
+ "interpretation": self._get_dignity_interpretation(planet, sign, condition),
142
+ "source": "HERMES Local MCP v1.0"
143
+ }
144
+
145
+ def _get_dignity_interpretation(self, planet: str, sign: str, condition: str) -> str:
146
+ """Generate interpretation text"""
147
+ if condition == "Very Strong":
148
+ return f"{planet} in {sign} is very strong, able to express its significations powerfully and effectively."
149
+ elif condition == "Strong":
150
+ return f"{planet} in {sign} is well-placed and can express its nature with strength."
151
+ elif condition == "Moderate/Peregrine":
152
+ return f"{planet} in {sign} is peregrine (wandering), having neutral strength without major dignities or debilities."
153
+ elif condition == "Weak/Debilitated":
154
+ return f"{planet} in {sign} is debilitated, struggling to express its significations effectively."
155
+ else:
156
+ return f"{planet} in {sign} is severely debilitated, facing major obstacles in expressing its nature."
157
+
158
+ def calculate_annual_profection(
159
+ self,
160
+ birth_date: str,
161
+ current_age: int
162
+ ) -> Dict:
163
+ """
164
+ Calculate annual profection for a given age
165
+
166
+ Args:
167
+ birth_date: Birth date in YYYY-MM-DD format
168
+ current_age: Current age in years
169
+
170
+ Returns:
171
+ Profected house and time-lord information
172
+ """
173
+ # Profections cycle through 12 houses
174
+ profected_house = (current_age % 12) + 1
175
+
176
+ house_themes = {
177
+ 1: "Self, body, vitality, new beginnings",
178
+ 2: "Resources, possessions, values, income",
179
+ 3: "Siblings, communication, short journeys, learning",
180
+ 4: "Home, family, foundations, parents",
181
+ 5: "Creativity, children, pleasure, romance",
182
+ 6: "Health, service, daily work, obstacles",
183
+ 7: "Partnerships, marriage, open enemies",
184
+ 8: "Death, inheritance, transformation, others' resources",
185
+ 9: "Philosophy, long journeys, higher education, religion",
186
+ 10: "Career, public reputation, status, achievements",
187
+ 11: "Friends, hopes, wishes, groups, benefactors",
188
+ 12: "Isolation, hidden matters, spirituality, undoing"
189
+ }
190
+
191
+ return {
192
+ "birth_date": birth_date,
193
+ "current_age": current_age,
194
+ "profected_house": profected_house,
195
+ "house_theme": house_themes.get(profected_house, "Unknown"),
196
+ "interpretation": f"At age {current_age}, the profection activates the {profected_house}th house. This year's themes center around: {house_themes.get(profected_house, 'Unknown')}.",
197
+ "lord_of_year": f"The ruler of the {profected_house}th house is the Lord of the Year",
198
+ "source": "HERMES Local MCP v1.0"
199
+ }
200
+
201
+ def calculate_lot_of_fortune(
202
+ self,
203
+ asc_degree: float,
204
+ sun_degree: float,
205
+ moon_degree: float,
206
+ is_day_chart: bool = True
207
+ ) -> Dict:
208
+ """
209
+ Calculate Lot of Fortune
210
+
211
+ Formula:
212
+ - Day chart: Ascendant + Moon - Sun
213
+ - Night chart: Ascendant + Sun - Moon
214
+
215
+ Args:
216
+ asc_degree: Ascendant in absolute degrees (0-360)
217
+ sun_degree: Sun position in absolute degrees
218
+ moon_degree: Moon position in absolute degrees
219
+ is_day_chart: Whether it's a day chart
220
+
221
+ Returns:
222
+ Lot of Fortune position and interpretation
223
+ """
224
+ if is_day_chart:
225
+ fortune = (asc_degree + moon_degree - sun_degree) % 360
226
+ formula = "ASC + Moon - Sun"
227
+ else:
228
+ fortune = (asc_degree + sun_degree - moon_degree) % 360
229
+ formula = "ASC + Sun - Moon"
230
+
231
+ # Convert to sign and degree
232
+ sign_num = int(fortune / 30)
233
+ degree = fortune % 30
234
+
235
+ signs = ["Aries", "Taurus", "Gemini", "Cancer", "Leo", "Virgo",
236
+ "Libra", "Scorpio", "Sagittarius", "Capricorn", "Aquarius", "Pisces"]
237
+ sign = signs[sign_num]
238
+
239
+ return {
240
+ "lot": "Fortune",
241
+ "position": f"{degree:.2f}° {sign}",
242
+ "absolute_degree": fortune,
243
+ "formula": formula,
244
+ "chart_type": "Day Chart" if is_day_chart else "Night Chart",
245
+ "interpretation": f"The Lot of Fortune represents the body, health, and material fortune. Placed at {degree:.2f}° {sign}, it shows where fortune and prosperity manifest.",
246
+ "source": "HERMES Local MCP v1.0"
247
+ }
248
+
249
+ def get_technique_explanation(self, technique: str) -> Dict:
250
+ """
251
+ Get educational explanation for a technique
252
+
253
+ Args:
254
+ technique: Name of technique (dignities, profections, lots, etc.)
255
+
256
+ Returns:
257
+ Educational content about the technique
258
+ """
259
+ explanations = {
260
+ "essential_dignities": {
261
+ "name": "Essential Dignities",
262
+ "summary": "A system for evaluating planetary strength based on zodiacal position",
263
+ "description": """Essential dignities measure how well-placed a planet is in the zodiac.
264
+ The system includes five major categories:
265
+
266
+ 1. **Domicile** (+5): Planet in its home sign
267
+ 2. **Exaltation** (+4): Planet in its sign of greatest strength
268
+ 3. **Triplicity** (+3): Planet ruling the element (day/night)
269
+ 4. **Bound/Term** (+2): Planet ruling a specific degree range
270
+ 5. **Decan/Face** (+1): Planet ruling a 10-degree section
271
+
272
+ Debilities are the opposites:
273
+ - **Detriment** (-5): Opposite of domicile
274
+ - **Fall** (-4): Opposite of exaltation
275
+
276
+ A planet's dignity score indicates its ability to act effectively.""",
277
+ "source": "Ptolemy's Tetrabiblos, Vettius Valens",
278
+ "period": "Hellenistic (1st-7th century CE)"
279
+ },
280
+ "annual_profections": {
281
+ "name": "Annual Profections",
282
+ "summary": "A timing technique that activates different life areas each year",
283
+ "description": """Annual profections move the Ascendant forward one house per year of life.
284
+
285
+ The technique works by:
286
+ 1. Starting at the Ascendant at birth (age 0)
287
+ 2. Moving one house forward each birthday
288
+ 3. The profected house becomes active that year
289
+ 4. The ruler of that house becomes 'Lord of the Year'
290
+
291
+ This creates a 12-year cycle where each house theme is activated in sequence.
292
+ The Lord of the Year becomes especially important for predicting events.""",
293
+ "source": "Vettius Valens, Firmicus Maternus",
294
+ "period": "Hellenistic (2nd century CE)"
295
+ },
296
+ "lots": {
297
+ "name": "Lots/Parts",
298
+ "summary": "Calculated sensitive points derived from planet positions",
299
+ "description": """Lots (Arabic Parts) are sensitive points calculated from planetary positions.
300
+
301
+ The most important lot is the **Lot of Fortune**:
302
+ - Day chart: ASC + Moon - Sun
303
+ - Night chart: ASC + Sun - Moon
304
+
305
+ Other important lots include:
306
+ - **Lot of Spirit**: Opposite calculation to Fortune
307
+ - **Lot of Eros**: Related to desire and love
308
+ - **Lot of Necessity**: Related to constraint and obligation
309
+
310
+ Lots represent abstract topics and show where certain life themes manifest.""",
311
+ "source": "Vettius Valens, Paulus Alexandrinus",
312
+ "period": "Hellenistic (1st-4th century CE)"
313
+ }
314
+ }
315
+
316
+ result = explanations.get(technique.lower().replace(" ", "_"), {
317
+ "name": technique,
318
+ "summary": "Technique not found in database",
319
+ "description": "No explanation available for this technique.",
320
+ "source": "Unknown",
321
+ "period": "Unknown"
322
+ })
323
+
324
+ result["requested_technique"] = technique
325
+ result["server"] = "HERMES Local MCP v1.0"
326
+
327
+ return result
328
+
329
+
330
+ def get_mcp_tools() -> List[Dict]:
331
+ """Return list of available HERMES Local MCP tools"""
332
+ return [
333
+ {
334
+ "name": "calculate_essential_dignity",
335
+ "description": "Calculate essential dignity score for a planet in a sign",
336
+ "parameters": {
337
+ "planet": "string (Sun, Moon, Mercury, Venus, Mars, Jupiter, Saturn)",
338
+ "sign": "string (Aries, Taurus, Gemini, etc.)",
339
+ "degree": "float (0-30)",
340
+ "is_day_chart": "boolean (optional, default True)"
341
+ },
342
+ "returns": "Dignity score, condition, and interpretation"
343
+ },
344
+ {
345
+ "name": "calculate_annual_profection",
346
+ "description": "Calculate annual profection for a given age",
347
+ "parameters": {
348
+ "birth_date": "string (YYYY-MM-DD)",
349
+ "current_age": "integer"
350
+ },
351
+ "returns": "Profected house and Lord of the Year information"
352
+ },
353
+ {
354
+ "name": "calculate_lot_of_fortune",
355
+ "description": "Calculate the Lot of Fortune position",
356
+ "parameters": {
357
+ "asc_degree": "float (0-360)",
358
+ "sun_degree": "float (0-360)",
359
+ "moon_degree": "float (0-360)",
360
+ "is_day_chart": "boolean (optional, default True)"
361
+ },
362
+ "returns": "Lot position and interpretation"
363
+ },
364
+ {
365
+ "name": "get_technique_explanation",
366
+ "description": "Get educational explanation for a traditional technique",
367
+ "parameters": {
368
+ "technique": "string (essential_dignities, annual_profections, lots, etc.)"
369
+ },
370
+ "returns": "Educational content with historical sources"
371
+ }
372
+ ]
373
+
374
+
375
+ # Main entry point for MCP server
376
+ if __name__ == "__main__":
377
+ if len(sys.argv) > 1 and sys.argv[1] == "tools":
378
+ print(json.dumps(get_mcp_tools(), indent=2))
379
+ else:
380
+ print("=" * 70)
381
+ print("HERMES Local MCP Server v1.0")
382
+ print("=" * 70)
383
+ print("\nAvailable Tools:")
384
+ print(json.dumps(get_mcp_tools(), indent=2))
385
+
386
+ # Test examples
387
+ print("\n" + "=" * 70)
388
+ print("TEST: Essential Dignity - Venus in Aries")
389
+ print("=" * 70)
390
+
391
+ server = HermesLocalMCP()
392
+ result = server.calculate_essential_dignity("Venus", "Aries", 8.5, True)
393
+ print(json.dumps(result, indent=2))
394
+
395
+ print("\n" + "=" * 70)
396
+ print("TEST: Annual Profection - Age 35")
397
+ print("=" * 70)
398
+
399
+ result = server.calculate_annual_profection("1990-01-15", 35)
400
+ print(json.dumps(result, indent=2))
401
+
402
+ print("\n" + "=" * 70)
403
+ print("TEST: Lot of Fortune")
404
+ print("=" * 70)
405
+
406
+ result = server.calculate_lot_of_fortune(120, 295, 210, True)
407
+ print(json.dumps(result, indent=2))