@openephemeris/mcp-server 3.9.2 → 3.10.0
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 +33 -0
- package/README.md +4 -3
- package/dist/index.js +1 -1
- package/dist/server-sse.js +7 -7
- package/dist/tools/index.d.ts +9 -8
- package/dist/tools/index.js +34 -1
- package/dist/tools/specialized/bi_wheel.js +2 -2
- package/dist/tools/specialized/chart_wheel.js +2 -2
- package/dist/tools/specialized/hd_bodygraph.js +5 -5
- package/dist/tools/specialized/human_design.js +23 -0
- package/dist/tools/specialized/natal.js +23 -0
- package/dist/tools/specialized/progressed.js +23 -0
- package/dist/tools/specialized/returns.js +23 -0
- package/dist/tools/specialized/synastry.js +23 -0
- package/package.json +6 -2
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
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
[](https://www.npmjs.com/package/@openephemeris/mcp-server)
|
|
5
5
|
[](https://status.openephemeris.com/)
|
|
6
6
|
|
|
7
|
-
Model Context Protocol server for OpenEphemeris —
|
|
7
|
+
Model Context Protocol server for OpenEphemeris — 52 typed astrology tools powered by the NASA JPL DE440 ephemeris. Zero hallucination on planetary positions, dates, and degrees. Covers 1,100 years of astronomical data.
|
|
8
8
|
|
|
9
9
|
**Hosted endpoint:** `https://mcp.openephemeris.com/mcp` (Streamable HTTP, MCP 2025-11-25 spec)
|
|
10
10
|
|
|
@@ -343,7 +343,8 @@ When you update the MCP server logic (handlers, bug fixes, hardening), you shoul
|
|
|
343
343
|
┌────────────────────────┐
|
|
344
344
|
│ OpenEphemeris API │
|
|
345
345
|
│ api.openephemeris.com │
|
|
346
|
-
│ JPL DE440
|
|
346
|
+
│ NASA JPL DE440 │
|
|
347
|
+
│ 1,100 years of data │
|
|
347
348
|
└────────────────────────┘
|
|
348
349
|
```
|
|
349
350
|
|
|
@@ -375,6 +376,6 @@ Generated by `npm run sync:readme` from `config/dev-allowlist.json` and the live
|
|
|
375
376
|
Most LLMs (like Claude and ChatGPT) struggle heavily with astronomical calculations (trigonometry, Julian date conversions, and planetary lookups). OpenEphemeris serves as a **secure, remote math engine**.
|
|
376
377
|
|
|
377
378
|
By pairing LLMs with the OpenEphemeris MCP server, your agents can instantly access:
|
|
378
|
-
- **Zero-hallucination coordinates**: Direct, sub-arcsecond NASA JPL DE440
|
|
379
|
+
- **Zero-hallucination coordinates**: Direct, sub-arcsecond NASA JPL DE440 calculations spanning 1,100 years of astronomical data.
|
|
379
380
|
- **LLM-optimized tokens (`format=llm`)**: We compress standard 25,000 token JSON chart responses into minimal text blocks, cutting your inference costs by 50%.
|
|
380
381
|
- **Ready-to-use astrology layers**: Built-in support for Astrocartography geoJSON lines, Hermetic Lots, Fixed Stars, and complex Human Design matrix generation.
|
package/dist/index.js
CHANGED
|
@@ -75,7 +75,7 @@ server.setRequestHandler(GetPromptRequestSchema, async (request) => {
|
|
|
75
75
|
content: {
|
|
76
76
|
type: "text",
|
|
77
77
|
text: "Welcome to the **Open Ephemeris MCP Server**!\n\n" +
|
|
78
|
-
"You are now connected to an enterprise-grade astrological and astronomical computation engine powered by NASA JPL DE440
|
|
78
|
+
"You are now connected to an enterprise-grade astrological and astronomical computation engine powered by NASA JPL DE440 ephemeris data (1550–2650 CE). As a generative guide, here is how you can best utilize these tools to help the user:\n\n" +
|
|
79
79
|
"### Core Capabilities\n" +
|
|
80
80
|
"- **Birth Charts:** Use `ephemeris_natal_chart` for full planetary positions, houses, dignities, and aspects.\n" +
|
|
81
81
|
"- **Predictive Timing:** `ephemeris_transits` searches for exact dates when transiting planets hit natal points.\n" +
|
package/dist/server-sse.js
CHANGED
|
@@ -154,7 +154,7 @@ const WELCOME_PROMPT_CONTENT = [
|
|
|
154
154
|
"• **Chart Wheels** — visual PNG/SVG wheels and bi-wheels\n" +
|
|
155
155
|
"• **Time Lords** — Firdaria, Profections, Zodiacal Releasing\n\n" +
|
|
156
156
|
"**Tips:** Use `format=\"llm\"` on any tool to get ~50% smaller, token-optimized output. " +
|
|
157
|
-
"All computations are sub-arcsecond precision using JPL DE440
|
|
157
|
+
"All computations are sub-arcsecond precision using JPL DE440 ephemerides.\n\n" +
|
|
158
158
|
"Just tell me what you'd like to explore!",
|
|
159
159
|
},
|
|
160
160
|
},
|
|
@@ -177,17 +177,17 @@ function createMcpServer() {
|
|
|
177
177
|
// description is in the MCP spec (spec.types.d.ts Implementation interface)
|
|
178
178
|
// but the SDK's Zod schema doesn't include it yet — pass via spread
|
|
179
179
|
...{
|
|
180
|
-
description: "NASA JPL-backed astronomical computation engine for AI agents. " +
|
|
181
|
-
"
|
|
180
|
+
description: "NASA JPL DE440-backed astronomical computation engine for AI agents. " +
|
|
181
|
+
"52+ typed tools covering natal charts, transit forecasting, Human Design " +
|
|
182
182
|
"bodygraphs, eclipses, astrocartography power lines, Venus Star Points, " +
|
|
183
183
|
"electional timing, synastry, composite charts, Vedic/Jyotish, Chinese BaZi, " +
|
|
184
|
-
"and more — powered by JPL DE440
|
|
184
|
+
"and more — powered by JPL DE440 ephemerides for sub-arcsecond accuracy.",
|
|
185
185
|
},
|
|
186
186
|
}, {
|
|
187
187
|
capabilities: { tools: {}, prompts: {} },
|
|
188
188
|
instructions: "Open Ephemeris is a precision astronomical computation engine. " +
|
|
189
189
|
"Use format='llm' on any tool for compact, token-efficient output. " +
|
|
190
|
-
"All computations use JPL DE440
|
|
190
|
+
"All computations use JPL DE440 ephemerides for sub-arcsecond accuracy. " +
|
|
191
191
|
"See the 'welcome_to_open_ephemeris' prompt for a full capability overview.",
|
|
192
192
|
});
|
|
193
193
|
// --- Tool handlers ---
|
|
@@ -290,10 +290,10 @@ async function main() {
|
|
|
290
290
|
serverInfo: {
|
|
291
291
|
name: "Open Ephemeris",
|
|
292
292
|
version,
|
|
293
|
-
description: "NASA JPL-backed astronomical computation engine for AI agents.
|
|
293
|
+
description: "NASA JPL DE440-backed astronomical computation engine for AI agents. 52+ typed tools covering " +
|
|
294
294
|
"natal charts, transit forecasting, Human Design bodygraphs, eclipses, astrocartography " +
|
|
295
295
|
"power lines, Venus Star Points, electional timing, synastry, composite charts, Vedic/Jyotish, " +
|
|
296
|
-
"Chinese BaZi, and more — powered by JPL DE440
|
|
296
|
+
"Chinese BaZi, and more — powered by JPL DE440 ephemerides for sub-arcsecond " +
|
|
297
297
|
"zero-hallucination accuracy. Free Explorer tier available.",
|
|
298
298
|
iconUrl: "https://mcp.openephemeris.com/icon.png",
|
|
299
299
|
homepage: "https://openephemeris.com",
|
package/dist/tools/index.d.ts
CHANGED
|
@@ -34,25 +34,26 @@ export declare function validateCoordinates(args: any, latKey: string, lonKey: s
|
|
|
34
34
|
/**
|
|
35
35
|
* Formats a raw tool response into native MCP content blocks.
|
|
36
36
|
* Intercepts binary image responses (like Chart Wheels) and returns them as native MCP Images.
|
|
37
|
+
* Intercepts embedded VisualResult objects (include_visual=true) and returns dual content.
|
|
37
38
|
* Applies a safety limit to JSON payloads to prevent crashing LLM contexts.
|
|
38
39
|
*/
|
|
39
40
|
export declare function formatToolResponse(toolName: string, result: any, durationMs: number): {
|
|
40
|
-
content: {
|
|
41
|
+
content: ({
|
|
41
42
|
type: string;
|
|
42
43
|
data: string;
|
|
43
44
|
mimeType: string;
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
} | {
|
|
47
|
-
content: {
|
|
45
|
+
text?: undefined;
|
|
46
|
+
} | {
|
|
48
47
|
type: string;
|
|
49
48
|
text: string;
|
|
50
|
-
|
|
51
|
-
|
|
49
|
+
data?: undefined;
|
|
50
|
+
mimeType?: undefined;
|
|
51
|
+
})[];
|
|
52
|
+
isError?: undefined;
|
|
52
53
|
} | {
|
|
53
54
|
content: {
|
|
54
55
|
type: string;
|
|
55
56
|
text: string;
|
|
56
57
|
}[];
|
|
57
|
-
isError
|
|
58
|
+
isError: boolean;
|
|
58
59
|
};
|
package/dist/tools/index.js
CHANGED
|
@@ -71,10 +71,43 @@ export function validateCoordinates(args, latKey, lonKey) {
|
|
|
71
71
|
/**
|
|
72
72
|
* Formats a raw tool response into native MCP content blocks.
|
|
73
73
|
* Intercepts binary image responses (like Chart Wheels) and returns them as native MCP Images.
|
|
74
|
+
* Intercepts embedded VisualResult objects (include_visual=true) and returns dual content.
|
|
74
75
|
* Applies a safety limit to JSON payloads to prevent crashing LLM contexts.
|
|
75
76
|
*/
|
|
76
77
|
export function formatToolResponse(toolName, result, durationMs) {
|
|
77
|
-
//
|
|
78
|
+
// Case: data response with embedded visual (include_visual=true)
|
|
79
|
+
// VisualResult.data for SVG is a raw string; for PNG it is already base64.
|
|
80
|
+
if (result &&
|
|
81
|
+
typeof result === "object" &&
|
|
82
|
+
result.visual &&
|
|
83
|
+
typeof result.visual === "object" &&
|
|
84
|
+
result.visual.data &&
|
|
85
|
+
result.visual.content_type) {
|
|
86
|
+
const visual = result.visual;
|
|
87
|
+
const isSvg = visual.content_type === "image/svg+xml";
|
|
88
|
+
// SVG data comes back as a raw string — must base64-encode for MCP image block.
|
|
89
|
+
const imageData = isSvg
|
|
90
|
+
? Buffer.from(visual.data, "utf8").toString("base64")
|
|
91
|
+
: visual.data; // PNG is already base64
|
|
92
|
+
// Strip the visual key from the data payload so the text block is clean.
|
|
93
|
+
const { visual: _omit, ...dataWithoutVisual } = result;
|
|
94
|
+
const jsonStr = JSON.stringify(dataWithoutVisual, null, 2);
|
|
95
|
+
console.error(`[MCP] 🎨 Returning embedded visual (${visual.content_type}) for ${toolName} (${durationMs}ms)`);
|
|
96
|
+
return {
|
|
97
|
+
content: [
|
|
98
|
+
{
|
|
99
|
+
type: "image",
|
|
100
|
+
data: imageData,
|
|
101
|
+
mimeType: visual.content_type,
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
type: "text",
|
|
105
|
+
text: jsonStr,
|
|
106
|
+
},
|
|
107
|
+
],
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
// Case: standalone binary backend responses (like direct Chart Wheel tool calls)
|
|
78
111
|
if (result &&
|
|
79
112
|
typeof result === "object" &&
|
|
80
113
|
"encoding" in result &&
|
|
@@ -9,7 +9,7 @@ const HOUSE_SYSTEM_MAP = {
|
|
|
9
9
|
};
|
|
10
10
|
registerTool({
|
|
11
11
|
name: "ephemeris_bi_wheel",
|
|
12
|
-
description: "Generate a Bi-Wheel (Synastry/Transit) image (
|
|
12
|
+
description: "Generate a Bi-Wheel (Synastry/Transit) image (SVG) comparing two charts. Draws Subject A's planets on the inside wheel and Subject B's on the outside wheel. Returns a native SVG that Claude displays inline in the conversation.\n\n" +
|
|
13
13
|
"CREDIT COST: 2 credits per call.\n\n" +
|
|
14
14
|
"EXAMPLE: Compare someone born April 15, 1990 (A) to someone born June 10, 1992 (B):\n" +
|
|
15
15
|
" datetime_a='...', latitude_a=..., longitude_a=..., datetime_b='...', latitude_b=..., longitude_b=...",
|
|
@@ -69,6 +69,6 @@ registerTool({
|
|
|
69
69
|
body.configuration = { house_system: mappedCode };
|
|
70
70
|
}
|
|
71
71
|
const styleParam = args.style ? `&style=${args.style}` : "";
|
|
72
|
-
return await getActiveClient().post(`/visualization/bi-wheel?format=
|
|
72
|
+
return await getActiveClient().post(`/visualization/bi-wheel?format=svg&size=800${styleParam}`, body);
|
|
73
73
|
},
|
|
74
74
|
});
|
|
@@ -9,7 +9,7 @@ const HOUSE_SYSTEM_MAP = {
|
|
|
9
9
|
};
|
|
10
10
|
registerTool({
|
|
11
11
|
name: "ephemeris_chart_wheel",
|
|
12
|
-
description: "Generate a classic astrological Chart Wheel image (
|
|
12
|
+
description: "Generate a classic astrological Chart Wheel image (SVG) for a person/event. This draws a standard circular chart wheel with planets, aspects, and house cusps. The tool returns a native SVG image that Claude displays inline in the conversation — no external tools needed.\n\n" +
|
|
13
13
|
"CREDIT COST: 2 credits per call.\n\n" +
|
|
14
14
|
"EXAMPLE: Generate a natal chart wheel for someone born April 15, 1990 in Chicago:\n" +
|
|
15
15
|
" datetime='1990-04-15T14:30:00', latitude=41.8781, longitude=-87.6298",
|
|
@@ -66,6 +66,6 @@ registerTool({
|
|
|
66
66
|
body.configuration = { house_system: mappedCode };
|
|
67
67
|
}
|
|
68
68
|
const styleParam = args.style ? `&style=${args.style}` : "";
|
|
69
|
-
return await getActiveClient().post(`/visualization/chart-wheel?format=
|
|
69
|
+
return await getActiveClient().post(`/visualization/chart-wheel?format=svg&size=800${styleParam}`, body);
|
|
70
70
|
},
|
|
71
71
|
});
|
|
@@ -8,11 +8,11 @@ function ensureTimezone(dt) {
|
|
|
8
8
|
}
|
|
9
9
|
registerTool({
|
|
10
10
|
name: "human_design_bodygraph",
|
|
11
|
-
description: "Generate a Human Design Bodygraph image (
|
|
11
|
+
description: "Generate a Human Design Bodygraph image (SVG) from a birth datetime (UTC). " +
|
|
12
12
|
"Renders the full bodygraph circuit board showing all 9 centers, 36 channels, and 64 gates " +
|
|
13
13
|
"with Personality (conscious) and Design (unconscious) activations color-coded. " +
|
|
14
14
|
"Defined centers are filled with their HD doctrine color; open/undefined centers remain muted. " +
|
|
15
|
-
"
|
|
15
|
+
"Returns a native SVG that Claude displays inline. Use format='png' to opt into raster output (requires server-side rasterizer).\n\n" +
|
|
16
16
|
"CREDIT COST: 2 credits per call.\n\n" +
|
|
17
17
|
"EXAMPLE: Generate a bodygraph for someone born April 15, 1990 at 19:30 UTC:\n" +
|
|
18
18
|
" datetime='1990-04-15T19:30:00Z'",
|
|
@@ -32,8 +32,8 @@ registerTool({
|
|
|
32
32
|
},
|
|
33
33
|
format: {
|
|
34
34
|
type: "string",
|
|
35
|
-
enum: ["
|
|
36
|
-
description: "Output format. Defaults to 'png'.",
|
|
35
|
+
enum: ["svg", "png"],
|
|
36
|
+
description: "Output format. Defaults to 'svg' (pure Go renderer — no external deps, displays natively in Claude). Use 'png' for raster output (requires server-side rasterizer).",
|
|
37
37
|
},
|
|
38
38
|
},
|
|
39
39
|
required: ["datetime"],
|
|
@@ -44,7 +44,7 @@ registerTool({
|
|
|
44
44
|
const body = {
|
|
45
45
|
birth_datetime_utc: ensureTimezone(args.datetime),
|
|
46
46
|
};
|
|
47
|
-
const format = args.format || "
|
|
47
|
+
const format = args.format || "svg";
|
|
48
48
|
const styleParam = args.style ? `&style=${args.style}` : "";
|
|
49
49
|
return await getActiveClient().post(`/visualization/bodygraph?format=${format}&size=800${styleParam}`, body);
|
|
50
50
|
},
|
|
@@ -45,6 +45,21 @@ registerTool({
|
|
|
45
45
|
description: "Output format. 'llm' returns compact array projection for token efficiency (available on all tiers). " +
|
|
46
46
|
"'json' returns verbose full output.",
|
|
47
47
|
},
|
|
48
|
+
include_visual: {
|
|
49
|
+
type: "boolean",
|
|
50
|
+
description: "When true, renders the Human Design bodygraph as an SVG and embeds it in the response. " +
|
|
51
|
+
"The bodygraph image will display in the conversation alongside the data. " +
|
|
52
|
+
"Costs 2 additional credits on top of the base call cost.",
|
|
53
|
+
},
|
|
54
|
+
visual_config: {
|
|
55
|
+
type: "object",
|
|
56
|
+
description: "Optional rendering preferences (only used when include_visual=true).",
|
|
57
|
+
properties: {
|
|
58
|
+
theme: { type: "string", enum: ["light", "dark"], description: "Color theme. Default: dark (HD convention)." },
|
|
59
|
+
size: { type: "number", description: "Canvas size in pixels, 200–4000. Default: 800." },
|
|
60
|
+
},
|
|
61
|
+
additionalProperties: false,
|
|
62
|
+
},
|
|
48
63
|
},
|
|
49
64
|
required: ["datetime"],
|
|
50
65
|
additionalProperties: false,
|
|
@@ -61,6 +76,14 @@ registerTool({
|
|
|
61
76
|
const query = {};
|
|
62
77
|
if (args.format)
|
|
63
78
|
query.format = args.format;
|
|
79
|
+
if (args.include_visual) {
|
|
80
|
+
body.include_visual = true;
|
|
81
|
+
body.visual_config = {
|
|
82
|
+
format: "svg",
|
|
83
|
+
theme: args.visual_config?.theme || "dark", // HD convention defaults to dark
|
|
84
|
+
size: args.visual_config?.size || 800,
|
|
85
|
+
};
|
|
86
|
+
}
|
|
64
87
|
return await getActiveClient().request("POST", "/human-design/chart", {
|
|
65
88
|
data: body,
|
|
66
89
|
params: query,
|
|
@@ -54,6 +54,21 @@ registerTool({
|
|
|
54
54
|
type: "boolean",
|
|
55
55
|
description: "Reserved for future use. Fixed star positions are currently available via the dedicated /ephemeris/fixed-stars endpoint.",
|
|
56
56
|
},
|
|
57
|
+
include_visual: {
|
|
58
|
+
type: "boolean",
|
|
59
|
+
description: "When true, renders the natal chart wheel as an SVG and embeds it directly in the response. " +
|
|
60
|
+
"The chart image will display in the conversation alongside the data. " +
|
|
61
|
+
"Costs 2 additional credits on top of the base call cost.",
|
|
62
|
+
},
|
|
63
|
+
visual_config: {
|
|
64
|
+
type: "object",
|
|
65
|
+
description: "Optional rendering preferences (only used when include_visual=true).",
|
|
66
|
+
properties: {
|
|
67
|
+
theme: { type: "string", enum: ["light", "dark"], description: "Color theme. Default: light." },
|
|
68
|
+
size: { type: "number", description: "Canvas size in pixels, 200–4000. Default: 800." },
|
|
69
|
+
},
|
|
70
|
+
additionalProperties: false,
|
|
71
|
+
},
|
|
57
72
|
},
|
|
58
73
|
required: ["datetime", "latitude", "longitude"],
|
|
59
74
|
additionalProperties: false,
|
|
@@ -91,6 +106,14 @@ registerTool({
|
|
|
91
106
|
const query = {};
|
|
92
107
|
if (args.format)
|
|
93
108
|
query.format = args.format;
|
|
109
|
+
if (args.include_visual) {
|
|
110
|
+
body.include_visual = true;
|
|
111
|
+
body.visual_config = {
|
|
112
|
+
format: "svg", // always SVG for MCP — no resvg dependency
|
|
113
|
+
theme: args.visual_config?.theme || "light",
|
|
114
|
+
size: args.visual_config?.size || 800,
|
|
115
|
+
};
|
|
116
|
+
}
|
|
94
117
|
return await getActiveClient().request("POST", "/ephemeris/natal-chart", {
|
|
95
118
|
data: body,
|
|
96
119
|
params: query,
|
|
@@ -37,6 +37,21 @@ registerTool({
|
|
|
37
37
|
type: "boolean",
|
|
38
38
|
description: "Whether to include aspect grid in the response. Default false.",
|
|
39
39
|
},
|
|
40
|
+
include_visual: {
|
|
41
|
+
type: "boolean",
|
|
42
|
+
description: "When true, renders the progressed chart wheel as an SVG and embeds it in the response. " +
|
|
43
|
+
"The chart image will display in the conversation alongside the data. " +
|
|
44
|
+
"Costs 2 additional credits on top of the base call cost.",
|
|
45
|
+
},
|
|
46
|
+
visual_config: {
|
|
47
|
+
type: "object",
|
|
48
|
+
description: "Optional rendering preferences (only used when include_visual=true).",
|
|
49
|
+
properties: {
|
|
50
|
+
theme: { type: "string", enum: ["light", "dark"], description: "Color theme. Default: light." },
|
|
51
|
+
size: { type: "number", description: "Canvas size in pixels, 200–4000. Default: 800." },
|
|
52
|
+
},
|
|
53
|
+
additionalProperties: false,
|
|
54
|
+
},
|
|
40
55
|
},
|
|
41
56
|
required: ["birth_datetime", "birth_latitude", "birth_longitude", "target_datetime"],
|
|
42
57
|
additionalProperties: false,
|
|
@@ -60,6 +75,14 @@ registerTool({
|
|
|
60
75
|
if (args.include_aspects != null) {
|
|
61
76
|
body.options = { include_aspects: args.include_aspects };
|
|
62
77
|
}
|
|
78
|
+
if (args.include_visual) {
|
|
79
|
+
body.include_visual = true;
|
|
80
|
+
body.visual_config = {
|
|
81
|
+
format: "svg",
|
|
82
|
+
theme: args.visual_config?.theme || "light",
|
|
83
|
+
size: args.visual_config?.size || 800,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
63
86
|
return await getActiveClient().post("/ephemeris/progressed", body);
|
|
64
87
|
},
|
|
65
88
|
});
|
|
@@ -40,6 +40,21 @@ registerTool({
|
|
|
40
40
|
type: "number",
|
|
41
41
|
description: "Location longitude for the return chart (optional).",
|
|
42
42
|
},
|
|
43
|
+
include_visual: {
|
|
44
|
+
type: "boolean",
|
|
45
|
+
description: "When true, renders the solar return chart wheel as an SVG and embeds it in the response. " +
|
|
46
|
+
"The chart image will display in the conversation alongside the data. " +
|
|
47
|
+
"Costs 2 additional credits on top of the base call cost.",
|
|
48
|
+
},
|
|
49
|
+
visual_config: {
|
|
50
|
+
type: "object",
|
|
51
|
+
description: "Optional rendering preferences (only used when include_visual=true).",
|
|
52
|
+
properties: {
|
|
53
|
+
theme: { type: "string", enum: ["light", "dark"], description: "Color theme. Default: light." },
|
|
54
|
+
size: { type: "number", description: "Canvas size in pixels, 200–4000. Default: 800." },
|
|
55
|
+
},
|
|
56
|
+
additionalProperties: false,
|
|
57
|
+
},
|
|
43
58
|
},
|
|
44
59
|
required: ["birth_datetime"],
|
|
45
60
|
additionalProperties: false,
|
|
@@ -64,6 +79,14 @@ registerTool({
|
|
|
64
79
|
longitude: { decimal: args.return_longitude },
|
|
65
80
|
};
|
|
66
81
|
}
|
|
82
|
+
if (args.include_visual) {
|
|
83
|
+
body.include_visual = true;
|
|
84
|
+
body.visual_config = {
|
|
85
|
+
format: "svg",
|
|
86
|
+
theme: args.visual_config?.theme || "light",
|
|
87
|
+
size: args.visual_config?.size || 800,
|
|
88
|
+
};
|
|
89
|
+
}
|
|
67
90
|
return await getActiveClient().post("/predictive/returns/solar", body);
|
|
68
91
|
},
|
|
69
92
|
});
|
|
@@ -28,6 +28,21 @@ registerTool({
|
|
|
28
28
|
enum: ["json", "llm"],
|
|
29
29
|
description: "Output format. 'llm' is compact and token-efficient (available on all tiers).",
|
|
30
30
|
},
|
|
31
|
+
include_visual: {
|
|
32
|
+
type: "boolean",
|
|
33
|
+
description: "When true, renders a bi-wheel SVG comparing both charts and embeds it in the response. " +
|
|
34
|
+
"The chart image will display in the conversation alongside the data. " +
|
|
35
|
+
"Costs 2 additional credits on top of the base call cost.",
|
|
36
|
+
},
|
|
37
|
+
visual_config: {
|
|
38
|
+
type: "object",
|
|
39
|
+
description: "Optional rendering preferences (only used when include_visual=true).",
|
|
40
|
+
properties: {
|
|
41
|
+
theme: { type: "string", enum: ["light", "dark"], description: "Color theme. Default: light." },
|
|
42
|
+
size: { type: "number", description: "Canvas size in pixels, 200–4000. Default: 800." },
|
|
43
|
+
},
|
|
44
|
+
additionalProperties: false,
|
|
45
|
+
},
|
|
31
46
|
},
|
|
32
47
|
required: [
|
|
33
48
|
"person_a_datetime", "person_a_latitude", "person_a_longitude",
|
|
@@ -63,6 +78,14 @@ registerTool({
|
|
|
63
78
|
const query = {};
|
|
64
79
|
if (args.format)
|
|
65
80
|
query.format = args.format;
|
|
81
|
+
if (args.include_visual) {
|
|
82
|
+
body.include_visual = true;
|
|
83
|
+
body.visual_config = {
|
|
84
|
+
format: "svg",
|
|
85
|
+
theme: args.visual_config?.theme || "light",
|
|
86
|
+
size: args.visual_config?.size || 800,
|
|
87
|
+
};
|
|
88
|
+
}
|
|
66
89
|
return await getActiveClient().request("POST", "/comparative/synastry", {
|
|
67
90
|
data: body,
|
|
68
91
|
params: query,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openephemeris/mcp-server",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.10.0",
|
|
4
4
|
"description": "Model Context Protocol server for the Open Ephemeris astronomical computation API",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -65,7 +65,8 @@
|
|
|
65
65
|
"node": ">=18.0.0"
|
|
66
66
|
},
|
|
67
67
|
"dependencies": {
|
|
68
|
-
"@modelcontextprotocol/
|
|
68
|
+
"@modelcontextprotocol/ext-apps": "^1.7.0",
|
|
69
|
+
"@modelcontextprotocol/sdk": "1.29.0",
|
|
69
70
|
"axios": "1.13.2",
|
|
70
71
|
"express": "5.1.0",
|
|
71
72
|
"zod": "4.1.13"
|
|
@@ -73,8 +74,11 @@
|
|
|
73
74
|
"devDependencies": {
|
|
74
75
|
"@types/express": "5.0.3",
|
|
75
76
|
"@types/node": "25.0.1",
|
|
77
|
+
"cross-env": "^10.1.0",
|
|
76
78
|
"tsx": "4.21.0",
|
|
77
79
|
"typescript": "5.9.3",
|
|
80
|
+
"vite": "^8.0.10",
|
|
81
|
+
"vite-plugin-singlefile": "^2.3.3",
|
|
78
82
|
"vitest": "4.0.15"
|
|
79
83
|
},
|
|
80
84
|
"packageManager": "pnpm@10.27.0+sha512.72d699da16b1179c14ba9e64dc71c9a40988cbdc65c264cb0e489db7de917f20dcf4d64d8723625f2969ba52d4b7e2a1170682d9ac2a5dcaeaab732b7e16f04a"
|