Dutch Tax Income Calculator
A remote MCP server that calculates Dutch net/gross salary, compares scenarios, and looks up official tax brackets, so an AI assistant can answer real salary and tax questions instead of guessing. Every calculation is delegated to the open-source dutch-tax-income-calculator package — this server never reimplements tax logic or tax tables itself.
Server address — paste this into Claude or ChatGPT below:
All three tools are read-only and require no authentication — nothing is written, changed, or deleted, and there's no sign-in step.
Example prompts, once connected:
- "What's my net salary if I earn €65,000 gross in 2026?"
- "How much do I need to earn gross to take home €3,500 a month?"
- "Compare my take-home pay at €50k vs €60k gross, with and without the 30% ruling"
Claude Claude.ai & Claude Desktop
- Open Settings → Connectors, click Add (top right), then
Add custom connector.
- Enter a name (e.g. "Dutch Tax Calculator") in the first field, and the server address from above
in the second field. Leave Advanced settings (OAuth Client ID / Secret) empty — this
server doesn't need them — then click Add.
- Click Connect.
- In any chat, open the + menu and turn the connector on to start using it.
ChatGPT Web, Developer mode required
- Go to Settings → Security and login and turn on Developer mode
(only needs to be done once). ChatGPT will flag it as elevated risk — that's expected, it's what
gates custom/unverified connectors like this one.
- Go to Settings → Plugins.
- Click Browse plugins, then the + button in the top right.
- Fill in the form: a Name (e.g. "Dutch Income Tax"), under Connection
choose Server URL and paste the server address from above, set
Authentication to No Auth, tick "I understand and want to
continue", then click Create.
- Click Connect in the confirmation popup.
- It's now in your installed plugins — use it from the Plugins (@) menu in any chat.
Claude Code & Codex CLI Terminal
These are coding agents with shell/file access, so instead of clicking through settings, just hand them the command or prompt below and let them do it.
Claude Code
A real CLI command — run it directly in your terminal:
claude mcp add --transport http dutch-tax-income-calculator https://thetax.nl/mcp
Codex CLI
Codex's CLI only has a one-liner for local (stdio) servers; for a remote HTTP server like this one it
needs a config.toml edit. Paste this into Codex chat and let it make the edit:
Add a remote MCP server to my Codex CLI config. Edit ~/.codex/config.toml (or ./.codex/config.toml for this project only) and add:
[mcp_servers.dutch-tax-income-calculator]
url = "https://thetax.nl/mcp"
No authentication is needed, so no bearer_token_env_var or http_headers are required. Then confirm the entry was added correctly.
What it can do
- Calculate net salary from gross income, for any supported tax year
- Work backwards from a target net salary to find the matching gross
- Compare 2–5 salary scenarios side by side (different years, hours, 30% ruling, etc.)
- Look up the official payroll tax, social security, and credit brackets for a given year
Tax year data
Every tool takes a year parameter. Supported years are exactly the years present in the
dutch-tax-income-calculator package's bundled data.json — nothing is extrapolated
or assumed for years outside that set. Passing an unsupported year returns a clear error listing which years
are currently supported, never a silent fallback to the nearest year. The full bracket data for a given year
is also readable directly as the tax://brackets/{year} MCP resource.
Tools: input and output
calculate_net_salary
Gross → net for a given tax year. Input schema:
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"year": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991,
"description": "Dutch tax year, e.g. 2026. Must be a year present in the package's data.json — see the tax://brackets/{year} resource for supported years."
},
"allowance": {
"default": false,
"description": "Whether the income figure already includes the 8% holiday allowance (vakantiegeld)",
"type": "boolean"
},
"socialSecurity": {
"default": true,
"description": "Whether Dutch social security contributions (AOW/Anw/Wlz) apply",
"type": "boolean"
},
"older": {
"default": false,
"description": "Whether the person has reached state pension (AOW) age",
"type": "boolean"
},
"hours": {
"default": 40,
"description": "Contracted hours per week",
"type": "number",
"exclusiveMinimum": 0
},
"ruling": {
"default": {
"checked": false
},
"description": "30% ruling (30%-regeling) settings",
"type": "object",
"properties": {
"checked": {
"default": false,
"description": "Whether the 30% ruling (30%-regeling) applies",
"type": "boolean"
},
"choice": {
"description": "Required when checked=true: 'normal' | 'young' (Master's degree, under 30) | 'research' (scientific research worker)",
"type": "string",
"enum": [
"normal",
"young",
"research"
]
}
},
"required": [
"checked"
],
"additionalProperties": false
},
"income": {
"type": "number",
"exclusiveMinimum": 0,
"description": "Gross income, denominated in the unit given by startFrom"
},
"startFrom": {
"default": "Year",
"description": "Which unit `income` is expressed in",
"type": "string",
"enum": [
"Year",
"Month",
"Week",
"Day",
"Hour"
]
}
},
"required": [
"year",
"allowance",
"socialSecurity",
"older",
"hours",
"ruling",
"income",
"startFrom"
],
"additionalProperties": false
}
Output shape (content[0].text, JSON-encoded):
{
"normalizedInput": { /* the validated input, with defaults filled in */ },
"result": { /* full computed paycheck: grossYear, netYear, netMonth, incomeTax, ... */ },
"breakdown": [
{ "label": "Payroll tax (loonbelasting)", "amountYear": -2916, "amountMonth": -243 },
{ "label": "Social security contributions (volksverzekeringen)", "amountYear": -9954, "amountMonth": -829.5 },
{ "label": "General tax credit (algemene heffingskorting)", "amountYear": 2714.29, "amountMonth": 226.19 },
{ "label": "Labour tax credit (arbeidskorting)", "amountYear": 5498.04, "amountMonth": 458.17 }
],
"assumptions": [ "This result is indicative only and is not tax advice ...", "..." ],
"permalink": "https://thetax.nl/?year=2026&startFrom=Year&salary=36000&..."
}
calculate_gross_from_net
Net → gross. Input schema:
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"year": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991,
"description": "Dutch tax year, e.g. 2026. Must be a year present in the package's data.json — see the tax://brackets/{year} resource for supported years."
},
"allowance": {
"default": false,
"description": "Whether the income figure already includes the 8% holiday allowance (vakantiegeld)",
"type": "boolean"
},
"socialSecurity": {
"default": true,
"description": "Whether Dutch social security contributions (AOW/Anw/Wlz) apply",
"type": "boolean"
},
"older": {
"default": false,
"description": "Whether the person has reached state pension (AOW) age",
"type": "boolean"
},
"hours": {
"default": 40,
"description": "Contracted hours per week",
"type": "number",
"exclusiveMinimum": 0
},
"ruling": {
"default": {
"checked": false
},
"description": "30% ruling (30%-regeling) settings",
"type": "object",
"properties": {
"checked": {
"default": false,
"description": "Whether the 30% ruling (30%-regeling) applies",
"type": "boolean"
},
"choice": {
"description": "Required when checked=true: 'normal' | 'young' (Master's degree, under 30) | 'research' (scientific research worker)",
"type": "string",
"enum": [
"normal",
"young",
"research"
]
}
},
"required": [
"checked"
],
"additionalProperties": false
},
"targetNet": {
"type": "number",
"exclusiveMinimum": 0,
"description": "Target net income to solve for"
},
"field": {
"default": "netYear",
"description": "Which net figure targetNet refers to: netYear (annual) or netMonth (monthly)",
"type": "string",
"enum": [
"netYear",
"netMonth"
]
},
"holidayAllowanceIncluded": {
"default": false,
"description": "Whether targetNet already includes the net holiday allowance payout",
"type": "boolean"
}
},
"required": [
"year",
"allowance",
"socialSecurity",
"older",
"hours",
"ruling",
"targetNet",
"field",
"holidayAllowanceIncluded"
],
"additionalProperties": false
}
Output shape is the same as calculate_net_salary, except when rounding makes the gross
non-unique or no gross produces the target net — see below.
{
"normalizedInput": { /* ... */ },
"result": { "plateau": true, "grossLow": 35999.5, "grossHigh": 36000.49 },
"breakdown": [ /* computed at grossHigh */ ],
"assumptions": [ "...", "Rounding to 2 decimals means more than one gross value produces this net income; ..." ],
"permalink": "https://thetax.nl/?..."
}
If no gross produces the target net at all, the tool returns isError: true with the
package's own error message verbatim (e.g. naming the nearest achievable net) — never a generic error.
compare_scenarios
2–5 scenarios, each shaped like calculate_net_salary's input plus an optional
label. Input schema:
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"scenarios": {
"minItems": 2,
"maxItems": 5,
"type": "array",
"items": {
"type": "object",
"properties": {
"year": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991,
"description": "Dutch tax year, e.g. 2026. Must be a year present in the package's data.json — see the tax://brackets/{year} resource for supported years."
},
"allowance": {
"default": false,
"description": "Whether the income figure already includes the 8% holiday allowance (vakantiegeld)",
"type": "boolean"
},
"socialSecurity": {
"default": true,
"description": "Whether Dutch social security contributions (AOW/Anw/Wlz) apply",
"type": "boolean"
},
"older": {
"default": false,
"description": "Whether the person has reached state pension (AOW) age",
"type": "boolean"
},
"hours": {
"default": 40,
"description": "Contracted hours per week",
"type": "number",
"exclusiveMinimum": 0
},
"ruling": {
"default": {
"checked": false
},
"description": "30% ruling (30%-regeling) settings",
"type": "object",
"properties": {
"checked": {
"default": false,
"description": "Whether the 30% ruling (30%-regeling) applies",
"type": "boolean"
},
"choice": {
"description": "Required when checked=true: 'normal' | 'young' (Master's degree, under 30) | 'research' (scientific research worker)",
"type": "string",
"enum": [
"normal",
"young",
"research"
]
}
},
"required": [
"checked"
],
"additionalProperties": false
},
"income": {
"type": "number",
"exclusiveMinimum": 0,
"description": "Gross income, denominated in the unit given by startFrom"
},
"startFrom": {
"default": "Year",
"description": "Which unit `income` is expressed in",
"type": "string",
"enum": [
"Year",
"Month",
"Week",
"Day",
"Hour"
]
},
"label": {
"description": "Optional label to identify this scenario in the comparison table",
"type": "string",
"minLength": 1,
"maxLength": 80
}
},
"required": [
"year",
"allowance",
"socialSecurity",
"older",
"hours",
"ruling",
"income",
"startFrom"
],
"additionalProperties": false
},
"description": "Between 2 and 5 salary scenarios to compare, each shaped like calculate_net_salary's input"
}
},
"required": [
"scenarios"
],
"additionalProperties": false
}
{
"assumptions": [ "This result is indicative only and is not tax advice ..." ],
"scenarios": [
{ "index": 1, "label": "Current", "normalizedInput": { /* ... */ }, "result": { /* ... */ }, "breakdown": [ /* ... */ ], "assumptions": [ /* ... */ ], "permalink": "..." },
{ "index": 2, "label": "After raise", "...": "..." }
],
"comparisonTable": "| # | Label | Year | Gross/yr | Net/yr | Net/mo | Income tax | Effective tax rate |\n|---|---|---|---|---|---|---|---|\n| 1 | Current | 2026 | ... |"
}
Manual client config (VS Code, Cursor, raw MCP clients)
claude_desktop_config.json (manual config via the
mcp-remote bridge):
{
"mcpServers": {
"dutch-tax-income-calculator": {
"command": "npx",
"args": [
"mcp-remote",
"https://thetax.nl/mcp",
"--transport",
"http-only"
]
}
}
}
mcp.json (VS Code, Cursor, and other clients supporting the standard config format):
{
"servers": {
"dutch-tax-income-calculator": {
"type": "http",
"url": "https://thetax.nl/mcp"
}
}
}
Rate limits and privacy
60 requests/minute per client, no authentication. No request bodies, tool arguments, or calculated amounts are ever logged — see the Privacy Policy for details.
Support
Source and issue tracker: https://github.com/stevermeister/dutch-tax-income-calculator-mcp. Contact: stevermeister@gmail.com.