Skip to main content
Glama

QuantCalc Retirement Engine

Tax-aware projection with the recommended withdrawal order

run_tax_aware_projection
Read-only

Runs the retirement projection with the household's accounts split by tax type and returns the withdrawal order and Roth-conversion programme the engine selected, its present-value advantage and range against drawing traditional first, and the after-tax success rate. Federal and state income tax (50 states and DC), Social Security taxability, required minimum distributions, Medicare IRMAA surcharges and the early-withdrawal penalty are paid from the portfolio year by year; spending is what the household keeps after tax. The result states every assumption it used, including the defaults for inputs that were not given, and what the engine does not model.

Input Schema

NameRequiredDescriptionDefault
stateNoTwo-letter state of residence (or DC) for state income tax with that state's retirement-income rules. When absent the result states that no state tax was modelled.
annuityNoOptional: a single-life immediate annuity bought at purchase_age with premium (today's dollars) from the traditional IRA (a qualified annuity: payments fully taxable) or the taxable account (non-qualified: each payment is tax-free up to the premium over the IRS Table V multiple until the premium is recovered). Payments start in the purchase year and stop at death.
pensionNoYearly pension income. Default 0.
lifespanNofixed (default): the plan runs to its end age. stochastic: each path draws your death year from the SSA period life table and ends after it (the estate is held at its value at death; success = the money lasted while you were alive). Not on a joint return.
ira_basisNoOptional: your Form 8606 basis (nondeductible traditional IRA contributions not yet recovered); that share of each traditional withdrawal and conversion is tax-free. Not with a per-owner traditional balance.
annual_qcdNoYearly qualified charitable distribution from the traditional account, in today's dollars, counted against required minimum distributions. Default 0.
birth_yearNoYear of birth, optional. Must match current_age: 2026 minus current_age, or 2025 minus current_age when this year's birthday is still to come (then every tax rule uses the age reached in each calendar year). Sets the RMD start age (73 if born 1951-1959, 75 if born 1960 or later). Default: 2026 minus current_age, stated in the result.
dependentsNoOptional: up to 8 people you claim, each {age (at the end of 2026; negative = born later), student, disabled}. Each retirement year counts the qualifying children that year for the child tax credit (under 17), the credit for other dependents and the earned income credit, and gives them to the state return.
spouse_ageNoSpouse's current age, for married filing jointly: sets the second aged deduction and Medicare surcharge. Default: the same as current_age, stated in the result.
allocationsNoPercentages summing to 100: [US stocks, international stocks, bonds, real estate, cash]. Default [60,10,25,5,0].
birth_monthNoMonth of birth, 1-12, optional. Times the half-year rules: the early-withdrawal penalty ends at 59 and a half, charitable distributions start at 70 and a half, Medicare starts in the birthday month. Default: not given, stated in the result.
current_ageYesCurrent age of the primary person.
bucket_yearsNoOnly with withdrawal_strategy bucket: years of spending held in the cash bucket, 1-10.
pension_typeNoWhether the pension is private or a government (public) pension, which several states exempt from state income tax. Only affects the tax-aware tool. Default private, and the tax-aware result states it.
return_modelNoHow returns are generated. parametric (default): the forward-looking published assumptions. bootstrap: stationary block bootstrap of historical months. historical: replays real months from 1926 in order. The last two need a PRO licence; without one the engine runs parametric and the result says so.
roth_balanceYesRoth IRA and Roth 401(k) balance today, in dollars. 0 if none.
spouse_splitNoMarried filing jointly with a state: whose IRA withdrawals, pension and Roth conversions they are on the state return: even (half each), filer (all the filer's) or spouse (all the spouse's). Arkansas, Delaware, Maryland, Minnesota, Missouri, North Dakota, Ohio and Virginia tax a couple by each spouse's own income, so there it can change the state tax; federal tax does not depend on it. Default on a joint return with a state: even (the spouse's age is then needed; when spouse_age is not given it is current_age), stated in the result. Not used off a joint return or without a state.
ss_start_ageNoAge Social Security starts. Default 67.
filing_statusYesFederal filing status: single, married filing jointly (mfj), married filing separately (mfs) or head of household (hoh).
inflation_rateNoAnnual inflation as a percent, e.g. 2.5. Default 2.5.
retirement_ageNoAge work income stops. Defaults to current age.
returns_sourceNoWhich published return set to use (see list_return_assumption_sources). Default jpmorgan.
aca_marketplaceNoOptional: the household buys marketplace (ACA) health coverage in the retirement years before Medicare. Each path's premium tax credit is figured each year by the federal engine's Form 8962 at that path's own income (no credit above 400% of the poverty line; Medicaid below 138% in expansion states), and the premium after the credit is funded each year and counted by the withdrawal-order search. Needs state.
annual_spendingYesPlanned yearly spending in today's dollars, after tax: what the household keeps. The engine withdraws enough each year to fund this plus that year's federal, state, Medicare-surcharge and penalty tax.
life_expectancyNoAge the plan must last until. Default 92.
roth_conversionNoThe household's own Roth-conversion plan: a fixed amount per year between two ages. When given, the engine applies it on every path and searches withdrawal orders around it instead of searching its own conversion programmes.
social_securityNoYearly Social Security in today's dollars. Default 0 — and 0 is reported as an explicit assumption, not hidden.
taxable_balanceYesTaxable brokerage and savings today, in dollars. 0 if none. The three balances together are the portfolio.
cost_basis_ratioNoPercentage of the taxable account that is cost basis, 0-100. Default 40, and the result says so when it is assumed.
pension_start_ageNoAge the pension starts. Default 65.
medicare_start_ageNoAge Medicare (and its IRMAA income surcharges) begins. Default 65. The year it begins is charged only for the months from the birthday month.
itemized_deductionsNoOptional Schedule A amounts, in today's dollars a year: each year the engine adds that year's own state and local income tax (capped with the property tax by the SALT limit), takes gifts over 0.5% of AGI and medical costs over 7.5% of AGI, and itemizes when that gives the lower tax; otherwise the standard deduction. They are deductions only, assumed to be inside annual_spending already. Mortgage interest stays fixed in dollars until its end year, property tax rises 3.5% a year, giving with inflation, medical costs with inflation. Do not include QCDs in charitable_giving. Default: none, stated in the result.
tax_exempt_interestNoYearly municipal-bond interest, which counts toward Social Security taxability and IRMAA income but is not itself taxed. Default 0.
traditional_balanceYesPre-tax retirement accounts today (traditional IRA, 401(k), 403(b)), in dollars. 0 if none.
withdrawal_strategyNoSpending rule. fixed (default): the planned amount, inflation-adjusted, every year. guyton-klinger: guardrails that cut or raise spending as the portfolio moves. vpw: variable percentage withdrawal. bucket: a cash reserve of bucket_years of spending.
monthly_contributionNoMonthly savings until retirement. Default 0.
roth_contribution_basisNoOptional: the part of roth_balance that is your own regular Roth IRA contributions (withdrawn first, tax-free). Giving it, roth_first_contribution_year or ira_basis turns on the Roth ordering and 5-year rules on Roth withdrawals (earnings before 59 1/2 or inside the 5-year clock are taxed, with the 10% additional tax before 59 1/2) and the Form 8606 pro-rata rule on traditional withdrawals and conversions. Default: all of roth_balance.
roth_first_contribution_yearNoOptional: the first year you contributed to or converted into any Roth IRA (the 5-year clock), 1998-2026. Default: 2021 when roth_balance > 0.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed12 schema fields changed
    • addedInput schema / properties / aca_marketplace
      Added value: +{
      +  "description": "Optional: the household buys marketplace (ACA) health coverage in the retirement years before Medicare. Each path's premium tax credit is figured each year by the federal engine's Form 8962 at that path's own income (no credit above 400% of the poverty line; Medicaid below 138% in expansion states), and the premium after the credit is funded each year and counted by the withdrawal-order search. Needs state.",
      +  "properties": {
      +    "benchmark_premium": {
      +      "description": "The household's 2026 annual benchmark (second-lowest-cost silver) premium at its 2026 ages, from healthcare.gov or the state's marketplace. Default: the state-average model, stated in the result.",
      +      "type": "number"
      +    },
      +    "cover_spouse": {
      +      "description": "Joint return: the spouse is on the plan too. Default true.",
      +      "type": "boolean"
      +    },
      +    "household_size": {
      +      "description": "Tax family size for the poverty line (you, a spouse on a joint return, dependents). Default 2 on a joint return, else 1.",
      +      "type": "integer"
      +    },
      +    "spending_includes_premium": {
      +      "description": "Required. true: annual_spending already includes the full, unsubsidized benchmark premium (it is taken out and the premium after the credit paid instead); false: the premium after the credit is paid on top of annual_spending.",
      +      "type": "boolean"
      +    }
      +  },
      +  "required": [
      +    "spending_includes_premium"
      +  ],
      +  "type": "object"
      +}
    • addedInput schema / properties / annuity
      Added value: +{
      +  "description": "Optional: a single-life immediate annuity bought at purchase_age with premium (today's dollars) from the traditional IRA (a qualified annuity: payments fully taxable) or the taxable account (non-qualified: each payment is tax-free up to the premium over the IRS Table V multiple until the premium is recovered). Payments start in the purchase year and stop at death.",
      +  "properties": {
      +    "cola": {
      +      "description": "Fixed yearly increase of the payment in percent. Default 0.",
      +      "type": "number"
      +    },
      +    "payout_rate": {
      +      "description": "First year's payments as a percent of the premium (from a quote).",
      +      "type": "number"
      +    },
      +    "premium": {
      +      "description": "Single premium in today's dollars.",
      +      "type": "number"
      +    },
      +    "purchase_age": {
      +      "description": "Age at purchase, in retirement.",
      +      "type": "integer"
      +    },
      +    "source": {
      +      "enum": [
      +        "traditional",
      +        "taxable"
      +      ],
      +      "type": "string"
      +    }
      +  },
      +  "required": [
      +    "purchase_age",
      +    "premium",
      +    "source",
      +    "payout_rate"
      +  ],
      +  "type": "object"
      +}
    • addedInput schema / properties / bucket_years
      Added value: +{
      +  "description": "Only with withdrawal_strategy bucket: years of spending held in the cash bucket, 1-10.",
      +  "type": "integer"
      +}
    • addedInput schema / properties / dependents
      Added value: +{
      +  "description": "Optional: up to 8 people you claim, each {age (at the end of 2026; negative = born later), student, disabled}. Each retirement year counts the qualifying children that year for the child tax credit (under 17), the credit for other dependents and the earned income credit, and gives them to the state return.",
      +  "items": {
      +    "properties": {
      +      "age": {
      +        "type": "integer"
      +      },
      +      "disabled": {
      +        "type": "boolean"
      +      },
      +      "student": {
      +        "type": "boolean"
      +      }
      +    },
      +    "required": [
      +      "age"
      +    ],
      +    "type": "object"
      +  },
      +  "type": "array"
      +}
    • addedInput schema / properties / ira_basis
      Added value: +{
      +  "description": "Optional: your Form 8606 basis (nondeductible traditional IRA contributions not yet recovered); that share of each traditional withdrawal and conversion is tax-free. Not with a per-owner traditional balance.",
      +  "type": "number"
      +}
    • addedInput schema / properties / itemized_deductions
      Added value: +{
      +  "description": "Optional Schedule A amounts, in today's dollars a year: each year the engine adds that year's own state and local income tax (capped with the property tax by the SALT limit), takes gifts over 0.5% of AGI and medical costs over 7.5% of AGI, and itemizes when that gives the lower tax; otherwise the standard deduction. They are deductions only, assumed to be inside annual_spending already. Mortgage interest stays fixed in dollars until its end year, property tax rises 3.5% a year, giving with inflation, medical costs with inflation. Do not include QCDs in charitable_giving. Default: none, stated in the result.",
      +  "properties": {
      +    "charitable_giving": {
      +      "description": "Cash gifts to charity per year, not counting QCDs.",
      +      "type": "number"
      +    },
      +    "medical_expenses": {
      +      "description": "Unreimbursed medical and dental costs per year, before the 7.5% floor.",
      +      "type": "number"
      +    },
      +    "mortgage_interest": {
      +      "description": "Deductible home mortgage interest per year.",
      +      "type": "number"
      +    },
      +    "mortgage_interest_end_year": {
      +      "description": "Last calendar year with mortgage interest. Default: every year.",
      +      "type": "integer"
      +    },
      +    "property_tax": {
      +      "description": "Real estate tax on the home per year.",
      +      "type": "number"
      +    }
      +  },
      +  "type": "object"
      +}
    • addedInput schema / properties / lifespan
      Added value: +{
      +  "description": "fixed (default): the plan runs to its end age. stochastic: each path draws your death year from the SSA period life table and ends after it (the estate is held at its value at death; success = the money lasted while you were alive). Not on a joint return.",
      +  "enum": [
      +    "fixed",
      +    "stochastic"
      +  ],
      +  "type": "string"
      +}
    • addedInput schema / properties / pension_type
      Added value: +{
      +  "description": "Whether the pension is private or a government (public) pension, which several states exempt from state income tax. Only affects the tax-aware tool. Default private, and the tax-aware result states it.",
      +  "enum": [
      +    "private",
      +    "public"
      +  ],
      +  "type": "string"
      +}
    • addedInput schema / properties / return_model
      Added value: +{
      +  "description": "How returns are generated. parametric (default): the forward-looking published assumptions. bootstrap: stationary block bootstrap of historical months. historical: replays real months from 1926 in order. The last two need a PRO licence; without one the engine runs parametric and the result says so.",
      +  "enum": [
      +    "parametric",
      +    "bootstrap",
      +    "historical"
      +  ],
      +  "type": "string"
      +}
    • addedInput schema / properties / roth_contribution_basis
      Added value: +{
      +  "description": "Optional: the part of roth_balance that is your own regular Roth IRA contributions (withdrawn first, tax-free). Giving it, roth_first_contribution_year or ira_basis turns on the Roth ordering and 5-year rules on Roth withdrawals (earnings before 59 1/2 or inside the 5-year clock are taxed, with the 10% additional tax before 59 1/2) and the Form 8606 pro-rata rule on traditional withdrawals and conversions. Default: all of roth_balance.",
      +  "type": "number"
      +}
    • addedInput schema / properties / roth_first_contribution_year
      Added value: +{
      +  "description": "Optional: the first year you contributed to or converted into any Roth IRA (the 5-year clock), 1998-2026. Default: 2021 when roth_balance > 0.",
      +  "type": "integer"
      +}
    • addedInput schema / properties / withdrawal_strategy
      Added value: +{
      +  "description": "Spending rule. fixed (default): the planned amount, inflation-adjusted, every year. guyton-klinger: guardrails that cut or raise spending as the portfolio moves. vpw: variable percentage withdrawal. bucket: a cash reserve of bucket_years of spending.",
      +  "enum": [
      +    "fixed",
      +    "guyton-klinger",
      +    "vpw",
      +    "bucket"
      +  ],
      +  "type": "string"
      +}
  2. Changed1 schema field changed
    • addedInput schema / properties / spouse_split
      Added value: +{
      +  "description": "Married filing jointly with a state: whose IRA withdrawals, pension and Roth conversions they are on the state return: even (half each), filer (all the filer's) or spouse (all the spouse's). Arkansas, Delaware, Maryland, Minnesota, Missouri, North Dakota, Ohio and Virginia tax a couple by each spouse's own income, so there it can change the state tax; federal tax does not depend on it. Default on a joint return with a state: even (the spouse's age is then needed; when spouse_age is not given it is current_age), stated in the result. Not used off a joint return or without a state.",
      +  "enum": [
      +    "even",
      +    "filer",
      +    "spouse"
      +  ],
      +  "type": "string"
      +}
  3. Changed3 schema fields changed
    • addedInput schema / properties / birth_month
      Added value: +{
      +  "description": "Month of birth, 1-12, optional. Times the half-year rules: the early-withdrawal penalty ends at 59 and a half, charitable distributions start at 70 and a half, Medicare starts in the birthday month. Default: not given, stated in the result.",
      +  "type": "integer"
      +}
    • addedInput schema / properties / birth_year
      Added value: +{
      +  "description": "Year of birth, optional. Must match current_age: 2026 minus current_age, or 2025 minus current_age when this year's birthday is still to come (then every tax rule uses the age reached in each calendar year). Sets the RMD start age (73 if born 1951-1959, 75 if born 1960 or later). Default: 2026 minus current_age, stated in the result.",
      +  "type": "integer"
      +}
    • changedInput schema / properties / medicare_start_age / description
      Previous value: -"Age Medicare (and its IRMAA income surcharges) begins. Default 65."New value: +"Age Medicare (and its IRMAA income surcharges) begins. Default 65. The year it begins is charged only for the months from the birthday month."
  4. Added
  5. Removed
  6. Added

