@openephemeris/mcp-server 3.13.9 → 3.13.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/README.md +2 -2
  2. package/config/dev-allowlist.json +28 -4
  3. package/dist/index.js +45 -0
  4. package/dist/oauth/dcr.d.ts +11 -0
  5. package/dist/oauth/dcr.js +49 -0
  6. package/dist/oauth/discovery.d.ts +11 -0
  7. package/dist/oauth/discovery.js +40 -0
  8. package/dist/oauth/pkce.d.ts +18 -0
  9. package/dist/oauth/pkce.js +34 -0
  10. package/dist/oauth/rate-limit.d.ts +20 -0
  11. package/dist/oauth/rate-limit.js +65 -0
  12. package/dist/oauth/store.d.ts +68 -0
  13. package/dist/oauth/store.js +247 -0
  14. package/dist/oauth/supabase-jwt.d.ts +39 -0
  15. package/dist/oauth/supabase-jwt.js +194 -0
  16. package/dist/oauth/token.d.ts +21 -0
  17. package/dist/oauth/token.js +213 -0
  18. package/dist/prompts.js +171 -159
  19. package/dist/server-sse.js +134 -36
  20. package/dist/tools/apps/bazi-app.d.ts +23 -0
  21. package/dist/tools/apps/bazi-app.js +224 -0
  22. package/dist/tools/apps/bi-wheel-app.d.ts +14 -7
  23. package/dist/tools/apps/bi-wheel-app.js +293 -108
  24. package/dist/tools/apps/bodygraph-app.js +38 -3
  25. package/dist/tools/apps/moon-phase-app.d.ts +19 -0
  26. package/dist/tools/apps/moon-phase-app.js +190 -0
  27. package/dist/tools/apps/transit-timeline-app.d.ts +20 -0
  28. package/dist/tools/apps/transit-timeline-app.js +243 -0
  29. package/dist/tools/apps/vedic-chart-app.d.ts +17 -0
  30. package/dist/tools/apps/vedic-chart-app.js +226 -0
  31. package/dist/tools/index.js +4 -0
  32. package/dist/tools/specialized/acg.js +2 -2
  33. package/dist/tools/specialized/bazi.js +367 -44
  34. package/dist/tools/specialized/bi_wheel.js +1 -1
  35. package/dist/tools/specialized/chart_wheel.js +1 -1
  36. package/dist/tools/specialized/comparative.js +4 -4
  37. package/dist/tools/specialized/eclipse.js +1 -1
  38. package/dist/tools/specialized/electional.js +4 -4
  39. package/dist/tools/specialized/ephemeris_core.js +2 -2
  40. package/dist/tools/specialized/ephemeris_extended.js +8 -8
  41. package/dist/tools/specialized/hd_bodygraph.js +1 -1
  42. package/dist/tools/specialized/hd_cycles.js +2 -2
  43. package/dist/tools/specialized/hd_group.js +2 -2
  44. package/dist/tools/specialized/human_design.js +1 -1
  45. package/dist/tools/specialized/moon.js +2 -2
  46. package/dist/tools/specialized/natal.js +1 -1
  47. package/dist/tools/specialized/progressed.js +1 -1
  48. package/dist/tools/specialized/relocation.js +1 -1
  49. package/dist/tools/specialized/returns.js +3 -3
  50. package/dist/tools/specialized/synastry.js +1 -1
  51. package/dist/tools/specialized/transits.js +1 -1
  52. package/dist/tools/specialized/vedic.js +1 -1
  53. package/dist/tools/specialized/venus_star_points.js +6 -6
  54. package/dist/ui/bazi.html +213 -0
  55. package/dist/ui/bi-wheel.html +762 -489
  56. package/dist/ui/bodygraph.html +1788 -1649
  57. package/dist/ui/chart-wheel.html +1772 -1593
  58. package/dist/ui/moon-phase.html +6758 -0
  59. package/dist/ui/transit-timeline.html +6835 -0
  60. package/dist/ui/vedic-chart.html +210 -0
  61. package/package.json +2 -2
