Skip to content

Tools

The anafpy[mcp] extra ships a local stdio MCP server that wraps the typed clients as tools for Claude (Desktop, Code, Cowork). It runs on your own machine: tool calls use your own tokens, and downloaded files land on your own filesystem. The setup walkthrough gets you from zero to a working connection.

The server is read-first: everything that only looks things up is freely callable, and everything that files anything with ANAF — e-Factura and e-Transport alike — is gated behind an explicit human confirmation.

Public lookups — no login needed

These ride ANAF's public no-auth services, so they work even before the certificate login (and with no OAuth credentials configured at all):

Tool What it does
anaf_lookup_taxpayers Verify partners by CUI/CIF: name, address, VAT status, TVA la încasare, split-VAT, inactive flag — in bulk if you like
anaf_lookup_efactura_register RO e-Factura register membership
anaf_lookup_farmers Farmers' register (RegAgric)
anaf_lookup_cult_entities Religious-entities register (RegCult)
anaf_financial_statement A company's filed financial statements (bilanț) for a year
efactura_validate ANAF's authoritative server-side invoice validation (CIUS-RO / BR-RO) — validates only, files nothing

Exchange rates — no login needed

The one tool that does not query ANAF. Romanian filings are in lei, so a foreign-currency invoice needs converting before its value can be declared — this is where that figure comes from, instead of Claude doing the arithmetic or recalling a rate.

Tool What it does
bnr_fx_rate The official BNR reference rate for a currency on a date, and amounts converted to RON at it

BNR publishes once per banking day, just after 13:00, so a weekend, a holiday or an early-morning call answers with the last published day. The result always carries rate_date (the day the rate is from) next to requested_date, and flags the difference — so the rate's real date is what reaches you.

The ANAF session

Tool What it does
auth_status Reports whether the stored ANAF login is valid, and when the tokens expire
auth_login Runs the one-time OAuth login: opens your browser on ANAF's certificate page, catches the redirect on a local listener, and stores the tokens — needs your explicit go-ahead (confirm=true), one attempt per call

auth_login is needed at first setup and again roughly yearly, when the refresh token expires. Claude never sees your PIN or the certificate — that step happens entirely in your browser, exactly as in anafpy auth login, which remains the terminal equivalent (and additionally offers paste mode and a TLS certificate of your own). Expect the browser's one-time "connection is not private" warning at localhost — the setup walkthrough explains why it is harmless.

e-Factura — inbox, plus two-step gated filing

Read tools, freely callable:

Tool What it does
efactura_list_messages List received/sent messages for a date window
efactura_download Download a message as an easy-to-read flat view; optionally save the signed ZIP (save_zip_as) and/or ANAF's official PDF rendering (save_pdf_as) to paths you name
efactura_get_status An upload's processing state (ok/nok), with the download id when accepted

Saved artifacts go to disk, never into the conversation — that's what powers batch flows like "export last month's invoices as <date> - <partner>.pdf". An existing file is never silently replaced: a name collision is refused and reported, and only an explicit overwrite=true replaces it. The PDF is also available as the MCP resource anafmsg://<message_id>/pdf.

Filing uses the same prepare → confirm → submit gate as e-Transport, with two ways in:

