API quickstart

A deterministic, §6694-disciplined tax-compute API. JSON in, computed (or honestly declined) tax out.

Supported scope

Tax MCP is coverage-bounded: it computes inside a documented supported envelope and returns a deterministic unsupported or needs_review decline (with a reason and next_action) when a case is outside it — never a wrong-but-plausible number.

Machine-readable: GET /api/mcp/tax-capabilities returns the full supported envelope (years, statuses, modeled fields, out-of-scope, decline codes, billing semantics) — no auth, no payloads.

Supported todayOut of scope (declines deterministically)
W-2 wage workflows with standard or itemized deductions (Schedule A: SALT with the OBBBA-2025 cap + home mortgage interest with the §163(h)(3) $750k limit — supply mortgageAvgBalance; greater-of standard is chosen automatically); documented taxable interest / ordinary dividend facts; clean covered capital-gain facts; §199A QBI deduction for REIT dividends (1099-DIV box 5) only. Selected federal (ordinary tax, NIIT, Additional Medicare, preferential LTCG/QDIV) and CA / NY / NYC computation paths. Non-mutating reconcile (match / mismatch / unsupported / needs_review).Full-return preparation or filing; credits; dependents; itemized deductions beyond SALT + mortgage interest (medical, charitable, etc.); broad payments/refund workflows; Schedule D loss / netting / carryforward; business / rental / pass-through income & business/PTP QBI (REIT §199A dividends ARE supported); broad multi-status state coverage; ambiguous or corrected source documents outside the documented envelope.

1. Get an API key

Sign inand create a key from your dashboard. Keys are shown once — copy it immediately. Your plan's monthly call limit is shared across all your keys.

2. Authenticate

Send your key as a Bearer token on every request:

Authorization: Bearer taxmcp_YOUR_KEY

3. Compute federal tax

curl https://tax-mcp.com/api/mcp/tax-compute/federal \
  -H "Authorization: Bearer taxmcp_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "year": 2025,
    "filingStatus": "single",
    "wages": 120000,
    "taxableInterest": 800
  }'

Supply at least one income field. Amounts are whole-dollar — the engine applies the form's rounding. An HTTP 200 is billable whether the engine computed a result or honestly declined.

Endpoints

MethodPathPurpose
POST/api/mcp/tax-compute/federalSelected federal paths — ordinary tax, NIIT, Additional Medicare, LTCG/QDIV (declines outside coverage)
POST/api/mcp/tax-compute/stateSelected CA / NY compute paths (set state); deterministic decline outside coverage
POST/api/mcp/tax-compute/reconcileNon-mutating, coverage-bounded reconcile vs a filed return (match / mismatch / unsupported / needs_review)
GET/api/mcp/tax-compute/{federal,state,reconcile}Capability / discovery (free — no quota charge)

Idempotency (safe retries)

Send an Idempotency-Key header (a unique value per logical request) so a retry never double-bills. Retrying with the same key + same body replays the byte-identical first response (with header Idempotent-Replayed: true) and bills exactly once. The same key with a different body returns 409 idempotency_key_reused; a concurrent in-flight duplicate returns 409 idempotency_key_in_progress (retry). Keys are scoped to your account and replay for 24h. Errors are never cached — a retry after a 4xx/5xx is a fresh request.

curl https://tax-mcp.com/api/mcp/tax-compute/federal \
  -H "Authorization: Bearer taxmcp_YOUR_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"year":2025,"filingStatus":"single","wages":120000}'

Response shape

A successful compute (200) returns either a computed return or an honest decline— both are billable answers. Every dollar amount is whole-dollar per the form's rounding, and each line carries its own primary-source derivation.

// computed
{
  "computed": true,
  "year": 2025,
  "filingStatus": "single",
  "taxableIncome": 44250,
  "incomeTax": 5072,
  "totalTax": 5072,
  "owedOrRefund": 0,            // present only when withholding is supplied
  "lines": [ { "lineId": "1040:16", "label": "Income tax", "amount": 5072, "derivation": [ … ] } ],
  "flags": [ … ],               // advisory engine flags
  "legal_notice": {             // not-tax-advice notice, on computed + reconcile 200s
    "ref": "https://tax-mcp.com/terms#compute-notice",
    "version": "v1",
    "text": "Computation support only. Not tax, legal, accounting, or financial advice. …"
  }
}

