Dutch Tax Income Calculator MCP
Enables Dutch income tax calculations: converts gross to net salary, net to gross, compares multiple salary scenarios, and provides tax bracket data for supported years. Every result includes a detailed breakdown and a thetax.nl permalink.
README
dutch-tax-income-calculator-mcp
A remote MCP server, deployed on Cloudflare Workers, that exposes the
dutch-tax-income-calculator npm package as MCP
tools and a resource. This server never reimplements Dutch tax logic or copies tax tables — every calculation is
delegated directly to the package.
Indicative only — not tax advice. Every tool result includes this disclaimer. Confirm with a qualified Dutch tax advisor or the Belastingdienst before acting on any number this server returns.
What it exposes
Tools
calculate_net_salary— gross → net, wraps the package'sSalaryPaycheckclass.calculate_gross_from_net— net → gross, wraps the package'snetToGrosssolver. Because every internal amount is rounded to 2 decimals, more than one gross can round to the same net; when that happens the tool returns the package's own plateau bounds (grossLow/grossHigh) verbatim instead of guessing. If no gross produces the target net, the package's "no solution" error message is returned verbatim, unmodified.compare_scenarios— runs 2 to 5calculate_net_salary-shaped scenarios side by side and returns a markdown comparison table alongside the per-scenario results.
Every tool result returns: normalizedInput, result, breakdown[] (payroll tax, social security, general
credit, labour credit), assumptions[], and a permalink to the equivalent scenario on
thetax.nl.
Resource
tax://brackets/{year}— readsdata.jsonfrom the package directly: payroll tax, social security, general credit and labour credit brackets, plus 30% ruling thresholds, for the requested year.
year is validated against the years actually present in the package's data.json on every tool call and
resource read. An unsupported year always returns a clear, explicit error — never a silent fallback to the
nearest year.
Stack
- MCP TypeScript SDK v2 (
@modelcontextprotocol/server) createMcpHandlerfromagents/mcp/server(Cloudflare Agents SDK) as the entire Workerfetchhandler — stateless, no Durable Objects, noMcpAgent.createMcpHandleris given a factory function (createServer) that builds a freshMcpServerper request; no server or transport instance is ever held in module scope.- Zod v4 for input validation
- Wrangler + Vitest
(
@cloudflare/vitest-pool-workers)
No Hono, no Express — src/index.ts is the whole HTTP layer.
Rate limiting & privacy
- 60 requests/minute per client IP, enforced via a Cloudflare Rate Limiting
binding (
wrangler.jsonc), on every request. Exceeding it returns429with aRetry-Afterheader. - Zero logging of input values. The handler never logs request bodies, tool arguments, or calculated amounts. The client IP is used only as an ephemeral rate-limit counter key, never stored or logged.
Development
npm install
npm run dev # wrangler dev, http://localhost:8787/mcp
npm test # vitest (unit tests + Worker-level MCP/HTTP integration tests)
npm run typecheck
npm run deploy # wrangler deploy
Connecting a client
The server speaks the MCP Streamable HTTP transport at /mcp.
Claude Desktop
Claude Desktop connects to remote MCP servers through the mcp-remote
bridge. Add this to claude_desktop_config.json:
{
"mcpServers": {
"dutch-tax-income-calculator": {
"command": "npx",
"args": [
"mcp-remote",
"https://mcp.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://mcp.thetax.nl/mcp"
}
}
}
Deployed at mcp.thetax.nl; if you deploy your own copy, replace the URL with the workers.dev subdomain
npm run deploy assigns (or your own custom domain).
Project layout
src/
index.ts Worker fetch handler: per-IP rate limit + createMcpHandler(createServer)
server.ts createServer() factory — registers the 3 tools and the tax://brackets/{year} resource
env.ts Env (RATE_LIMITER binding) type
tax/
schemas.ts Zod v4 input schemas
years.ts Year validation against the package's constants.years
paycheck.ts Thin wrappers around SalaryPaycheck / netToGross — no tax logic here
breakdown.ts breakdown[] / assumptions[] builders
permalink.ts thetax.nl permalink builder
compare.ts Comparison table builder for compare_scenarios
test/ Vitest unit tests + Worker-level MCP/HTTP integration tests
Recommended Servers
playwright-mcp
A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.
Magic Component Platform (MCP)
An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.
Audiense Insights MCP Server
Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.
VeyraX MCP
Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.
graphlit-mcp-server
The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.
Kagi MCP Server
An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.
Neon Database
MCP server for interacting with Neon Management API and databases
E2B
Using MCP to run code via e2b.
Exa Search
A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.
Qdrant Server
This repository is an example of how to create a MCP server for Qdrant, a vector search engine.