Tax MCP docs

A deterministic, §6694-disciplined tax-compute API for human-led product and engineering teams. Tax MCP computes only inside the published supported envelope, returns deterministic declines or needs_review when review is safer, and makes billed, retry_safe, next_action, reason, and provenance fields part of the product contract.

Read the supported envelopeRun the first safe call

What Tax MCP is for

Use Tax MCP when an accountable product owner needs reproducible tax-compute behavior in a bounded workflow. Agent workflows are valid only under accountable human product owners. The docs start with scope and trust because unsupported cases should be discovered through docs, OpenAPI, and the capability manifest before a customer depends on runtime behavior.

Reference links: GET /api/mcp/tax-capabilities for the supported envelope, OpenAPI for request and response schema, roadmap feedback, changelog/release notes, support/contact, and terms.

Docs home

Scope, trust model, response states, billing, retries, and next steps.

Open docs home

Quickstart

Run the first safe call, then inspect decline and needs_review examples.

Run the first safe call

User guides

Operational guides for response interpretation, review UI, envelope use, and retries.

Read the guides

Start here — your first ten minutes

A guided path from zero to a first computed call, a first deterministic decline, and where to get help. Each step links to its full section below; the standalone route is Run the first safe call.

  1. Get an API key. Create one in your dashboard (see Get an API key). Treat it like a password: send it only in the Authorization: Bearer header over HTTPS, never commit it to source, put it in a URL, or paste it into feedback or a support email.
  2. Know your plan & quota. Every plan has a monthly call limit; see pricing and your live usage in the dashboard. Each response carries X-Quota-* / X-RateLimit-* headers (see Rate limits & usage headers). At the cap you get a 429 — no overage, no surprise bill.
  3. Run your first compute. One authenticated POST to /api/mcp/tax-compute/federal returns a full computed result (Compute federal tax). A computed 200 is one billable call.
  4. See a deterministic decline — and why it's a good thing. Send a case outside the supported envelope and the engine returns a 200 with computed:false, a reason, and a next_action (Try a decline). This is a safety success, not a failure or an outage: the engine refuses to guess a wrong-but-plausible number (§6694). It is not something you did wrong. Whether it will ever compute depends on your INPUT — a bare retry of the same request re-declines deterministically (a decline is a billable 200, like a compute); see every response state for bills?/retry-safe?/next-action per outcome.
  5. Get help or shape the roadmap. Hit something unexpected? Send structured feedback, read recent changes, or email support@tax-mcp.com. (Please don't paste API keys or taxpayer documents — see the privacy & sanitization note.)

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.

Modeled now

The engine computes documented federal, CA, NY, NYC, reconcile, what-if, and review-packet slices when the request includes the required facts. Examples include ordinary tax, selected credits, selected Schedule A, bounded Schedule C/E, capital-loss carryover, selected Schedule D / 8949, special-rate gains, and affirmed positive §1256 aggregates. The authoritative field list is the capabilities endpoint.

Requires caller/preparer inputs

Many paths compute only after explicit §6694 affirmations such as final-net Schedule C/E, clean covered brokerage, special-rate portions, state conformity, or state-specific adjustment assertions. Missing or contradictory affirmations return a deterministic decline instead of a guessed tax number.

Deterministic decline

Unsupported years, states, source facts, dirty lots, missing affirmations, over-threshold QBI, broad K-1 / partnership / S-corp surfaces, and source-document upload-to-compute all fail closed with a reason, retry_safe, and next_action. A decline is a final safety answer, not an outage.

needs_review

Reconcile can return needs_review when the engine computed independently but the source set or filed-return comparison needs a human. It is not a filing conclusion, not a blame assignment, and not a compute input promotion from uploaded documents.

Not in v1

Full return preparation, filing, broad document ingestion to compute, broad Schedule A / K-1 / partnership / S-corp / Form 1116 / part-year state support, and public one-click marketplace connectors are not shipped. The roadmap separates shipped, certifying, planned, and blocked work.

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; selected child/dependent and foreign-tax-credit slices; bounded Schedule C/E paths with required affirmations; capital-loss carryover, selected clean covered capital-gain facts, special-rate gain portions, and affirmed positive §1256 aggregates; §199A QBI deduction for REIT dividends (1099-DIV box 5) and below-threshold affirmed Schedule C QBI 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 beyond the documented child/dependent, ACTC, and §904(j) FTC slices; itemized deductions beyond SALT + mortgage interest (medical, charitable, etc.); broad payments/refund workflows; dirty or unsupported Schedule D / Form 8949 residuals; Schedule C/E cases missing required affirmations or outside the bounded final-net paths; pass-through K-1 / partnership / S-corp income and business/PTP QBI; broad multi-status state coverage; ambiguous or corrected source documents outside the documented envelope.

Need a workflow that isn't modeled yet? Tell us what you were trying to compute — it helps us prioritize the roadmap. (The engine declines outside the envelope rather than guess.)

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" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "year": 2025,
    "filingStatus": "single",
    "wages": 120000,
    "taxableInterest": 800
  }'

