kishida-devil

jp-payroll-mcp

Community kishida-devil
Updated

Japanese payroll, social insurance and labour law as an MCP server and HTTP API. Computes rather than looks up, and cites the statute it relied on.

jp-payroll-mcp

Japanese payroll, social insurance and labour law, computed rather than looked up —premiums for all 47 prefectures, withholding tax, standard remuneration decisions andrevisions, leave exemptions, minimum wage — with the statute or ministerial notice eachanswer rests on.

Verified against the published tables cell by cell: 3,638 assertions on every change.

Two ways in

As an MCP server, for asking questions through an AI assistant. 17 tools, free, no key:

claude mcp add jp-payroll -- npx -y jp-payroll-mcp

As an HTTP API, for building it into software. 36 endpoints, OpenAPI 3.0, batch:

curl "https://japan-payroll-api.tsumugi.workers.dev/v1/payroll?prefecture=Tokyo&monthly_salary=350000&birth_date=1986-04-01"

The MCP server is a thin layer over the API, so both give the same answers. Which youwant depends on whether a person or a program is asking.

  • MCP server source and its own README: mcp/ · 日本語
  • Live API: https://japan-payroll-api.tsumugi.workers.dev
  • OpenAPI spec: /openapi.json

Related tools

Japanese statutory MCP servers mostly retrieve — they hand you the text of a law andleave the reasoning to you. This one computes, and returns the provision it relied on.They fit together rather than compete:

"What does the law say?" "So what do I pay?"
labor-law-mcp 45 labour and social insurance laws, MHLW and JAISH notices
tax-law-mcp 24 tax laws, 17 NTA circulars, tribunal decisions
hourei-mcp-server Any Japanese law, via e-Gov
jp-payroll-mcp The 28 provisions it cites, in full Premiums, withholding tax, grade revisions, exemptions

If you already run one of those, add this alongside it. An assistant with both picks theright one per question.

Why this exists

  • No consolidated API exists. Developers assemble this from 協会けんぽ, 厚生労働省 andeach prefectural labour bureau separately.
  • The rules are fiddly. Premiums are computed on the standard monthly remuneration(a 50-grade step function), not on actual salary — except employment insurance, whichuses actual salary. Pension caps at grade 32. Long-term care applies only to ages 40–64.The employee share rounds half down (≤ 0.50 yen truncates). Getting one of these wrongproduces numbers that look plausible and are wrong.

MCP server

Source in mcp/, with its own README ·日本語. Test it with npm run mcp:test — it drives a real stdiotransport with the real MCP client, because a tool with a broken handler still listsperfectly and only fails when something calls it.

The MCP server is free and always will be. It is a distribution channel rather than arevenue one: npm pays nothing and MCP has no billing of its own. That is deliberate —the problem was never billing, which RapidAPI already handles, but discovery, and MCPis where the traffic for Japanese statutory data measurably is.

Endpoints

