Wire in five minutes.
Tools live from the server.
The tool catalog below is rendered live from mcp.kundalimcp.com/mcp via ISR, revalidated hourly — so it lags a release by up to an hour but cannot diverge beyond that.
tools/list, so it cannot drift.Direct API — from zero to a real chart in three steps.
Every authenticated request is JSON-RPC 2.0 over HTTPS to https://mcp.kundalimcp.com/mcp.
Protocol revision. We speak MCP 2026-07-28 and still accept 2025-11-25, 2025-06-18 and 2025-03-26. At initialize we answer with the revision YOU asked for whenever we speak it; only an unsupported request gets ours back, as -32001.
server/discover returns our identity and accepted revisions with no handshake and no auth — the quickest way to check what a deployment speaks.
Every result carries resultType: "complete", or "input_required" when a chat turn needs birth data before it can answer. tools/list declares ttlMs and cacheScope so you can cache the catalog, and returns tools in a stable order.
Get an API key
Sign up at kundalimcp.com/pricing, create a key from your dashboard, and pass it as a Bearer token. Keys are prefixed sutra_ followed by 32 hex characters.
Authorization: Bearer sutra_<32 hex chars>Cast your first chart
Five required fields: birth_datetime (local clock time at the birth place, ISO 8601 naive — no Z, no offset; the server resolves the historical timezone from the coordinates), latitude, longitude, school, locale. Everything else defaults — see Tools below for the full input schema.
curl -X POST https://mcp.kundalimcp.com/mcp \
-H "Authorization: Bearer sutra_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "kundali",
"arguments": {
"birth_datetime": "1990-01-15T05:00:00",
"latitude": 28.6139,
"longitude": 77.2090,
"school": "parashari",
"locale": "en"
}
}
}'Read the response
You get ONE XML document in content[0].text — a <kundalimcp> root carrying planet positions, divisional charts, qualified yogas, the dasha timeline, panchanga and classical citations, all in the requested locale, with every id resolved once in the closing <glossary>. There is no structuredContent (removed in 16.0.0). Every datetime is LOCAL clock time read against the tz_iana the root declares — no _utc twins, no Julian days. The chart_hash identifies it for idempotency / dedupe; it is not a shortcut for follow-up calls — every chart-anchored tool re-supplies the underlying birth data (either as flat birth_datetime/latitude/longitude fields directly, or wrapped in a chart_ref object). The resulting artifact is auto-cached in encrypted form keyed off your API key (operator-blind), TTL up to 30 days. Pass cache: “skip” per-call to disable.
The exact element set evolves with the API version surfaced in every _meta.api_version, which stays on the JSON-RPC result beside the document. Read one response to learn the shape; introspect tools/list to wire types in code.
Two steps to your first Jyotish answer.
KundaliMCP is a native MCP server — Claude, ChatGPT, and any other MCP host connect directly. No SDK, no adapter. Add the server, paste the system prompt, ask about your chart.
Add the MCP server
In your AI client, add a new MCP server and paste the endpoint URL. Authorize with OAuth (one click) or use a sutra_ API key as the bearer token.
https://mcp.kundalimcp.com/mcpAdd the system prompt
Paste this into your AI's custom instructions or system prompt. It encodes seven rules the server expects the agent to follow — chart-first discipline, boundary sensitivity, classical citation, locale fidelity, privacy scope — so you don't have to re-teach them every session.
You are using KundaliMCP, a Vedic Jyotish computation server. The server is the source of truth — never paraphrase astrology from memory; always read it from a tool response.
1. CHART FIRST. When the user supplies birth data (datetime + latitude + longitude), call kundali before answering any chart-related question. Every chart-anchored tool accepts the flat fields (birth_datetime + latitude + longitude) directly; a chart_ref object wrapping the same three fields also works. chart_hash is for bookkeeping (idempotency, dedupe), not for skipping re-supply.
2. ONE CALL, MANY SECTIONS. kundali returns the chart AND its sections from a single computation. Yogas, the Vimshottari timeline, the forward dasha reading, current transits, remedies, graha positions and the birth panchanga all ship by DEFAULT — do not make a second call for them. Add more with include, a comma-separated list: vargas (divisional charts; pass vargas: ["D9","D10"]), classical_rules (the cited rules that fired, LARGE — bound it with classical_rules_limit: N per bhava, or classical_rules_bhavas: [7,2] to keep only the houses you asked about), narrative (a plain-language reading for one domain), transit_events (ingresses/stations/returns across a window; pass transit_start and transit_end), reasoning and idl. A section parameter sent WITHOUT its include token is an error, not a no-op.
3. RESPECT BOUNDARY SENSITIVITY. kundali returns a <boundary_margins> block flagging placements near nakshatra / pada / sign cusps. If any row carries sensitive="true", ask the user to confirm exact birth time before quoting any nakshatra-, pada-, or D9-based prediction.
3b. READ THE LABELS OFF THE ELEMENTS. Every response is ONE XML document in content[0].text; there is no structuredContent. A block states which chart and frame it is of on its own attributes - <placements chart="D1" frame="natal"> is the birth chart, chart="D9" is a divisional, frame="transit" is where the grahas are NOW. Never state a divisional or transiting placement as a natal one. Ids are resolved once in the closing <glossary>; a row that names a subject carries that name inline. Every datetime is LOCAL clock time in the zone the root declares as tz_iana.
4. PICK THE RIGHT TOOL FOR TIME.
- Active dasha, forward reading, and the sky right now: already in the kundali response (dashas, dasha_forecast, transits).
- Deeper Vimshottari levels: kundali with dasha_depth (1=MD, 2=MD+AD default, 3=+pratyantar).
- Significant transits across a range: kundali with include=transit_events plus transit_start and transit_end.
- Triggered life events: kundali with include=events. eval_date alone gives a snapshot at that date; add events_until for a horizon scan, which is what "when will I…" actually needs.
- Lifetime view (dasha tree, life-area trajectories, life events, sade sati, returns): lifemap.
- A day's panchanga at a place: panchang. An auspicious moment for an activity: muhurat.
- Why one specific claim is true, back to the ephemeris: pramaan, addressed by the concept URI the response already gave you (e.g. concept:yoga/gajakesari).
5. PRESERVE LOCALIZATION. Response strings are returned in the requested locale (en, hi, sa, ta, te, kn, bn). Quote them verbatim — never re-translate. If a response signals a locale fallback (English shown because that locale is not yet authored), surface the English and note the locale is pending.
6. CITE THE SOURCE. Every row that asserts a verdict carries its witness as a child: <why><cond> for the condition that fired, <cite> for the classical locus. A verdict without one cannot be produced. Quote the <cite> when stating a verdict, and never state a verdict whose row you cannot point at.
7. PRIVACY. Birth data is processed in-process and may be cached in encrypted form, with cache lifetime up to 30 days. Cached entries are encrypted with material derived from your API key, which KundaliMCP cannot decrypt without your live key. Pass cache: "skip" per-call to disable.
8. SCOPE. KundaliMCP is Vedic / Indian-tradition only. Synastry, composite charts, Western aspects, Babylonian ayanamshas, Regiomontanus / Porphyry / Morinus / Alcabitius houses, and Western dignity are out of scope. If the user asks, redirect to the Vedic equivalent (e.g. kundali_milan for Kundali Milan) or decline.Ask your first question
Once connected, the agent calls kundali automatically when you give it birth data. Try:
I was born on January 15, 1990 at 5:00 AM in New Delhi.
Cast my Parashari chart in English.The agent will call kundali — one call returning graha positions, active yogas, the Vimshottari timeline, current transits, remedies, the birth panchanga and classical citations. All from the server, nothing from memory.
Two paths. One bearer header.
Two methods — both via Authorization: Bearer
- OAuth 2.1 — for interactive AI clients (Claude, ChatGPT). One-click connect; no secret to manage. Setup guides →
- API key — long-lived
sutra_…bearer for CI and server-to-server callers. Generate from dashboard →
Discovery methods (initialize, tools/list, ping, get_version) are unauthenticated — agents can introspect before paying.
API key format
Authorization: Bearer sutra_<32 hex chars>Storage
Keys are stored as SHA-256 hashes; plaintext is never persisted. Copy your key immediately on creation — it cannot be recovered.
Rotation
Create and revoke keys from your dashboard at any time. Revoked keys return 401 immediately.
Transport
TLS 1.3 required on all endpoints. HMAC signing available for webhook callbacks.
Best practice
Never embed keys in client-side code. Use environment variables or a backend proxy.
Every tool. Live schema.
Rendered directly from https://mcp.kundalimcp.com/mcp. If a field appears here, the server accepts it; if it doesn't, we don't document it because we can't guarantee it.
Discover from your agent in two unauthenticated calls
# What can this server do?
{"jsonrpc":"2.0","id":1,"method":"tools/list"}
# What's the API version + protocol?
{"jsonrpc":"2.0","id":2,"method":"tools/call",
"params":{"name":"get_version","arguments":{}}}Both bypass auth; tools/call for any other tool requires a sutra_ key.
Server conventions (apply to every tool)
KundaliMCP — agentic-AI Vedic Jyotish MCP. Authenticated tier. See https://kundalimcp.com/docs.
TIME: every datetime input is naive local clock time at the relevant location (no 'Z', no ±HH:MM offset); the server resolves the historical UTC offset from latitude + longitude. Every emitted datetime is likewise naive local clock time, read against the ONE zone the root declares — `tz_iana` + `tz_offset_minutes` on <kundalimcp>. There is no UTC twin, no `_local` suffix and no Julian Day. A block for a different zone (a milan party's birth) carries its own `tz_iana` / `tz_offset_minutes` and those govern its subtree.
chat
Open-ended Jyotish conversation grounded in citations from the classical canon (BPHS, Phaladeepika, Saravali, and curated commentaries). Birth data is OPTIONAL.
Tier: All · Typical response: 1-3 KB.
Response shape
Returns: · ONE XML document in content[0].text — `<kundalimcp tool="chat" schema="1" locale=… tool_class="conversational" answered=… needs_birth_data=… [time_known]>` — and NO structuredContent. · <headline>, then <answer>: the composed prose. · <claims n> of <claim>: a claim with no resolved citation carries kind="uncited". On an LLM-generated answer effectively every claim is uncited BY DESIGN — the generator writes prose with no inline markers, and a marker is forgeable. · <citations kind="grounding" n> of <citation concept [name] [locus] [source]>: the GROUNDING SET — what the engine knew about this chart and question, not evidence the answer cited. · <citations kind="addressed" n> of <provenance concept>: the subset the answer actually engaged with. · <needs kind="birth_data" n> of <need field>: the fields still required, present only when needs_birth_data is true. · <classification tier="tier1|tier2|tier3" category on_topic [specialty] [intent_kind]>: a tier="tier1" (crisis) turn ships NO <answer> element, <claims n="0">, answered="false" and <metadata route="tier1_crisis">. It carries no crisis-resource content of its own; `tier` and `route` are the only signals it emits. · <metadata validator_passed route [thread_context_chars]>: `route` names how the turn was produced — `llm_synthesis` for a composed answer; `off_topic`, `ask_back`, `milan_ask_back`, `tier1_crisis`, `longevity_gate`, `diagnosis_gate`, `classify_unavailable`, `safety_review_unavailable`, `unsourced_concept` or `well_exhausted` (the thread has covered everything on this subject) for a deterministic reply. An answered="false" turn names its reason here, plus <validator_issues n> only when the safety scan flagged something (absent when clean). · <redirect_cta> when the turn was redirected rather than answered. · answered="false" when needs_birth_data is true or there are no claims — but it can arrive WITH a non-empty <claims>, because an ask-back turn answers the general doctrine before asking — `answered` and a non-empty <claims> are independent.
Input
male · femaleen · hi · sa · ta · te · kn · bnget_version
Return engine + API version + protocol info. Unauthenticated — no API key required.
Tier: All (no auth required) · Typical response: <1 KB.
Response shape
Returns ONE XML document in content[0].text — `<kundalimcp tool="get_version" schema="1" locale="en" tool_class="metadata" engine=… api=…>` — and NO structuredContent: <headline>, <version engine api api_released rules vedaksha codename mcp_protocol tools_available>, <build sha number at>. Takes no parameters.
No input parameters.
kundali
Compute a Vedic (Jyotish) birth chart. RESPONSE FORMAT (schema 1): ONE XML document in content[0].text — `<kundalimcp tool="kundali" schema="1" locale=… tz_iana=… tz_offset_minutes=… tool_class="chart_anchored" engine=… api=… school=… chart_hash=…>` — and NO structuredContent. Every datetime is naive LOCAL clock time in the natal zone the root declares (no UTC, no Julian Day); Sade Sati spans and nodal transits are YYYY-MM-DD dates. Scalars are attributes, prose is a child element, ids are ASCII slugs and every referenced id (graha, rashi, nakshatra, remedy target) is named ONCE in the trailing <glossary> in the request locale; a row's own subject keeps `name` inline. EVERY ROW THAT `pramaan` CAN EXPLAIN CARRIES `claim` — the exact `claim_id` to send it, verbatim; `id` always NAMES the row and is never a URI. Verdict attributes (quality, polarity, confidence, severity) appear only on rows that carry their <why> witness or <cite> locus. Root blocks, in order: <headline>; <context frame="natal" [gender]> (<school id ayanamsa house_system node_type>, <computed as_of> — the ONE evaluation instant every "now" block is anchored on: the caller's `transit_date`, else now); <lagna rashi nakshatra pada lord>, <chandra>, <surya>, <arudha_lagna>; <placements chart="D1" frame="natal" ref="lagna" n="9"> of <graha id name abbr rashi bhava bhava_from_moon nakshatra pada nakshatra_lord dignity motion [flags="retrograde combust deeply_combust war"] [war_opponent war_winner]>; <bhavas chart="D1" ref="lagna"> and <bhavas ref="chandra"> (the Chandra kundali) of <bhava n rashi lord_in occupants>; <yutis>; <aspects frame="natal"> of <aspect from from_bhava to_bhava [to] ordinal>; <yogas chart="D1" n of active> of <yoga id name claim category quality rarity bhavas grahas> rows each with a <narrative domain=…> child, and under `include=provenance` their <why><cond>…</cond></why>, <cite> and <description>; <afflictions> of <affliction id claim type affected cause_kind [cause] bhavas severity cancelled> with its mechanism as <why> under `include=provenance`; <active_dasha system as_of> of <period level lord ends> rows (plus <period rel="next">); <sade_sati active as_of [phase]> with <span rel start end>; <nodal_transit as_of> of <graha id rashi bhava bhava_from_moon since until>; <placements frame="transit" as_of> of <graha id rashi bhava bhava_from_moon [flags]>; <aspects frame="transit" as_of n of> of <aspect from to ordinal>; <dashas system="vimshottari" frame="natal" depth n total_years [branch]> of nested <period level lord start end days> — the FIRST mahadasha's `start` is the token `birth`, not a timestamp, because the Vimshottari clock begins at the nativity; <dashas kind="forecast" as_of> (the period active at `eval_date`, its <label kind="theme">s and the next changes); <mangal_dosha present base_severity [mitigations]> with <bhava n ref> rows; <panchanga frame="birth"> of <limb kind id name …> (the same limb shape as the `panchang` tool); <chara_karakas>; <profession>; <marakas>; <shadbala unit="virupa"> (the seven grahas Surya to Shani; BPHS Ch.27 excludes the nodes), <ashtakavarga kind="sarva" points>, <vimshopak>, <functional_classifications> (each graha with <relations kind="compound">; the naisargika and tatkalika tables are NOT emitted — the first is a universal constant, the second a pure function of signs already in <placements>), <boundary_margins> of <graha id sensitive>, <dispositions> of <bhava n disposition readings>; <synthesis kind="yogas">; <remedies n top overall_confidence> of <remedy id name type addresses>; then the opt-in blocks, <absent not_requested=…> plus one <absent section reason>text</absent> per section that had nothing to say (not_applicable) or broke (failed), <disclaimers>, <glossary>. OPT-IN, via `include`: `classical_rules` adds <insights n of [limit bhavas omitted]> — one <insight rule claim topic bhava polarity confidence grahas [suppressed_by]> per cited rule that fired, with <why>, <cite>, <title>, <reading>; pass `classical_rules_limit` (per-bhava cap, the <bhava n shown of> marker rows keep the totals) and/or `classical_rules_bhavas`. `provenance` adds THE GROUNDS for every claim in the response: the <why> witness (which limb of the classical condition held on THIS chart), the <cite> locus, the rule source text (<description>, <reading>) and a <trace significator shadbala strength_ratio> under each insight. Without it a row still states its verdict and carries `claim` — the exact `claim_id` to send `pramaan` for that one row. Same token and meaning on `lifemap`, `kundali_milan`, `muhurat` and `pramaan`. `vargas` adds, per requested divisional, <placements chart="D9" kind="varga" lagna reliability> of <graha id rashi bhava dignity amsa [flags]> (+ <label kind="devata">) and <bhavas chart="D9" kind="varga">. `events` adds <events frame="natal" kind="forecast" as_of age n of suppressed [horizon_to]> of <event id name claim life_area band confidence [peaks]> rows, with their <why> witness under `include=provenance` — a snapshot at `eval_date`, or a weekly scan to `events_until`. `transit_events` (needs `transit_start` / `transit_end`) adds <events frame="transit" kind="ingress" start end n major_ingresses sade_sati_changes return_events> of <event date graha from to bhava significance> rows. `narrative` (needs `domain`) adds <synthesis kind="narrative" domain claim band insights> with <paragraph> and <cite rule>. `idl` enriches in place: every active yoga (no cap) with practitioner notes and cancellations, <ashtakavarga kind="bhinna">, the forecast's interpretation, the per-varga yoga assessment. Default-on sections (active_yogas, dashas, dasha_forecast, transits, remedies, planets, panchanga) ship on every call. sensitive="true" on a <graha> in <boundary_margins> means that placement straddles a classical boundary: its nakshatra, pada and D9 position can change with a small shift in birth time. The chart artifact is auto-cached encrypted, keyed off the API key, TTL up to 30 days; `cache: "skip"` disables the read and the write for one call.
Tier: All · Typical default response: ~51 KB.
Sections · one call, not several
Opt-in — add with include (comma-separated):
classical_rulesclassical_rules_limitclassical_rules_bhavasCited classical rules that fired on this chart, each with its source locus. ~61 KB; `classical_rules_limit: N` keeps the N highest-confidence rules PER BHAVA, and the per-bhava totals stay on the section marker.
eventseval_dateevents_untilLifetime forecast events with likelihood band, confidence, why-clauses and per-factor breakdown, evaluated at `eval_date` (default: now). Two modes: `eval_date` alone gives a point-in-time SNAPSHOT of what is firing then; adding `events_until` (YYYY-MM-DD) runs a weekly SCAN across the window, keeping each event's strongest firing. There is no default horizon. Zero-confidence entries are withheld and counted in `suppressed_zero_confidence`.
transit_eventstransit_starttransit_endSign-ingresses, retrograde stations and returns across a date range. Needs `transit_start` and `transit_end`. Scans the window, so it costs compute.
vargasvargasDivisional charts. Defaults to D9 when the section is named without the parameter.
narrativedomainPlain-language reading for one life domain.
provenanceThe GROUNDS for every claim in this response: the <why> witness (which limb of the classical condition actually held on THIS chart), the <cite> classical locus, the rule's source text (<description>, <reading>) and the Vivek <trace> under each insight. Same token and same meaning as `kundali_milan` and `muhurat`. Without it a row still states its verdict and carries `claim` — the exact `claim_id` to send `pramaan` for the reasoning about that one row.
idllargeThe raw deterministic artifact, pre-shaping. LARGE.). Default-on: active_yogas, dashas, dasha_forecast, transits, remedies, planets, panchanga
A section parameter sent without its include token is an error, not a no-op.
Input
skipmale · femaleen · hi · sa · ta · te · kn · bnparashari · jaimini · kpkundali_milan
Compute Ashtakoota compatibility between two Vedic birth charts. Inputs are `groom: {birth_datetime, latitude, longitude}` and `bride: {birth_datetime, latitude, longitude}`. RESPONSE FORMAT (schema 1): ONE XML document in content[0].text — `<kundalimcp tool="kundali_milan" schema="1" locale=… tz_iana=… tz_offset_minutes=… tool_class="chart_anchored" engine=… api=… school=…>` — and NO structuredContent. The root declares the GROOM's zone and every pair-level instant reads in it; each <party role="groom|bride" tz_iana tz_offset_minutes> declares its own zone and every party-level instant reads in it. Root blocks, in order: <headline>, <context frame="pair"> (two <party> + <computed as_of>), <kootas kind="ashtakoota" n total of verdict> of <koota id name score of passes groom bride><why><cond>verdict sentence</cond></why></koota> rows, <doshas> of <dosha id name [groom bride] present [cancelled] severity> rows each with <why><cond rule=…>fired cancellation</cond></why>, <cite source_class=…>, <reading> and — when Mars sits in a dosha house the source exempts — <non_arising exemptions> with <bhava n ref> rows and the reasons, <temporal as_of> (<sade_sati groom bride band>, <afflictions kind="ashtama_shani">, <overlaps kind="nodal"> with <overlap from direction to_bhava> rows and one <yoga id="kaal-sarpa" party state …> per partner, <spans kind="antardasha_sync">, <dashas kind="transitions">, <paragraph>), the cross-chart blocks (<placements chart="D1|D9" frame="pair" kind="overlay|karaka">, <bhavas frame="pair">, <dashas kind="compatibility">, <synthesis kind="longevity">), <kootas kind="dashakoota">, <synthesis kind="composite|consensus|confidence">, <evidence kind="concepts"> — every koota, dosha and temporal concept ONCE with its <description>, mechanism/significance <note>s, <cite>s and source_class, keyed by the ids the rows carry — then <absent>, <disclaimers>, <glossary> (every graha, rashi, koota class and the verdict token named once, in the request locale). OPT-IN, via `include`: `provenance` adds <evidence kind="rules"> — the compendium rule overlay, one <rule id slug stage role anchor> per rule that applied to this pair with its <label> indication, source text <note> and <cite> loci — and <synthesis kind="verdict">. ~110 KB.
Tier: All · Typical default response: ~33 KB.
Sections · one call, not several
Opt-in — add with include (comma-separated):
provenanceThe compendium rule overlay: every matching rule that applied to this pair — koota scoring, dosha detection and cancellation, cross-chart and temporal slices, aggregation thresholds — as <evidence kind="rules"> rows with the rule's indication, its source text and its classical loci, plus the assembled <synthesis kind="verdict"> narrative. Large (~80 rules).
A section parameter sent without its include token is an error, not a no-op.
Input
skipen · hi · sa · ta · te · kn · bnparashari · jaimini · kplifemap
Compute a lifetime Vedic forecast across Vimshottari dasha periods. RESPONSE FORMAT (schema 1): ONE XML document in content[0].text — `<kundalimcp tool="lifemap" schema="1" locale=… tz_iana=… tz_offset_minutes=… tool_class="chart_anchored" engine=… api=… school=… chart_hash=…>` — and NO structuredContent. Every datetime is LOCAL clock time in the natal zone the root declares; dasha boundaries, Sade Sati spans, returns and event windows are YYYY-MM-DD dates. Root blocks, in order: <headline>, <context frame="natal"> (<computed as_of lookahead_years>), <active_dasha system as_of> with a <period level="mahadasha" lord ends> and <period level="antardasha"> row (each with <label kind="theme"> children; reason="beyond_timeline" when the native has outlived the computed timeline), <dashas rel="next" n> of <period lord start end years> rows, <sade_sati active [phase]> with <span rel="previous|next" start end>, <returns n> of <return graha ord age date> rows, <events frame="life" kind="key" n> of <event kind age date><title/></event> rows, then the opt-in blocks, <absent not_requested=…>, <disclaimers>, and a <glossary> naming every id (graha lords, in the request locale) once. OPT-IN, via `include`: `life_events` adds <events frame="life" kind="forecast" n of windows …census…> — one <event id name bhava related_bhavas frequency> per forecast event with its <why><cond kind=…> witness, its <cite> sources and one <when from to from_age to_age md ad score status tier nth [flags="headline"]> row per dasha window (Raman's tier: par_excellence | ordinary | limited | feeble) — plus <windows frame="life" kind="fructification"> (per-bhava windows, each with <why><cond ref=event-id/>), <ashtakavarga kind="sarva" points> and <vimshopak> rows. `trajectories` adds <trajectories authority="experimental" step n>: twelve <bhava n band values> curves over ONE <sample age md ad width> spine (~10 KB). Default-on sections (active_dasha, dashas, sade_sati, returns, events) ship on every call.
Tier: All · Typical default response: ~2 KB.
Sections · one call, not several
Opt-in — add with include (comma-separated):
life_eventsThe lifetime forecast-event list (<events frame="life" kind="forecast">, each event with its witness, its sources and one <when> row per dasha window carrying Raman's tier and rank), the per-bhava fructification windows (<windows frame="life" kind="fructification">), and the strength evidence behind them (<ashtakavarga>, <vimshopak>, <strength_profiles>), with the census denominators on the two blocks. Large — tens of KB.
provenanceThe GROUNDS for every life-event row: the <why> witness (which natal and dasha limbs actually held on THIS chart) and the <cite> classical locus. Without it a row still states its bands and windows and carries `claim` — the exact `claim_id` to send `pramaan` for the reasoning about that one event.
trajectoriesThe per-bhava journey curve: twelve <bhava n band values> rows over ONE shared <sample age md ad width> spine (~126 samples at the default step). Heuristic values, marked authority="experimental". ~10 KB.). Default-on: active_dasha, dashas, sade_sati, returns, events
A section parameter sent without its include token is an error, not a no-op.
Input
skipmale · femaleen · hi · sa · ta · te · kn · bn0.5 · 0.8 · 1 · 2parashari · jaimini · kpmuhurat
RESPONSE FORMAT (schema 1): ONE XML document in content[0].text — `<kundalimcp tool="muhurat" schema="1" locale=… tz_iana=… tz_offset_minutes=… tool_class="location_anchored" engine=… api=… school=…>` — and NO structuredContent. Root blocks, in order: <headline>, <context frame="election" event=… event_type=…> (<observer lat lng> + <span kind="range" start end>), <windows frame="election" kind="recommended" n of order> and <windows … kind="blocked" …> of <window id name quality band [favorable] start end> rows — every window is a JUDGEMENT ROW carrying its reason: <why> with one <cond ref=…/> per rule or inauspicious span that decided it (ids named in the trailing <glossary>) and a text <cond> per personal verdict; then in scan mode <scan days_scanned windows_examined windows_recommended windows_blocked days_without_windows> with <day date recommended blocked best_quality> and <blocker id kind windows of_windows days of_days first last> rows (blocker ids are glossary-named), <personalization doctrine applied not_evaluated><note>, then <unchecked family name><note>, <coverage own general reached equivalent_to_general>, <evidence> (include=provenance), <absent not_requested=…>, <disclaimers>, <glossary>. Every datetime is naive LOCAL clock time in the zone the root declares; `quality` is 0.00–1.00 and `band` its favorability token. An empty windows block carries n="0" with `of` (the count examined) and a reason. `order` says how the list is sorted (quality_desc / time_asc / moment). Spec: docs/specs/2026-09-09-xml-document-model.md. Find auspicious windows (muhurtha) for an event. TWO MODES: · SINGLE MOMENT (default) — judges the `datetime` supplied. Returns at most one window, `[datetime, datetime + 2h)`, on a day-level panchanga verdict; quality does not vary by hour. · RANGE SCAN (`scan_end` present) — scans every day from `datetime`'s date through `scan_end`. Max 31 days; a longer range is REJECTED, never truncated. A scanned window is an auspicious choghadiya part (Labha, Amrita, Shubha) or the Abhijit muhurta, bounded by sunrise/sunset-derived transitions and judged on the panchanga at its own midpoint. Scan-mode blocks: · <windows kind="recommended"> — ranked by quality; 10 rows by default, capped by `max_windows`. · <windows kind="blocked"> — ruled-out windows in time order with their <why>, same cap; a SPREAD sample across the range (first, last, evenly between), not the first N chronologically. · <evidence> — OPT-IN via `include=provenance`. A dictionary holding each distinct rule, window scheme and blocker ONCE, keyed by its stable id, with its localised `name` and `classical_locus`. A window's provenance REFERENCES those ids, grouped by effect: `structural` (one id), `favorable`/`unfavorable`/`blocker` (arrays of ids), `personal` (FULL entries inline, NOT ids). `classical_locus` is OMITTED where no verified citation is held, including rahu kalam and yamaganda. · <scan> — untruncated denominators: days_scanned, windows_examined, windows_recommended, windows_blocked, days_without_windows, plus one <day date recommended blocked best_quality> row per day. · <scan>/<blocker> — one row per blocker over EVERY window judged (the window lists are samples; this is the population): {id, kind (rule|span|personal), name, windows/of_windows, days/of_days, first_date, last_date}, most-blocking first. `days` can exceed `of_days` by one: a night window beginning after midnight starts on the next civil date. · <personalization doctrine applied not_evaluated> — whether this event type has a personal doctrine and whether it was applied; `not_evaluated` names the doctrines skipped for this event_type and this set of charts. · <unchecked family name> — rule families this tool does not check at all (Holashtak, Pitru paksha), each with a localized name and a reason. · <coverage own general reached equivalent_to_general> — `general_auspicious`'s rules are added to every event; `equivalent_to_general="true"` means the event's own rules cannot change WHICH windows qualify, only their ranking. `native` is OPTIONAL and scan-mode only. It adds the Tarabala and Chandra Shuddhi checks and, on `general_auspicious`, a natal-lagna Upachaya check; for `marriage_ceremony` it also accepts `{bride, groom}`, which adds Guru Shuddhi (from the bride) and Ravi Shuddhi (from the groom). Without it the date-only method is used and <personalization> says so. Varjya kala (visha ghati) is evaluated as a blocker and appears as `varjya_kala` in a window's provenance. `event_type` selects the rule set; there are 24 event ids. An unrecognised value is REJECTED.
Tier: All · Typical response: ~2.4 KB single-moment, ~8.7 KB for a 31-day scan.
Input
skipannaprashan · bhoomi_pujan · business_opening · contract_signing · convocation · engagement · exam_start · general_auspicious · griha_pravesh · journey_start · loan_repayment · marriage_ceremony · medicine_start · mundana · name_ceremony · partnership · pilgrimage · property_purchase · puja · surgery · treatment_start · upanayana · vehicle_purchase · vidyarambhaen · hi · sa · ta · te · kn · bnparashari · jaimini · kppanchang
Compute the Vedic panchanga (five-limbed almanac) for any date, time, and location. RESPONSE FORMAT (schema 1): ONE XML document in content[0].text — `<kundalimcp tool="panchang" schema="1" locale=… tz_iana=… tz_offset_minutes=… tool_class=… engine=… api=…>` — and NO structuredContent. Root blocks, in order: <headline>, <context frame="observer"> (<observer lat lng> + <moment at>), <panchanga frame="moment"> with one <limb kind=…> per tithi/nakshatra/yoga/karana/vara, <sun>, <moon>, <day>, <agnivasa>, <calendar>, <day_yogas>, <windows frame="day" kind=…> (inauspicious always; choghadiya/hora/muhurta under include=windows), <eclipses>, <timeline> (include=timeline), <absent not_requested=…>, <disclaimers>, <glossary>. Scalars are attributes; EVERY datetime is naive LOCAL clock time in the zone the root declares (tz_iana + tz_offset_minutes) — no UTC, no Julian Day, exactly the form the `datetime` input takes; ids are ASCII slugs and every referenced id is named in the trailing <glossary> in the request locale; `quality` is an ASCII token (auspicious/neutral/inauspicious) whose localized band name is a glossary term. A computed "none" is the literal token none with a reason (polar day). Spec: docs/specs/2026-09-09-xml-document-model.md.
Tier: All · Typical response: ~4 KB.
Response shape
Returns for each of the five limbs (tithi, nakshatra, yoga, karana, vara): · Entity (id + localized name) · Quality, lord, pada as applicable · Remaining degrees until the limb changes · End time Also returns: · Sunrise, sunset and meridian transit of Sun and Moon, day/night length, moon elongation and illumination, agnivasa · Rahu Kalam, Gulika Kalam, Yamaganda windows with active flag · Calendar: masa (with adhika/kshaya flags), samvatsara, Vikrama and Shaka year, ayana, ritu, and the next sankranti · Day yogas: anandadi yoga + the active dainika yogas (Sarvartha Siddhi, Amrita Siddhi, Ravi, Dagdha, etc.), each tier-tagged standard (Drik-Panchang set) or classical (extended) · Moon's rashi (Chandra rashi — the Vedic moon sign), localized · Eclipses: next solar + next lunar eclipse (grahana) — <eclipse kind certainty in_days at>
Sections · one call, not several
Opt-in — add with include (comma-separated):
windowsDay divisions: choghadiya (16), hora (24), and the brahma / abhijit / amrita / varjya / dur muhurtas.
timelineEvery segment of each limb (tithi, nakshatra, yoga, karana, vara) intersecting the queried local day, each with its own start and end. Overhang at both ends is real, not clamped: the first segment opens before local midnight and the last closes after it. Boundaries only — no per-segment pada, lord or quality. ~12 segments a day. The default response carries only the CURRENT segment plus its successor's name.). Default-on: calendar, day_yogas, inauspicious, eclipses
A section parameter sent without its include token is an error, not a no-op.
Input
skipen · hi · sa · ta · te · kn · bnpramaan
Explain WHY a specific Jyotish claim is true for a chart — the claim's own trigger-limb witness, its supporting and counter factors with weights, and (opt-in) the full Vivek provenance chain. RESPONSE FORMAT (schema 1): ONE XML document in content[0].text — `<kundalimcp tool="pramaan" schema="1" locale=… tz_iana=… tz_offset_minutes=… tool_class="chart_anchored" engine=… api=… school=… chart_hash=…>` — and NO structuredContent. Root blocks, in order: <headline>, <context frame="natal">, <claim id name tier grounded domain> carrying <why><cond>…</cond></why> when the claim has a trigger limb (yoga and natal-event claims; domain and affliction claims have none), <supporting n> and <counter n> of <factor id name weight> rows each with a <description> when the concept has one, then the opt-ins, <absent not_requested=…>, <disclaimers>, <glossary>. Every datetime is naive LOCAL clock time in the zone the root declares (the birth zone); ids are ASCII slugs and every referenced id (the `domain` lens, the grahas) is named in the trailing <glossary> in the request locale. Spec: docs/specs/2026-09-09-xml-document-model.md. `claim_id` is the `claim` attribute of a `kundali` row, verbatim — every explainable row carries one. The families are: `concept:yoga/<id>`, `concept:natal-event/<rule>`, `concept:affliction/<type>/<graha>/<cause>`, `concept:domain/<slug>`, `concept:life-event/<rule>`, `concept:cancellation/<rule>`. An id this chart cannot answer is refused (-32602) naming the addressable families.
Tier: All · Typical default response: ~3-5 KB; all three opt-ins add ~10-20 KB.
Response shape
Opt-in via `include=` (comma-separated; an unknown token is an error naming the valid set): · provenance — <provenance n> with one <trace stage> per Vivek stage (ephemeris → chart casting → bhava selection → factor collection → weighted roll-up), and on every <factor> its `kind`, `grahas`, `bhavas` and its own identification <trace>. This channel is English structural data on every locale; on a non-English document each of its text children carries lang="en". · detail — <claims kind="disputed" n> rows: conclusions other schools dispute for this domain, `agree`/`disagree` school keys, <title> and <note>. n="0" reason="consensus" when every school agrees. · metrics — <shadbala n unit="virupa">: a <component id name> legend (six classical components, each with its <description>) and one <graha id total meets_minimum sthana dig kala chesta naisargika drik> row per participating graha. This tool returns no classical locus of its own; `<factor id>` is a concept slug.
Sections · one call, not several
Opt-in — add with include (comma-separated):
provenanceThe Vivek provenance chain (ephemeris → chart casting → bhava selection → factor collection → weighted roll-up) as <provenance> rows, plus each factor's kind, grahas, bhavas and its own identification trace. Its text is English on every locale and marked lang="en".
detailClaims other schools dispute for this domain, as <claims kind="disputed"> rows. Empty (n="0") when every school agrees.
metricsShadbala per participating graha — the six classical components and the total in virupas — as <shadbala> rows.
A section parameter sent without its include token is an error, not a no-op.
Input
en · hi · sa · ta · te · kn · bnparashari · jaimini · kpsubmit_feedback
Submit feedback on a chart / claim / explanation. Stored anonymously for engine improvement — no birth data is retained; the claim_id is the only correlator.
Tier: All · Typical response: <1 KB.
Response shape
Returns ONE XML document in content[0].text — `<kundalimcp tool="submit_feedback" schema="1" locale="en" tool_class="metadata">` — and NO structuredContent: <headline>, then <feedback kind rating [claim] recorded="true">. No identifier for the stored row is returned. Requires an authenticated caller (-32001 otherwise); an unknown `feedback_type` or a `rating` outside 1-5 is -32602.
Input
accuracy · completeness · relevance · claritytithi
Which civil day each recurring TITHI-derived observance falls on, over a DATE RANGE, resolved by the sunrise rule — Ekadashi, Purnima, Amavasya, Sankashti Chaturthi, Masik Shivaratri, Trayodashi, and the three weekday-qualified amavasyas that carry names (Somavati, Bhaumavati, Shani). Sankranti ingress moments are SOLAR, not tithi-derived, and ship in their own <sankrantis> block (no vyapti applies). DOES NOT RETURN named festivals — Diwali, Holi, Navaratri, Janmashtami, Ganesh Chaturthi, Karwa Chauth, Onam, Pongal, Ugadi: each needs a nirnaya ruling that is not encoded. `<coverage absent=…>` lists them on every response with the reason in its note. No sub-day windows (nishitha, aparahna, madhyahna, arunodaya) are resolved. RESPONSE FORMAT (schema 1): ONE XML document in content[0].text — `<kundalimcp tool="tithi" schema="1" locale=… tz_iana=… tz_offset_minutes=… tool_class="location_anchored" engine=… api=…>` — and NO structuredContent. Root blocks, in order: <headline>, <context frame="observer"> (<observer lat lng> + <span kind="range" start end days>), <observances n scheme> of one-line <observance kind tithi tithi_number date sunrise masa paksha adhika kshaya vyapti rule rejected fasted first_of_kind [qualifies] [split split_resolved split_rule]> rows (+ <astronomy sunset moonrise moonset> under include=astronomy), <sankrantis n> of <sankranti rashi rashi_index at>, <kshaya_tithis n> of <kshaya_tithi tithi tithi_number after>, <spans n> of <span id kind … effect boundary_rule start end> with <cite> and <note>s, <coverage resolution_rule computed absent> with two <note>s, <evidence n> — the rules the rows reference by `rule=`, each ONCE with its <label>, <cite> or the note saying why there is none — then <absent not_requested=…>, <disclaimers>, <glossary>. Every datetime is naive LOCAL clock time in the zone the root declares; `date` is the civil day (YYYY-MM-DD) and `sunrise` the instant that named it; ids (tithi, masa, rashi) are ASCII slugs named in the trailing <glossary> in the request locale. An empty block carries n="0" and a reason (`no_sunrise_in_range` at the pole, `none_in_range` otherwise). The engine's own English disclosures carry lang="en" on a non-English document. Spec: docs/specs/2026-09-09-xml-document-model.md. RESOLUTION: the tithi holding a day's sunrise names that day. `vyapti` on each <observance> says which case it is — one sunrise, NONE (`kshaya`, destroyed) or TWO (`vriddhi`, added) — and `rejected` says whether that disqualifies it for auspicious acts. <kshaya_tithis> lists the tithis no sunrise in the range held. `first_of_kind="true"` marks the earliest row of each kind in the requested range. Inputs: `start_date`, `end_date` (naive local dates, YYYY-MM-DD), `latitude`, `longitude`, `locale`, optional `masa_scheme` (amanta | purnimanta). Max 400 days; a longer range is REJECTED, never truncated.
Tier: All · Typical response: ~4 KB for a week, ~12 KB for 45 days. It grows with the number of observances in the range.
Input
skipen · hi · sa · ta · te · kn · bnamanta · purnimantaLimits by tier.
Exceeding the per-minute limit or the monthly quota returns a JSON-RPC error with code -32029 and an explanatory message (the minute window resets automatically):
{"jsonrpc":"2.0","id":1,"error":{"code":-32029,
"message":"Rate limit exceeded: 600 requests/min for the Standard tier. See https://kundalimcp.com/pricing"}}Once a monthly quota is spent, Standard and High Traffic accounts with extra usage enabled keep serving (wallet-metered); Free Forever hard-caps until the UTC month rolls over.
JSON-RPC errors with hints.
Errors follow JSON-RPC 2.0. Every error carries a machine-readable code, a human-readable message, and — where applicable — data.hint with a self-correction suggestion for agents.
Agents should inspect data.hint before retrying. Supported datetime window: approximately 2000 BCE – 3000 CE (the analytic ephemeris validity range); out-of-range inputs return -32000.
Three calls to feel the product.
The shortest path from “I have a key” to “I just got real data about myself.” Run them in order; each grounds the next.
1 · Read today's panchanga
No birth data needed, instant result. panchang returns the five limbs (tithi, nakshatra, yoga, karana, vara), sunrise/sunset, and the Rahu Kalam / Gulika / Yamaganda windows for any date and location. The perfect first call to confirm your key works.
{
"jsonrpc": "2.0", "id": 1,
"method": "tools/call",
"params": {
"name": "panchang",
"arguments": {
"datetime": "2026-07-16T09:00:00",
"latitude": 28.6139,
"longitude": 77.2090,
"locale": "en"
}
}
}2 · Cast the chart
kundali with birth data returns the full chart document. Before quoting nakshatra-, pada-, or D9-based predictions, scan <boundary_margins>: any graha row with sensitive="true" means the placement straddles a classical boundary and the agent should confirm exact birth time first.
{
"jsonrpc": "2.0", "id": 2,
"method": "tools/call",
"params": {
"name": "kundali",
"arguments": {
"birth_datetime": "1990-01-15T05:00:00",
"latitude": 28.6139,
"longitude": 77.2090,
"school": "parashari",
"locale": "en"
}
}
}3 · Read today's sky
The transits section of kundali overlays planetary positions on the natal chart — gochara, vedic aspects, Sade Sati phase — and ships by default, so this needs no include and no second call. The active dasha across all 5 levels with fraction elapsed arrives in the same response at <active_dasha>. For ingresses, retrograde stations and returns across a window, add include=transit_events with transit_start and transit_end. Birth data is re-supplied each call — pass flat birth_datetime + latitude + longitude (recommended), or wrap them in a chart_ref object for legacy compatibility.
{
"jsonrpc": "2.0", "id": 3,
"method": "tools/call",
"params": {
"name": "kundali",
"arguments": {
"chart_ref": {
"birth_datetime": "1990-01-15T05:00:00",
"latitude": 28.6139,
"longitude": 77.2090
},
"transit_date": "2026-04-26",
"school": "parashari",
"locale": "en"
}
}
}Ready to wire in your agent?
Free compute tier — no credit card required. 10 tools, 7 languages, every rule source-cited — live at mcp.kundalimcp.com/mcp.