// honest decline (still HTTP 200, still billable)
{
  "computed": false,
  "code": "schedule_c_needs_review",
  "reason": "Schedule C self-employment compute (slice 1) requires scheduleCIsSingleSolePropFinalNetAffirmed:true — attesting the amount is the FINAL Schedule C line-31 net of ONE sole proprietor with no §199A QBI / depreciation / §179 / SE health-insurance / home-office, not farm/clergy/statutory, and not two spouses' combined SE …; a preparer must complete Schedule C + Schedule SE",
  "billed": true,               // a 200 decline is a billable answer on a metered key
  "retry_safe": false,          // resubmitting the same body will decline again — fix inputs, don't retry
  "next_action": "review_inputs"
}

The decline code names the specific surface a preparer must handle — e.g. year_not_modeled, out_of_scope_income, surtax_additional_medicare, capital_gain_lots_need_review, schedule_c_needs_review, schedule_e_needs_review, digital_asset_needs_review, and others. The authoritative, always-current set is published at GET /api/mcp/tax-capabilities (jurisdictions.federal.decline_codes) and in the OpenAPI DeclineCode enum. A decline is never a wrong-but-plausible number — it tells you the case is outside the modeled surface.

Try a decline (the §6694 discipline, hands-on)

The point of this API is that it refuses to guess. This request looks computable — a W-2 wage-earner with $20,000 of Schedule C income — but it omits the required §6694 affirmation (scheduleCIsSingleSolePropFinalNetAffirmed) that the amount is a single sole-proprietor final net with no QBI / depreciation / spouse-split, so the engine returns a deterministic 200 decline instead of a plausible-but-wrong number. (Add the affirmation — and socialSecurityWages when W-2 wages are present — and it computes the self-employment tax.) Paste it with your key and you get the exact schedule_c_needs_review body above, every time:

curl https://tax-mcp.com/api/mcp/tax-compute/federal \
  -H "Authorization: Bearer taxmcp_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"year":2025,"filingStatus":"single","wages":80000,"scheduleCIncome":20000}'
# -> HTTP 200  { "computed": false, "code": "schedule_c_needs_review", "next_action": "review_inputs", ... }

Same idea for other boundaries: an unmodeled year (e.g. 2019) → year_not_modeled; a §1250 / collectibles special-rate gain → special_rate_gain_unmodeled. Discover the whole envelope up front (no taxpayer payload needed) at GET /api/mcp/tax-capabilities.

Roadmap & feedback

The product roadmap is published so users can see what is next and influence the order.

  1. Legal notice shape + /terms — finalize the deploy-held legal notice contract, then publish binding terms only after the legal facts are cleared.
  2. Support / feedback / changelog — add a durable path for blockers, requests, and release notes so user pain can reorder the next slice of work.
  3. First-call onboarding — improve the quickstart and checklist so the first successful call is easier.
  4. Document upload → JSON envelopes — let users upload source documents and receive a structured JSON envelope they can inspect, store, and route downstream.
  5. Broader trust surfaces — expand docs, marketplace copy, and envelope depth based on validated demand.
Influence the roadmapSend feedback

Rate limits & usage headers

Successful responses carry your current usage so you can back off before hitting a limit. Both quota (monthly, account-wide) and rate (per-minute) fail closed with 429 — never a silent overage charge.

HeaderMeaning
X-Quota-Limit / X-Quota-RemainingMonthly call allowance and calls left (shared across your keys)
X-RateLimit-Limit / X-RateLimit-RemainingPer-minute request allowance and requests left this minute
Idempotent-Replayedtrue when this response was replayed from a prior Idempotency-Key

Errors

Full machine-readable spec: /api/openapi.json (OpenAPI 3.1).