The same first safe call in Python (requests):

import requests, uuid

resp = requests.post(
    "https://tax-mcp.com/api/mcp/tax-compute/federal",
    headers={
        "Authorization": "Bearer taxmcp_YOUR_KEY",
        "Content-Type": "application/json",
        "Idempotency-Key": str(uuid.uuid4()),  # safe retries, bills once
    },
    json={"year": 2025, "filingStatus": "single", "wages": 85000,
          "medicareWages": 85000, "federalWithholding": 9500},
)
data = resp.json()
if data.get("computed"):
    print("total tax:", data["totalTax"], "owed/refund:", data.get("owedOrRefund"))
else:  # a deterministic decline is a FINAL answer, not an error — do not blind-retry
    print("declined:", data["code"], "->", data["next_action"])

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)

Cookbook — recipes by scenario

Copy-paste-ready recipes for every modeled combination. Each request body is complete, and the # -> line is the actual live response (captured from https://tax-mcp.com) — not illustrative. Swap in your key and run. Every billable POST shows the Idempotency-Key header (safe retries, bills once).

Federal · clean W-2 (single)

The simplest compute — one wage figure. Standard deduction is applied automatically (greater-of vs itemized).

curl https://tax-mcp.com/api/mcp/tax-compute/federal \
  -H "Authorization: Bearer taxmcp_YOUR_KEY" -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"year":2025,"filingStatus":"single","wages":75000}'
# -> 200  {"computed":true, "taxableIncome":59250, "totalTax":7949, "next_action":"none"}

Federal · wages + interest + qualified dividends

Qualified dividends get the preferential rate. Rule: qualifiedDividends must be ≤ ordinaryDividends (it is a subset of them).

curl https://tax-mcp.com/api/mcp/tax-compute/federal \
  -H "Authorization: Bearer taxmcp_YOUR_KEY" -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"year":2025,"filingStatus":"single","wages":90000,
       "taxableInterest":1200,"ordinaryDividends":4000,"qualifiedDividends":4000}'
# -> 200  {"computed":true, "taxableIncome":79450, "totalTax":12113}

Federal · married filing jointly

filingStatus is one of single · married_filing_jointly · married_filing_separately · head_of_household.

curl https://tax-mcp.com/api/mcp/tax-compute/federal \
  -H "Authorization: Bearer taxmcp_YOUR_KEY" -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"year":2025,"filingStatus":"married_filing_jointly","wages":180000}'
# -> 200  {"computed":true, "taxableIncome":148500, "totalTax":22498}

Federal · a deterministic decline (and how to resolve it)

