@openephemeris/mcp-server 3.2.4 → 3.2.7

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.
@@ -256,6 +256,10 @@ export class BackendClient {
256
256
  if (status >= 500)
257
257
  return new BackendError(`Backend error (${status}): ${msg}`, status, "server_error", true);
258
258
  }
259
+ // Explicit timeout or abort interception
260
+ if (error.code === "ECONNABORTED" || error.code === "ETIMEDOUT") {
261
+ return new BackendError(`The computation took too long and timed out. This usually happens when requesting a massive date range (like 20+ years of transits) or an overly complex query. Please narrow your request and try again.`, 408, "timeout", false);
262
+ }
259
263
  return new BackendError(`Network error: ${error.message}`, 0, "network_error", true);
260
264
  }
261
265
  async get(path, params, timeoutMs) {
package/dist/src/index.js CHANGED
@@ -4,7 +4,7 @@ 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, } from "@modelcontextprotocol/sdk/types.js";
7
+ import { CallToolRequestSchema, ListToolsRequestSchema, ListPromptsRequestSchema, GetPromptRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
8
8
  import { initTools, toolRegistry } from "./tools/index.js";
9
9
  function resolveServerVersion() {
10
10
  try {
@@ -33,6 +33,7 @@ const server = new Server({
33
33
  }, {
34
34
  capabilities: {
35
35
  tools: {},
36
+ prompts: {},
36
37
  },
37
38
  });
38
39
  // List available tools
@@ -50,6 +51,47 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
50
51
  })),
51
52
  };
52
53
  });
54
+ // List available prompts
55
+ server.setRequestHandler(ListPromptsRequestSchema, async () => {
56
+ return {
57
+ prompts: [
58
+ {
59
+ name: "welcome_to_open_ephemeris",
60
+ description: "Getting started guide for the Open Ephemeris MCP. Use this to orient yourself to available tools, astrology terminology, and usage.",
61
+ }
62
+ ]
63
+ };
64
+ });
65
+ // Get prompt content
66
+ server.setRequestHandler(GetPromptRequestSchema, async (request) => {
67
+ if (request.params.name !== "welcome_to_open_ephemeris") {
68
+ throw new Error(`Unknown prompt: ${request.params.name}`);
69
+ }
70
+ return {
71
+ description: "Open Ephemeris Agent & Developer Orientation",
72
+ messages: [
73
+ {
74
+ role: "user",
75
+ content: {
76
+ type: "text",
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 and DE441 ephemeris data. As a generative guide, here is how you can best utilize these tools to help the user:\n\n" +
79
+ "### Core Capabilities\n" +
80
+ "- **Birth Charts:** Use `ephemeris_natal_chart` for full planetary positions, houses, dignities, and aspects.\n" +
81
+ "- **Predictive Timing:** `ephemeris_transits` searches for exact dates when transiting planets hit natal points.\n" +
82
+ "- **Location Astrology:** `ephemeris_relocation` projects a natal chart to a new geographic location (Astrocartography).\n" +
83
+ "- **Specialized Modalities:** Dedicated tools for `vedic_chart`, `chinese_bazi`, and `human_design_chart`.\n" +
84
+ "- **Eclipse Hunter:** `ephemeris_next_eclipse` dynamically scans 20 years for the next total or partial hit at the user's location.\n\n" +
85
+ "### Best Practices for AI Agents\n" +
86
+ "1. **Coordinate Formatting:** Always convert addresses/city names into `latitude` and `longitude` decimals *before* calling the tools (e.g., Chicago is `41.8781, -87.6298`).\n" +
87
+ "2. **Datetime Handling:** Most endpoints accept ISO 8601 strings. If you have a local birth time but the endpoint asks for UTC, explicitly append a `Z` or timezone offset (e.g., `1990-04-15T19:30:00Z`).\n" +
88
+ "3. **Token Efficiency:** Our responses are hyper-condensed to save you context space. You don't need to struggle with raw JSON arrays; interpret the condensed strings directly (e.g., `Su 15°Pi30 H10`).\n\n" +
89
+ "You're equipped with professional-grade math. Start by asking the user if they'd like to calculate a natal chart, check recent transits, or explore another modality!"
90
+ }
91
+ }
92
+ ]
93
+ };
94
+ });
53
95
  // Handle tool calls