Endpoint Description
GET / API info and endpoint list
Payroll and insurance
GET /v1/prefectures All 47 prefectures with JIS codes
GET /v1/insurance-rates?prefecture=Tokyo Health, long-term care, pension, child-support rates
GET /v1/standard-remuneration?remuneration=350000 Grade lookup for a monthly amount
GET /v1/standard-remuneration/table Full 50-grade table
GET /v1/employment-insurance?business_type=general Employment insurance rates
GET /v1/payroll?prefecture=Tokyo&monthly_salary=350000&age=40 Full deduction breakdown
Minimum wage
GET /v1/minimum-wage?prefecture=Tokyo&date=2020-01-01 Rate in effect on a date
GET /v1/minimum-wage/history?prefecture=Tokyo Full history since FY2002
Calendar
GET /v1/holidays?year=2026 Public holidays (or from=/to= for a range)
GET /v1/holidays/check?date=2026-01-01 Holiday / weekend / business-day flags
GET /v1/business-days?from=&to= Count business days in a range
GET /v1/business-days/shift?date=&days=1 Move N business days forward or back
Tax
GET /v1/consumption-tax?date=&amount=&reduced= Rate in force, optionally applied to an amount
GET /v1/consumption-tax/history Every rate change since 1989
Identifiers
GET /v1/corporate-number/validate?number=8700110005901 法人番号 check digit (Peppol ICD 0188)
GET /v1/corporate-number/check-digit?base=700110005901 Check digit for a 12-digit base number
GET /v1/invoice-number/validate?number=T8700110005901 Qualified invoice registration number
Withholding tax
GET /v1/withholding-tax?taxable_amount=300000&dependants=2 Monthly withholding income tax (月額表)
GET /v1/withholding-tax/daily?taxable_amount=12000&column=hei Daily table (日額表), including the 丙 column
GET /v1/withholding-tax/computer?taxable_amount=400000 Same, by the formula method (電算機計算の特例)
Bonuses
GET /v1/bonus-tax?bonus=500000&previous_month_pay=350000 Withholding on a bonus (賞与の算出率表)
GET /v1/bonus-insurance?prefecture=Tokyo&bonus=800000&age=40 Social insurance on a bonus, with both caps
Standard remuneration decisions
GET /v1/standard-remuneration/regular?months=350000:30,352000:31,349000:30 定時決定 (算定基礎) from April–June
GET /v1/standard-remuneration/revision?current_remuneration=&months=&fixed_pay_change= Is a 随時改定 (月額変更) due?
GET /v1/standard-remuneration/leave-end?kind=childcare&current_remuneration=&months= Revision on returning from leave
POST /v1/standard-remuneration/annual-average 年間平均による保険者算定, for seasonal work
Eligibility and leave
GET /v1/eligibility?month=2026-03&left_on=2026-03-30 Is a premium due in a joining or leaving month?
GET /v1/leave-exemption?kind=childcare&start=&end= Which months a maternity or childcare leave exempts
GET /v1/age-milestones?birth_date=1986-04-01 When 40, 65, 70 and 75 are reached, and what changes
Batch
POST /v1/payroll/batch Up to 500 payslips in one call, with run totals
Statutes
GET /v1/statute?ref=健康保険法第43条 Full text of a provision this API cites
GET /v1/statute/index Every provision available, with its law
include=statute_text Add to any endpoint to attach the text of whatever it cited
Meta
GET /v1/enums Every accepted enum value and error code
GET /v1/data-freshness What each dataset covers and when it changes next

prefecture accepts an English name (Tokyo, case-insensitive), Japanese (東京 or東京都), or a JIS code (13).

The one call that matters

Running payroll for one employee is a single request:

curl "https://japan-payroll-api.tsumugi.workers.dev/v1/payroll?prefecture=Tokyo&monthly_salary=350000&age=40&dependants=2"
gross                    350,000
social insurance          -55,750
                       ----------
after social insurance   294,250   <- the base withholding tax is charged on
withholding income tax    -4,480
                       ----------
net pay                  289,770

That middle line is the point. Income tax is charged on pay after social insurance,not on gross pay, and deriving it by hand is the mistake this endpoint exists to stop.The response also carries the grade that was resolved, every premium split into employeeand employer shares, and which bracket produced the tax — so the arithmetic can beaudited rather than trusted.

Resident tax (住民税) is assessed by the municipality and notified to the employer; no APIcan compute it. Pass resident_tax= and it will be subtracted from net pay.

Pass income_tax=false to get social insurance only.

Before you integrate

  • GET /v1/enums lists every accepted value — business_type, column, calendar —and every error code, so they can be read at build time instead of discovered from a 400.
  • Errors carry a stable code. invalid_request and missing_parameter mean fix thecall; out_of_coverage means the input was valid but falls outside what is published,which needs a different branch. Do not match on the English prose — it will change.
  • GET /v1/data-freshness tells you how current each dataset is.

Data

Dataset Coverage Source
Social insurance rates 47 prefectures, FY2026 (令和8年度), effective 2026-03 協会けんぽ 保険料額表
Standard remuneration table 50 health grades / 32 pension grades same
Employment insurance 3 business types, FY2026, effective 2026-04-01 厚生労働省
Minimum wage 47 prefectures × 24 years (FY2002–FY2025) 厚生労働省 地域別最低賃金
Public holidays 1,067 days, 1955–2027 内閣府 国民の祝日について
Consumption tax 4 rate periods since 1989, with reduced rate 国税庁 No.6303
Corporate number check digit algorithm, no dataset 国税庁 チェックデジットの計算
Withholding tax (monthly) 231 brackets + 9 high-income anchors, 令和8年分 国税庁 源泉徴収税額表
Withholding tax (formula) 4 statutory tables, 令和8年分以降 電算機計算の特例

