Examples
Recipes
Patterns, not whole apps. Every worked example in this repo uses all five of these. Copy the one you need.
1. Deny-by-default tool allowlisting
The server sees 204 tools. Every example allows a fixed, named subset and nothing else, by passing default_config: { enabled: false } and enabling only the tools in the request. This is not documentation, it is enforcement: the model cannot call a tool that is not in configs, no matter what the prompt says or what a user tries to talk it into.
const ALLOWED_TOOLS = [
"set_birth_profile",
"get_ayurvedic_constitution",
"get_shadbala",
// ...the rest of what THIS feature needs, and nothing else
] as const;
const configs: Record<string, { enabled: true }> = {};
for (const tool of ALLOWED_TOOLS) configs[tool] = { enabled: true };
tools: [
{
type: "mcp_toolset",
mcp_server_name: "lumin",
default_config: { enabled: false }, // deny by default
configs,
},
],Two reasons this matters beyond security:
- It bounds the metered cost. A feature with a 9-tool allowlist cannot accidentally run a 40-call reading because the model decided to be thorough.
- It documents the feature. The array of tool names is a more accurate description of what a feature actually reads than any paragraph of prose, and it cannot drift out of date the way a comment can.
2. Reading a paged tool to exhaustion
Eight tools page: get_weather_windows, get_health_transit_alerts, get_transit_crossings, analyze_natal_promise, get_ephemeris, get_rp_interval, find_birth_time and get_election_catalog. None of them was capped for a reason your product gets to decide; a 3-month get_transit_crossings scan returns over a thousand rows, and every one of them is a KP claim nothing else can produce.
async function readToExhaustion<T>(
callPage: (page: number) => Promise<{
rows: T[];
pagination: { page: number; totalItems: number; pageNote?: string };
}>,
): Promise<T[]> {
const all: T[] = [];
let page = 1;
for (;;) {
const { rows, pagination } = await callPage(page);
all.push(...rows);
if (all.length >= pagination.totalItems) break;
page += 1;
}
return all;
}A page is a unit of thinking, not a payload optimisation
The point of paging is that each slice gets a real reasoning pass, not that the total response is smaller. Framing paging, narrowing or a composite tool as ways to finish sooner inverts the design. More calls and more elapsed time reading each page is the intent, not a cost to be minimised.
3. The composite-versus-expanded call-count tradeoff
Calls are topped up in any amount, starting at 1 USD for 400 tool calls. The eight run_* composites chain several engine calls into one, so the choice between a composite and its expanded form is a real product decision, not a style preference. More calls means more readings, and deeper ones.
| Pattern | Metered calls | What you get | When to use it |
|---|---|---|---|
| Composite | 1 (e.g. run_kundli_match_complete) | One blended, synthesized result | Your UI shows one verdict and does not need the intermediate results, or your budget is tight |
| Expanded | 3 to 10 (e.g. get_ashta_koota_milan, check_compatibility, get_compatibility_advanced) | Each system's own verdict, independently inspectable | Your UI shows disagreement between systems as a feature, the way kundli-match does |
Neither is wrong. Pick the composite when your UI collapses the result anyway, and the expanded chain when the disagreement between systems is the product. The expanded chain costs more calls and returns more to reason over.
4. Rendering a cross-system chip
70 of 201 tools are not orthodox KP: 46 Parashari, 15 KP-extended, 6 Jaimini, 2 Tajik, 1 Lumin extension. Call get_tool_catalog with a tool filter (or read it once and cache the map) to get each tool's system field, and render it beside any panel built from that tool's output. Presenting a Parashari or Jaimini finding as a KP verdict is a methodology error that reads as thoroughness.
const SYSTEM_LABEL: Record<string, string> = {
kp: "KP",
"kp-extended": "KP-extended",
"vedic-parashari": "Vedic Parashari",
jaimini: "Jaimini",
tajik: "Tajik",
"lumin-extension": "Lumin extension",
};
function SystemChip({ system }: { system: string }) {
const label = SYSTEM_LABEL[system] ?? system;
const isKp = system === "kp";
return (
<span
className={`inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium ring-1 ${
isKp
? "bg-primary/10 text-primary ring-primary/20"
: "bg-muted text-muted-foreground ring-black/10"
}`}
>
{label}
</span>
);
}
// e.g. next to a get_health_organ_panel card:
<SystemChip system="vedic-parashari" />Showing the tradition an answer came from is part of reading it correctly. A Parashari result and a KP result answer the same question by different methods, and a product that merges them silently is stating something neither system said.
5. The chart-integrity gate as a confidence pill
run_pre_verdict_audit bundles the sub-lord boundary check, combustion, planetary war and vargottama strength into one confidence band (HIGH, MODERATE, LOW) and a numeric modifier. get_boundary_warnings alone gives the finer-grained signal: a CRITICAL flag means a birth time or ayanamsa correction of a few arc-minutes could flip a sub lord and invert a verdict. Render either as a small pill next to the result it qualifies, not buried in a tooltip.
const BAND_STYLE: Record<string, string> = {
high: "bg-emerald-50 text-emerald-700 ring-emerald-200",
moderate: "bg-amber-50 text-amber-700 ring-amber-200",
low: "bg-rose-50 text-rose-700 ring-rose-200",
};
function ConfidencePill({ band, summary }: { band: string; summary: string }) {
return (
<span
title={summary}
className={`inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium ring-1 ${
BAND_STYLE[band] ?? BAND_STYLE.moderate
}`}
>
Chart confidence: {band}
</span>
);
}health-risk-analyzer and kundli-match both render this pill, in the second case once per person, so a low-confidence chart on either side of a match is visible before the compatibility read is trusted.
Where to next
- Examples overview for the nine apps these recipes are drawn from.
- Reading depth and call floors for the budget arithmetic behind recipe 3.
- Meta-tools reference for the full get_tool_catalog schema behind recipe 4.