@openephemeris/mcp-server 3.9.0 → 3.9.1

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 (3) hide show
  1. package/README.md +139 -11
  2. package/dist/server-sse.js +114 -14
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -1,11 +1,115 @@
1
1
  # OpenEphemeris MCP Server
2
2
 
3
+ [![smithery badge](https://smithery.ai/badge/open-ephemeris/openephemeris)](https://smithery.ai/servers/open-ephemeris/openephemeris)
4
+ [![npm version](https://img.shields.io/npm/v/@openephemeris/mcp-server)](https://www.npmjs.com/package/@openephemeris/mcp-server)
3
5
  [![System Status](https://img.shields.io/badge/Status-Operational-brightgreen)](https://status.openephemeris.com/)
4
6
 
5
- Model Context Protocol server for OpenEphemeris. This package exposes typed astrology tools and an allowlist-gated generic proxy (`dev.call`) for MCP-compatible clients.
7
+ Model Context Protocol server for OpenEphemeris 50+ typed astrology tools powered by NASA JPL DE440/DE441 ephemerides. Zero hallucination on planetary positions, dates, and degrees.
8
+
9
+ **Hosted endpoint:** `https://mcp.openephemeris.com/mcp` (Streamable HTTP, MCP 2025-11-25 spec)
6
10
 
7
11
  ## Quick Start
8
12
 
13
+ ### Install via Smithery (recommended)
14
+
15
+ The fastest way to connect any MCP-compatible client:
16
+
17
+ ```bash
18
+ npx -y @smithery/cli install @open-ephemeris/openephemeris --client claude
19
+ ```
20
+
21
+ Or browse the listing and copy connection snippets: **[smithery.ai/servers/open-ephemeris/openephemeris](https://smithery.ai/servers/open-ephemeris/openephemeris)**
22
+
23
+ ---
24
+
25
+ ### Connect via AI SDK (Vercel AI SDK)
26
+
27
+ ```typescript
28
+ import Smithery from "@smithery/api"
29
+ import { createMCPClient } from "@ai-sdk/mcp"
30
+ import { generateText } from "ai"
31
+ import { anthropic } from "@ai-sdk/anthropic"
32
+ import { createConnection } from "@smithery/api/mcp"
33
+
34
+ const smithery = new Smithery()
35
+
36
+ const conn = await smithery.connections.create("{your-namespace}", {
37
+ mcpUrl: "https://server.smithery.ai/open-ephemeris/openephemeris",
38
+ headers: {
39
+ apiKey: "your-openephemeris-api-key", // get one free at openephemeris.com/dashboard
40
+ },
41
+ })
42
+
43
+ const { transport } = await createConnection({
44
+ client: smithery,
45
+ namespace: "{your-namespace}",
46
+ connectionId: conn.connectionId,
47
+ })
48
+
49
+ const mcpClient = await createMCPClient({ transport })
50
+ const tools = await mcpClient.tools()
51
+
52
+ const { text } = await generateText({
53
+ model: anthropic("claude-sonnet-4-20250514"),
54
+ tools,
55
+ prompt: "Calculate a natal chart for someone born April 15, 1990 at 2:30 PM in Chicago.",
56
+ })
57
+
58
+ await mcpClient.close()
59
+ ```
60
+
61
+ ### Connect via MCP SDK (TypeScript)
62
+
63
+ ```typescript
64
+ import Smithery from "@smithery/api"
65
+ import { Client } from "@modelcontextprotocol/sdk/client/index.js"
66
+ import { createConnection } from "@smithery/api/mcp"
67
+
68
+ const smithery = new Smithery()
69
+
70
+ const conn = await smithery.connections.create("{your-namespace}", {
71
+ mcpUrl: "https://server.smithery.ai/open-ephemeris/openephemeris",
72
+ headers: {
73
+ apiKey: "your-openephemeris-api-key",
74
+ },
75
+ })
76
+
77
+ const { transport } = await createConnection({
78
+ client: smithery,
79
+ namespace: "{your-namespace}",
80
+ connectionId: conn.connectionId,
81
+ })
82
+
83
+ const mcpClient = new Client(
84
+ { name: "my-app", version: "1.0.0" },
85
+ { capabilities: {} }
86
+ )
87
+ await mcpClient.connect(transport)
88
+
89
+ const { tools } = await mcpClient.listTools()
90
+ const result = await mcpClient.callTool({
91
+ name: "ephemeris_natal_chart",
92
+ arguments: { datetime: "1990-04-15T14:30:00", latitude: 41.8781, longitude: -87.6298, format: "llm" },
93
+ })
94
+ ```
95
+
96
+ ### Connect directly (Streamable HTTP, no Smithery)
97
+
98
+ ```typescript
99
+ import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js"
100
+ import { Client } from "@modelcontextprotocol/sdk/client/index.js"
101
+
102
+ const transport = new StreamableHTTPClientTransport(
103
+ new URL("https://mcp.openephemeris.com/mcp"),
104
+ { requestInit: { headers: { "X-API-Key": "your-openephemeris-api-key" } } }
105
+ )
106
+
107
+ const client = new Client({ name: "my-app", version: "1.0.0" }, { capabilities: {} })
108
+ await client.connect(transport)
109
+ ```
110
+
111
+ ---
112
+
9
113
  ### One-click install (Cursor)
10
114
 
11
115
  <!-- GENERATED:CURSOR_INSTALL:BEGIN -->
@@ -54,10 +158,12 @@ Cursor deeplink payload:
54
158
 
55
159
  | Client | Install mode | Config location |
56
160
  |---|---|---|
161
+ | Smithery | One-click | [smithery.ai](https://smithery.ai/servers/open-ephemeris/openephemeris) |
57
162
  | Cursor | One-click deeplink or manual | `~/.cursor/mcp.json` |
58
163
  | Claude Desktop (macOS) | Manual | `~/Library/Application Support/Claude/claude_desktop_config.json` |
59
164
  | Claude Desktop (Windows) | Manual | `%APPDATA%\Claude\claude_desktop_config.json` |
60
165
  | Windsurf | Manual | `~/.codeium/windsurf/mcp_config.json` (or legacy `~/.codeium/mcp_config.json`) |
166
+ | Claude Web / ChatGPT / remote clients | Hosted URL | `https://mcp.openephemeris.com/mcp` |
61
167
 
62
168
  ### Client install walkthroughs
63
169
 
@@ -73,9 +179,13 @@ Cursor deeplink payload:
73
179
  - Add the `mcpServers.openephemeris` block from "Manual install".
74
180
  - Restart Windsurf.
75
181
 
76
- ### Remote-only clients (ChatGPT Developer Mode, Antigravity, etc.)
182
+ ### Remote-only clients (Claude Web, ChatGPT, etc.)
183
+
184
+ The server is hosted at `https://mcp.openephemeris.com/mcp` with full Streamable HTTP support (MCP 2025-11-25 spec). Remote-only clients can connect directly — no bridge/proxy required:
77
185
 
78
- This package runs as a local stdio MCP server. Remote-only clients require a hosted MCP endpoint (Streamable HTTP/SSE), so you must run this server behind an MCP bridge/proxy and expose it over HTTPS before adding it in those clients.
186
+ - **Claude Web**: Add `https://mcp.openephemeris.com/mcp` as a remote MCP server with `X-API-Key: your-key` header
187
+ - **Via Smithery**: Use the [Smithery listing](https://smithery.ai/servers/open-ephemeris/openephemeris) for managed connections with any client
188
+ - **Legacy SSE**: `https://mcp.openephemeris.com/sse` remains available for SSE-only clients
79
189
 
80
190
  ### Auth and upgrade behavior in MCP clients
81
191
 
@@ -209,14 +319,32 @@ When you update the MCP server logic (handlers, bug fixes, hardening), you shoul
209
319
  ## Architecture
210
320
 
211
321
  ```text
212
- MCP Client (Cursor / Claude / Windsurf / other stdio clients)
213
- | stdio JSON-RPC
214
- v
215
- openephemeris-mcp (Node.js)
216
- | typed tools + dev.call/dev.list_allowed
217
- | auth chain: Service Key > API Key > JWT
218
- v
219
- OpenEphemeris API
322
+ ┌─────────────────────────────────────────────────────────┐
323
+ │ MCP Clients │
324
+ │ Smithery Gateway · Claude Web · ChatGPT · Remote apps │
325
+ └──────────────────┬──────────────────────────────────────┘
326
+ Streamable HTTP (MCP 2025-11-25)
327
+ https://mcp.openephemeris.com/mcp
328
+
329
+ ┌─────────────────────────────────────────────────────────┐
330
+ │ Cursor · Claude Desktop · Windsurf │
331
+ └──────────────────┬──────────────────────────────────────┘
332
+ │ stdio JSON-RPC
333
+ │ npx @openephemeris/mcp-server
334
+
335
+ ┌────▼────────────────────┐
336
+ │ openephemeris-mcp │
337
+ │ Node.js MCP Server │
338
+ │ 52 typed tools │
339
+ │ auth: Key > JWT │
340
+ └────────────┬────────────┘
341
+ │ HTTPS
342
+
343
+ ┌────────────────────────┐
344
+ │ OpenEphemeris API │
345
+ │ api.openephemeris.com │
346
+ │ JPL DE440/DE441 │
347
+ └────────────────────────┘
220
348
  ```
221
349
 
222
350
  <!-- GENERATED:RUNTIME_SNAPSHOT:BEGIN -->
@@ -21,7 +21,7 @@ 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, isInitializeRequest, } from "@modelcontextprotocol/sdk/types.js";
24
+ import { CallToolRequestSchema, ListToolsRequestSchema, ListPromptsRequestSchema, GetPromptRequestSchema, 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
27
  // ---------------------------------------------------------------------------
@@ -93,31 +93,125 @@ function extractApiKey(req) {
93
93
  undefined);
94
94
  }
95
95
  // ---------------------------------------------------------------------------
96
- // MCP Server factory — one per SSE session
96
+ // Helpers
97
+ // ---------------------------------------------------------------------------
98
+ /** Convert snake_case tool name → Human Title (e.g. "ephemeris_natal_chart" → "Natal Chart") */
99
+ function humanTitle(name) {
100
+ // Strip common prefixes that don't add value in a title context
101
+ const stripped = name
102
+ .replace(/^ephemeris_/, "")
103
+ .replace(/^acg_/, "ACG ")
104
+ .replace(/^hd_/, "Human Design ")
105
+ .replace(/^human_design_/, "Human Design ")
106
+ .replace(/^electional_/, "Electional ")
107
+ .replace(/^venus_/, "Venus ")
108
+ .replace(/^vedic_/, "Vedic ")
109
+ .replace(/^bazi_/, "BaZi ")
110
+ .replace(/^chinese_/, "Chinese ");
111
+ return stripped
112
+ .split("_")
113
+ .map((w) => w.charAt(0).toUpperCase() + w.slice(1))
114
+ .join(" ");
115
+ }
116
+ /** Build MCP-spec tool annotations for a tool */
117
+ function buildAnnotations(tool) {
118
+ return {
119
+ title: humanTitle(tool.name),
120
+ readOnlyHint: true,
121
+ destructiveHint: false,
122
+ idempotentHint: true,
123
+ openWorldHint: false,
124
+ ...(tool.annotations ?? {}),
125
+ };
126
+ }
127
+ // ---------------------------------------------------------------------------
128
+ // Welcome prompt — orientation guide for LLMs connecting via MCP
129
+ // ---------------------------------------------------------------------------
130
+ const WELCOME_PROMPT = {
131
+ name: "welcome_to_open_ephemeris",
132
+ description: "An orientation guide that introduces the Open Ephemeris MCP server, " +
133
+ "its capabilities, and how to use its tools effectively. " +
134
+ "Invoke this prompt when a user first connects or asks 'what can you do?'",
135
+ arguments: [],
136
+ };
137
+ const WELCOME_PROMPT_CONTENT = [
138
+ {
139
+ role: "assistant",
140
+ content: {
141
+ type: "text",
142
+ text: "🌟 **Welcome to Open Ephemeris** — a NASA JPL-backed astronomical computation engine.\n\n" +
143
+ "I have access to 50+ precision tools covering:\n\n" +
144
+ "• **Natal Charts** — full planetary positions, house cusps, aspects, dignities\n" +
145
+ "• **Transits & Progressions** — real-time and secondary progressions\n" +
146
+ "• **Synastry & Composites** — relationship compatibility analysis\n" +
147
+ "• **Human Design** — bodygraph charts, gates, channels, types & profiles\n" +
148
+ "• **Astrocartography (ACG)** — power lines, city hits, local space lines\n" +
149
+ "• **Eclipses** — solar/lunar eclipse lookup with visibility data\n" +
150
+ "• **Vedic/Jyotish** — D-charts, dashas, nakshatras, Ashtakavarga\n" +
151
+ "• **Chinese BaZi** — Four Pillars, Ten Gods, Luck Pillars\n" +
152
+ "• **Venus Star Points** — 8-year Venus cycle phases\n" +
153
+ "• **Electional Astrology** — station tracking, timing windows\n" +
154
+ "• **Chart Wheels** — visual PNG/SVG wheels and bi-wheels\n" +
155
+ "• **Time Lords** — Firdaria, Profections, Zodiacal Releasing\n\n" +
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/DE441 ephemerides.\n\n" +
158
+ "Just tell me what you'd like to explore!",
159
+ },
160
+ },
161
+ ];
162
+ // ---------------------------------------------------------------------------
163
+ // MCP Server factory — one per SSE/HTTP session
97
164
  // ---------------------------------------------------------------------------
98
165
  function createMcpServer() {
99
166
  const server = new Server({
100
167
  name: "openephemeris-mcp",
168
+ title: "Open Ephemeris",
101
169
  version,
170
+ websiteUrl: "https://openephemeris.com",
102
171
  icons: [
103
172
  {
104
173
  src: "https://mcp.openephemeris.com/icon.png",
105
174
  mimeType: "image/png",
106
175
  }
107
- ]
108
- }, { capabilities: { tools: {} } });
176
+ ],
177
+ // description is in the MCP spec (spec.types.d.ts Implementation interface)
178
+ // but the SDK's Zod schema doesn't include it yet — pass via spread
179
+ ...{
180
+ description: "NASA JPL-backed astronomical computation engine for AI agents. " +
181
+ "50+ typed tools covering natal charts, transit forecasting, Human Design " +
182
+ "bodygraphs, eclipses, astrocartography power lines, Venus Star Points, " +
183
+ "electional timing, synastry, composite charts, Vedic/Jyotish, Chinese BaZi, " +
184
+ "and more — powered by JPL DE440/DE441 ephemerides for sub-arcsecond accuracy.",
185
+ },
186
+ }, {
187
+ capabilities: { tools: {}, prompts: {} },
188
+ instructions: "Open Ephemeris is a precision astronomical computation engine. " +
189
+ "Use format='llm' on any tool for compact, token-efficient output. " +
190
+ "All computations use JPL DE440/DE441 ephemerides for sub-arcsecond accuracy. " +
191
+ "See the 'welcome_to_open_ephemeris' prompt for a full capability overview.",
192
+ });
193
+ // --- Tool handlers ---
109
194
  server.setRequestHandler(ListToolsRequestSchema, async () => ({
110
195
  tools: Object.values(toolRegistry).map((tool) => ({
111
196
  name: tool.name,
112
197
  description: tool.description,
113
198
  inputSchema: tool.inputSchema,
114
- annotations: tool.annotations ?? {
115
- title: tool.name,
116
- readOnlyHint: true,
117
- destructiveHint: false,
118
- },
199
+ annotations: buildAnnotations(tool),
119
200
  })),
120
201
  }));
202
+ // --- Prompt handlers ---
203
+ server.setRequestHandler(ListPromptsRequestSchema, async () => ({
204
+ prompts: [WELCOME_PROMPT],
205
+ }));
206
+ server.setRequestHandler(GetPromptRequestSchema, async (request) => {
207
+ if (request.params.name !== WELCOME_PROMPT.name) {
208
+ throw new Error(`Unknown prompt: ${request.params.name}`);
209
+ }
210
+ return {
211
+ description: WELCOME_PROMPT.description,
212
+ messages: WELCOME_PROMPT_CONTENT,
213
+ };
214
+ });
121
215
  server.setRequestHandler(CallToolRequestSchema, async (request) => {
122
216
  const toolName = request.params.name;
123
217
  const tool = toolRegistry[toolName];
@@ -158,8 +252,8 @@ async function main() {
158
252
  // CORS — required for Claude Web cross-origin SSE connections
159
253
  app.use((_req, res, next) => {
160
254
  res.setHeader("Access-Control-Allow-Origin", "*");
161
- res.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
162
- res.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization, X-API-Key, X-OpenEphemeris-API-Key");
255
+ res.setHeader("Access-Control-Allow-Methods", "GET, POST, DELETE, OPTIONS");
256
+ res.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization, X-API-Key, X-OpenEphemeris-API-Key, mcp-session-id");
163
257
  if (_req.method === "OPTIONS") {
164
258
  res.status(204).end();
165
259
  return;
@@ -190,23 +284,29 @@ async function main() {
190
284
  name: tool.name,
191
285
  description: tool.description,
192
286
  inputSchema: tool.inputSchema,
287
+ annotations: buildAnnotations(tool),
193
288
  }));
194
289
  res.json({
195
290
  serverInfo: {
196
291
  name: "Open Ephemeris",
197
292
  version,
198
- description: "NASA JPL-backed astronomical computation engine for AI agents. 48+ typed tools covering natal charts, transit forecasting, Human Design, eclipses, astrocartography, BaZi, and more — powered by DE440/DE441 for sub-arcsecond accuracy.",
293
+ description: "NASA JPL-backed astronomical computation engine for AI agents. 50+ typed tools covering " +
294
+ "natal charts, transit forecasting, Human Design bodygraphs, eclipses, astrocartography " +
295
+ "power lines, Venus Star Points, electional timing, synastry, composite charts, Vedic/Jyotish, " +
296
+ "Chinese BaZi, and more — powered by JPL DE440/DE441 ephemerides for sub-arcsecond " +
297
+ "zero-hallucination accuracy. Free Explorer tier available.",
199
298
  iconUrl: "https://mcp.openephemeris.com/icon.png",
200
299
  homepage: "https://openephemeris.com",
201
300
  },
202
301
  authentication: {
203
302
  required: true,
204
303
  schemes: ["apiKey"],
205
- instructions: "Pass your Open Ephemeris API key via the X-API-Key header. Get a free Explorer key at https://openephemeris.com/dashboard",
304
+ instructions: "Pass your Open Ephemeris API key via the X-API-Key header. " +
305
+ "Get a free Explorer key at https://openephemeris.com/dashboard — no credit card required.",
206
306
  },
207
307
  tools,
208
308
  resources: [],
209
- prompts: [],
309
+ prompts: [WELCOME_PROMPT],
210
310
  });
211
311
  });
212
312
  // ---------------------------------------------------------------------------
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openephemeris/mcp-server",
3
- "version": "3.9.0",
3
+ "version": "3.9.1",
4
4
  "description": "Model Context Protocol server for the Open Ephemeris astronomical computation API",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",