All figures are extracted programmatically from the official spreadsheets — nottranscribed by hand. See scripts/ for the extractors.

Why not the statute

Income tax figures come from the National Tax Agency's published tables rather than from所得税法 via the e-Gov law API, because the statutory version omits the 2.1% reconstructionsurtax. At 105,000–107,000 yen the 乙 column is 3,700 yen in 別表第二 and 3,800 yen inpractice; below 105,000 yen it is 3% rather than 3.063%. The statute is the wrong sourcefor payroll.

Above 740,000 yen the table stops being a table: it becomes anchor points with a marginalrate. Those anchors are not collinear — rounding is baked into each — so the publishedanchor values are carried rather than recomputed. The 乙 column has only two anchors(740,000 and 1,710,000) where 甲 has nine, and measuring the 乙 excess from a 甲 anchorsilently under-charges. That was a real bug here, caught by the cell-by-cell comparison.

Citations resolve to text

Naming a statute and leaving the reader to find it is half an answer. Every provisionthis API cites is bundled, so 健康保険法第43条 can be turned into its actual words inthe same round trip:

curl 'https://japan-payroll-api.tsumugi.workers.dev/v1/statute?ref=健康保険法第43条'
curl '…/v1/standard-remuneration/revision?…&include=statute_text'

Citations are written many ways in practice and all of them resolve — 健保法43条,厚年法81条の2, 徴収法11条, a missing 第, paragraph-level references, full-widthdigits. The e-Gov abbreviations are not the ones practitioners use (e-Gov calls it厚生年金法; everyone writes 厚年法), so both are accepted.

Text comes from the e-Gov 法令API at build time rather than at request time: callingout to e-Gov on every request would mean this API goes down when theirs does.

scripts/extract-statutes.py holds the one list of provisions, and the test suitechecks that every citation the code emits resolves — a citation added without aprovision to back it fails the build rather than silently returning nothing.

Known gaps

  • The year-end adjustment tables are not included. 令和8年分's「給与所得控除後の給与等の金額の表」 was not yet published as of 2026-08; the Tax Agencyreleases it around September. 令和8年度税制改正 also raises the minimum employment incomededuction to 740,000 yen with effect from 2026-12-01, so that table changes too.

  • FY2026 minimum wage is not included. As of 2026-08, revisions were still beingissued prefecture by prefecture and take effect from October 2026. The API servesFY2025, which is the rate currently in force. This must be refreshed once all 47prefectures publish.

  • Employment insurance history is FY2026 only. Earlier years were not verifiedagainst a primary source, so they are omitted rather than guessed.

  • Resident tax is out of scope. It depends on the previous year's income and onthe municipality, and it is levied by the municipality rather than computed by theemployer, so /v1/payroll deducts whatever figure you pass and never derives one.

  • The judgement endpoints decide whether a filing is due; they are not the filing.Several rules turn on facts an API cannot see — whether a seasonal swing is「業務の性質上例年発生することが見込まれる」, whether an allowance is 実費弁償, whether theemployee consented. Those are declared inputs, echoed back in the response, and theinsurer can still reach a different conclusion under 保険者算定.

  • Not every standard-remuneration route is covered. 資格取得時決定 returns how longthe decision stays in force but does not compute the initial 報酬月額 (健保法42条1項has four methods, three of which need figures about other employees). 二以上事業所勤務 — where remuneration from several employers is summed and the premium splitbetween them — is not implemented at all. Neither is the re-anchoring that happenswhen fixed pay changes twice inside the three-month window.

  • A few practice points could not be sourced to a primary document and are listedas guidance.fixed_pay.unverified in the response rather than being asserted:whether 家族手当 counts as fixed pay, how paid leave is counted toward 支払基礎日数,and how 年俸制 is treated. Secondary sources agree on all three; the ministries donot appear to say so in writing.

Verification