Schedule-C income needs a §6694 affirmation that it is a single sole-proprietor final net — absent it, the engine declines rather than guess. To make it compute, add scheduleCIsSingleSolePropFinalNetAffirmed:true AND socialSecurityWages (SE tax needs the wage base). Discover the exact affirmations at GET /api/mcp/tax-capabilities (affirmations).

curl https://tax-mcp.com/api/mcp/tax-compute/federal \
  -H "Authorization: Bearer taxmcp_YOUR_KEY" -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"year":2025,"filingStatus":"single","wages":40000,"scheduleCIncome":30000}'
# -> 200  {"computed":false, "code":"schedule_c_needs_review", "next_action":"review_inputs"}
#    (a decline is a FINAL, billable answer — do not blind-retry the same body)

State · California (Form 540)

Set state:"ca". Supply medicareWages + caWithholding alongside wages. Returns CA 540 lines with FTB primary-source cites.

curl https://tax-mcp.com/api/mcp/tax-compute/state \
  -H "Authorization: Bearer taxmcp_YOUR_KEY" -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"state":"ca","year":2025,"filingStatus":"single",
       "wages":80000,"medicareWages":80000,"caWithholding":5000}'
# -> 200  {"computed":true, "stateAGI":80000, "stateTaxableIncome":74294, "totalTax":3196}

State · New York (IT-201) + New York City

Set state:"ny". NY fail-closes without nyWageAdditions (the NY-specific wage add-backs the engine can't infer). Add nycResident:true for the NYC resident tax.

curl https://tax-mcp.com/api/mcp/tax-compute/state \
  -H "Authorization: Bearer taxmcp_YOUR_KEY" -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"state":"ny","year":2025,"filingStatus":"single",
       "wages":80000,"nyWageAdditions":0,"nycResident":true}'
# -> 200  {"computed":true, ...NY IT-201 (+ NYC resident) lines...}

State · an unsupported state declines up front

Only CA and NY/NYC are modeled today. Any other state is a 400 (a request-shape error, not a compute) — check GET /api/mcp/tax-capabilities before sending.

curl https://tax-mcp.com/api/mcp/tax-compute/state \
  -H "Authorization: Bearer taxmcp_YOUR_KEY" -H "Content-Type: application/json" \
  -d '{"state":"tx","year":2025,"filingStatus":"single","wages":80000}'
# -> 400  (Texas is not modeled — no wrong-but-plausible number is returned)

Reconcile · check a computed return against what was filed

Non-mutating. sourceProfile is what YOU assert (same shape as /state); filed is the return's own figures (display-only — never fed into the compute, §6694). The engine computes independently and diffs. A subset of filed lines → needs_review (the source set looks incomplete), never a false 'wrong'.

curl https://tax-mcp.com/api/mcp/tax-compute/reconcile \
  -H "Authorization: Bearer taxmcp_YOUR_KEY" -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"sourceProfile":{"state":"ca","year":2025,"filingStatus":"single",
        "wages":80000,"medicareWages":80000,"caWithholding":5000},
       "filed":{"stateAGI":95000}}'
# -> 200  {"status":"needs_review", "diff":[...DIFFERS on CA AGI: engine 80000 vs filed 95000...],
#          "summary":{"DIFFERS":1,"NO-FILED":5}, "next_action":"review_inputs"}

What-if · compute a SET of scenarios (N independent results)

Federal-only. Send up to 25 complete profiles; get each result back INDEPENDENTLY — no deltas, no comparison, no ranking (any comparison is YOUR act). Bills PER SCENARIO (each computed/decline slot is one billable unit). Idempotency-Key is MANDATORY here (absent → 400) — unlike the single-compute endpoints.

curl https://tax-mcp.com/api/mcp/tax-compute/what-if \
  -H "Authorization: Bearer taxmcp_YOUR_KEY" -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"scenarios":[
        {"label":"base","profile":{"year":2025,"filingStatus":"single","wages":90000}},
        {"label":"with-bonus","profile":{"year":2025,"filingStatus":"single","wages":120000}}]}'
