MCP server: the Roth vs Traditional optimizer inside your AI assistant
https://roth-vs-traditional-calculator.kindoflost.com/mcpFree, no signup, no API key. Streamable HTTP transport. Version 1.0.0.
What it does
This server gives an AI assistant the same optimizer that runs in the Roth vs Traditional calculator. Given your age, pay, retirement age, spending, balances and plan features (traditional and Roth 401(k), employer match, IRA or backdoor Roth, HSA, brokerage), it solves a linear program over the US federal tax brackets and returns how much to put in each account this year. The model also plans Roth conversions and withdrawals through retirement, and it compares the best mix with “always traditional” and “always Roth” so you can see what the split is worth. An assistant that does this arithmetic by itself will guess; here a solver does it.
How to connect
Claude: it is listed in the Claude connector directory: add Roth vs Traditional Calculator to Claude. Or, at https://claude.ai/customize/connectors, add a custom connector with the URL above. No OAuth needed.
Claude Code: claude mcp add --transport http roth-vs-traditional https://roth-vs-traditional-calculator.kindoflost.com/mcp
Other assistants and clients: anything that accepts a remote MCP server over HTTP; use the same URL.
Tools
Three tools, all read-only: none of them changes anything or stores your numbers.
get_contribution_example
Return a complete example input for optimize_retirement_contributions with a one-line explanation of every field. No solve. Edit it to the user's situation. kind 'single' (default) or 'married' (two earners, kids, HSA, two-tier match).
Inputs (* = required):
| Input | Type | Range | Meaning |
|---|---|---|---|
kind | single | married |
Returns: A complete example input object (single or married), a one-line explanation of every field (field_notes), the required fields and the next step. Nothing is solved.
optimize_retirement_contributions
Find the best yearly split of retirement savings between traditional and Roth 401(k), IRA/backdoor Roth, HSA and brokerage, including employer match, Roth conversions and retirement withdrawals. Returns this year's dollars per account, how the optimal mix compares with always-traditional and always-Roth, Roth share, lifetime totals, the first working years and retirement milestones. Runs in a few seconds (a few more with exact_income_limits). All money in today's dollars. Optimal for the stated assumptions; not tax advice. Call get_contribution_example first if unsure of the shape.
Inputs (* = required):
| Input | Type | Range | Meaning |
|---|---|---|---|
filing | single | married | Tax filing status. Default 'single'. 'married' = one joint return; fill in the spouse_* fields. | |
age * | integer | 18 to 80 | Your age this year. The plan starts now. |
end_age | integer | max 110 | Plan until this age (default 92; horizon at most 90 years). |
salary * | number | 0 to 5,000,000 | Your gross pay this year, in dollars. |
retire_age * | integer | Age you stop working. Must be above 'age'. | |
spouse_salary | number | 0 to 5,000,000 | Married only: spouse's gross pay this year (0 or omitted = spouse does not work). |
spouse_retire_age | integer | Married only: the age YOU will be when your spouse stops working (all ages on this server are the primary earner's). Default = retire_age. | |
real_raise_pct | number | -5 to 10 | Yearly raise above inflation, whole percent (1 = 1%). Default 1. |
spending_while_working | number | 0 to 5,000,000 | Yearly living costs while still working, today's dollars. Default = spending_in_retirement. |
spending_in_retirement * | number | 0 to 5,000,000 | Yearly spending after retiring, today's dollars (before income tax). |
balances | object | Current household balances, dollars. Omitted = 0. | |
balances.traditional | number | min 0 | Traditional 401(k)/IRA balance. |
balances.roth | number | min 0 | Roth 401(k)/IRA balance. |
balances.brokerage | number | min 0 | Taxable brokerage and cash. |
balances.brokerage_gain | number | min 0 | Unrealized long-term gain inside the brokerage balance (cannot exceed it). |
social_security | object | Expected Social Security (household). Omitted = none modeled. | |
social_security.annual | number | min 0 | Yearly benefit in today's dollars. |
social_security.start_age | integer | 62 to 70 | Age benefits start. Default 67. |
accounts | object | Which accounts the user can use. Defaults: 401(k) and Roth 401(k) available, IRA allowed, no HSA, no match. | |
accounts.has_401k | boolean | Employer 401(k) available. Default true. | |
accounts.has_roth_401k | boolean | Plan offers a Roth 401(k) option. Default true. | |
accounts.match | list of object | Your employer match tiers, richest first. | |
accounts.match[].match_pct * | number | 0 to 300 | Employer match rate in whole percent (100 = dollar for dollar, 50 = 50 cents per dollar). |
accounts.match[].of_first_pct_of_pay * | number | 0 to 100 | WIDTH of this tier in whole percent of pay (not cumulative). '100% of the first 3% then 50% of the next 2%' = [{100,3},{50,2}]. |
accounts.ira | boolean | May contribute to an IRA / Roth IRA. Default true. | |
accounts.hsa | none | self | family | HSA-eligible health plan coverage. Default none. | |
accounts.spouse_has_401k | boolean | Default true. | |
accounts.spouse_has_roth_401k | boolean | Default true. | |
accounts.spouse_match | list of object | Spouse's employer match tiers. | |
accounts.spouse_match[].match_pct * | number | 0 to 300 | Employer match rate in whole percent (100 = dollar for dollar, 50 = 50 cents per dollar). |
accounts.spouse_match[].of_first_pct_of_pay * | number | 0 to 100 | WIDTH of this tier in whole percent of pay (not cumulative). '100% of the first 3% then 50% of the next 2%' = [{100,3},{50,2}]. |
children_birth_years | list of integer | Birth years of dependent children (child tax credit, head of household). | |
assumptions | object | Modeling assumptions; the defaults are reported back. | |
assumptions.real_return_pct | number | -5 to 15 | Investment return above inflation, whole percent. Default 5. |
assumptions.retirement_tax_rate_pct | number | 0 to 60 | Income tax rate applied to leftover traditional money at the end of the plan. Default 22. |
assumptions.state_tax_pct | number | 0 to 20 | Flat state income tax rate, whole percent. Default 0. |
assumptions.backdoor_roth | boolean | Roth IRA open at any income via backdoor. Default true. | |
assumptions.exact_income_limits | boolean | Model exact Roth IRA / deduction income phase-outs (slower MILP, a few seconds). Default false. |
Returns: A short plain-text summary plus structured data: this year's dollars per account (traditional and Roth 401(k), traditional and Roth IRA, HSA, employer match, brokerage remainder, Roth conversion of the existing traditional balance), the after-tax wealth of the optimal mix against always-traditional and always-Roth, the Roth share of contributions, lifetime totals while working, the first working years, balances and withdrawals at retirement milestones, the assumptions used (defaults included) and the disclaimer.
check_request
Say in plain words what the user wants (e.g. 'I'm self-employed with a solo 401k and a pension'). Returns whether this optimizer can do it and, if not, the closest thing it can do. Fast, no solve.
Inputs (* = required):
| Input | Type | Range | Meaning |
|---|---|---|---|
description * | string | The user's question in a sentence or two. |
Returns: Whether the request fits (supported), the unsupported parts with the closest thing the server can do, and what the server does.
Example
Prompt:
I'm 35, single, making $110,000 and planning to retire at 60. I'll spend about $55,000 a year in retirement. I have $60,000 in a traditional 401(k)/IRA, $15,000 in Roth and $20,000 in a brokerage account. My employer matches 100% of the first 4% of pay, and I expect $28,000 a year of Social Security from 67. Assume a 5% real return. How much should go to Roth and how much to traditional this year?
The assistant calls get_contribution_example, fills in your numbers and calls
optimize_retirement_contributions. The text the tool returns for that example (generated
live from the server):
Optimal for these assumptions (age 35, single, retire at 60). This year, put: Roth 401(k) $24,500; Roth IRA $7,500; employer match $4,400 (free money, claim it); remainder to brokerage $0. Also convert $11,800 of the existing traditional balance to Roth this year. Over 25 working years 61.4% of employee contributions go to Roth. After-tax wealth at 92 (today's dollars): optimal $6.71M; always-traditional $6.56M (optimal +2.4%); always-Roth $6.49M (optimal +3.5%). Assumes 5% real return, 22% tax on leftover traditional money, 0% state tax, raises 1% above inflation. Optimal for these assumptions only; not tax advice. Results depend on the assumed real return and the future tax rate. See every year and adjust inputs: https://roth-vs-traditional-calculator.kindoflost.com
And the start of the structured data, trimmed:
{
"status": "ok",
"optimal_for_these_assumptions": true,
"this_year": {
"age": 35,
"calendar_year": 2026,
"household_pay": 110000,
"k401_traditional": 0,
"k401_roth": 24500,
"ira_traditional": 0,
"ira_roth": 7500,
"hsa": 0,
"employer_match_free_money": 4400,
"brokerage_remainder": 0,
"roth_conversion_of_existing_traditional": 11800,
"marginal_tax_rate_pct": 22.0
},
"comparison": {
"metric": "after_tax_terminal_wealth (today's dollars, at end age)",
"optimal": 6712726,
"always_traditional": 6558226,
"always_roth": 6488204,
"optimal_vs_traditional": {
"dollars": 154499,
"pct": 2.4
},
"optimal_vs_roth": {
"dollars": 224521,
"pct": 3.5
}
},
"roth_share_of_employee_contributions_pct": 61.4,
"...": "lifetime totals, first working years, retirement milestones, assumptions, note"
}
Limits
- Ages 18 to 80; plan horizon up to 90 years (end age up to 110); salary up to $5,000,000; balances up to $1,000,000,000.
- One or two earners, 2026 US federal tax plus an optional flat state rate. No pensions, rental or business income, no self-employed plans (solo 401(k), SEP-IRA). NIIT and IRMAA are not modeled.
- One solve runs at a time; a run takes a few seconds (a few more with
exact_income_limits). If the server is busy the assistant is told to retry in about 20 seconds. - Rate limit: 20 solves per network address per 10 minutes. Requests larger than 1 MB are refused.
Honest note
The plan is optimal for the stated assumptions (the real return, the future tax rate and the other inputs), not for the future. Change the return or the tax rate and the answer can change. This is not tax advice, and I'm not a CPA: use the result as a starting point to bring to one. Money is in today's dollars.
Try it yourself
Prefer a form with charts and every year laid out? Use the calculator. Details on what is stored are in the privacy policy.
Support: mario@kindoflost.com.