Date: 2026-06-06 Status: Draft — for review and discussion before implementation
Astro-MCP already computes everything: planetary positions, houses, aspects, patterns, chart shapes, Davison/composite charts, transit previews. What's missing is visual output — turning that rich data into actual chart wheels and tables that a human can look at.
The goal is to add chart rendering that covers:
The existing MCP tools return all the data we need:
| Tool | Data Available |
|---|---|
calculate_natal_chart |
Planets (sign, degree, house, retrograde), houses, aspects, angles, lunar phase, overview (elements, modalities, hemispheres, stelliums, empty houses, chart ruler, house rulers, retro list), aspect patterns, chart shape, karmic (nodal axis, Saturn, Pluto polarity point, Part of Fortune, 12th house) |
calculate_transit_chart |
Natal planets + transiting planets + transit-to-natal aspects + houses |
calculate_synastry_chart |
Both natal charts + interaspects + house overlays + composite + Davison |
calculate_composite_chart |
Composite planets + houses + aspects + angles |
calculate_davison_chart |
Davison planets + houses + aspects + angles |
get_transit_preview |
Daily transit snapshots with significance scores |
get_planetary_positions |
Quick lookup with zodiac positions |
No new calculation logic is needed — rendering is purely a presentation layer on top of existing tools.
The classic circular zodiac wheel:
Two concentric zodiac wheels:
A matrix grid showing all planet-to-planet aspects:
Tabular view of all planet positions:
Traditional / Old-Fashioned:
Modern / Clean:
Dark Theme (for web):
URL: https://www.zodiacfonts.com/ License: Free tier under SIL OFL (Open Font License). Pro license for premium exclusives.
What they offer:
How we'd use this:
@font-face in CSS, render zodiac
glyphs with a single unicode character. This is the cleanest approach for both
web SVG and WeasyPrint PDF generation.<image> or inline <svg> in
the chart wheel for planet markers.Integration plan:
static/fonts/ directory@font-face { font-family: 'ZodiacFont'; src: url('/static/fonts/zodiac-sans-regular.ttf'); }Code point mapping (to verify from the actual font):
Zodiac signs: ♈ ♉ ♊ ♋ ♌ ♍ ♎ ♏ ♐ ♑ ♒ ♓ (U+2648..U+2653)
Planets: ☉ ☽ ☿ ♀ ♃ ♄ ♅ ♆ ♇ ⚳ ⚷ ⚴ ⚵ ⚶ (various unicode)
Aspects: ☌ ⚹ △ □ ⚻ ☍ (U+260C, U+26B9, etc.)
Recommended approach: Use svgwrite (Python library) to programmatically
generate SVG chart wheels directly on the server side.
Why SVGWrite over alternatives:
Alternative considered:
┌─────────────────────┐
│ MCP Tool (data) │
│ calculate_natal_ │
│ chart / transit / │
│ synastry / etc. │
└────────┬────────────┘
│ JSON data
▼
┌─────────────────────┐
│ Chart Renderer │
│ (new module: │
│ chart_renderer.py) │
│ │
│ - wheel SVG gen │
│ - aspect grid SVG │
│ - planet table SVG │
│ - style engine │
│ - color themes │
└────────┬────────────┘
│ SVG string
┌────────────┼─────────────┐
▼ ▼
┌──────────────┐ ┌──────────────────┐
│ Web Route │ │ PDF Export │
│ (inline SVG │ │ (WeasyPrint │
│ in HTML) │ │ SVG -> PDF) │
└──────────────┘ └──────────────────┘
src/astro_mcp/
chart_renderer.py — Main rendering module
chart_styles.py — Theme/style definitions (colors, fonts, line styles)
chart_templates/ — (optional) Jinja2 templates for HTML wrapping
static/
fonts/ — ZodiacFonts TTF files
chart-colors.yaml — User-configurable color themes
templates/
chart-wheel.html — Standalone chart display page
chart-aspects.html — Aspect table page
chart-print.html — Print-optimized layout
docs/
chart-rendering-proposal.md ← this file
New tools that return chart data ready for rendering, or even render and return SVG/PDF directly:
@mcp.tool()
async def render_chart(
chart_data: dict, # output from calculate_natal_chart etc.
format: str = "svg", # "svg" | "pdf" | "png"
style: str = "modern", # "modern" | "traditional" | "minimal"
color_mode: str = "color" | "bw",
include_aspects: bool = True,
include_table: bool = True,
) -> dict:
"""Render an astrological chart wheel as SVG, PDF, or PNG.
Returns the rendered chart as base64-encoded data or saves to file
and returns the path.
"""
GET /dashboard/charts/person/{id} — Select chart type + options
GET /dashboard/charts/person/{id}/natal — Render natal chart wheel
GET /dashboard/charts/person/{id}/transit?date=... — Transit bi-wheel
GET /dashboard/charts/compare/{id1}/{id2} — Synastry bi-wheel
GET /dashboard/charts/aspects/{id} — Aspect grid/table
Each route accepts query params:
format=svg|pdf|png (default: inline SVG)style=modern|traditional|minimalcolor=color|bw (default: color for web, bw for pdf)width=800 (SVG pixel width)house_system=placidus| Aspect | Color (web) | Line style (B&W) | Symbol |
|---|---|---|---|
| Conjunction | Red (#e74c3c) | Solid (2px) | ☌ |
| Sextile | Blue (#3498db) | Dotted (1px) | ⚹ |
| Square | Red (#c0392b) | Dashed (2px) | □ |
| Trine | Green (#2ecc71) | Dashed (2px) | △ |
| Quincunx | Orange (#e67e22) | Dash-dot (1px) | ⚻ |
| Opposition | Red (#e74c3c) | Solid (2px) | ☍ |
Colors fully customizable per theme.
1. call calculate_natal_chart(birth_data, include_overview=true, include_patterns=true)
→ get full chart JSON
2. pass JSON to chart_renderer.render_wheel(chart_data, style="modern", color="color")
→ get SVG string
3. either:
a. embed SVG inline in Jinja2 template → HTML page (web dashboard)
b. pass SVG to WeasyPrint → PDF (download/print)
c. use cairosvg to convert SVG → PNG (thumbnail/preview)
(person_id, chart_type, style, color_mode, options)The existing /dashboard/persons/{id} page shows person data but no chart.
Add a tab or section:
# Default color theme
zodiac_signs:
fire: "#e74c3c"
earth: "#27ae60"
air: "#f39c12"
water: "#3498db"
aspect_colors:
conjunction: "#e74c3c"
sextile: "#3498db"
square: "#c0392b"
trine: "#2ecc71"
quincunx: "#e67e22"
opposition: "#e74c3c"
# B&W theme
bw:
aspect_styles:
conjunction: { stroke: "#000", stroke_width: 2, dasharray: "none" }
sextile: { stroke: "#000", stroke_width: 1, dasharray: "3,3" }
square: { stroke: "#000", stroke_width: 2, dasharray: "6,3" }
trine: { stroke: "#000", stroke_width: 2, dasharray: "6,3" }
quincunx: { stroke: "#000", stroke_width: 1, dasharray: "6,3,2,3" }
opposition: { stroke: "#000", stroke_width: 2, dasharray: "none" }
# Dark theme (web)
dark:
background: "#0f1117"
text: "#c9d1d9"
ring_fill: "#161b22"
ring_stroke: "#30363d"
# Light theme (print)
light:
background: "#ffffff"
text: "#000000"
ring_fill: "#f8f4e8" # parchment
ring_stroke: "#8b7355"
Page 1: Title + Chart Wheel
┌──────────────────────────────┐
│ John Doe — Natal Chart │
│ 1965-07-02 00:05 GMT+1 │
│ Graz, Austria │
│ │
│ [ CHART WHEEL ] │
│ │
│ Placidus | Tropical │
└──────────────────────────────┘
Page 2: Aspect Table
┌──────────────────────────────┐
│ Aspect Grid │
│ [ colored/symbol grid ] │
│ │
│ Tightest Aspects: │
│ Sun ☌ Moon 0°32' │
│ Mars △ Jupiter 1°15' │
│ ... │
└──────────────────────────────┘
Page 3: Planet & House Data
┌──────────────────────────────┐
│ Planet Positions │
│ Sun Leo 9°23' 10H │
│ Moon Cancer 22°17' 9H │
│ ... │
│ │
│ House Cusps │
│ ASC Virgo 28°41' │
│ MC Gemini 25°12' │
│ ... │
└──────────────────────────────┘
svgwrite dependencychart_styles.py with theme definitionschart_renderer.py with basic wheel SVG generation
static/fonts/show_info=true/false, per privacy settingEnd of document — ready for review.