# -> 200  {"workflow":"what-if", "scenario_count":2, "results":[
#            {"index":0,"label":"base","computed":true,"totalTax":11249},
#            {"index":1,"label":"with-bonus","computed":true,"totalTax":17867}]}
#    (iterate by index; a slot can independently decline; NO winner/delta field is returned)

Review packet · assemble N profiles into a reviewable packet

Federal-only. Recomputes up to 25 profiles fresh and returns a packet of N items, each with its OWN computed envelope / decline / provenance / legal_notice. Present-not-conclude: NO packet-level total, summary, count, or ranking — it is a non-exhaustive assembly for human review, NOT a completed or filed return. Bills per scenario; Idempotency-Key MANDATORY.

curl https://tax-mcp.com/api/mcp/tax-compute/review-packet \
  -H "Authorization: Bearer taxmcp_YOUR_KEY" -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"scenarios":[
        {"label":"single-90k","profile":{"year":2025,"filingStatus":"single","wages":90000}},
        {"label":"mfj-180k","profile":{"year":2025,"filingStatus":"married_filing_jointly","wages":180000}}]}'
# -> 200  {"workflow":"review-packet", "items":[
#            {"index":0,"label":"single-90k","computed":true,"totalTax":11249,"legal_notice":{...}},
#            {"index":1,"label":"mfj-180k","computed":true,"totalTax":22498,"legal_notice":{...}}]}
#    (each item is self-contained; there is deliberately NO cross-item total/summary)

Discover the whole envelope first (free, no payload)

Before sending any taxpayer data, read the machine-readable supported envelope — years, jurisdictions, statuses, modeled fields, required affirmations, decline codes, and billing semantics. No auth, no quota charge.

curl https://tax-mcp.com/api/mcp/tax-capabilities
# -> 200  {"supported_envelope":{...}, "decline_codes":{...}, "affirmations":{...},
#          "billing_semantics":{...}, "review_states":{...}, ...}

These cover the full advertised surface (federal · CA/NY/NYC state · reconcile · what-if · review-packet · capability discovery). The authoritative, always-current field lists, affirmations, and decline codes are published at GET /api/mcp/tax-capabilities and the OpenAPI spec at /api/openapi.json — the docs and the manifest never drift.

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.

The computed and deterministic-decline examples below preserve captured live response shapes from https://tax-mcp.com (long line/derivation arrays are elided with a marker for brevity; run the call to see them in full). The needs_review reconcile example is sanitized to show the same contract fields without publishing taxpayer-like line values. Note on billed: it reflects the calling key's plan — these were captured with an internal test key (billed: false); on a customer plan a computed or declined 200 bills per the published billing_semantics (see the state table below).

// COMPUTED 200 — exact live response
// request: {"year":2025,"filingStatus":"single","wages":85000,"medicareWages":85000,"federalWithholding":9500}
{
  "computed": true,
  "year": 2025,
  "filingStatus": "single",
  "taxableIncome": 69250,
  "incomeTax": 10149,
  "totalTax": 10149,
  "lines": "<3 whole-dollar line items, each with a per-line primary-source derivation \u2014 elided for brevity; run the call to see them in full>",
  "flags": [
    "OBBBA-2025-new-deductions-senior-bonus/tips/overtime/car-loan-NOT-evaluated-engine-cannot-verify-eligibility-from-W2/1099-preparer-must-confirm"
  ],
  "owedOrRefund": 649,
  "billed": false,
  "retry_safe": true,
  "next_action": "none",
  "provenance": {
    "engine": "deterministic",
    "jurisdiction": "federal",
    "tax_year": 2025
  },
  "legal_notice": {
    "ref": "https://tax-mcp.com/terms#compute-notice",
    "version": "v1",
    "text": "Computation support only. Not tax, legal, accounting, or financial advice. Customer is responsible for review, filing positions, and use only within the documented supported envelope."
  }
}
// DETERMINISTIC DECLINE 200 — a real captured response, shown IN FULL (no elision).
// This is the exact response to the 'Try a decline' request below.
{
  "computed": false,
  "code": "schedule_c_needs_review",
  "reason": "Schedule C self-employment compute requires scheduleCIsSingleSolePropFinalNetAffirmed:true \u2014 attesting the amount is the FINAL Schedule C line-31 net of ONE sole proprietor with no depreciation/\u00a7179/bonus, no SE health-insurance (\u00a7162(l)) or home-office (\u00a7280A), not farm/clergy/statutory-employee, not a \u00a71402 optional method, and not two spouses' combined self-employment (the Social-Security OASDI cap is per-individual \u2014 combining two spouses' SE into one scalar under-collects). Any of those \u2192 a preparer must complete Schedule C + Schedule SE. (The \u00a7199A QBI 20% deduction is a separate opt-in, scheduleCQbiEligible.)",
  "billed": false,
  "retry_safe": false,
  "next_action": "review_inputs"
}

