Developers
Every calculator on this site is also a stateless API endpoint. No API key, no accounts, no rate limit beyond ordinary abuse protection, no persisted data. Three ways to call them, all backed by the same formulas as the tool pages themselves.
MCP server
A remote Model Context Protocol
server exposing 18 tools (position sizing, risk/reward, margin, liquidation price, pivot points, RMD,
I bonds, Coast FIRE, inflation, FX rates and more) over Streamable HTTP. Listed on the
official MCP registry
as com.economicium/mcp, and on
Smithery.
Server URL: https://economicium-mcp.economicium.workers.dev/mcp
Claude Desktop / Claude Code config:
{
"mcpServers": {
"economicium": {
"url": "https://economicium-mcp.economicium.workers.dev/mcp"
}
}
}
ChatGPT can connect to the same URL via Settings > Connectors > Advanced > Developer mode.
REST API & Custom GPT
Every tool is also a plain GET endpoint
under /api/tools/*, described by a full
OpenAPI 3.1 schema at /openapi.json.
Paste that URL into a Custom GPT's Actions configuration (Import from URL) to give it the same tools.
curl "https://economicium.com/api/tools/risk-reward?entry=100&stop=95&target=115&winRatePct=50"
Google Sheets
Spreadsheet functions (=ECONOMICIUM_FX(...),
=ECONOMICIUM_CPI(...), and a few full
calculators) that pull the same live data into a spreadsheet. Open a blank Google Sheet, Extensions > Apps
Script, paste the script below in, save. The first time you call one of these functions you'll see Google's
"unverified app" prompt (Advanced > Go to economicium (unsafe) > Allow); that's expected for a script that
hasn't gone through Google's formal review, and it's safe: the script only makes a read-only HTTPS request to
this same public API.
Show the script (economicium.gs)
/**
* Economicium custom functions for Google Sheets.
*
* Setup (no Google Workspace Marketplace listing, no review, works today):
* 1. Open a blank Google Sheet.
* 2. Extensions > Apps Script.
* 3. Delete the placeholder code, paste this whole file in, save.
* 4. Back in the sheet, type =ECONOMICIUM_FX("EUR","USD") into any cell.
* 5. The first call shows Google's "this app isn't verified" prompt -
* Advanced > Go to (unsafe) > Allow. That's expected: this script only
* makes a read-only HTTPS call to economicium.com's own public API, it
* never reads or writes anything else in your Google account, but it
* hasn't been through Google's formal app-verification review (see
* docs/plans/2026-08-10-agent-distribution-design.md for why that's
* the right tradeoff for a free tool with no user base yet).
* 6. File > Share a copy of this Sheet (or File > Make a template) to
* distribute it - the script travels with the Sheet.
*
* Every function here calls the exact same stateless API the site's own
* pages and its MCP server use (see functions/api/tools/, worker/mcp-server/,
* /openapi.json) - one source of truth, three interfaces.
*/
var ECONOMICIUM_BASE_URL = 'https://economicium.com';
/** Fetches one /api/tools/* endpoint and returns its parsed JSON, or throws
* with the API's own error message so it surfaces as a clear cell error. */
function economicium_callApi_(path, params) {
var query = [];
for (var key in params) {
if (params[key] !== undefined && params[key] !== null && params[key] !== '') {
query.push(encodeURIComponent(key) + '=' + encodeURIComponent(params[key]));
}
}
var url = ECONOMICIUM_BASE_URL + '/api/tools/' + path + (query.length ? '?' + query.join('&') : '');
var response = UrlFetchApp.fetch(url, { muteHttpExceptions: true });
var body = JSON.parse(response.getContentText());
if (response.getResponseCode() >= 400) {
throw new Error('Economicium: ' + (body.error || 'request failed'));
}
return body;
}
/**
* Daily ECB reference exchange rate between two currencies.
* @param {string} from Currency code, e.g. "EUR".
* @param {string} to Currency code, e.g. "USD".
* @return The exchange rate: one unit of `from` in `to`.
* @customfunction
*/
function ECONOMICIUM_FX(from, to) {
return economicium_callApi_('fx-rate', { from: from, to: to }).rate;
}
/**
* US CPI-U annual (yearly-average) index for a given year.
* @param {number} year e.g. 2020.
* @return The CPI-U index value (1982-84 = 100).
* @customfunction
*/
function ECONOMICIUM_CPI(year) {
return economicium_callApi_('cpi', { year: year }).index;
}
/**
* What a dollar amount in one year is worth in another year's dollars,
* based on annual US CPI-U.
* @param {number} amount The starting amount.
* @param {number} fromYear The year `amount` is denominated in.
* @param {number} toYear The year to convert to.
* @return The inflation-adjusted equivalent amount.
* @customfunction
*/
function ECONOMICIUM_INFLATION(amount, fromYear, toYear) {
return economicium_callApi_('inflation', { amount: amount, fromYear: fromYear, toYear: toYear }).equivalent;
}
/**
* This year's required minimum distribution from a prior-year-end IRA or
* employer-plan balance, per the IRS Uniform Lifetime Table.
* @param {number} priorYearBalance Account balance as of December 31 last year.
* @param {number} age Age at the end of this year.
* @return The required distribution amount (0 if RMDs don't yet apply at that age).
* @customfunction
*/
function ECONOMICIUM_RMD(priorYearBalance, age) {
return economicium_callApi_('rmd', { priorYearBalance: priorYearBalance, age: age }).rmd;
}
/**
* Whether a pay change kept pace with inflation, in real terms. Returns a
* small table: nominal change %, inflation %, real change %, and what the
* new pay is worth in the old year's dollars.
* @param {number} oldPay Old salary.
* @param {number} oldYear Year of the old salary.
* @param {number} newPay New salary.
* @param {number} newYear Year of the new salary.
* @return {Array<Array<string|number>>} A 2-column [label, value] table.
* @customfunction
*/
function ECONOMICIUM_REAL_WAGE(oldPay, oldYear, newPay, newYear) {
var r = economicium_callApi_('real-wage', { oldPay: oldPay, oldYear: oldYear, newPay: newPay, newYear: newYear });
return [
['Nominal change %', r.nominalPct],
['Inflation %', r.inflationPct],
['Real change %', r.realPct],
['New pay in old-year dollars', r.realInOld],
['Break-even pay (old pay, inflation-adjusted)', r.breakEven],
];
}
/**
* Account growth curve under compounding, one row per period. Drag this
* formula's spill range down/right, or wrap in ARRAYFORMULA as needed.
* @param {number} start Starting balance.
* @param {number} ratePct Return per period, as a percent (e.g. 1 for 1%).
* @param {number} periods Number of periods to compound over (max 600).
* @param {number=} contribution Recurring contribution added each period.
* @return {Array<Array<string|number>>} Period number and balance, one row per period.
* @customfunction
*/
function ECONOMICIUM_COMPOUND(start, ratePct, periods, contribution) {
var r = economicium_callApi_('compounding', { start: start, ratePct: ratePct, periods: periods, contribution: contribution || 0 });
var rows = [['Period', 'Balance']];
for (var i = 0; i < r.curve.length; i++) rows.push([i, r.curve[i]]);
return rows;
}
Source & limits
All three interfaces call the same stateless functions, open under
functions/api/tools/ in the
GitHub repository.
No calculator here reads or writes user accounts, holdings, or trades - the tools that do (net worth, the trading
journal, budget tracking) are local-first in the browser and aren't exposed as an API, since there's no
server-side account for an API key to belong to.