@openephemeris/mcp-server 3.9.3 → 3.10.2

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.
package/CHANGELOG.md CHANGED
@@ -7,8 +7,41 @@ Version numbering follows [Semantic Versioning](https://semver.org/).
7
7
 
8
8
  ---
9
9
 
10
+ ## [3.10.0] — 2026-04-23
11
+
12
+ ### Added
13
+ - **Native visual rendering (Tier 1 MCP App)** — `ephemeris_natal_chart`, `ephemeris_synastry`,
14
+ `human_design_chart`, `ephemeris_progressed_chart`, and `ephemeris_solar_return` now accept
15
+ `include_visual: true` to embed a live chart image directly in the conversation alongside
16
+ the JSON data. A single tool call returns both interpretation data and a rendered chart.
17
+ - **`visual_config` parameter** — optional `{ theme, size }` object on all visual-capable data
18
+ tools. Astrology charts default to `theme: "light"`, HD bodygraphs default to `theme: "dark"`
19
+ (per HD convention). Size range 200–4000 px, default 800.
20
+ - **Dual-content response handler** — `formatToolResponse` in `tools/index.ts` now intercepts
21
+ embedded `VisualResult` objects: base64-encodes raw SVG strings on the fly, emits an MCP image
22
+ block (`{ type: "image" }`) first, then a clean JSON text block with the `visual` key stripped.
23
+ PNG payloads (already base64 from the sidecar) are passed through without double-encoding.
24
+ - **`test/visual-rendering.test.ts`** — 26 new unit tests covering the full visual pipeline:
25
+ SVG encoding, PNG passthrough, dual-block output, key stripping, standalone binary passthrough,
26
+ plain JSON fallthrough, and defensive handling of incomplete `visual` keys.
27
+
28
+ ### Changed
29
+ - `ephemeris_chart_wheel`, `ephemeris_bi_wheel`, and `human_design_bodygraph` (standalone
30
+ visualization tools) now **default to SVG** instead of PNG. This eliminates the `resvg` binary
31
+ dependency that caused runtime environment mismatches in Docker/Fly deployments. PNG remains
32
+ available as an explicit opt-in via `format: "png"`.
33
+ - Tool descriptions for standalone visual tools updated to reflect SVG-first rendering.
34
+
35
+ ### Fixed
36
+ - Chart render failures caused by `resvg` binary not being available in the Node.js MCP
37
+ server runtime environment. SVG is now rendered natively by the Go sidecar with no external
38
+ binary dependencies.
39
+
40
+ ---
41
+
10
42
  ## [3.9.0] — 2026-04-22
11
43
 
44
+
12
45
  ### Added
13
46
  - **Streamable HTTP transport** (`POST/GET/DELETE /mcp`) — implements the MCP 2025-11-25
14
47
  specification. New integrations (Smithery, cursor, Claude Web) should prefer
package/README.md CHANGED
@@ -355,8 +355,8 @@ Generated by `npm run sync:readme` from `config/dev-allowlist.json` and the live
355
355
 
356
356
  - Allowlisted operations: **23**
357
357
  - Methods: `GET=4`, `POST=19`, `PUT=0`, `PATCH=0`, `DELETE=0`
358
- - Registered tools (`OPENEPHEMERIS_PROFILE=dev`): **52**
359
- - Typed tools: `acg_hits`, `acg_power_lines`, `auth_login`, `auth_logout`, `auth_status`, `chinese_bazi`, `dev_call`, `dev_list_allowed`, `electional_aspect_search`, `electional_moment_analysis`, `electional_station_tracker`, `ephemeris_angles_points`, `ephemeris_aspect_check`, `ephemeris_bi_wheel`, `ephemeris_chart_wheel`, `ephemeris_composite`, `ephemeris_composite_midpoint`, `ephemeris_dignities`, `ephemeris_electional`, `ephemeris_fixed_stars`, `ephemeris_hermetic_lots`, `ephemeris_house_cusps`, `ephemeris_lunar_return`, `ephemeris_midpoints`, `ephemeris_moon_phase`, `ephemeris_natal_batch`, `ephemeris_natal_chart`, `ephemeris_natal_transits`, `ephemeris_next_eclipse`, `ephemeris_next_lunar_phase`, `ephemeris_overlay`, `ephemeris_planet_position`, `ephemeris_planetary_return`, `ephemeris_progressed_chart`, `ephemeris_relocation`, `ephemeris_retrograde_status`, `ephemeris_solar_return`, `ephemeris_synastry`, `ephemeris_transits`, `hd_opposition`, `hd_planetary_return`, `human_design_bodygraph`, `human_design_chart`, `human_design_composite`, `human_design_penta`, `vedic_chart`, `venus_eight_year_star`, `venus_elongations`, `venus_phase`, `venus_star_points`, `venus_star_points_conjunctions`, `venus_stations`
358
+ - Registered tools (`OPENEPHEMERIS_PROFILE=dev`): **57**
359
+ - Typed tools: `acg_hits`, `acg_power_lines`, `auth_login`, `auth_logout`, `auth_status`, `chart_wheel_on_aspect_click`, `chart_wheel_on_house_click`, `chart_wheel_on_planet_click`, `chart_wheel_recalculate`, `chinese_bazi`, `dev_call`, `dev_list_allowed`, `electional_aspect_search`, `electional_moment_analysis`, `electional_station_tracker`, `ephemeris_angles_points`, `ephemeris_aspect_check`, `ephemeris_bi_wheel`, `ephemeris_chart_wheel`, `ephemeris_composite`, `ephemeris_composite_midpoint`, `ephemeris_dignities`, `ephemeris_electional`, `ephemeris_fixed_stars`, `ephemeris_hermetic_lots`, `ephemeris_house_cusps`, `ephemeris_lunar_return`, `ephemeris_midpoints`, `ephemeris_moon_phase`, `ephemeris_natal_batch`, `ephemeris_natal_chart`, `ephemeris_natal_transits`, `ephemeris_next_eclipse`, `ephemeris_next_lunar_phase`, `ephemeris_overlay`, `ephemeris_planet_position`, `ephemeris_planetary_return`, `ephemeris_progressed_chart`, `ephemeris_relocation`, `ephemeris_retrograde_status`, `ephemeris_solar_return`, `ephemeris_synastry`, `ephemeris_transits`, `explore_natal_chart`, `hd_opposition`, `hd_planetary_return`, `human_design_bodygraph`, `human_design_chart`, `human_design_composite`, `human_design_penta`, `vedic_chart`, `venus_eight_year_star`, `venus_elongations`, `venus_phase`, `venus_star_points`, `venus_star_points_conjunctions`, `venus_stations`
360
360
  - Generic tools:
361
361
 
362
362
  ### Allowlist Families
@@ -391,14 +391,6 @@
391
391
  ],