The engine also has a first-class needs_review state on the reconcile surface — when the engine computes independently and finds a filed-return comparison or source set that needs human adjudication. The source profile is caller-supplied; filed values are reconciliation oracles, not compute inputs. The engine returns needs_reviewwhen the source set looks incomplete and never declares either figure “wrong”:

// NEEDS_REVIEW 200 (reconcile) — sanitized response shape; tax values elided
// request shape: {"sourceProfile":{"state":"ca","year":2025,"filingStatus":"single",...},
//                 "filed":{"stateAGI":"<caller-supplied filed value>"}}
{
  "status": "needs_review",
  "computed": {
    "computed": true,
    "state": "ca",
    "year": 2025,
    "stateTaxableIncome": "<computed value elided>",
    "totalTax": "<computed value elided>",
    "lines": "<CA 540 line items with FTB primary-source cites elided>"
  },
  "filed": {
    "stateAGI": "<filed value supplied by caller, elided>"
  },
  "diff": [
    {
      "line": "CA AGI (540:17)",
      "engine": "<computed value elided>",
      "filed": "<filed value elided>",
      "delta": "<difference elided>",
      "cls": "DIFFERS",
      "note": "source set appears INCOMPLETE vs the filed oracle \u2014 a human reviews; the engine never assigns blame"
    }
  ],
  "summary": {
    "MATCH": 0,
    "ENGINE-DECLINED": 0,
    "DIFFERS": 1,
    "NO-FILED": 5
  },
  "docTriage": [],
  "billed": false,
  "retry_safe": true,
  "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 (decline_codes.federal) 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.

Every response state — bills? retry-safe? what next?

The complete state contract, tied to the live retry_safe / next_action enums (the exact strings the API returns) and the published billing_semantics. Glosses in parentheses.

StateHTTPBills?retry_safenext_action (gloss) — what YOU do nextWhat a client may show its user
Computed200Yes (customer plans)truenone (done — the answer is final)The computed figures + the per-line derivation (primary-source citations)
Deterministic decline200Yes (customer plans)falsereview_inputs (same body re-declines; a preparer handles the named surface)“This case needs preparer review” + the named reason (a safe, final answer — not an error)
needs_review (reconcile)200Yes (customer plans)truereview_inputs (the reconcile ran; a human resolves the flagged items)The reconcile diff + the flagged items for a human to resolve
Validation failure400Nofalsefix_request_and_resubmit (correct the body)A request-error state (nothing computed, nothing billed) — fix and resend
Auth failure401/403Nofalsecheck_credentials (fix or replace the key)A sign-in / API-key problem
Monthly quota exhausted429Nofalseupgrade_plan_or_wait_next_period (hard cap — no overage billing)“Monthly limit reached” — upgrade or wait for the next period
Per-minute rate exceeded429Notrueretry_after_backoff (back off and retry)A transient “busy, retrying” state (retry succeeds shortly)
Idempotent replay (same key + body)200Once totalnone needed (byte-identical replay; header Idempotent-Replayed: true)The same result as the first call — reassure “no double charge”
Idempotency key reused (different body)409Nofalseuse_new_idempotency_keyA client bug (a key was reused for a changed request) — mint a fresh key
Idempotency in progress (concurrent dup)409Notrueretry_after_inflight_completes (wait, retry the same key)A transient “still processing” state — retry the same key shortly
Compute error500Nofalsefix_request_and_resubmit (report it — a 500 is our bug)A generic “something went wrong” (nothing billed; it’s our bug, not the caller’s)
Metering outage503Notrueretry_after_backoff (never silently served free)A transient “temporarily unavailable” state — retry (never silently billed)

Integrations — use Tax MCP from ChatGPT or Claude

A hosted ChatGPT/Claude one-click connector is not yet generally available. What exists today is self-configured integration: you bring your own API key and wire the connection yourself. Two supported paths:

ChatGPT — a self-configured Custom GPT Action

Steps as of July 2026 — the GPT-builder UI evolves, so cross-check OpenAI's Actions docs if a step looks different:

  1. In ChatGPT, create a GPT (Explore GPTs → Create), open Configure → Actions, and choose Import from URL with https://tax-mcp.com/api/openapi.json. The spec is OpenAPI 3.1 — if your importer rejects 3.1, the supported fields are also listed (machine-readable) at tax-capabilities.
  2. Authentication: API Key, auth type Bearer — the spec declares the Authorization: Bearer scheme, so the importer should prompt for the key. Use a dedicated, revocable key for assistant integrations (create one in your dashboard) — you can revoke it without touching your production key. (Note: quota is per-account, not per-key — a leaked key can consume your account's monthly quota until revoked.)
  3. Keep the GPT private, then test: ask it to compute the docs quickstart example (single filer, 2025, wages only). A deterministic decline in a test is a correct result, not a broken Action — see Try a decline.

Calls made through a GPT Action hit the normal metered REST API — the same billing, quota, idempotency, and 429 semantics as any other client (response states).

Claude — an MCP client with your own key

Tax MCP exposes a bounded machine MCP transport at POST https://tax-mcp.com/mcp (Streamable HTTP) with three tools: tax_capabilities, tax_compute_federal, tax_compute_state. It authenticates with the same Authorization: Bearer key, checked before the MCP handshake.

Safety: Do not paste taxpayer facts into a generic chatbot unless your integration is configured to call Tax MCP through an authenticated, logged, policy-compliant tool path — anything you type into an assistant is processed by that assistant's provider before a tool call ever reaches Tax MCP.

Every computed:true compute 200 and every reconcile 200 (regardless of status) carries a legal_notice object (ref / version / text); it is absent only from 200 declines (computed:false) and non-200 errors. That absence never means the Terms don't apply: /terms governs every response — declines and errors included — and legal_notice is simply a per-success machine-readable echo of it. The output is computation support only — not tax, legal, accounting, or financial advice, and not a filing. A §6694 preparer relying on a computed line remains responsible for the return; the per-line derivation cites the primary source (IRC / Rev. Proc. / FTB schedule) precisely so that responsibility is auditable. Binding terms live at /terms.

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 "Idempotency-Key: $(uuidgen)" \
  -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 full product roadmap is published at /roadmap— what is modeled now, what is certifying, and what is planned — so you can see what is next and influence the order. Live today: the federal 1040, CA / NY / NYC state, and reconcile surfaces documented above, plus the what-if and review-packet workflows. Binding Terms and the per-response legal_notice (v1) are live and govern every response. The next major surface on the roadmap is document-upload → structured-JSON-envelope extraction (source-intake only; nothing is promoted to a compute input without your assertion).

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).