54
96
  server.setRequestHandler(CallToolRequestSchema, async (request) => {
55
97
  const toolName = request.params.name;
@@ -57,19 +99,44 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
57
99
  if (!tool) {
58
100
  throw new Error(`Unknown tool: ${toolName}`);
59
101
  }
102
+ const startTime = Date.now();
103
+ console.error(`[MCP] Executing tool: ${toolName}`);
60
104
  try {
61
105
  const result = await tool.handler(request.params.arguments ?? {});
106
+ const durationMs = Date.now() - startTime;
107
+ console.error(`[MCP] ✅ Success: ${toolName} (${durationMs}ms)`);
108
+ const jsonStr = JSON.stringify(result, null, 2);
109
+ // Safety limit: ~100kb JSON is roughly 20-30k tokens.
110
+ // Usually happens if LLMs ask for 50+ years of transits or raw ephemeris arrays.
111
+ if (jsonStr.length > 100_000) {
112
+ console.error(`[MCP] ⚠️ Warning: Payload too large (${(jsonStr.length / 1024).toFixed(1)}kb) for ${toolName}`);
113
+ return {
114
+ content: [
115
+ {
116
+ type: "text",
117
+ text: JSON.stringify({
118
+ success: false,
119
+ error: "PAYLOAD_TOO_LARGE",
120
+ message: `The requested query produced too much data (${(jsonStr.length / 1024).toFixed(1)}kb). Please significantly narrow your request parameters (e.g., fewer years, smaller coordinate bounding box, etc.) to fit within context limits.`
121
+ }, null, 2),
122
+ },
123
+ ],
124
+ isError: true,
125
+ };
126
+ }
62
127
  return {
63
128
  content: [
64
129
  {
65
130
  type: "text",
66
- text: JSON.stringify(result, null, 2),
131
+ text: jsonStr,
67
132
  },
68
133
  ],
69
134
  };
70
135
  }
71
136
  catch (error) {
137
+ const durationMs = Date.now() - startTime;
72
138
  const errorMessage = error instanceof Error ? error.message : String(error);
139
+ console.error(`[MCP] ❌ Failed: ${toolName} (${durationMs}ms) - ${errorMessage}`);
73
140
  return {
74
141
  content: [
75
142
  {
@@ -70,10 +70,15 @@ registerTool({
70
70
  const code = HOUSE_SYSTEM_MAP[args.house_system] ?? args.house_system;
71
71
  body.configuration = { house_system: code };
72
72
  }
73
- if (args.include_arabic_parts || args.include_fixed_stars) {
73
+ if (args.include_fixed_stars) {
74
+ body.configuration = {
75
+ ...(body.configuration || {}),
76
+ fixed_star_options: { include: true }
77
+ };
78
+ }
79
+ if (args.include_arabic_parts) {
74
80
  body.options = {
75
- ...(args.include_arabic_parts && { include_arabic_parts: args.include_arabic_parts }),
76
- ...(args.include_fixed_stars && { include_fixed_stars: args.include_fixed_stars }),
81
+ include_hermetic_lots: true,
77
82
  };
78
83
  }
79
84
  const query = {};
@@ -70,6 +70,11 @@ registerTool({
70
70
  const body = {
71
71
  start_date: startStr,
72
72
  end_date: endStr,
73
+ natal_chart: {
74
+ datetime: args.natal_datetime,
75
+ latitude: args.natal_latitude,
76
+ longitude: args.natal_longitude,
77
+ },
73
78
  };
74
79
  if (args.transiting_planets)
75
80
  body.planet_names = args.transiting_planets;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openephemeris/mcp-server",
3
- "version": "3.2.4",
3
+ "version": "3.2.7",
4
4
  "description": "Model Context Protocol server for the Open Ephemeris astronomical computation API",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -42,7 +42,11 @@
42
42
  "astrology",
43
43
  "astronomy",
44
44
  "ephemeris",
45
- "openephemeris"
45
+ "openephemeris",
46
+ "llm",
47
+ "claude",
48
+ "ai",
49
+ "swiss ephemeris"
46
50
  ],
47
51
  "author": "Open Ephemeris",
48
52
  "license": "MIT",