pricewise-mcp
This server does not currently have a deployable release on Glama. Follow the repository's setup instructions to install and configure it for your MCP client, including any required credentials and local dependencies.
pricewise-mcp
An MCP server that lets Claude Desktop, Claude Code or any MCP client compute Portuguese vehicle taxes (ISV and IUC) and price ranges, using the tested code in pricewise-pt.
In 30 seconds
Three tools:
calculate_isv,calculate_iuc,estimate_price_range.Deterministic: same input, same output. No network calls and no file writes; the tests block all non-loopback network access and fail if a tool path opens a file for writing. The tax arithmetic lives in pricewise-pt, written from the legal articles and checked against hand-worked examples; this server adds typed inputs, validation, sources and error messages a language model can act on.
Every tax answer lists its assumptions (
flags), its legal sources and a not-tax-advice disclaimer.The price tool is a demo on synthetic data, labelled as such in every answer.
Resources for the versioned tax tables and a limitations document, plus one prompt.
stdio for local clients, Streamable HTTP for remote use.
Real transcript of every tool: docs/demo-transcript.md.
Related MCP server: Clara Carros MCP server
Install and connect
Needs uv. Nothing is published to PyPI; the commands install straight from GitHub.
1. Install once
uv tool install git+https://github.com/cardohso/pricewise-mcp
pricewise-mcp --version # run it once now: the first launch is slow, later ones take secondsInstall once instead of launching with uvx --from git+...: uvx contacts GitHub on
start and rebuilds the package after the repo changes, and a cold start can exceed the 30-second connect timeout
Claude Code applies (this happened while testing). The installed command starts offline. To
update later: uv tool upgrade pricewise-mcp.
2. Connect a client
Claude Code
claude mcp add pricewise -- pricewise-mcpClaude Desktop: add to claude_desktop_config.json (Settings, Developer, Edit Config):
{
"mcpServers": {
"pricewise": {
"command": "pricewise-mcp"
}
}
}Claude Desktop may not find the command on its PATH. If the server does not start, put the
full path from which pricewise-mcp in "command".
Streamable HTTP (remote or shared use):
pricewise-mcp --transport http --port 8000
claude mcp add --transport http pricewise http://127.0.0.1:8000/mcpHTTP is stateless, answers in JSON and binds to 127.0.0.1 by default. The server has no
authentication; if you bind another address it warns on stderr. Put it behind a reverse proxy
that authenticates callers before exposing it.
No install (slower and more fragile): replace pricewise-mcp in the commands above with
uvx --from git+https://github.com/cardohso/pricewise-mcp pricewise-mcp.
From a clone
git clone https://github.com/cardohso/pricewise-mcp && cd pricewise-mcp
python -m venv .venv && .venv/bin/pip install -e ".[dev]"
.venv/bin/pricewise-mcp --versionThe first valuation call after the server starts can take up to about 20 seconds: the model is fitted in a background thread at launch.
Tools
All three are read-only, idempotent and closed-world (tool annotations). Responses are
structured JSON matching the tool's output schema. Examples below are real server output;
sources and disclaimer are shortened here and complete in the
transcript.
calculate_isv
The one-off registration tax for a used passenger car brought in from another EU/EEA state.
Input: a vehicle (first registration date, fuel, engine cc, CO2 g/km, CO2 test standard, and
optional Euro class, diesel particles, electric range, hybrid base fuel), a required
declaration_date, and an optional tax_year.
{"vehicle": {"first_registration": "2019-06-15", "fuel": "petrol", "engine_cc": 1199,
"co2_g_km": 125, "co2_standard": "wltp"},
"declaration_date": "2026-10-01"}{
"total_eur": 211.3,
"engine_component_eur": 197.45,
"co2_component_eur": 13.85,
"age_reduction": 0.65,
"regime": "normal",
"minimum_applied": false,
"co2_standard_used": "wltp",
"co2_standard_assumed": false,
"flags": [],
"tax_year": 2026,
"sources": ["Código do Imposto sobre Veículos (Lei 22-A/2007), art. 7, tabela A ...", "..."],
"disclaimer": "Illustration only, not tax advice. ..."
}With the CO2 standard and a diesel's particle value left out, the same call still answers, with the costlier assumption made explicit:
{
"total_eur": 1717.64,
"particle_surcharge_eur": 500.0,
"co2_standard_assumed": true,
"flags": [
"CO2 standard (NEDC/WLTP) assumed from the registration date: confirm it on the certificate of conformity",
"diesel particle value unknown: check field V.5 of the registration document"
]
}(Other fields omitted. Input: a 2020-03-01 diesel, 1598 cc, 115 g/km.)
calculate_iuc
One year of the yearly circulation tax for a category B car (first registered on or after
1 July 2007). Same vehicle object; optional tax_year.
{"vehicle": {"first_registration": "2019-06-15", "fuel": "petrol", "engine_cc": 1199,
"co2_g_km": 125, "co2_standard": "wltp"}}{"total_eur": 111.46, "engine_component_eur": 31.77, "co2_component_eur": 65.15,
"co2_extra_eur": 0.0, "year_coefficient": 1.15, "diesel_extra_eur": 0.0,
"co2_standard_assumed": false, "flags": [], "tax_year": 2026}(sources and disclaimer omitted.) Cars registered before July 2007 get an error.
estimate_price_range
A used-car asking price with a 50% and an 80% range. Trained on synthetic, made-up listings:
it demonstrates calibrated uncertainty and says nothing about a real car or market. Input:
category (compact, hatchback, crossover, estate, electric), age_years, usage
(km), optional condition.
{"category": "compact", "age_years": 6, "usage": 90000, "condition": "good"}{
"point_eur": 10504.17,
"range_50": {"low_eur": 9362.4, "high_eur": 11535.41},
"range_80": {"low_eur": 8548.65, "high_eur": 12704.31},
"comparables_median_eur": 10190.0,
"data_source": "synthetic",
"flags": [],
"notice": "Trained on synthetic, made-up listings. ..."
}Inputs outside the synthetic training range add an extrapolation flag.
What a wrong call looks like
Invalid arguments for calculate_isv. Fix these and call again:
- vehicle.first_registration: input should be a valid date or datetime, invalid character in year (got '15/06/2019'). Hint: dates are YYYY-MM-DD; if '15/06/2019' is day/month/year, send '2019-06-15'
- vehicle.fuel: input should be 'petrol', 'diesel', 'hybrid', 'plugin_hybrid' or 'electric' (got 'gasoline'). Hint: use 'petrol' for 'gasoline'Resources and prompt
URI | What |
| Index of the available table years, with legal sources |
| The ISV rate tables exactly as the calculator uses them |
| The IUC rate tables |
| What the server does not do |
Prompt explain_tax_breakdown(vehicle_description, declaration_date): tells the model to call
both tax tools, ask for missing fields instead of guessing, explain each component, list the
flags and finish with the disclaimer.
Design decisions
Deterministic tools only. A model is good at conversation and bad at arithmetic on legal tables. These tools do the arithmetic; the model only gathers inputs and explains outputs. All tax logic stays in pricewise-pt, the server is a thin typed layer.
declaration_dateis required. ISV depends on the car's age on that date. A hidden default of "today" would make results change silently, so the model must pass it.Assumptions are data. Instead of refusing when the CO2 standard or a diesel's particle value is unknown, ISV computes the costlier case and returns the assumption in
flags, with the other standard's total inalternative_total_eurwhere both apply. IUC assumes the standard from the registration year and flags it. Tool descriptions tell the model to relay flags; engine size and CO2 are never guessed (the model is told to ask).Structured output plus provenance. Every tax result carries
sources(the articles the tables come from) and the disclaimer, so they survive however the model paraphrases.Errors written for a model, not a developer. pydantic's raw text (internal names, the echoed input, a docs URL) is replaced by one line per problem with the field, the value sent and a hint for common mistakes (
gasoline, day/month/year dates, litres for cm3). Domain errors say whether retrying makes sense. Unknown top-level arguments are rejected: the SDK would otherwise drop a misspelt optional argument silently.One nested
vehicleobject shared by the tax tools, so the model fills the same shape every time and a future multi-vehicle tool can reuse it.No
compare_coststool. A model can call the two tools and add the results. A multi-year total would assume today's IUC rates and coefficients hold for N years, which is false, and would look more precise than it is.Synthetic valuation, labelled everywhere. The model is fitted at startup from pricewise-pt's generator (about 15 s), so no data file ships and the output is reproducible.
Stateless HTTP. No sessions to store; any instance can answer any request.
Pinned library. pricewise-pt is not on PyPI, so it is pinned to a commit in
pyproject.tomland its tax tests remain the source of truth.
Limitations
Short version; the full text is the pricewise://limitations resource.
Not tax advice. 2026 tables only; confirm with the Autoridade Tributária e Aduaneira.
Used passenger cars from another EU/EEA state. Not covered: imports from outside the EU/EEA, commercial vehicles, motorcycles, exemptions beyond the hybrid regimes in the tables.
IUC is one year at the table year's rates; category A (before July 2007) is rejected.
The price model is trained on synthetic data and its ranges are calibrated only on that data.
HTTP has no authentication.
Tested with the MCP Python SDK's client over stdio and HTTP (in CI), and by hand on 2 November 2026 in two clients, asking for the ISV and IUC of the 2019 petrol car above and for a compact's price range:
Claude Code (terminal): called the three tools and reported €211.30, €111.46 and the synthetic range, with the disclaimer and the synthetic-data warning. That session also hit the cold-start timeout described under Install.
Claude Desktop chat: called the three tools and reported the same figures and the synthetic-data warning, but did not repeat the "not tax advice" disclaimer even though every tax result carries it and the tool descriptions ask the model to relay it. The server returns the disclaimer; whether a client shows it is up to the model.
Development
pip install -e ".[dev]"
ruff check . && ruff format --check .
pytest -q # about 30 s: the valuation model is fitted a few times
python examples/demo_client.py > docs/demo-transcript.md # regenerate the transcriptThe tests run offline (only loopback is reachable), assert no file is opened for writing in the ISV, IUC and valuation paths, list the tools through an in-process client, start the server as a real subprocess over stdio and HTTP, and reuse the hand-worked ISV and IUC cases from pricewise-pt as golden values.
Licence
MIT, see LICENSE.
This server cannot be deployed
Maintenance
Related MCP Connectors
An open MCP server for the Portuguese housing market, run by flatin.pt. No API key, no registration, no rate-limit negotiation. Twelve tools: • imt_calculate — IMT and Imposto do Selo on a purchase, 2026 tables, including the reduced table, the relief for buyers aged 35 or under and the flat rate for non-residents • imi_rate / imi_annual_cost — the IMI rate of any of the 308 municipalities for 2023–2025, and the annual bill for a given VPT • construction_barometer — how many building-permit cases enter a town hall each month (our own indicator: monthly for three municipalities, annual for eight, method and revision policy published) • search_newbuilds / get_newbuild — 250 new developments, 53 municipalities, 71 developers, with stage and, where published, price • where_to_live / municipality_stats / compare_municipalities — municipal comparisons • glossary_lookup — Portuguese property and tax terms • request_consultation / subscribe_digest — reaching a human The data behind the tax tools is published as open data under CC BY 4.0 on the Portuguese national portal (dados.gov.pt) and archived on Zenodo with a permanent DOI. Anyone may reuse it. Humans, not bots, answer the people who get in touch: a home purchase involves personal data under the GDPR and decisions that cannot be refunded.
CarsXE MCP — wraps the CarsXE Vehicle Data API (carsxe.com)
Vehicle valuations and market reports in Claude or ChatGPT. Pay per report, no subscription.
Auto.dev MCP — wraps the Auto.dev automotive data API (auto.dev)
Related MCP Servers
- AlicenseNot gradedqualityAmaintenanceEnables AI assistants to provide Portuguese legal advice by exposing legal calculators, templates, and reference documents through the MCP protocol.MIT
- AlicenseAqualityCmaintenanceEnables AI assistants to search car inventory, estimate import taxes (ISV) and resale values, and request quotes from Clara Carros, a Portuguese used and imported cars marketplace.947 npm1MIT
- AlicenseAqualityCmaintenanceEnables AI assistants to search live used-car inventory, verify whether asking prices are fair market value, estimate annual road tax and running costs, and initiate contact with sellers for the Portuguese market.645 npmMIT
- FlicenseCqualityCmaintenanceIt enables documented checks on Milan's Area B and Area C vehicle access, MoVe-In budget calculations, and anti-smog restriction status, returning structured MCP responses with references and clear limitations.41-