@openephemeris/mcp-server 3.13.3 → 3.13.5

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.
@@ -17,7 +17,7 @@
17
17
  import fs from "node:fs";
18
18
  import path from "node:path";
19
19
  import { fileURLToPath } from "node:url";
20
- import { registerTool } from "../index.js";
20
+ import { registerTool, SERVER_VERSION } from "../index.js";
21
21
  import { getActiveClient } from "../../backend/client.js";
22
22
  // ── Constants ─────────────────────────────────────────────────────────────────
23
23
  export const BI_WHEEL_RESOURCE_URI = "ui://openephemeris/bi-wheel";
@@ -303,7 +303,7 @@ registerTool({
303
303
  return {
304
304
  content: [
305
305
  { type: "text", text: summary },
306
- { type: "text", text: JSON.stringify(payload) },
306
+ { type: "text", text: JSON.stringify({ ...payload, server_version: SERVER_VERSION }) },
307
307
  {
308
308
  type: "resource",
309
309
  resource: {
@@ -17,7 +17,7 @@
17
17
  import fs from "node:fs";
18
18
  import path from "node:path";
19
19
  import { fileURLToPath } from "node:url";
20
- import { registerTool } from "../index.js";
20
+ import { registerTool, SERVER_VERSION } from "../index.js";
21
21
  import { getActiveClient } from "../../backend/client.js";
22
22
  // ── Constants ─────────────────────────────────────────────────────────────
23
23
  export const BODYGRAPH_RESOURCE_URI = "ui://openephemeris/bodygraph";
@@ -78,6 +78,7 @@ const CENTER_NAME_ALIASES = {
78
78
  "heart": "Heart",
79
79
  "will": "Heart",
80
80
  "solar plexus": "Solar Plexus",
81
+ "solar_plexus": "Solar Plexus",
81
82
  "emotional": "Solar Plexus",
82
83
  "sp": "Solar Plexus",
83
84
  "spleen": "Spleen",
@@ -114,7 +115,7 @@ function buildHdModelPayload(data, birthParams) {
114
115
  const authority = String(data.authority ?? data.inner_authority ?? "");
115
116
  const definition = String(data.definition ?? data.definition_type ?? "");
116
117
  const incarnation_cross = String(data.incarnation_cross ?? data.cross ?? "");
117
- // Normalize centers — API may return array or keyed object
118
+ // Normalize centers API may return array or keyed object
118
119
  let centers = [];
119
120
  const rawCenters = data.centers;
120
121
  if (Array.isArray(rawCenters)) {
@@ -143,8 +144,16 @@ function buildHdModelPayload(data, birthParams) {
143
144
  return 1;
144
145
  return a.name.localeCompare(b.name);
145
146
  });
146
- // Compact active gate list — just gate numbers, no planets
147
- const rawGates = data.active_gates ?? data.gates ?? data.defined_gates ?? [];
147
+ // Active gates from activations array (deduplicated gate numbers across all planets)
148
+ // API returns activations at top level and nested under personality/design
149
+ const allActivations = [
150
+ ...(data.activations ?? []),
151
+ ...(data.personality?.activations ?? []),
152
+ ...(data.design?.activations ?? []),
153
+ ];
154
+ const rawGates = allActivations.length > 0
155
+ ? allActivations
156
+ : (data.active_gates ?? data.gates ?? data.defined_gates ?? []);
148
157
  let active_gates = [];
149
158
  if (Array.isArray(rawGates)) {
150
159
  active_gates = rawGates
@@ -156,8 +165,8 @@ function buildHdModelPayload(data, birthParams) {
156
165
  .filter((n, i, arr) => arr.indexOf(n) === i) // unique
157
166
  .sort((a, b) => a - b);
158
167
  }
159
- // Active channels as "gate1-gate2" strings
160
- const rawChannels = data.active_channels ?? data.channels ?? data.defined_channels ?? [];
168
+ // Active channels API returns objects with .id ("11-56"), .gates[], or .gate1/.gate2
169
+ const rawChannels = (data.channels ?? data.active_channels ?? data.defined_channels ?? []);
161
170
  let active_channels = [];
162
171
  if (Array.isArray(rawChannels)) {
163
172
  active_channels = rawChannels.map((ch) => {
@@ -168,9 +177,9 @@ function buildHdModelPayload(data, birthParams) {
168
177
  return g1 != null && g2 != null ? `${g1}-${g2}` : String(ch);
169
178
  });
170
179
  }
171
- // Personality / Design gate extraction (API may return multiple field name variants)
172
- const rawP = data.personality_gates ?? data.personality ?? data.conscious_gates ?? [];
173
- const rawD = data.design_gates ?? data.unconscious_gates ?? [];
180
+ // Personality / Design gates API nests them under personality.activations / design.activations
181
+ const rawP = data.personality?.activations ?? data.personality_gates ?? data.conscious_gates ?? [];
182
+ const rawD = data.design?.activations ?? data.design_gates ?? data.unconscious_gates ?? [];
174
183
  const personality_gates = [...new Set(extractGateNums(rawP))].sort((a, b) => a - b);
175
184
  const design_gates = [...new Set(extractGateNums(rawD))].sort((a, b) => a - b);
176
185
  return {
@@ -263,8 +272,10 @@ registerTool({
263
272
  const chartData = await client.request("POST", "/human-design/chart", {
264
273
  data: body,
265
274
  });
266
- // Build payload once \u2014 summary and model data both derive from the same object
267
- const modelPayload = buildHdModelPayload(chartData, {
275
+ // API returns { chart: {...}, metadata: {...} } unwrap the inner chart object
276
+ const chart = chartData.chart ?? chartData;
277
+ // Build payload once — summary and model data both derive from the same object
278
+ const modelPayload = buildHdModelPayload(chart, {
268
279
  datetime,
269
280
  location: args.location ?? null,
270
281
  });
@@ -274,7 +285,7 @@ registerTool({
274
285
  return {
275
286
  content: [
276
287
  { type: "text", text: summary },
277
- { type: "text", text: JSON.stringify(modelPayload) },
288
+ { type: "text", text: JSON.stringify({ ...modelPayload, server_version: SERVER_VERSION }) },
278
289
  {
279
290
  type: "resource",
280
291
  resource: {
@@ -18,7 +18,7 @@
18
18
  import fs from "node:fs";
19
19
  import path from "node:path";
20
20
  import { fileURLToPath } from "node:url";
21
- import { registerTool } from "../index.js";
21
+ import { registerTool, SERVER_VERSION } from "../index.js";
22
22
  import { getActiveClient } from "../../backend/client.js";
23
23
  // ── Constants ─────────────────────────────────────────────────────────────
24
24
  export const CHART_WHEEL_RESOURCE_URI = "ui://openephemeris/chart-wheel";
@@ -181,7 +181,7 @@ registerTool({
181
181
  return {
182
182
  content: [
183
183
  { type: "text", text: summary },
184
- { type: "text", text: JSON.stringify(modelPayload) },
184
+ { type: "text", text: JSON.stringify({ ...modelPayload, server_version: SERVER_VERSION }) },
185
185
  {
186
186
  type: "resource",
187
187
  resource: {
@@ -1,4 +1,6 @@
1
1
  import { z } from "zod";
2
+ /** Resolved from package.json at startup — stamped into all app tool payloads. */
3
+ export declare const SERVER_VERSION: string;
2
4
  export interface ToolDefinition {
3
5
  name: string;
4
6
  description: string;
@@ -1,3 +1,17 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+ /** Resolved from package.json at startup — stamped into all app tool payloads. */
5
+ export const SERVER_VERSION = (() => {
6
+ try {
7
+ const here = path.dirname(fileURLToPath(import.meta.url));
8
+ const raw = fs.readFileSync(path.resolve(here, "..", "..", "package.json"), "utf-8");
9
+ return JSON.parse(raw).version?.trim() ?? "0.0.0-unknown";
10
+ }
11
+ catch {
12
+ return "0.0.0-unknown";
13
+ }
14
+ })();
1
15
  /**
2
16
  * Returns tools that should be exposed to Claude in the ListTools response.
3
17
  * Filters out tools that have visibility restricted to the UI (app-only).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openephemeris/mcp-server",
3
- "version": "3.13.3",
3
+ "version": "3.13.5",
4
4
  "description": "Model Context Protocol server for the Open Ephemeris astronomical computation API",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",