392
392
  "operationId": "reverse_geocode_location_reverse_get"
393
393
  },
394
- {
395
- "method": "GET",
396
- "path": "/tidal/forcing/deep-time",
397
- "tags": [
398
- "tidal"
399
- ],
400
- "operationId": "get_tidal_forcing_deep_time_endpoint_tidal_forcing_deep_time_get"
401
- },
402
394
  {
403
395
  "method": "GET",
404
396
  "path": "/tidal/forcing",
package/dist/index.js CHANGED
@@ -4,8 +4,9 @@ import path from "node:path";
4
4
  import { fileURLToPath } from "node:url";
5
5
  import { Server } from "@modelcontextprotocol/sdk/server/index.js";
6
6
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
7
- import { CallToolRequestSchema, ListToolsRequestSchema, ListPromptsRequestSchema, GetPromptRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
7
+ import { CallToolRequestSchema, ListToolsRequestSchema, ListPromptsRequestSchema, GetPromptRequestSchema, ListResourcesRequestSchema, ReadResourceRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
8
8
  import { initTools, toolRegistry, formatToolResponse } from "./tools/index.js";
9
+ import { CHART_WHEEL_RESOURCE_URI, CHART_WHEEL_MIME_TYPE, getChartWheelBundle, } from "./tools/apps/chart-wheel-app.js";
9
10
  function resolveServerVersion() {
10
11
  try {
11
12
  const here = path.dirname(fileURLToPath(import.meta.url));
@@ -34,6 +35,7 @@ const server = new Server({
34
35
  capabilities: {
35
36
  tools: {},
36
37
  prompts: {},
38
+ resources: {},
37
39
  },
38
40
  });
39
41
  // List available tools
@@ -92,6 +94,41 @@ server.setRequestHandler(GetPromptRequestSchema, async (request) => {
92
94
  ]
93
95
  };
94
96
  });
97
+ // List available resources
98
+ server.setRequestHandler(ListResourcesRequestSchema, async () => {
99
+ const bundle = getChartWheelBundle();
100
+ if (!bundle)
101
+ return { resources: [] };
102
+ return {
103
+ resources: [
104
+ {
105
+ uri: CHART_WHEEL_RESOURCE_URI,
106
+ name: "Chart Wheel Explorer",
107
+ description: "Interactive natal chart wheel with clickable planets, houses, and aspects.",
108
+ mimeType: CHART_WHEEL_MIME_TYPE,
109
+ },
110
+ ],
111
+ };
112
+ });
113
+ // Read resource
114
+ server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
115
+ if (request.params.uri !== CHART_WHEEL_RESOURCE_URI) {
116
+ throw new Error(`Unknown resource: ${request.params.uri}`);
117
+ }
118
+ const bundle = getChartWheelBundle();
119
+ if (!bundle) {
120
+ throw new Error("Chart Wheel UI bundle not found. Run `npm run build:ui` to build it.");
121
+ }
122
+ return {
123
+ contents: [
124
+ {
125
+ uri: CHART_WHEEL_RESOURCE_URI,
126
+ mimeType: CHART_WHEEL_MIME_TYPE,
127
+ text: bundle,
128
+ },
129
+ ],
130
+ };
131
+ });
95
132
  // Handle tool calls
96
133
  server.setRequestHandler(CallToolRequestSchema, async (request) => {
97
134
  const toolName = request.params.name;
@@ -21,9 +21,10 @@ import axios from "axios";
21
21
  import { Server } from "@modelcontextprotocol/sdk/server/index.js";
22
22
  import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
23
23
  import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
24
- import { CallToolRequestSchema, ListToolsRequestSchema, ListPromptsRequestSchema, GetPromptRequestSchema, isInitializeRequest, } from "@modelcontextprotocol/sdk/types.js";
24
+ import { CallToolRequestSchema, ListToolsRequestSchema, ListPromptsRequestSchema, GetPromptRequestSchema, ListResourcesRequestSchema, ReadResourceRequestSchema, isInitializeRequest, } from "@modelcontextprotocol/sdk/types.js";
25
25
  import { initTools, toolRegistry, formatToolResponse } from "./tools/index.js";
26
26
  import { BackendClient, runWithClient } from "./backend/client.js";
27
+ import { CHART_WHEEL_RESOURCE_URI, CHART_WHEEL_MIME_TYPE, getChartWheelBundle, } from "./tools/apps/chart-wheel-app.js";
27
28
  // ---------------------------------------------------------------------------
28
29
  // Helpers
29
30
  // ---------------------------------------------------------------------------
@@ -184,7 +185,7 @@ function createMcpServer() {
184
185
  "and more — powered by JPL DE440 ephemerides for sub-arcsecond accuracy.",
185
186
  },
186
187
  }, {
187
- capabilities: { tools: {}, prompts: {} },
188
+ capabilities: { tools: {}, prompts: {}, resources: {} },
188
189
  instructions: "Open Ephemeris is a precision astronomical computation engine. " +
189
190
  "Use format='llm' on any tool for compact, token-efficient output. " +
190
191
  "All computations use JPL DE440 ephemerides for sub-arcsecond accuracy. " +
@@ -240,6 +241,40 @@ function createMcpServer() {
240
241
  };
241
242
  }
242
243
  });
