@openephemeris/mcp-server 4.14.3 → 4.15.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.
- package/CHANGELOG.md +21 -0
- package/README.md +18 -1
- package/dist/index.js +3 -12
- package/dist/server-sse.js +3 -12
- package/dist/tools/apps/bazi-app.js +1 -1
- package/dist/tools/apps/bodygraph-app.js +2 -2
- package/dist/tools/apps/chart-wheel-app.js +1 -1
- package/dist/tools/apps/moon-phase-app.js +1 -1
- package/dist/tools/apps/transit-timeline-app.js +1 -1
- package/dist/tools/apps/vedic-chart-app.js +1 -1
- package/dist/tools/specialized/bi_wheel.js +1 -1
- package/dist/tools/specialized/chart_wheel.js +1 -1
- package/dist/tools/specialized/electional.js +18 -1
- package/dist/tools/specialized/ephemeris_core.js +3 -0
- package/dist/tools/specialized/hd_bodygraph.js +2 -2
- package/dist/tools/ui-meta.d.ts +39 -0
- package/dist/tools/ui-meta.js +48 -0
- package/dist/ui/bazi.html +6 -1
- package/dist/ui/bi-wheel.html +201 -174
- package/dist/ui/bodygraph.html +176 -150
- package/dist/ui/chart-wheel.html +164 -135
- package/dist/ui/moon-phase.html +1 -1
- package/dist/ui/transit-timeline.html +2 -2
- package/dist/ui/vedic-chart.html +82 -56
- package/package.json +7 -3
- package/smithery.yaml +3 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,27 @@ Version numbering follows [Semantic Versioning](https://semver.org/).
|
|
|
7
7
|
|
|
8
8
|
---
|
|
9
9
|
|
|
10
|
+
## [4.15.1] — 2026-09-10
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
- **`ephemeris_planet_position` now says what `planet_id=10` actually returns.** The body is named
|
|
14
|
+
"North Node (Mean)", but the API serves the osculating **true** node for it (DE440, true ecliptic of
|
|
15
|
+
date) — the node Human Design uses and the one `/human-design/chart` derives gates from. It wobbles
|
|
16
|
+
±1.7° about the mean and can go direct, so a `longitude_speed` that varies or turns positive is
|
|
17
|
+
correct, not a defect. Id 11 is the analytical true node; neither id is a classical mean node. The
|
|
18
|
+
tool description states this so no caller selects id 10 believing it a mean node. Names and ids are
|
|
19
|
+
unchanged.
|
|
20
|
+
|
|
21
|
+
## [4.15.0] — 2026-09-03
|
|
22
|
+
|
|
23
|
+
### Added
|
|
24
|
+
- **`electional_angle_crossings` gains `natal_datetime`.** Pass a zoned natal instant and the search
|
|
25
|
+
finds when the **secondary-progressed** positions of Sun, Moon, Mercury, Venus, Mars and the lunar
|
|
26
|
+
nodes reach an angle at the place — the same body set and day-for-a-year formula the hybrid CCG
|
|
27
|
+
transit map draws with — while slower bodies stay transits. Progressed crossings carry
|
|
28
|
+
`progressed: true` and `search_summary.progression` names the mode, the natal instant and the
|
|
29
|
+
bodies progressed. Omit the parameter for the plain transit search, which is unchanged.
|
|
30
|
+
|
|
10
31
|
## [4.14.3] — 2026-09-02
|
|
11
32
|
|
|
12
33
|
### Fixed
|
package/README.md
CHANGED
|
@@ -198,6 +198,14 @@ Cursor deeplink payload:
|
|
|
198
198
|
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:
|
|
199
199
|
|
|
200
200
|
- **Claude Web**: Add `https://mcp.openephemeris.com/mcp` as a custom connector URL — leave OAuth Client ID and Secret **blank**. The server uses OAuth 2.1 + PKCE (Dynamic Client Registration), so Claude handles authentication via a browser popup automatically.
|
|
201
|
+
- **ChatGPT**: OpenEphemeris is not in the ChatGPT app directory — you add it yourself.
|
|
202
|
+
Turn on **Settings → Plugins → Advanced → Developer mode**, then use the **+ (Create app)**
|
|
203
|
+
button on [chatgpt.com/plugins](https://chatgpt.com/plugins). Server URL:
|
|
204
|
+
`https://mcp.openephemeris.com/mcp` (append `?profile=core` for the curated 39-tool
|
|
205
|
+
surface, which still includes every interactive chart). Leave Authentication on **OAuth**;
|
|
206
|
+
the same PKCE + Dynamic Client Registration flow applies, so there is no client ID or
|
|
207
|
+
secret to enter. Charts render inline, exactly as they do in Claude. *Developer mode was
|
|
208
|
+
available on a Free plan when this was last checked (2026-09-04); availability may vary.*
|
|
201
209
|
- **Via Smithery**: Use the [Smithery listing](https://smithery.ai/servers/open-ephemeris/openephemeris) for managed connections with any client
|
|
202
210
|
- **Legacy SSE**: retired in 3.20.0 — use Streamable HTTP at `/mcp`
|
|
203
211
|
|
|
@@ -235,7 +243,16 @@ Nine of the tools don't answer with JSON. They open a chart in the conversation
|
|
|
235
243
|
|
|
236
244
|
This matters more than it sounds. A natal chart returned as JSON is a list of numbers you have to already understand to read. The same chart rendered as a wheel is something you can point at. Click a planet and you get that placement explained; click a house and you get what's in it. The chart stays on screen while you keep talking, and it doesn't cost another credit to keep looking at it.
|
|
237
245
|
|
|
238
|
-
These need a host that supports MCP Apps
|
|
246
|
+
These need a host that supports MCP Apps. **Claude and ChatGPT both do**, and they render
|
|
247
|
+
the same widget — there is no separate ChatGPT build. MCP Apps ([SEP-1865][sep1865]) was
|
|
248
|
+
co-authored by Anthropic and OpenAI and became the first official MCP extension in January
|
|
249
|
+
2026, so one `ui://` resource serves both. In ChatGPT you add the server yourself as a
|
|
250
|
+
custom app (see [Setup](#setup)); OpenEphemeris is not in the ChatGPT app directory.
|
|
251
|
+
|
|
252
|
+
In a client without app support the same tools still work; you get the underlying data
|
|
253
|
+
instead of the picture, so nothing breaks, you just don't get the wheel.
|
|
254
|
+
|
|
255
|
+
[sep1865]: https://modelcontextprotocol.io/seps/1865-mcp-apps-interactive-user-interfaces-for-mcp
|
|
239
256
|
|
|
240
257
|
| Tool | What opens | What you can click | Credits |
|
|
241
258
|
|---|---|---|---|
|
package/dist/index.js
CHANGED
|
@@ -6,6 +6,7 @@ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
|
6
6
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
7
7
|
import { CallToolRequestSchema, ListToolsRequestSchema, ListPromptsRequestSchema, GetPromptRequestSchema, ListResourcesRequestSchema, ReadResourceRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
|
|
8
8
|
import { initTools, toolRegistry, formatToolResponse, formatToolError, modelVisibleTools, parseToolSurface, SERVER_VERSION } from "./tools/index.js";
|
|
9
|
+
import { buildUiMeta } from "./tools/ui-meta.js";
|
|
9
10
|
import { SERVER_INSTRUCTIONS } from "./instructions.js";
|
|
10
11
|
import { captureEvent, captureFirstToolCallOnce, distinctIdFor } from "./analytics.js";
|
|
11
12
|
import { listPrompts, getPromptContent } from "./prompts.js";
|
|
@@ -124,18 +125,8 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
124
125
|
idempotentHint: tool.annotations?.idempotentHint ?? true,
|
|
125
126
|
openWorldHint: tool.annotations?.openWorldHint ?? false,
|
|
126
127
|
},
|
|
127
|
-
//
|
|
128
|
-
...(tool
|
|
129
|
-
? {
|
|
130
|
-
_meta: {
|
|
131
|
-
"ui/resourceUri": tool._meta.ui.resourceUri,
|
|
132
|
-
ui: {
|
|
133
|
-
resourceUri: tool._meta.ui.resourceUri,
|
|
134
|
-
visibility: tool._meta.ui.visibility ?? ["model", "app"],
|
|
135
|
-
},
|
|
136
|
-
},
|
|
137
|
-
}
|
|
138
|
-
: {}),
|
|
128
|
+
// MCP Apps UI linkage (+ ChatGPT aliases) so hosts can prefetch the resource.
|
|
129
|
+
...buildUiMeta(tool),
|
|
139
130
|
}));
|
|
140
131
|
if (!toolsListedReported) {
|
|
141
132
|
toolsListedReported = true;
|
package/dist/server-sse.js
CHANGED
|
@@ -24,6 +24,7 @@ import { InMemoryEventStore } from "./event-store.js";
|
|
|
24
24
|
import { captureEvent, captureFirstToolCallOnce, distinctIdFor } from "./analytics.js";
|
|
25
25
|
import { CallToolRequestSchema, ListToolsRequestSchema, ListPromptsRequestSchema, GetPromptRequestSchema, ListResourcesRequestSchema, ReadResourceRequestSchema, isInitializeRequest, } from "@modelcontextprotocol/sdk/types.js";
|
|
26
26
|
import { initTools, toolRegistry, formatToolResponse, formatToolError, modelVisibleTools, parseToolSurface, describeSurface } from "./tools/index.js";
|
|
27
|
+
import { buildUiMeta } from "./tools/ui-meta.js";
|
|
27
28
|
import { SERVER_INSTRUCTIONS } from "./instructions.js";
|
|
28
29
|
import { BackendClient, runWithClient } from "./backend/client.js";
|
|
29
30
|
import { CHART_WHEEL_RESOURCE_URI, CHART_WHEEL_MIME_TYPE, getChartWheelBundle, } from "./tools/apps/chart-wheel-app.js";
|
|
@@ -304,18 +305,8 @@ function createMcpServer(analyticsId = "anonymous", surface = "core", activity =
|
|
|
304
305
|
description: tool.description,
|
|
305
306
|
inputSchema: tool.inputSchema,
|
|
306
307
|
annotations: buildAnnotations(tool),
|
|
307
|
-
//
|
|
308
|
-
...(tool
|
|
309
|
-
? {
|
|
310
|
-
_meta: {
|
|
311
|
-
"ui/resourceUri": tool._meta.ui.resourceUri,
|
|
312
|
-
ui: {
|
|
313
|
-
resourceUri: tool._meta.ui.resourceUri,
|
|
314
|
-
visibility: tool._meta.ui.visibility ?? ["model", "app"],
|
|
315
|
-
},
|
|
316
|
-
},
|
|
317
|
-
}
|
|
318
|
-
: {}),
|
|
308
|
+
// MCP Apps UI linkage (+ ChatGPT aliases) so hosts can prefetch the resource.
|
|
309
|
+
...buildUiMeta(tool),
|
|
319
310
|
}));
|
|
320
311
|
// Once per session: the host has fetched the surface. Everything after this
|
|
321
312
|
// point is the model's choice, so this is the denominator for activation.
|
|
@@ -118,7 +118,7 @@ registerTool({
|
|
|
118
118
|
"Click any pillar for an instant interpretation of what it reveals about that life domain " +
|
|
119
119
|
"(Year = ancestry/early life, Month = parents/career, Day = self/spouse, Hour = children/later life).\n\n" +
|
|
120
120
|
"CREDIT COST: 3 credits per call (1 base + 2 visual render).\n\n" +
|
|
121
|
-
"Use this for a rich, interactive BaZi experience in MCP Apps-capable hosts (Claude
|
|
121
|
+
"Use this for a rich, interactive BaZi experience in MCP Apps-capable hosts (Claude and ChatGPT). " +
|
|
122
122
|
"Falls back to a text summary in other hosts, so it is also the right call without a " +
|
|
123
123
|
"renderer. Deeper derivations (Ten Gods, element balance, luck pillars) and a plain " +
|
|
124
124
|
"non-visual pillars lookup have dedicated tools on the full surface (`?profile=full`).",
|
|
@@ -316,7 +316,7 @@ registerTool({
|
|
|
316
316
|
"and Incarnation Cross. " +
|
|
317
317
|
"The chart is calculated using NASA JPL DE440 ephemerides for both Personality and Design positions. " +
|
|
318
318
|
"Use this instead of human_design_chart for a richer, interactive HD " +
|
|
319
|
-
"experience in MCP Apps-capable hosts (Claude
|
|
319
|
+
"experience in MCP Apps-capable hosts (Claude and ChatGPT). " +
|
|
320
320
|
"Falls back to a text summary in other hosts." +
|
|
321
321
|
HD_DISCLAIMER,
|
|
322
322
|
inputSchema: {
|
|
@@ -1312,7 +1312,7 @@ registerTool({
|
|
|
1312
1312
|
"CREDIT COST: 3 credits per call.\n\n" +
|
|
1313
1313
|
"Highlights the channels a transit temporarily COMPLETES with the natal chart and any centers it " +
|
|
1314
1314
|
"newly defines — the core of a Human Design transit reading. " +
|
|
1315
|
-
"Returns an interactive overlay bodygraph in MCP Apps-capable hosts (Claude
|
|
1315
|
+
"Returns an interactive overlay bodygraph in MCP Apps-capable hosts (Claude and ChatGPT), with a text " +
|
|
1316
1316
|
"summary fallback elsewhere. Premium (Pro tier). Calculated with NASA JPL DE440 ephemerides." +
|
|
1317
1317
|
HD_DISCLAIMER,
|
|
1318
1318
|
inputSchema: {
|
|
@@ -127,7 +127,7 @@ registerTool({
|
|
|
127
127
|
"CREDIT COST: 1 credit per call.\n\n" +
|
|
128
128
|
"Supports house system switching (Placidus, Whole Sign, Equal, Koch). " +
|
|
129
129
|
"The chart is computed using NASA JPL DE440 ephemerides for sub-arcsecond precision. " +
|
|
130
|
-
"Renders interactively in MCP Apps-capable hosts (Claude
|
|
130
|
+
"Renders interactively in MCP Apps-capable hosts (Claude and ChatGPT) and falls back to " +
|
|
131
131
|
"static SVG in other hosts.",
|
|
132
132
|
inputSchema: {
|
|
133
133
|
type: "object",
|
|
@@ -204,7 +204,7 @@ registerTool({
|
|
|
204
204
|
" • Upcoming New Moon and Full Moon dates\n\n" +
|
|
205
205
|
"CREDIT COST: 3 credits per call (phase + void-of-course + aspects, 1 each).\n\n" +
|
|
206
206
|
"Use this instead of ephemeris_moon_phase for a rich, interactive lunar phase experience in " +
|
|
207
|
-
"MCP Apps-capable hosts (Claude
|
|
207
|
+
"MCP Apps-capable hosts (Claude and ChatGPT). Falls back to a text summary in other hosts.",
|
|
208
208
|
inputSchema: {
|
|
209
209
|
type: "object",
|
|
210
210
|
properties: {
|
|
@@ -106,7 +106,7 @@ registerTool({
|
|
|
106
106
|
"SEARCH RANGE LIMITS: Explorer/PayG → 1 year; Pro → 5 years; Startup → 10 years.\n\n" +
|
|
107
107
|
"CREDIT COST: 6 credits per call (natal chart + predictive transit search).\n\n" +
|
|
108
108
|
"Use this for a rich, interactive transit-forecast experience in MCP Apps-capable hosts " +
|
|
109
|
-
"(Claude
|
|
109
|
+
"(Claude and ChatGPT). Falls back to a text summary in other hosts.",
|
|
110
110
|
inputSchema: {
|
|
111
111
|
type: "object",
|
|
112
112
|
properties: {
|
|
@@ -102,7 +102,7 @@ registerTool({
|
|
|
102
102
|
"Returns an embedded visual explorer that lets you click any rashi cell for its themes and " +
|
|
103
103
|
"any planets placed there. Shows sidereal (Lahiri by default) planet placements, nakshatra with " +
|
|
104
104
|
"pada, navamsa, and the Lagna (Ascendant) rashi. Uses NASA JPL DE440 ephemerides. " +
|
|
105
|
-
"Use this for a rich, interactive Jyotish experience in MCP Apps-capable hosts (Claude
|
|
105
|
+
"Use this for a rich, interactive Jyotish experience in MCP Apps-capable hosts (Claude and ChatGPT). " +
|
|
106
106
|
"Falls back to a text summary in other hosts.",
|
|
107
107
|
inputSchema: {
|
|
108
108
|
type: "object",
|
|
@@ -10,7 +10,7 @@ const HOUSE_SYSTEM_MAP = {
|
|
|
10
10
|
};
|
|
11
11
|
registerTool({
|
|
12
12
|
name: "ephemeris_bi_wheel",
|
|
13
|
-
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
|
|
13
|
+
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 the host displays inline in the conversation.\n\n" +
|
|
14
14
|
"For a user-facing interactive bi-wheel, use explore_bi_wheel instead.\n\n" +
|
|
15
15
|
"CREDIT COST: 2 credits per call.\n\n" +
|
|
16
16
|
"EXAMPLE: Compare someone born April 15, 1990 (A) to someone born June 10, 1992 (B):\n" +
|
|
@@ -10,7 +10,7 @@ const HOUSE_SYSTEM_MAP = {
|
|
|
10
10
|
};
|
|
11
11
|
registerTool({
|
|
12
12
|
name: "ephemeris_chart_wheel",
|
|
13
|
-
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
|
|
13
|
+
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 the host displays inline in the conversation — no external tools needed.\n\n" +
|
|
14
14
|
"For a user-facing interactive chart wheel, use explore_natal_chart instead.\n\n" +
|
|
15
15
|
"CREDIT COST: 2 credits per call.\n\n" +
|
|
16
16
|
"EXAMPLE: born 15 April 1990 at 2:30 PM local time in Chicago:\n" +
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { registerTool, validateRequired } from "../index.js";
|
|
2
2
|
import { getActiveClient } from "../../backend/client.js";
|
|
3
3
|
import { OUTPUT_SCHEMA_JSON } from "../output-schemas.js";
|
|
4
|
-
import { WINDOW_DATE_DESC } from "../datetime.js";
|
|
4
|
+
import { DATETIME_DESC, WINDOW_DATE_DESC, localToUtcIso, timezoneProperty } from "../datetime.js";
|
|
5
5
|
// All electional endpoints are GET endpoints with query params.
|
|
6
6
|
// GET /electional/find-window — already existed, keeping it
|
|
7
7
|
registerTool({
|
|
@@ -279,6 +279,10 @@ registerTool({
|
|
|
279
279
|
"Crossing times use the same in-mundo geometry as the astrocartography line engine, so casting a " +
|
|
280
280
|
"map at a returned moment puts that line through the query point. Circumpolar cases (a body that " +
|
|
281
281
|
"never rises or never sets at that latitude) simply return no event.\n\n" +
|
|
282
|
+
"PROGRESSED (hybrid) lines: pass natal_datetime to search the SECONDARY-PROGRESSED positions of " +
|
|
283
|
+
"Sun, Moon, Mercury, Venus, Mars and the lunar nodes — the same body set and formula the CCG hybrid " +
|
|
284
|
+
"transit map (/acg/ccg mode=ccg_hybrid) draws with; every other body stays a transit. Progressed " +
|
|
285
|
+
"crossings carry progressed: true and search_summary.progression names what was progressed.\n\n" +
|
|
282
286
|
"CREDIT COST: 5 credits per call.\n\n" +
|
|
283
287
|
"EXAMPLE: When does Mercury cross the Descendant over Warsaw on 2026-07-30?\n" +
|
|
284
288
|
" latitude=52.2297, longitude=21.0122, bodies='Mercury', angles='DC',\n" +
|
|
@@ -320,6 +324,14 @@ registerTool({
|
|
|
320
324
|
type: "number",
|
|
321
325
|
description: "Maximum number of crossing events to return (default 5000).",
|
|
322
326
|
},
|
|
327
|
+
natal_datetime: {
|
|
328
|
+
type: "string",
|
|
329
|
+
description: "Optional natal (birth) instant. When given, Sun, Moon, Mercury, Venus, Mars and the lunar " +
|
|
330
|
+
"nodes are secondary-progressed from it (day-for-a-year) and the search finds when their " +
|
|
331
|
+
"PROGRESSED position reaches the angle — the line a hybrid CCG map paints. Slow bodies " +
|
|
332
|
+
"(Jupiter outward) are unaffected. Omit for the plain transit search. " + DATETIME_DESC,
|
|
333
|
+
},
|
|
334
|
+
natal_timezone: timezoneProperty("the natal birth location", "Europe/London"),
|
|
323
335
|
format: {
|
|
324
336
|
type: "string",
|
|
325
337
|
enum: ["json", "llm"],
|
|
@@ -349,6 +361,11 @@ registerTool({
|
|
|
349
361
|
query.refraction_correction = args.refraction_correction;
|
|
350
362
|
if (args.max_results !== undefined)
|
|
351
363
|
query.max_results = args.max_results;
|
|
364
|
+
// A naive birth time plus its zone is a legitimate call (the datetime
|
|
365
|
+
// contract); the API's GET takes one zoned instant, so resolve here.
|
|
366
|
+
if (args.natal_datetime) {
|
|
367
|
+
query.natal_datetime = localToUtcIso("natal_datetime", args.natal_datetime, args.natal_timezone, "natal_timezone");
|
|
368
|
+
}
|
|
352
369
|
if (args.format)
|
|
353
370
|
query.format = args.format;
|
|
354
371
|
return await getActiveClient().request("GET", "/electional/angle-crossings", {
|
|
@@ -12,6 +12,9 @@ registerTool({
|
|
|
12
12
|
"12=Lilith (Mean), 15=Chiron, 17=Ceres, 18=Pallas, 19=Juno, 20=Vesta.\n\n" +
|
|
13
13
|
"SOUTH NODE: there is no South Node id. The South Node is always exactly " +
|
|
14
14
|
"opposite the North Node — request id 10 or 11 and add 180° (mod 360).\n\n" +
|
|
15
|
+
"NODES: despite its name, id 10 returns the osculating TRUE node (DE440, ecliptic of " +
|
|
16
|
+
"date) — the Human Design node. It wobbles ±1.7° about the mean and can go direct; " +
|
|
17
|
+
"that is correct. Id 11 is the analytical true node. Neither is a classical mean node.\n\n" +
|
|
15
18
|
"CREDIT COST: 1 credit per call.\n\n" +
|
|
16
19
|
"EXAMPLE: Where is Mars on 2026-03-20 at noon UTC?\n" +
|
|
17
20
|
" planet_id=4, datetime='2026-03-20T12:00:00Z'",
|
|
@@ -9,7 +9,7 @@ registerTool({
|
|
|
9
9
|
"Renders the full bodygraph circuit board showing all 9 centers, 36 channels, and 64 gates " +
|
|
10
10
|
"with Personality (conscious) and Design (unconscious) activations color-coded. " +
|
|
11
11
|
"Defined centers are filled with their HD doctrine color; open/undefined centers remain muted. " +
|
|
12
|
-
"Returns a native SVG
|
|
12
|
+
"Returns a native SVG the host displays inline. Use format='png' to opt into raster output (requires server-side rasterizer).\n\n" +
|
|
13
13
|
"For a user-facing interactive bodygraph explorer, use explore_human_design instead.\n\n" +
|
|
14
14
|
"CREDIT COST: 2 credits per call.\n\n" +
|
|
15
15
|
"EXAMPLE (local birth time + zone): born 15 April 1990 at 14:30 in Chicago:\n" +
|
|
@@ -42,7 +42,7 @@ registerTool({
|
|
|
42
42
|
format: {
|
|
43
43
|
type: "string",
|
|
44
44
|
enum: ["svg", "png"],
|
|
45
|
-
description: "Output format. Defaults to 'svg' (pure Go renderer — no external deps, displays
|
|
45
|
+
description: "Output format. Defaults to 'svg' (pure Go renderer — no external deps, displays inline in any host that renders images). Use 'png' for raster output (requires server-side rasterizer).",
|
|
46
46
|
},
|
|
47
47
|
},
|
|
48
48
|
required: ["datetime"],
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* src/tools/ui-meta.ts — the `_meta` block a tool carries when it renders an MCP App.
|
|
3
|
+
*
|
|
4
|
+
* One builder, used by both transports (stdio `src/index.ts`, remote
|
|
5
|
+
* `src/server-sse.ts`), because the two had drifted into copy-paste twins of the
|
|
6
|
+
* same object literal and only one of them would ever get updated.
|
|
7
|
+
*
|
|
8
|
+
* Three wire forms, all describing the same `ui://` resource:
|
|
9
|
+
*
|
|
10
|
+
* 1. `_meta.ui.{resourceUri,visibility}` — the canonical MCP Apps form
|
|
11
|
+
* (SEP-1865, first official MCP extension 2026-01-26, folded into the
|
|
12
|
+
* 2026-07-28 spec). This is what the spec says hosts read.
|
|
13
|
+
* 2. `_meta["ui/resourceUri"]` — the deprecated flat alias. The spec says it
|
|
14
|
+
* "will be removed before general availability"; kept only for pre-GA
|
|
15
|
+
* hosts still on the older shape. Drop it once those are gone.
|
|
16
|
+
* 3. `_meta["openai/*"]` — ChatGPT's compatibility aliases. OpenAI co-authored
|
|
17
|
+
* SEP-1865 and its own reference documents `openai/outputTemplate` as an
|
|
18
|
+
* "optional/compatibility alias for `_meta.ui.resourceUri`", so a fully
|
|
19
|
+
* converged ChatGPT host needs nothing here. Emitting it anyway is a few
|
|
20
|
+
* bytes and removes the question of which side converged first.
|
|
21
|
+
*
|
|
22
|
+
* `openai/widgetAccessible` marks a tool the widget itself may invoke. That is
|
|
23
|
+
* exactly what `visibility` already encodes: a tool visible to "app" is one the
|
|
24
|
+
* iframe calls (the `*_recalculate` and `*_on_*_click` handlers), so the flag is
|
|
25
|
+
* derived rather than hand-maintained on 92 tools.
|
|
26
|
+
*/
|
|
27
|
+
export interface UiMetaSource {
|
|
28
|
+
_meta?: {
|
|
29
|
+
ui?: {
|
|
30
|
+
resourceUri?: string;
|
|
31
|
+
visibility?: Array<"app" | "model">;
|
|
32
|
+
};
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Build the `_meta` wrapper for a tool, or `{}` when the tool renders no UI.
|
|
37
|
+
* Spread the result into the tools/list entry.
|
|
38
|
+
*/
|
|
39
|
+
export declare function buildUiMeta(tool: UiMetaSource): Record<string, unknown>;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* src/tools/ui-meta.ts — the `_meta` block a tool carries when it renders an MCP App.
|
|
3
|
+
*
|
|
4
|
+
* One builder, used by both transports (stdio `src/index.ts`, remote
|
|
5
|
+
* `src/server-sse.ts`), because the two had drifted into copy-paste twins of the
|
|
6
|
+
* same object literal and only one of them would ever get updated.
|
|
7
|
+
*
|
|
8
|
+
* Three wire forms, all describing the same `ui://` resource:
|
|
9
|
+
*
|
|
10
|
+
* 1. `_meta.ui.{resourceUri,visibility}` — the canonical MCP Apps form
|
|
11
|
+
* (SEP-1865, first official MCP extension 2026-01-26, folded into the
|
|
12
|
+
* 2026-07-28 spec). This is what the spec says hosts read.
|
|
13
|
+
* 2. `_meta["ui/resourceUri"]` — the deprecated flat alias. The spec says it
|
|
14
|
+
* "will be removed before general availability"; kept only for pre-GA
|
|
15
|
+
* hosts still on the older shape. Drop it once those are gone.
|
|
16
|
+
* 3. `_meta["openai/*"]` — ChatGPT's compatibility aliases. OpenAI co-authored
|
|
17
|
+
* SEP-1865 and its own reference documents `openai/outputTemplate` as an
|
|
18
|
+
* "optional/compatibility alias for `_meta.ui.resourceUri`", so a fully
|
|
19
|
+
* converged ChatGPT host needs nothing here. Emitting it anyway is a few
|
|
20
|
+
* bytes and removes the question of which side converged first.
|
|
21
|
+
*
|
|
22
|
+
* `openai/widgetAccessible` marks a tool the widget itself may invoke. That is
|
|
23
|
+
* exactly what `visibility` already encodes: a tool visible to "app" is one the
|
|
24
|
+
* iframe calls (the `*_recalculate` and `*_on_*_click` handlers), so the flag is
|
|
25
|
+
* derived rather than hand-maintained on 92 tools.
|
|
26
|
+
*/
|
|
27
|
+
const DEFAULT_VISIBILITY = ["model", "app"];
|
|
28
|
+
/**
|
|
29
|
+
* Build the `_meta` wrapper for a tool, or `{}` when the tool renders no UI.
|
|
30
|
+
* Spread the result into the tools/list entry.
|
|
31
|
+
*/
|
|
32
|
+
export function buildUiMeta(tool) {
|
|
33
|
+
const resourceUri = tool._meta?.ui?.resourceUri;
|
|
34
|
+
if (!resourceUri)
|
|
35
|
+
return {};
|
|
36
|
+
const visibility = tool._meta?.ui?.visibility ?? DEFAULT_VISIBILITY;
|
|
37
|
+
return {
|
|
38
|
+
_meta: {
|
|
39
|
+
// Deprecated flat form — pre-GA hosts only.
|
|
40
|
+
"ui/resourceUri": resourceUri,
|
|
41
|
+
// Canonical MCP Apps form.
|
|
42
|
+
ui: { resourceUri, visibility },
|
|
43
|
+
// ChatGPT compatibility aliases.
|
|
44
|
+
"openai/outputTemplate": resourceUri,
|
|
45
|
+
"openai/widgetAccessible": visibility.includes("app"),
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
}
|
package/dist/ui/bazi.html
CHANGED
|
@@ -6802,7 +6802,7 @@ function E_(e4, t2, n2 = []) {
|
|
|
6802
6802
|
let e5 = document.getElementById("fs-hint-banner");
|
|
6803
6803
|
e5 && e5.remove();
|
|
6804
6804
|
let t3 = document.createElement("div");
|
|
6805
|
-
t3.id = "fs-hint-banner", Object.assign(t3.style, { position: "fixed", top: "12px", left: "50%", transform: "translateX(-50%)", background: "oklch(14% 0.012 265 / 0.90)", backdropFilter: "blur(12px)", WebkitBackdropFilter: "blur(12px)", border: "1px solid oklch(72% 0.12 80 / 0.3)", borderRadius: "20px", padding: "6px 16px", fontSize: "11px", fontWeight: "600", color: "oklch(80% 0.08 80)", letterSpacing: "0.04em", zIndex: "9999", pointerEvents: "none", opacity: "0", transition: "opacity 300ms ease", whiteSpace: "nowrap" }), t3.textContent = "Esc \u2014 exit fullscreen & return to
|
|
6805
|
+
t3.id = "fs-hint-banner", Object.assign(t3.style, { position: "fixed", top: "12px", left: "50%", transform: "translateX(-50%)", background: "oklch(14% 0.012 265 / 0.90)", backdropFilter: "blur(12px)", WebkitBackdropFilter: "blur(12px)", border: "1px solid oklch(72% 0.12 80 / 0.3)", borderRadius: "20px", padding: "6px 16px", fontSize: "11px", fontWeight: "600", color: "oklch(80% 0.08 80)", letterSpacing: "0.04em", zIndex: "9999", pointerEvents: "none", opacity: "0", transition: "opacity 300ms ease", whiteSpace: "nowrap" }), t3.textContent = "Esc \u2014 exit fullscreen & return to chat", document.body.appendChild(t3), requestAnimationFrame(() => {
|
|
6806
6806
|
t3.style.opacity = "1";
|
|
6807
6807
|
}), setTimeout(() => {
|
|
6808
6808
|
t3.style.opacity = "0", setTimeout(() => t3.remove(), 350);
|
|
@@ -6856,6 +6856,11 @@ async function V_(e4) {
|
|
|
6856
6856
|
}
|
|
6857
6857
|
}
|
|
6858
6858
|
async function H_(e4) {
|
|
6859
|
+
let t2 = F_ == null ? void 0 : F_._birth_params;
|
|
6860
|
+
if (t2) {
|
|
6861
|
+
let n2 = String(t2.hour).padStart(2, "0");
|
|
6862
|
+
e4 = "BaZi chart: ".concat(t2.year, "-").concat(String(t2.month).padStart(2, "0"), "-").concat(String(t2.day).padStart(2, "0"), " ").concat(n2, ":00\n\n").concat(e4);
|
|
6863
|
+
}
|
|
6859
6864
|
try {
|
|
6860
6865
|
(await P_.sendMessage({ role: "user", content: [{ type: "text", text: e4 }] })).isError && console.error("[BaZi] Host rejected sendMessage");
|
|
6861
6866
|
} catch (e5) {
|