test/verify.mjs runs 3,638 assertions against a live server. The core of it compares theAPI's computed premiums to the amounts printed in the official 協会けんぽ workbook for250 prefecture × grade combinations — the published half-share figures, not areimplementation of the formula. It also checks:

  • grade boundary contiguity, and that a boundary yen value belongs to the upper grade
  • pension clamping at grades 1 and 32
  • long-term care switching on at 40 and off at 65
  • employment insurance charged on actual salary while other premiums use the grade
  • point-in-time minimum wage (including the day before an effective date)
  • prefecture resolution across all four input forms
  • all 47 prefectures returning a valid payroll response
  • business-day counts against an independently computed reference
  • the 2026-09-22 国民の休日 (a holiday only because it sits between two others)
  • one-off imperial holidays: 大喪の礼, 即位礼正殿の儀, 結婚の儀
  • the corporate-number check digit against the worked example in the NTA PDF, and thatevery other check digit is rejected for the same base
  • every published cell of the withholding tax table — 231 brackets x 8 甲 columns plusthe 乙 column, 2,079 figures, compared against the National Tax Agency's own workbook
  • that a passing invoice check digit is not attributed to a corporation: soleproprietors satisfy the same rule, so the holder cannot be inferred from the number
  • all eight single-grade 随時改定 cases 日本年金機構 publishes — four for health, fourfor pension — each landing on the standard remuneration the table names, on boththe real grade and the extended scale the implementation uses
  • that health and pension are judged independently: a raise above the pension ceilingmoves six health grades and no pension grade at all
  • the 15-day 定時決定 fallback firing for 短時間就労者 and not for anyone else, andnot in 随時改定 at any time
  • that every closed set of values appears in /v1/enums, so a new enum cannot shipwithout reaching the endpoint integrators generate their types from
npx wrangler dev --port 8799
node test/verify.mjs

# or against production
BASE=https://japan-payroll-api.tsumugi.workers.dev node test/verify.mjs

Develop / deploy

npm install
npx wrangler dev
npx wrangler deploy

Data is embedded in the bundle (~40 KB gzipped), so there is no database, no KV, and nocold start.

Responses carry Cache-Control: public, max-age=3600, stale-while-revalidate=86400.An hour rather than a day, because rates change on known dates and a correction shouldreach callers the same day; stale-while-revalidate keeps responses instant while therefresh happens behind it. Note that workers.dev responses are not cached atCloudflare's own edge — every request invokes the Worker. A custom domain would enableedge caching if that becomes worth doing.

Measured from Japan against the deployed Worker: median 65 ms, max 83 ms round trip;gzip takes the 50-grade table from 6,841 to 1,041 bytes.

Maintenance

Statutory figures change on fixed dates, and an API that misses a revision keepsanswering — with numbers that stopped being true. Two mechanisms guard against that.

The API reports its own staleness. GET /v1/data-freshness states what each datasetcovers and when it is next due to change, and the main data responses carry a freshnessmarker. A caller can see a stale figure even if our monitoring failed.

A weekly job watches the sources.

npm run watch          # fingerprints each source, alerts Discord on change
npm run watch:dry      # same, without notifying

It checks two independent things, because either alone leaves a gap: the source file'shash and Last-Modified (catches a silent re-issue), and the calendar (catches the casewhere a ministry publishes the revision at a new URL and leaves the old one untouched).

An alert carries the exact commands for that dataset rather than pointing back here. Thealert is read months later, usually by someone who has forgotten the layout of this repo.

Rehearse an extractor before you need it. The minimum wage extractor takes --check,which runs the full extraction and compares it to the data currently shipped instead ofwriting anything:

curl -L -A "Mozilla/5.0" -o mw.xlsx https://www.mhlw.go.jp/content/11200000/001571219.xlsx
python scripts/extract-minimum-wage.py --check

It should say the output matches. If it does not while the fiscal year is unchanged, theextractor and the shipped data have drifted apart — which is worth knowing in Augustrather than discovering on the day the new figures land, when the temptation is to shipwhatever the script produces.

Register it to run weekly:

powershell -ExecutionPolicy Bypass -File scripts
egister_watch_task.ps1

Verifying the paid path

The test suite cannot check that RapidAPI's paid plans get full-size batches: doing soneeds the proxy secret RapidAPI issues, and a secret that lives in a test is not asecret. It checks the half that matters for revenue — that a caller without thesecret cannot claim a paid plan by setting a header.

