estv-mcp

estv-mcp

MCP server for the Swiss federal tax calculator, providing income, wealth, inheritance, and corporate tax figures for all Swiss municipalities and tax years 2010-2026.

Category
访问服务器

README

estv-mcp

CI

MCP server for the official Swiss federal tax administration calculator at swisstaxcalculator.estv.admin.ch.

It wraps the undocumented JSON API behind that SPA (no key, no auth) and exposes income, wealth, lump-sum, inheritance and corporate tax figures for every Swiss municipality and tax years 2010-2026.

Tools

Household income and wealth:

Tool What it does
find_location Postal code or place name to tax_location_id
calculate_tax Federal, cantonal, municipal and church tax from gross income, wealth and family situation
list_deductions The ESTV budget sheet with its default values, and which lines you may override
calculate_tax_from_taxable_amounts Applies the tax scales to taxable income read off an assessment
explain_tax_brackets The statutory rate ladder and where an income sits in it

Comparing places:

Tool What it does
compare_locations Ranks municipalities by total burden for the same household
find_cheapest_nearby Same ranking, restricted to a radius around a point

Planning:

Tool What it does
plan_capital_withdrawals Cheapest way to split a pension lump sum across tax years
deduction_value What a deduction is worth, franc by franc, at this income

Other taxes:

Tool What it does
calculate_capital_payment_tax Tax on a pillar 2 / pillar 3a lump-sum withdrawal, single place or ranked
calculate_inheritance_tax Inheritance and gift tax by beneficiary relationship
calculate_company_tax Profit and capital tax for a GmbH or AG
get_tax_years Covered year range per calculator and the ESTV data version

Install

uv sync

Register with Claude Code

From inside the repository:

claude mcp add estv-tax -- uv run --directory "$PWD" estv-mcp

Add -s user to make it available in every project rather than just this one.

Or in any MCP client config, with /path/to/estv-mcp replaced by wherever you cloned it:

{
  "mcpServers": {
    "estv-tax": {
      "command": "uv",
      "args": ["run", "--directory", "/path/to/estv-mcp", "estv-mcp"]
    }
  }
}

Development

uv sync                            # install, including dev group
uv run pytest -q                   # tool-level tests plus golden values
uv run python scripts/stdio_smoke.py  # real MCP stdio handshake
uv run ruff check . && uv run ruff format --check .

Tests hit the live ESTV API, so they need network access but no credentials. CI runs lint, the suite on Python 3.11/3.12/3.13, and the stdio smoke check on every push and pull request, plus weekly on a schedule.

Golden values

tests/golden.json pins recorded figures for a closed tax year, where the scales should never move again. tests/test_golden.py re-checks them against the live API with caching disabled, so the weekly run reports upstream drift as a concrete diff rather than just confirming the endpoint still answers.

When a golden test fails, read the diff first. It usually means ESTV changed something, not that this repo is broken. Once the change is understood:

uv run python scripts/update_golden.py   # prints every value that moved

Caching

Responses are cached under ~/.cache/estv-mcp for a week, which matters because the planning tools fan out into dozens of sub-queries. ESTV_MCP_NO_CACHE=1 disables it, ESTV_MCP_CACHE_DIR and ESTV_MCP_CACHE_TTL override the location and lifetime.

Notes

  • Amounts are CHF per year. income_type='employed' means gross salary; the model derives AHV/IV/EO, ALV, NBU and BVG contributions itself.
  • Deduction overrides go through deductions={id: value} on calculate_tax, using the ids from list_deductions (PRAEMIEN3A pillar 3a, SCHULDZINSEN mortgage interest, KKPRAEMIEN health insurance premiums, MIETAUSGABEN rent, KINDBETREUUNGSKOSTEN childcare, and so on).
  • compare_locations(scope='switzerland') covers ~2100 municipalities; only the extremes plus summary statistics come back so results stay readable.
  • Church tax is only charged for confession values other than none.
  • plan_capital_withdrawals models the rule that payouts received in the same calendar year are aggregated before the rate applies, so splitting within a year correctly shows no saving. It does not model the federal aggregation of a spouse's payouts, and years beyond ESTV's published range are priced with the latest available scales. Both are stated in the result's caveats.
  • explain_tax_brackets always takes the amount from ESTV. The ladder is rebuilt from the published scale and reproduces ESTV exactly for the ZUERICH and BUND table layouts; splitting cantons apply extra rounding (flagged via ladder_note), and BL, FR, VD and VS publish formulas rather than tables, where the ladder is omitted rather than guessed at.
  • Figures are the official ESTV model, not a binding assessment.

API notes

Base URL: https://swisstaxcalculator.estv.admin.ch/delegate/ost-integration/v1/lg-proxy/operation/c3b67379_ESTV. Every operation is a POST with a JSON body answering {"response": ...}. Bad input returns an HTML 500 page rather than a structured error, which api.EstvClient translates into an EstvError.

Enum values (from the SPA bundle):

  • Relationship: single 1, married 2, concubinage 3, registered partnership 4
  • Confession: reformed 1, roman catholic 2, christ catholic 3, none 4, other 5
  • Income type: employed 1, self-employed 2, pensioner 3, other 4
  • Language: de 1, fr 2, it 3, en 4
  • TaxGroupID: cantons alphabetically 1-26 (AG=1 … ZH=26), capitals 88, all of Switzerland 99

Two gotchas worth recording:

  • API_exportManyTaxScales reuses the same field names for two different layouts. In ZUERICH tables Amount is the width of a band; in BUND tables it is the lower threshold and Taxes carries the tax already due at it. Reading a BUND table with the ZUERICH rule gives a plausible but wrong number, so TableType has to be honoured.
  • The geo search returns at most 200 results, silently clipping a large radius. find_cheapest_nearby detects the cap and says so.

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选