@@ -0,0 +1,226 @@
1
+ /**
2
+ * vedic-chart-app.ts — MCP App tool registration for the Vedic Jyotish Chart Explorer.
3
+ *
4
+ * Registers 1 tool:
5
+ * • explore_vedic_chart — primary entry point [model + app visible]
6
+ * Calls POST /vedic/chart and returns a data payload + UI resource URI
7
+ * so Claude Desktop can render the interactive South Indian Rashi grid.
8
+ *
9
+ * Also exports resource helpers (getVedicChartBundle, etc.) for use in
10
+ * server-sse.ts resource listing and reading.
11
+ */
12
+ import fs from "node:fs";
13
+ import path from "node:path";
14
+ import { fileURLToPath } from "node:url";
15
+ import { registerTool, SERVER_VERSION } from "../index.js";
16
+ import { getActiveClient } from "../../backend/client.js";
17
+ // ── Constants ─────────────────────────────────────────────────────────────────
18
+ export const VEDIC_CHART_RESOURCE_URI = "ui://openephemeris/vedic-chart";
19
+ export const VEDIC_CHART_MIME_TYPE = "text/html;profile=mcp-app";
20
+ const here = path.dirname(fileURLToPath(import.meta.url));
21
+ const BUNDLE_PATHS = [
22
+ path.resolve(here, "..", "..", "..", "dist", "ui", "vedic-chart.html"),
23
+ ];
24
+ function findBundlePath() {
25
+ for (const p of BUNDLE_PATHS) {
26
+ if (fs.existsSync(p))
27
+ return p;
28
+ }
29
+ return null;
30
+ }
31
+ let cachedBundle = null;
32
+ /** Read the pre-built HTML bundle. Returns null if not yet built. */
33
+ export function getVedicChartBundle() {
34
+ if (cachedBundle)
35
+ return cachedBundle;
36
+ const bundlePath = findBundlePath();
37
+ if (!bundlePath)
38
+ return null;
39
+ try {
40
+ cachedBundle = fs.readFileSync(bundlePath, "utf-8");
41
+ return cachedBundle;
42
+ }
43
+ catch {
44
+ return null;
45
+ }
46
+ }
47
+ /** Reset cache (useful in dev watch mode or tests). */
48
+ export function clearVedicChartBundleCache() {
49
+ cachedBundle = null;
50
+ }
51
+ function parseVedicArgs(args) {
52
+ const { datetime, latitude, longitude, ayanamsa } = args;
53
+ if (!datetime) {
54
+ throw new Error("datetime is required. Provide an ISO 8601 datetime in UTC, " +
55
+ "e.g. datetime='1987-07-15T14:30:00Z'.");
56
+ }
57
+ if (latitude == null || longitude == null) {
58
+ throw new Error("latitude and longitude are required for Vedic chart calculation. " +
59
+ "Example: latitude=28.6, longitude=77.2 (New Delhi).");
60
+ }
61
+ return { datetime, latitude, longitude, ayanamsa: ayanamsa || undefined };
62
+ }
63
+ // ── Summary builder ──────────────────────────────────────────────────────────
64
+ // Convert a sidereal longitude (0–360°) to the Western sign name
65
+ function lonToSignName(lon) {
66
+ const SIGNS = [
67
+ "Aries", "Taurus", "Gemini", "Cancer", "Leo", "Virgo",
68
+ "Libra", "Scorpio", "Sagittarius", "Capricorn", "Aquarius", "Pisces",
69
+ ];
70
+ const idx = Math.floor(((lon % 360) + 360) % 360 / 30) % 12;
71
+ return SIGNS[idx];
72
+ }
73
+ function buildVedicSummary(data) {
74
+ const planets = data.planets || [];
75
+ const metadata = data.metadata || {};
76
+ // lagna is a degree float from the backend — convert to sign name
77
+ const lagnaSign = typeof metadata.lagna === "number"
78
+ ? lonToSignName(metadata.lagna)
79
+ : metadata.lagna || "unknown";
80
+ // Backend returns "ayanamsha" (with extra h) — normalise
81
+ const ayanamsa = metadata.ayanamsa || metadata.ayanamsha || "Lahiri";
82
+ const ayanamsaVal = metadata.ayanamsa_value != null
83
+ ? " (" + metadata.ayanamsa_value.toFixed(2) + "°)"
84
+ : metadata.correction != null
85
+ ? " (" + metadata.correction.toFixed(2) + "°)"
86
+ : "";
87
+ let summary = "**Vedic Jyotish Chart** — Lagna: **" + lagnaSign + "** · Ayanamsa: " +
88
+ ayanamsa + ayanamsaVal + "\n\n";
89
+ // Planet placement table
90
+ if (planets.length > 0) {
91
+ summary += "| Planet | Rashi | Degree | Nakshatra | Pada |\n";
92
+ summary += "|--------|-------|--------|-----------|------|\n";
93
+ for (const p of planets) {
94
+ const retroMark = p.is_retrograde ? " ℞" : "";
95
+ summary +=
96
+ "| " + capFirst(String(p.planet)) + retroMark +
97
+ " | " + (p.rashi_western || p.rashi || "?") +
98
+ " | " + (typeof p.rashi_degree === "number" ? p.rashi_degree.toFixed(2) + "°" : "?") +
99
+ " | " + (p.nakshatra?.name || "?") +
100
+ " | " + (p.nakshatra?.pada || "?") +
101
+ " |\n";
102
+ }
103
+ summary += "\n";
104
+ }
105
+ summary += "Click on any Rashi cell to explore the planets placed there.";
106
+ return summary;
107
+ }
108
+ function capFirst(s) {
109
+ return s.charAt(0).toUpperCase() + s.slice(1);
110
+ }
111
+ // ── Tool: explore_vedic_chart ─────────────────────────────────────────────────
112
+ registerTool({
113
+ name: "explore_vedic_chart",
114
+ description: "Generate an interactive Vedic Jyotish (South Indian) Rashi chart visualization.\n\n" +
115
+ "Renders a 4×4 fixed-sign grid with:\n" +
116
+ " • All nine Jyotish planets (Sun through Ketu) placed in their Rashi\n" +
117
+ " • Lagna (Ascendant) cell marked with a gold diagonal\n" +
118
+ " • Sanskrit/Devanagari sign labels toggle\n" +
119
+ " • Click any Rashi cell → detailed planet info drawer\n" +
120
+ " (degree, Nakshatra, Pada, lord, Navamsa sign, dignity)\n" +
121
+ " • Ask Claude buttons for Lagna, Moon/Nakshatra, and full chart interpretation\n" +
122
+ " • Ayanamsa system displayed (Lahiri by default)\n\n" +
123
+ "CREDIT COST: 1 credit.\n\n" +
124
+ "Use this for a rich, interactive Vedic chart experience in MCP Apps-capable hosts " +
125
+ "(Claude Desktop). Falls back to a markdown table summary in other hosts.",
126
+ inputSchema: {
127
+ type: "object",
128
+ properties: {
129
+ datetime: {
130
+ type: "string",
131
+ description: "Birth date and time as ISO 8601, e.g. '1987-07-15T14:30:00Z'. " +
132
+ "Always include time when known — it determines the Lagna (Ascendant).",
133
+ },
134
+ latitude: {
135
+ type: "number",
136
+ description: "Birth latitude in decimal degrees, e.g. 28.6 for New Delhi.",
137
+ },
138
+ longitude: {
139
+ type: "number",
140
+ description: "Birth longitude in decimal degrees, e.g. 77.2 for New Delhi.",
141
+ },
142
+ ayanamsa: {
143
+ type: "string",
144
+ enum: ["lahiri", "fagan_bradley", "krishnamurti", "raman", "yukteshwar"],
145
+ description: "Ayanamsa system for sidereal calculation. " +
146
+ "Options: 'lahiri' (default, most common), 'raman', 'krishnamurti', 'fagan_bradley', 'yukteshwar'.",
147
+ },
148
+ },
149
+ required: ["datetime", "latitude", "longitude"],
150
+ additionalProperties: false,
151
+ },
152
+ annotations: {
153
+ title: "Interactive Vedic Jyotish Chart",
154
+ readOnlyHint: true,
155
+ destructiveHint: false,
156
+ idempotentHint: true,
157
+ openWorldHint: false,
158
+ },
159
+ _meta: {
160
+ ui: {
161
+ resourceUri: VEDIC_CHART_RESOURCE_URI,
162
+ visibility: ["model", "app"],
163
+ },
164
+ },
165
+ handler: async (args) => {
166
+ const { datetime, latitude, longitude, ayanamsa } = parseVedicArgs(args);
167
+ const client = getActiveClient();
168
+ // Backend field is datetime_utc (matches vedic.ts specialized tool)
169
+ const body = {
170
+ datetime_utc: datetime,
171
+ latitude,
172
+ longitude,
173
+ };
174
+ if (ayanamsa)
175
+ body.ayanamsa = ayanamsa;
176
+ const result = await client.request("POST", "/vedic/chart", { data: body });
177
+ const rawMeta = result.metadata || {};
178
+ // Backend returns lagna as a degree float (e.g. 213.4) but the iframe
179
+ // expects a sign name string (e.g. "Scorpio") for cell matching.
180
+ const lagnaRaw = rawMeta.lagna;
181
+ const lagnaSign = typeof lagnaRaw === "number"
182
+ ? lonToSignName(lagnaRaw)
183
+ : lagnaRaw || "";
184
+ // Backend returns "ayanamsha" (extra h) — normalise to "ayanamsa".
185
+ const ayanamsaName = rawMeta.ayanamsa || rawMeta.ayanamsha || "Lahiri";
186
+ const normalizedMeta = {
187
+ ...rawMeta,
188
+ lagna: lagnaSign,
189
+ ayanamsa: ayanamsaName,
190
+ // Expose correction as ayanamsa_value so the iframe can show the degree
191
+ ayanamsa_value: rawMeta.ayanamsa_value ?? rawMeta.correction ?? null,
192
+ };
193
+ // Build a Set from the retrograde_planets list the Go handler populated.
194
+ const retrogradeList = Array.isArray(rawMeta.retrograde_planets)
195
+ ? rawMeta.retrograde_planets
196
+ : [];
197
+ const retrogradeSet = new Set(retrogradeList);
198
+ const uiPayload = {
199
+ // Stamp is_retrograde on each planet using the retrograde_planets list
200
+ // from metadata — the Go struct has no such field, so it lives in metadata.
201
+ planets: (result.planets || []).map((p) => ({
202
+ ...p,
203
+ is_retrograde: retrogradeSet.has(String(p.planet)),
204
+ })),
205
+ metadata: normalizedMeta,
206
+ server_version: SERVER_VERSION,
207
+ };
208
+ const summary = buildVedicSummary(uiPayload);
209
+ const bundleAvailable = Boolean(getVedicChartBundle());
210
+ if (bundleAvailable) {
211
+ return {
212
+ content: [
213
+ { type: "text", text: summary },
214
+ // Second text block is injected as window.__VEDIC_CHART_DATA__ by ext-apps SDK
215
+ { type: "text", text: JSON.stringify(uiPayload) },
216
+ ],
217
+ _meta: {
218
+ "ui/resourceUri": VEDIC_CHART_RESOURCE_URI,
219
+ ui: { resourceUri: VEDIC_CHART_RESOURCE_URI },
220
+ },
221
+ };
222
+ }
223
+ // Fallback: text-only table
224
+ return { content: [{ type: "text", text: summary }] };
225
+ },
226
+ });
@@ -74,6 +74,10 @@ export async function initTools(profile) {
74
74
  await import("./apps/chart-wheel-app.js");
75
75
  await import("./apps/bodygraph-app.js");
76
76
  await import("./apps/bi-wheel-app.js");
77
+ await import("./apps/transit-timeline-app.js");
78
+ await import("./apps/moon-phase-app.js");
79
+ await import("./apps/bazi-app.js");
80
+ await import("./apps/vedic-chart-app.js");
77
81
  await import("./apps/location-tools.js");
78
82
  }
79
83
  }
@@ -54,7 +54,7 @@ registerTool({
54
54
  required: ["birth_datetime", "birth_latitude", "birth_longitude"],
55
55
  additionalProperties: false,
56
56
  },
57
- annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true },
57
+ annotations: { title: "Astrocartography Lines", readOnlyHint: true, destructiveHint: false, idempotentHint: true },
58
58
  handler: async (args) => {
59
59
  validateRequired(args, ["birth_datetime", "birth_latitude", "birth_longitude"]);
60
60
  const body = {
@@ -147,7 +147,7 @@ registerTool({
147
147
  required: ["birth_datetime", "birth_latitude", "birth_longitude", "query_latitude", "query_longitude"],
148
148
  additionalProperties: false,
149
149
  },
150
- annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true },
150
+ annotations: { title: "Astrocartography Location Hits", readOnlyHint: true, destructiveHint: false, idempotentHint: true },
151
151
  handler: async (args) => {
152
152
  validateRequired(args, ["birth_datetime", "birth_latitude", "birth_longitude", "query_latitude", "query_longitude"]);
153
153
  const body = {