Albanian NIPT validation, TVSH (VAT) & invoice math, gross↔net payroll on verified 2026 rates.
Zero-dependency utilities for Albanian fiscalization (Law 87/2019 "On the invoice and the circulation monitoring system") and payroll: NIPT/NUIS validation, TVSH (VAT) math, fiscal invoice totals with the per-rate VAT breakdown every fiscalized invoice must report, and gross↔net salary / profit-tax math over a verified, dated rates config. Also available as an MCP server for AI agents.
Built and maintained by Square Software, a software company in Tirana that ships fiscalization integrations for POS, ERP and e-commerce systems. These are the same pure functions that power our free online tools:
📖 Full documentation: fiskalizimi-utils.readthedocs.io
| Where | Install | Contents |
|---|---|---|
| npm | npm install fiskalizimi-utils | NIPT, TVSH, invoice totals, payroll, profit tax (ESM + types) |
| JSR | deno add jsr:@square-al/fiskalizimi-utils | same, TypeScript source |
| PyPI | pip install fiskalizimi-utils | the above + severance, annual leave |
| MCP | al.square/fiskalizimi in the MCP registry · .mcpb on Releases | every calculator as a tool for AI agents — see mcp/ |
| Docker | docker run --rm squaresoftware/fiskalizimi --help | the CLI, no runtime to install |
npm install fiskalizimi-utils
# or straight from GitHub:
npm install github:square-al/fiskalizimi-utils
import { validateNipt } from 'fiskalizimi-utils'
const res = validateNipt(' m5 1418-039h ') // separators + case are normalized
res.valid // true
res.normalized // 'M51418039H'
res.parts // { prefix: 'M', digits: '51418039', checkLetter: 'H' }
validateNipt('M5141803OH')
// { valid: false, issues: ['digits-not-numeric'], likelyTypo: true } ← O vs 0
Format-level validation only (letter A–M + 8 digits + control letter). A well-formed NIPT is not necessarily registered — check existence in the official registry (QKB), e.g. https://opencorporates.al/sq/nipt/m51418039h.
import { addVat, extractVat, ALBANIA_VAT, KOSOVO_VAT } from 'fiskalizimi-utils'
addVat(1000, ALBANIA_VAT.standard) // { net: 1000, vat: 200, gross: 1200, rate: 0.2 }
extractVat(1180, KOSOVO_VAT.standard) // net 1000, vat 180 — Kosovo 18%
import { invoiceTotals } from 'fiskalizimi-utils'
const t = invoiceTotals([
{ description: 'Service A', quantity: 2, unitPrice: 500, vatRate: 0.2 },
{ description: 'Book', quantity: 1, unitPrice: 800, vatRate: 0.06, discountRate: 0.1 },
])
t.subtotal // net total
t.totalVat // VAT total
t.vatByRate // [{ rate: 0.2, base: 1000, vat: 200 }, { rate: 0.06, base: 720, vat: 43.2 }]
vatByRate is the per-rate base/VAT table a fiscalized invoice reports.
import { grossToNet, netToGross, profitTax, AL_2026 } from 'fiskalizimi-utils'
const b = grossToNet(100_000, AL_2026.salary)
b.empSocial // 9500 (9.5%)
b.empHealth // 1700 (1.7%)
b.incomeTax // 5044 (progressive 0 / 13 / 23%)
b.net // 83756
b.employerCost // 116700 (gross + employer 15% + 1.7%)
netToGross(83_756, AL_2026.salary) // ≈ 100000
profitTax(20_000_000, AL_2026.profitTax).tax // 900000 (0% to 14M, 15% above)
Every number comes from AL_2026 — a dated config verified against tatime.gov.al on 2026-06-29 — and none are hard-coded in the functions. Read AL_2026.notes for the disclosed approximation in the 50,000–60,000 ALL/month band.
mcp/ wraps all of the above as an MCP server (al.square/fiskalizimi) so AI agents can validate a NIPT, total an invoice or compute a net salary without a network call: validate_nipt, add_vat, extract_vat, invoice_totals, net_salary, gross_salary_from_net, profit_tax, tax_rates. Claude Desktop users install the .mcpb from the latest release; any stdio client can run node mcp/dist/main.js. Details in mcp/README.md.
The Python package is a faithful port with the payroll calculators added, and it carries the dated rates config the square.al calculators read:
from fiskalizimi_utils import AL_2026, gross_to_net, validate_nipt, add_vat
validate_nipt("m5141 8039h").normalized # 'M51418039H'
add_vat(1000, 0.20).gross # 1200.0
b = gross_to_net(100_000, AL_2026.salary)
b.net # 83756.0
b.employer_cost # 116700.0
A parity test suite generates fixtures from this TypeScript source and asserts
the Python implementation against them — down to the half-up rounding JavaScript
does and Python does not — so the two packages cannot silently diverge.
Regenerate the fixtures with npx tsx scripts/gen-parity-fixture.mjs.
$ fiskalizimi nipt M51418039H # pip install fiskalizimi-utils
$ fiskalizimi paga 100000 --json
$ fiskalizimi tvsh 1200 --extract
$ docker run --rm squaresoftware/fiskalizimi rates
Every subcommand takes --json. nipt exits non-zero on a bad format, so it
composes in shell scripts.
dataset/ publishes the same figures as a
Frictionless data package under CC-BY-4.0:
income-tax and profit-tax bands, contribution rates and their base window, VAT
rates, the minimum wage, and the filing deadlines — one row per band, rates as
decimal fractions. It is generated from the library
(cd dataset && PYTHONPATH=../python/src python3 generate.py), so the data and
the code cannot drift apart.
Mjete TypeScript pa varësi për fiskalizimin shqiptar: verifikim i formatit të NIPT/NUIS, llogaritje TVSH-je (shto/hiq nga një vlerë) dhe totalet e faturës me TVSH-në e ndarë sipas normës — ashtu siç e raporton një faturë e fiskalizuar. I njëjti kod që fuqizon llogaritësit tanë falas. Për integrime fiskalizimi në sistemet tuaja, shihni square.al.
The AL-2026 rates config was confirmed against
tatime.gov.al on 2026-06-29 and carries
verified = true. Two limitations are disclosed in the config's own notes
field: the personal-income-tax bracket model is a deliberate approximation of the
official schedule inside the ~50,000–60,000 ALL/month transitional band, and the
severance figures are orientues values from the Labor Code's general
principles rather than a statutory table. See
Accuracy & limitations.
Rates and rules change; confirm with the tax authority before invoicing. Nothing here is tax or legal advice.
npm test (TypeScript) and
cd python && PYTHONPATH=src python -m unittest discover -s tests -t tests (104 tests).Bug reports and pull requests are welcome, on the
issue tracker and against
main respectively. Read CONTRIBUTING.md first: it explains the
process and the two rules that decide whether a change is accepted, namely zero runtime
dependencies and a cited legal source for every rate or formula change. Tests are
required in the same pull request as the functionality they cover.
For a wrong number, the fastest report to act on gives the exact inputs, the output you got, the output you expected, and the legal basis for expecting it.
Do not report security problems in a public issue. Use
GitHub private vulnerability reporting
or email info@square.al. Initial response within 14 days. Full policy in
SECURITY.md; ours for square.al as a whole is at
square.al/en/security-compliance.
CodeQL runs over the TypeScript and Python sources on every push, every pull request, and weekly.
See PUBLISHING.md. Tagging vX.Y.Z publishes to PyPI and JSR
over OIDC with no stored tokens and attaches the MCP bundle to the GitHub release;
the MCP registry entry is then refreshed with mcp-publisher publish.
MIT © Square Software SHPK
This listing does not have a supported local package template. Use the maintainer’s documentation for its hosted endpoint, authentication, and client-specific setup. No install command has been inferred.
https://github.com/square-al/fiskalizimi-utils/releases/download/v0.2.0/fiskalizimi-mcp.mcpbotherFiskalizimi — Albanian tax & payroll works with any MCP-compatible client. Copy the config snippet from the Configuration section above and add it to the file shown for your client, then restart the application.
~/Library/Application Support/Claude/claude_desktop_config.jsonRestart Claude Desktop completely for changes to take effect.~/.cursor/mcp.jsonRestart Cursor for changes to take effect..vscode/mcp.jsonReload VS Code window for changes to take effect.~/.codeium/windsurf/mcp_config.jsonRestart Windsurf for changes to take effect..mcp.jsonSave at the project root, then start Claude Code in that project and review the MCP server approval prompt. Keep real credentials out of shared files.