Tool What it does
efactura_prepare Gate ready-made UBL XML your invoicing software produced — the strongly recommended path when you have such software (its ledger, not ANAF's SPV, is your durable record: SPV purges messages after ~60 days); the bytes go to ANAF verbatim
efactura_prepare_invoice Compose a complete CIUS-RO invoice or credit note from structured fields — no XML and no invoicing software needed; totals and the VAT breakdown are computed, and local_findings reports anafpy's translated rule check (informational — ANAF stays authoritative)
efactura_submit File a prepared document; returns the upload id for efactura_get_status

e-Transport — reads plus two-step gated filing

Read tools, freely callable:

Tool What it does
etransport_list Recent notifications for a CIF
etransport_get_status An upload's processing status
etransport_lookup Active declarations / UIT lookups
etransport_uit_card Render a filed declaration's UIT as the driver card — a phone-shaped PDF written to a caller-given path — plus the plain-text message to send with it. Prints ANAF's data_exp_uit when you have one, otherwise the OUG 41/2022 window derived from the transport date, marked as an estimate
etransport_uit_details Render the whole filing as the A4 detail document (goods table, caller's observations), written to a caller-given path; same validity treatment as the card
etransport_nomenclature The XSD code lists (counties, border points, customs offices, operation types, …) plus the UN/ECE unit codes — names are accepted anywhere a coded field is; operation types also carry the UIT's validity in calendar days

Filing is split prepare → confirm → submit, and nothing reaches ANAF without your explicit approval:

Tool What it does
etransport_prepare_declaration Compose a new declaration (or a correction, via correction_of_uit) from structured fields; the preview states the validity window the issued UIT would carry, while the transport date can still be changed
etransport_prepare_deletion Compose a UIT deletion
etransport_prepare_confirmation Compose an arrival confirmation
etransport_prepare_vehicle_change Compose a vehicle change
etransport_prepare Same gate, for ready-made XML you already have
etransport_submit File a prepared document

Every prepare* — e-Factura and e-Transport — returns a human-readable preview plus a confirmation token cryptographically bound to the exact document bytes and the CIF being filed for. The matching *_submit files only when given that token and confirm=true, and each token is single-use — so a non-idempotent upload can never be repeated on one approval, and any mangling of the document between prepare and submit fails closed.

SPV — the taxpayer's mailbox, read-only

The spv_* tools read SPV (Spațiul Privat Virtual) — receipts, decisions, notifications — and request official reports. They authenticate with your qualified certificate, not the OAuth application, and are read-only by design: no declaration submission of any kind.

Pick a certificate once (spv_list_certificates / spv_select_certificate, or anafpy spv certs + anafpy spv select), then establish a session either by asking Claude to log in (spv_login — gated on your explicit approval, because it fires your token/2FA prompt) or by running anafpy spv login in a terminal. Sessions idle out in under an hour; the tools then ask for a fresh login rather than failing obscurely.

Tool What it does
spv_list_certificates Certificates usable for SPV in the OS key store (Keychain / CertStore), token and cloud-HSM ones included
spv_select_certificate Persist which certificate the SPV login uses
spv_login Establish a fresh SPV session — requires your explicit approval (confirm=true) since it fires your certificate PIN/2FA
spv_status Session smoke test; reports the certificate's CNP/serial and authorized_cuis — every CUI/CNP it has SPV rights for
spv_lista_mesaje Inbox messages from the last N days, filterable by CUI and message kind, paged
spv_descarca Download one message's PDF to a path you name (never into context; existing files never replaced without overwrite)
spv_nomenclature The SPV code lists: every report type spv_cerere accepts, each with a plain-language description of what it contains (so "my VAT return for March" finds D300 without you knowing the code) and its per-type parameters, and ANAF's fixed reason (motiv) list for income certificates — Claude maps your stated purpose onto the exact wording ANAF prints on the certificate
spv_cerere Request a report — VECTOR FISCAL, Obligatii de plata, Istoric declaratii, the D1xx/D3xx duplicates, Duplicat Recipisa, Adeverinte Venit, … Parameters are validated per report type before anything is sent; identical same-day repeats are deduped
spv_asteapta_raport Wait for a requested report to land in the inbox and save its PDF; a pending answer just means "call again later"

Like the e-Factura PDF, a message's document is also available as the MCP resource spvmsg://<mesaj_id>/pdf — a disk-free path for hosts with resource UX. It needs an active SPV session (a resource read can't ask for a login); spv_descarca remains the save-to-disk path.

Declarations — author, validate, render, sign, file, track

Prepare tax declarations — any form ANAF's validator covers, with hands-on completion guides for the common SME declarations (D100, D101, D112, D205, D212, D300, D301, D390, D394, D406, D700, D710) — entirely on your machine: ANAF's own DUKIntegrator validates and renders the official PDF, and your qualified certificate signs it. Filing the signed PDF is automated too, on ANAF's declaration portal (the same one behind anaf.ro → Depunere declarații). Two things to know before using it: filing goes to the production portal — declarations have no test environment, so every submission is a real filing — and it is an opt-out feature (ANAFPY_DECLARATII_UPLOAD=off removes the filing tools and Claude guides you through manual portal filing instead). The portal login is deliberately a separate step from submitting: it fires your certificate PIN/2FA once (like spv_login), and the session it establishes is probed — without any 2FA — before anything is uploaded. The authoring tools need DUKIntegrator + Java — declaratie_duk_install provisions DUK itself into ~/.anafpy/duk-dist (an explicit ANAFPY_DUK_DIR wins over the managed install) — and signing needs your qualified certificate in the platform key store (macOS Keychain or the Windows certificate store); the status/recipisa tools ride ANAF's public StareD112 service and need no configuration and no login at all.

Tool What it does
declaratie_validate Validate a declaration with ANAF's own DUKIntegrator (authoritative); returns its findings verbatim — the compose→validate→fix loop. Missing DUK/Java configuration is a tool error, not an invalid-document result
declaratie_render Render the official multi-page PDF (XML embedded) directly to a path you name; validates first, so a failure writes no PDF. Missing DUK/Java configuration is a tool error
declaratie_sign Sign a rendered PDF with your qualified certificate — requires your explicit approval (confirm=true) since it fires your PIN/2FA prompt; failures come back as signed=false + guidance
declaratie_nr_evid Compose the 23-char nr_evid payment-evidence number for the self-assessed forms — form= D300 (needs tip_decont), D100/D710 (need cod_oblig + scadenta), D101 (adds in_liquidation), D301 (takes mijl_trans). It has a check digit — never compute it by hand
declaratie_duk_install Install or update DUKIntegrator from ANAF's official update feed — no manual download. Named forms install exactly those validators; a bare call converges the common preinstall set plus everything already installed. HTTPS-pinned to static.anaf.ro, manifest-audited, safe to repeat; the ~91 MB D406T archive downloads only when that form is named
declaratie_duk_status The DUKIntegrator install: directory, Java version, and installed-vs-current validator versions (CLI-mode DUK does not auto-update — declaratie_duk_install refreshes it); the current feed is still returned before DUK is installed. Each form's state keeps current / stale / not installed / not in feed (D406T) apart, and stale flags only the ones an update would fix
declaratie_portal_status Probe whether the filing-portal session is still alive (they die after ~10 idle minutes) — a plain page fetch, never fires your PIN/2FA
declaratie_portal_login Log in to the filing portal with the selected certificate — requires your explicit approval (confirm=true) since it fires your PIN/2FA prompt; deliberately outside the submit flow, so one login serves the whole filing
declaratie_prepare STEP 1 of filing: reads the signed PDF and returns a confirmation token bound to its exact bytes (plus a local heads-up if no embedded signature is detected). Nothing is filed
declaratie_submit STEP 2: uploads the signed PDF to the production portal — requires the prepare token and your explicit confirm=true, probes the session before spending the single-use token, and returns the portal's verdict with the upload index (feed it to declaratie_status / declaratie_recipisa)
declaratie_status Check a filed declaration's processing state by upload index + CUI — returns the client-layer DeclarationStatusList directly, containing all the CUI's filings from the last 3 months (max 200). Config/network/input failures return the same typed shape with found=false and message
declaratie_recipisa Save the digitally signed recipisa (filing receipt) PDF to a path you name — available only ~60 days from filing, so archive it

Resources and prompts

The compiled ANAF API reference is served as read-only MCP resources — URIs mirror the file tree without the .md suffix (the D300 completion guide is anafref://declaratii/forms/d300, the form inventory anafref://declaratii/forms/README) — and the workflow skills as MCP prompts.

Configuration

Configuration is environment-only, set in the MCP client's server entry:

Variable Meaning
ANAFPY_CLIENT_ID / ANAFPY_CLIENT_SECRET Your ANAF OAuth application. Optional — without them the server still starts and serves the public anaf_* lookups and efactura_validate; the authenticated tools explain how to enable themselves
ANAFPY_CIF Default fiscal code (digits only) used when the conversation doesn't say otherwise
ANAFPY_ENV prod (default) or test — ANAF's TEST environment for practicing
ANAFPY_TOKEN_STORE_BACKEND keyring (default, OS credential store) or file for headless/Docker hosts
ANAFPY_TOKEN_STORE Token file path for the file backend (default ~/.anafpy/tokens.json)
ANAFPY_REDIRECT_URI OAuth callback URL the auth_login browser flow listens on — must exactly match a Callback URL registered on your ANAF application (default https://localhost:9002/callback, the URL the setup guide registers; anafpy auth login reads the same variable and default)
ANAFPY_DOCS_DIR ANAF reference served as resources (defaults to the repo's docs/anaf-reference/ when present, else the copy packaged in the wheel)
ANAFPY_SKILLS_DIR Workflow skills served as prompts (defaults to the repo's plugins/anafpy-workflows/skills/ when present, else the copy packaged in the wheel)
ANAFPY_SPV_SESSION SPV cookie-session store written by anafpy spv login (default ~/.anafpy/spv-session.json)
ANAFPY_SPV_IDENTITY_FILE Persisted SPV certificate selection (default ~/.anafpy/spv-identity.json)
ANAFPY_DUK_DIR An extracted DUKIntegrator dist/ folder; overrides the managed install that declaratie_duk_install maintains at ~/.anafpy/duk-dist
ANAFPY_DUK_JAVA The java binary DUKIntegrator runs under (optional; falls back to java on PATH, then to JAVA_HOME)
ANAFPY_SIGN_IDENTITY Certificate to sign declarations with — the Keychain identity name on macOS, the SHA-1 thumbprint on Windows (optional; falls back to the persisted SPV certificate selection)
ANAFPY_DECLARATII_UPLOAD Set to off to opt out of automated declaration filing — the portal tools (declaratie_portal_*, declaratie_prepare, declaratie_submit) are then not served and Claude guides manual filing instead (default: on)
ANAFPY_CURL The curl program the SPV and declaration-portal certificate logins run (optional). Set it only to work around a broken one — see the setup guide's troubleshooting table. It outranks everything below
ANAFPY_BUNDLED_CURL Set by the Windows extension to the curl it ships, and preferred over the computer's own (which is the one that breaks there). Not a setting to fill in yourself; without it the OS curl is used — /usr/bin/curl on macOS, System32\curl.exe on Windows

All three interactive logins are exposed as tools with the same contract — your explicit go-ahead per attempt, one attempt per call, failure reported as guidance rather than an error, and the sensitive step out-of-band: auth_login drives the OAuth browser login (the certificate happens in your browser), while spv_login and declaratie_portal_login drive the certificate logins whose human gate is your PIN/2FA approval. Beyond the login, the server only reads and headlessly refreshes the token store the login wrote.