244
+ // --- Resource handlers ---
245
+ server.setRequestHandler(ListResourcesRequestSchema, async () => {
246
+ const bundle = getChartWheelBundle();
247
+ if (!bundle)
248
+ return { resources: [] };
249
+ return {
250
+ resources: [
251
+ {
252
+ uri: CHART_WHEEL_RESOURCE_URI,
253
+ name: "Chart Wheel Explorer",
254
+ description: "Interactive natal chart wheel with clickable planets, houses, and aspects.",
255
+ mimeType: CHART_WHEEL_MIME_TYPE,
256
+ },
257
+ ],
258
+ };
259
+ });
260
+ server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
261
+ if (request.params.uri !== CHART_WHEEL_RESOURCE_URI) {
262
+ throw new Error(`Unknown resource: ${request.params.uri}`);
263
+ }
264
+ const bundle = getChartWheelBundle();
265
+ if (!bundle) {
266
+ throw new Error("Chart Wheel UI bundle not found. Run `npm run build:ui` to build it.");
267
+ }
268
+ return {
269
+ contents: [
270
+ {
271
+ uri: CHART_WHEEL_RESOURCE_URI,
272
+ mimeType: CHART_WHEEL_MIME_TYPE,
273
+ text: bundle,
274
+ },
275
+ ],
276
+ };
277
+ });
243
278
  return server;
244
279
  }
245
280
  const httpSessions = new Map();
@@ -0,0 +1,19 @@
1
+ /**
2
+ * chart-wheel-app.ts — MCP App tool registration for the Chart Wheel Explorer.
3
+ *
4
+ * Registers 5 tools:
5
+ * • explore_natal_chart — primary entry point, returns data + UI resource
6
+ * • chart_wheel_on_planet_click — event handler for planet clicks
7
+ * • chart_wheel_on_house_click — event handler for house clicks
8
+ * • chart_wheel_on_aspect_click — event handler for aspect clicks
9
+ * • chart_wheel_recalculate — recalculates with a different house system
10
+ *
11
+ * Also exports resource helpers (getChartWheelBundle, etc.) for use in
12
+ * index.ts and server-sse.ts.
13
+ */
14
+ export declare const CHART_WHEEL_RESOURCE_URI = "ui://openephemeris/chart-wheel";
15
+ export declare const CHART_WHEEL_MIME_TYPE = "text/html;profile=mcp-app";
16
+ /** Read the pre-built HTML bundle. Returns null if not yet built. */
17
+ export declare function getChartWheelBundle(): string | null;
18
+ /** Reset cache (useful in dev watch mode or tests). */
19
+ export declare function clearBundleCache(): void;