Confirm the other half from the logs after any change to entitlement:

npx wrangler tail --format json

Call any endpoint from the RapidAPI playground and look for the request line. It shouldcarry the subscription name:

{"channel":"rapidapi","path":"/","status":200,"plan":"BASIC"}

plan present means the proxy secret matches. plan: null on a rapidapi requestmeans it does not — and every paying customer is being served the free-tier caps whilebeing charged. That failure is silent from the outside, which is why it is worth adeliberate check rather than waiting for a complaint.

The dates that matter

When What changes
March 協会けんぽ prefectural rates, effective with the March salary month
April Employment insurance rates; tax tables
Late Aug – October Minimum wage, issued prefecture by prefecture, effective from October
February Cabinet Office publishes the following year's holidays

After refreshing any dataset, update src/data/freshness.json and runnpm run rapidapi:prepare so the live API is re-verified and the OpenAPI spec regenerated.

Publishing pipeline

Each API is a recipe under recipes/<slug>/recipe.py — endpoints are declared oncethere, and both the OpenAPI spec and the RapidAPI listing text are generated from it.

npm run rapidapi:prepare

That command, for every recipe:

  1. validates the recipe,
  2. hits every declared endpoint on the live API and requires a 200 with parseableJSON — and for endpoints with required parameters, requires a 400 when they areomitted. This is what catches drift between recipe.py and src/index.ts,
  3. writes build/openapi/<slug>.openapi.json,
  4. sends a Discord notification containing the listing URL, the spec path, and theexact values to paste.

Listing itself is manual. The Add-API form athttps://rapidapi.com/provider/<id>/new is protected by reCAPTCHA v3, so the finalsubmit is done by a person — three fields, choose "Specify using: OpenAPI", upload thegenerated spec. Roughly two minutes per API, which does not bottleneck aone-or-two-per-week cadence.

Set DISCORD_WEBHOOK_URL in .env (see .env.example) for the notification toactually arrive; without it the message only prints to the console.

Browser session

npm run rapidapi:login opens a real Chrome window for you to sign in by hand — thescript never sees the password. The session persists in rapidapi_profile/ (gitignored).Re-run it when the session expires.

Operational safety

  • state/pipeline.halt.json halts everything until a human removes it. set_halt() iscalled when a session dies; clear_halt() on successful re-login.
  • MAX_PUBLISH_PER_DAY / MIN_SECONDS_BETWEEN_PUBLISH inpipeline/rapidapi/config.py keep the pace human.

Licence and attribution

Underlying data is Japanese government open data under公共データ利用規約(第1.0版),which permits commercial use and redistribution with attribution. Every response carriesan attribution block naming the source.

This service is not endorsed by any Japanese government agency. Verify against theofficial source before relying on it for statutory filings.

MCP Server · Populars

MCP Server · New

    PSU3D0

    agent-spreadsheet

    MCP server for spreadsheet analysis and editing. Slim, token-efficient tool surface designed for LLM agents.

    Community PSU3D0
    pitiflautico

    NeoBrowser

    MCP server that drives real Chrome with your real logged-in sessions — genuine fingerprint (passes bot.sannysoft), human-like input, bot-wall aware. 43 tools, single static Rust binary.

    Community pitiflautico
    aeonfun

    Aeon MCP Server

    The most autonomous AI agent framework: runs unattended on GitHub Actions, self-healing skills, drives Claude Code, Grok, Codex & more. No approval loops. Configure once, forget forever.

    Community aeonfun
    nhadaututtheky

    NeuralMemory

    NeuralMemory stores experiences as interconnected neurons and recalls them through spreading activation, mimicking how the human brain works. Instead of searching a database, memories are retrieved through associative recall - activating related concepts until the relevant memory emerges.

    Community nhadaututtheky
    norrietaylor

    Distillery

    Team knowledge evaporates daily — pairing sessions, debugging context, architectural rationale lost to Slack. Distillery captures it at the point of creation, connects it into a living graph, and surfaces it conversationally. It monitors feeds, tracks what matters to your projects, and alerts you before you know to ask. A team brain that learns.

    Community norrietaylor