TDQS

B3.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations cover only readOnly/openWorld, so the description carries real weight and delivers: taxes, Social Security taxability, RMDs, IRMAA and early-withdrawal penalties are paid from the portfolio year by year, and spending is defined as what the household keeps after tax. It further discloses that the result reports every assumption including defaults and what the engine does not model, which is unusually candid scope disclosure. It stops short of runtime/cost hints for a stochastic search.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two dense sentences, front-loaded with the action and followed by the returned artifacts and tax mechanics; nothing is padded. Given the size of the tool, this is efficiently packaged, though the second sentence is long enough that a clause could be trimmed.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, 38 parameters and nested objects, the description does describe the returned content and the modelled/not-modelled boundary, which is the right coverage for a computation tool. However, it omits the one thing an agent most needs at selection time: how this differs from run_retirement_projection and when it is worth the heavier modelling.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% across 38 parameters, several with enums and nested objects, so the schema already documents all input semantics including defaults. The description adds only the framing that accounts are split by tax type; it does not clarify interaction between, say, roth_conversion, withdrawal_strategy and pension_type. Baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description gives a specific verb and resource (runs the retirement projection with accounts split by tax type) and enumerates the return payload: withdrawal order, Roth-conversion programme, present-value advantage and range vs drawing traditional first, and after-tax success rate. That is far clearer than a generic 'projection' tool. It never names or contrasts the near-identical sibling run_retirement_projection, so an agent cannot tell the two apart from the description alone.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No when-to-use or when-not-to-use guidance is present; the description only says what the engine computes. The critical routing decision against run_retirement_projection is left entirely to inference, even though the schema's own pension_type field refers to 'the tax-aware tool' as a distinct thing.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.