内容
estv-mcp
](https://github.com/noaahh/estv-mcp/actions/workflows/ci.yml/badge.svg)](https://github.com/noaahh/estv-mcp/actions/workflows/ci.yml)
瑞士联邦税务局官方税收计算器的MCP服务器,访问地址为 [swisstaxcalculator.estv.admin.ch](https://swisstaxcalculator.estv.admin.ch/)。
了单页应用(SPA)背后的未公开JSON API(无需密钥,无需认证),并为瑞士每个市镇和2010-2026年的税收年度提供收入、财富、一次性付款、遗产和公司税数据。
## 工具列表
家庭收入和财富:
| 工具 | 功能描述 |
| --- | --- |
| `find_location` | 通过邮政编码或地名查找 `tax_location_id` |
| `calculate_tax` | 根据总收入、财富和家庭情况计算联邦、州、市和教会税 |
| `list_deductions` | 提供ESTV预算表的默认值,以及可覆盖的项目 |
| `calculate_tax_from_taxable_amounts` | 将税率应用于从评估中读取的应税收入 |
| `explain_tax_brackets` | statutory rate ladder 及收入在其中的位置 |
比较地区:
| 工具 | 功能描述 |
| --- | --- |
| `compare_locations` | 按相同家庭的总负担对市镇进行排名 |
| `find_cheapest_nearby` | 同样排名,限制在某个半径范围内 |
规划:
| 工具 | 功能描述 |
| --- | --- |
| `plan_capital_withdrawals` | 将养老金一次性付款分配到多个税收年度的最便宜方式 |
| `deduction_value` | 在当前收入水平下,扣除额的价值 |
其他税收:
| 工具 | 功能描述 |
| --- | --- |
| `calculate_capital_payment_tax` | 养老金第二支柱/第三支柱一次性付款的税款,单个地点或排名 |
| `calculate_inheritance_tax` | 按受益人关系计算遗产和赠与税 |
| `calculate_company_tax` | GmbH或AG的利润和资本税 |
| `get_tax_years` | 每个计算器覆盖的年度范围和ESTV数据版本 |
## 安装
```sh
uv sync
```
## 在Claude Code中注册
在仓库内:
```sh
claude mcp add estv-tax -- uv run --directory "$PWD" estv-mcp
```
添加 `-s user` 以使其在所有项目中可用,而不仅仅是当前项目。
或者在任何MCP客户端配置文件中path/to/estv-mcp` 替换为克隆的实际路径:
```json
{
"mcpServers": {
estv-tax": {
"command": "uv",
": ["run", "--directory", "/path/to/estv", "estv-mcp"]
}
}
}
```
```sh
uv sync # 安装,包括开发组
uv run pytest -q # 工具级测试和黄金值测试
uv run python scripts/stdio_smoke.py # 真实的MCP/输出握手
uv run ruff check . && uvuff format --check .
```
测试会访问实时ESTV API,因此需要网络访问但不需要凭证运行lint、Python 3/3.12/3.13的测试套件和/输出烟雾测试,并在每次推送和拉取请求时运行,以及每周按计划运行。
### 黄金值
`tests/golden.json` 锁定了一个封闭税收年度的记录值,税率应该不会再变化。`tests/test_golden.py` 在禁用缓存的情况下重新检查它们与实时API的匹配情况,因此每周运行会以具体的差异报告上游漂移,而不是简单地确认端点仍然存在。
当黄金测试失败时,首先读取差异。通常意味着ESTV更改了某些内容,而不是这个存储库损坏了。 一旦更改被理解:
```sh
uv run python scripts/update_golden.py # 打印所有更改的值
```
### 缓存
响应在 `~/.cache/estv-mcp缓存一周,这对于规划工具来说很重要,因为它们会扩展到数十个子查询。`_MCP_NO_CACHE=1` 禁用缓存,`ESTCP_CACHE_DIR` 和 `ESTV_MCP_CACHE_TTL`位置和生命周期。
## 注意事项
- 金额为士法郎。`income_type='employed'` 表示总工资;模型本身派生 AHV/IV/EO、ALV、NBU 和 BVG 贡献。
- 扣除覆盖通过 `deductions={id: value}` 在 `calculate_tax` 上进行,使用 `list_deductions` 中的 id(`PRAEMIEN` 第三支`SCHULDZINSEN` 抵押贷款利息,`KKPRAEMIEN` 健康保险费,`MIETAUSGABEN`,`KINDBETREUUNGSKOSTEN` 儿童保育等)。
compare_locations(scope='switzerland')` 涵盖约2100个市镇;只有极端值和汇总统计数据会返回,因此结果仍然可读。
- 教仅在 `confession` 值不为 `none`。
- `plan_capital_withdrawals` 模拟了在同一日历年内收到的聚合后才应用税率的规则,因此在一年内分割无节省。它不模拟配偶的联邦聚合,超过已发布范围的年份最新的可用税率定两者都在结果的 `ats` 中说明。
- `explain_tax_brackets` ESTV获取金额。阶梯根据发布的税率重建,并完全复制ESTV的ZUERICH和BUND表格布局州应用额外舍入(通过 `ladder_note` 标记),而BL、FR、VS发布公式而不是表格,其中省略阶梯而不是猜测 数据为官方ESTV模型,而非具有约束力的评估。
##注意事项
基准URL:`https://swisstaxv.admin.ch/delegate-integration/v1/lgoperation/c3b67379_ESTV`。
每个操作JSON正文的 `POST` 请求,回答 `{"response": ...}`。错误的输入返回HTML 500页面,而不是结构化错误,`api.EstvClient` 将其转换为 `EstvError`。
枚举值(来自SPA包):
- 关系:1,已婚2,同,注册伴侣4 信仰:改革派1,天主教2,基督教天主教3,无4,其他5
- 收入类型:就业1,自雇2,退休人员3,其他4
- 语言:德语1,法语2,意大利语3,英语4
- `TaxGroupID`:州(按字母顺序1-26,AG=1 ... ZH=26),首都88,整个瑞士99
两个值得记录的陷阱:
- `API_exportManyTaxScales` 重用两个不同布局的相同字段名称。在`ZUERICH`表格中,`Amount`是频段的宽度;在`BUND`表格中,它是下限阈值,`Taxes`携带已到账的税款。 使用`ZUERICH`规则读取`BUND`表格会得到一个看似合理但错误的值,因此必须遵守`TableType`。
- 地