# mcp-jp-corporate-id [Health: Active]

**Category:** 💻 Developer Tools  
**Repository:** https://github.com/skypier-jp-works/mcp-jp-corporate-id  
**GitHub Stars:** 0  
**npm Downloads (last month):** 163  
**Views:** 0  
**Installs:** 0  
**Upvotes:** 0  
**Directory Page:** https://allmcps.com/mcp/mcp-jp-corporate-id

## Description
Validates and normalizes Japanese corporate numbers and invoice registration numbers (format only).

## Tools
Capabilities this server exposes over MCP:

- **validate_corporate_number** — Verifies the check digit of a 13-digit corporate number
- **calculate_check_digit** — Computes the check digit for a 12-digit company registration number and derives the 13-digit corporate number
- **validate_invoice_number** — Validates a qualified invoice registration number ("T" + 13 digits)
- **parse_corporate_number** — Breaks down the structure of a corporate number (category, registry office code, organization type, serial number)
- **normalize_company_name** — Normalizes company-name notation (株式会社/(株)/㈱ etc., prefix/suffix placement, legacy kanji forms)
- **generate_matching_key** — Generates a normalized key for company-name deduplication/matching
- **compare_company_names** — Judges whether two company names likely refer to the same entity (`likely_different` only under a strict, narrow condition; returns "unknown" whenever it cannot tell)

## Claude Desktop Quick Installation
Heuristic fallback — verify the package name and runner against the repository README before running it. Uses `npx` (confidence: low):

```json
"mcpServers": {
  "mcp-jp-corporate-id": {
    "command": "npx",
    "args": ["-y","mcp-jp-corporate-id"]
  }
}
```

## Documentation & README

# mcp-jp-corporate-id

[日本語版はこちら](https://github.com/skypier-jp-works/mcp-jp-corporate-id/blob/HEAD/README.ja.md)

An [MCP](https://modelcontextprotocol.io) (Model Context Protocol) server that validates and normalizes Japanese
**corporate numbers (houjin bangou)** and **qualified invoice issuer registration numbers**, and normalizes/matches
company names across common notation variants.

No network access is used at all (v1 calls no external APIs). Every check is done with formulas and dictionary
data embedded in the code.

## Read this first

- **This tool only validates the *format* of numbers and names. It does NOT verify that a company actually exists,
  or that an invoice registration is currently valid.** For real-world verification, always check the official
  National Tax Agency sites directly:
  - [Corporate Number Publication Site](https://www.houjin-bangou.nta.go.jp/)
  - [Qualified Invoice Issuer Publication Site](https://www.invoice-kohyo.nta.go.jp/)
- **Never enter a Japanese Individual Number (My Number).** A company registration number (12 digits) and an
  individual My Number (12 digits) have the same length, and this tool cannot distinguish which kind of number it
  was given. `calculate_check_digit` always includes a caution about this in its response.
- This server never logs request input, and validation-error messages never echo back the raw number that was
  submitted.

## Tools (7 total)

| Tool | Description |
| --- | --- |
| `validate_corporate_number` | Verifies the check digit of a 13-digit corporate number |
| `calculate_check_digit` | Computes the check digit for a 12-digit company registration number and derives the 13-digit corporate number |
| `validate_invoice_number` | Validates a qualified invoice registration number ("T" + 13 digits) |
| `parse_corporate_number` | Breaks down the structure of a corporate number (category, registry office code, organization type, serial number) |
| `normalize_company_name` | Normalizes company-name notation (株式会社/(株)/㈱ etc., prefix/suffix placement, legacy kanji forms) |
| `generate_matching_key` | Generates a normalized key for company-name deduplication/matching |
| `compare_company_names` | Judges whether two company names likely refer to the same entity (`likely_different` only under a strict, narrow condition; returns "unknown" whenever it cannot tell) |

Every tool's response includes the primary sources (`sources`) behind its logic.

### 1. validate_corporate_number

Verifies whether the check digit of a 13-digit corporate number is correct. Accepts full-width digits, hyphens,
and whitespace, which are normalized before validation. If the normalized length isn't 13 digits, or the check
digit doesn't match, the tool returns `valid: false` rather than throwing.

### 2. calculate_check_digit

Computes the check digit from a 12-digit company registration number (assigned based on commercial registry
records) and derives the 13-digit corporate number. Throws if the normalized input isn't exactly 12 digits (no
guessing or zero-padding).

**Caution**: a 12-digit number could just as easily be a My Number (individual number) as a company registration
number. Every response includes a `caution` field reminding callers never to submit a My Number. If the registry
office code portion falls outside the typical range (0100–5000) confirmed from primary sources, a `note` is added.

### 3. validate_invoice_number

Validates a qualified invoice registration number ("T" + 13 digits).

- For numbers held by corporations ("T" + corporate number), the check digit is verified mathematically; a match
  returns `entityType: "corporate"`.
- Numbers held by sole proprietors and unincorporated associations are separate 13-digit numbers issued by the
  NTA that overlap with neither My Number nor any corporate number. **The check-digit algorithm for this class of
  number could not be confirmed as publicly documented within the primary sources reviewed.** When the number
  doesn't match the corporate-number check-digit formula, the tool returns `entityType: "individual_or_other"`,
  validates format only, and explicitly states that mathematical verification isn't possible in this case.
- If the input doesn't even match the "T" + 13 digits shape, `formatValid: false` is returned (not an exception).

### 4. parse_corporate_number

Verifies the check digit of a 13-digit corporate number and then parses the structure of its 12-digit base number.

- `category`: `national_organ_legislative` / `national_organ_administrative` / `national_organ_judicial` /
  `local_government` / `registered_corporation` / `unregistered_corporation_or_unincorporated_association` /
  `unused_range`
- For `registered_corporation`, returns `registryOfficeCode` (4 digits), `organizationTypeCode` (raw 2 digits),
  and `serialNumber` (6 digits).
- **The mapping from the 2-digit organization type code to an actual corporate form (stock company, LLC, etc.)
  could not be confirmed as a documented numeric code table in the primary sources reviewed** (the Commercial
  Registration Rules define three textual categories but the reviewed article text does not spell out numeric
  codes for them). The tool therefore returns only the raw 2-digit code with no label — see "Items that could not
  be verified" below.

### 5. normalize_company_name

Normalizes company-name notation and separates out the "body name" with the corporate form removed.

- Converts between major corporate-form notations (株式会社/(株)/（株）/㈱, etc.).
- Detects whether the corporate form appears as a prefix (株式会社○○) or suffix (○○株式会社).
- Normalizes full-width/half-width characters and a curated set of legacy/variant kanji forms (e.g. 髙→高, 﨑→崎).

**Dictionary limits**: only major corporate forms and variant characters are covered. This is not exhaustive of
every Japanese corporate form or notation variant; anything not in the dictionary is left unrecognized and stays
in the body name as-is.

### 6. generate_matching_key

Uses `normalize_company_name` internally and strips whitespace from the body name to produce a matching key for
deduplication.

### 7. compare_company_names

Normalizes both names and compares them, returning a `verdict`, a `confidence` level, and `reasons`.

#### Design: the verdict and the reasons are both machine-generated from the same structured evidence

Rather than hand-writing the verdict/confidence logic and the explanatory text separately, this tool derives both
from a single structured object, `evidence`, which is included as-is in the response:

| Field | Meaning |
| --- | --- |
| `scriptMismatch` | Whether the body names differ so much in character type that comparison itself was judged meaningless |
| `bodyMatch` | How the body names relate: `"exact"`, `"partial"`, or `"none"` |
| `commonTokens` | The actual shared substring(s) found |
| `labelMatch` | Whether the corporate-form label (株式会社/合同会社/etc.) matches (`null` when not applicable) |
| `positionMatch` | Whether the prefix/suffix placement matches (`null` when not applicable) |
| `distinguishing` | The common-token + distinguishing-element pair behind a `likely_different` verdict (`null` otherwise) |

The decision logic (`evidence` → `verdict`/`confidence`) and the explanation logic (`evidence` → `reasons`) are
two separate functions that both read only from this same `evidence` object. Changing the decision rules
automatically keeps the explanation in sync, so it's structurally impossible to end up with a confident verdict
whose `reasons`/`notes` say "cannot be determined."

#### Script-mismatch guard (runs before any scoring)

If the two body names differ greatly in character type — one is Latin-only while the other contains Japanese
(hiragana/katakana/kanji) — comparing them as strings is meaningless in principle. For example, "日本電気株式会社"
(Nippon Electric Company) and "NEC" refer to the same company, yet their body-name strings share no characters at
all ("NEC" is an abbreviation that cannot be detected by string comparison). Whenever this script mismatch is
detected, the tool returns `unknown` (`confidence: "low"`) immediately, before attempting any scoring.

#### Condition for returning `likely_different`

`likely_different` is returned only when **all** of the following hold:

- The two body names share a common prefix or suffix ("common token") of at least 2 characters.
- The remaining, non-shared part on each side (the "distinguishing element") is at least 2 characters long on
  both sides, and the two distinguishing elements differ.

**Example**: "東京電力" (Tokyo Electric Power) vs. "東北電力" (Tohoku Electric Power) — they share the suffix
"電力" ("Electric Power") as a common token, with "東京" (Tokyo) and "東北" (Tohoku) as the distinguishing
elements. Because both names follow the same naming pattern but diverge on a clear, region-identifying element,
this tool treats them as likely different companies.

When this condition is not met (no shared part at all, or one name simply being a substring of the other), there
is no positive evidence of being different companies, so the tool always returns `unknown`. **The mere fact that
two strings don't match or overlap is never, by itself, grounds for `likely_different`** — string non-overlap is
not evidence of being different entities. The `reasons` text distinguishes "no shared part at all" from "only a
partial match" rather than using the same wording for both.

#### Confidence is capped at `medium`, and stays consistent with the verdict by construction

`confidence` has only two possible values: `"medium"` and `"low"`. **`"high" has been removed.** Since the 2006
enactment of the Companies Act abolished the similar-trade-name restriction, two unrelated companies can be
registered under the same name as long as their head-office locations differ — so a match based on trade name
alone can never justify strong confidence (`"high"`) in principle.

The set of valid `confidence` values is constrained per `verdict` at the TypeScript type level: `unknown` can
only ever carry `confidence: "low"`, and both `likely_same` and `likely_different` can only ever carry
`confidence: "medium"`. It is structurally impossible for this tool to return `unknown` together with
`confidence: "medium"`.

**This tool never "hedges by lowering confidence."** When something is inherently indeterminate — such as the
prefix/suffix placement mismatch below — the tool sets `verdict` itself to `unknown` rather than downgrading
`likely_same` to a lower confidence. This matters for callers that branch purely on `verdict` (e.g. a batch job
that auto-merges everything marked `likely_same`): such a caller would silently swallow the ambiguity if it were
only reflected in `confidence`.

`reasons` always states concretely why the tool reached its conclusion — or why it couldn't (script mismatch, no
shared token, partial overlap only, a mismatched corporate form or prefix/suffix placement, possibility of an
abbreviation/English name, etc.), generated directly from `evidence`. Every response also includes a fixed note
on the method's limitations:

> This tool only performs text comparison based on notation normalization; it cannot judge whether an
> abbreviation, English name, or nickname refers to the same entity. A definitive identity check requires
> cross-referencing corporate numbers.

#### What this tool can and cannot determine

| Case | Example | verdict | confidence |
| --- | --- | --- | --- |
| Body name, corporate form, and prefix/suffix placement all match | "株式会社サンプル" vs. "㈱サンプル" | `likely_same` | `medium` (same trade name could still belong to a different company — cross-reference the corporate number) |
| Body name and corporate form match, but prefix/suffix placement differs (prefix vs. suffix) | "株式会社サンプル" vs. "サンプル(株)" | `unknown` | `low` (prefix/suffix placement is part of the trade name itself — legally a different trade name that could belong to a different company) |
| Body name matches, but the corporate form itself differs (株式会社 vs. 合同会社) | "株式会社サンプル" vs. "合同会社サンプル" | `unknown` | `low` (an organizational conversion — e.g. a stock company converting to an LLC — keeps the same corporate number, so the two records could just be the same entity at different points in time) |
| Script mismatch (one Latin-only, the other contains Japanese) | "日本電気株式会社" vs. "NEC" | `unknown` | `low` (guard fires before scoring) |
| Shared common token (≥2 chars) with clearly different distinguishing elements (≥2 chars each) | "東京電力" vs. "東北電力" | `likely_different` | `medium` |
| One body name is a substring of the other (doesn't meet the distinguishing-element condition) | "株式会社サンプル" vs. "株式会社サンプル商事" | `unknown` | `low` |
| No shared token at all | "株式会社あいうえお" vs. "株式会社かきくけこ" | `unknown` | `low` |

**The only case where this tool returns `likely_same` (`medium`) is when the body name, corporate form, and
prefix/suffix placement all match.** Even when the body name appears to match, a differing prefix/suffix
placement or a differing corporate form leaves a real possibility of a different entity that cannot be ruled out
in principle, so the tool returns `unknown`. `likely_different` is returned only when the strict "shared pattern
+ clearly different identifier" condition above is met. Every other case is `unknown`. `unknown` does not mean
"probably different" — it means "this method cannot determine it." When a definitive identity check is required,
obtain each company's corporate number and cross-reference with `validate_corporate_number` or similar.

## Primary sources

The number-validation logic was implemented only after retrieving and reading the following primary sources
directly (last checked: 2026-07-29):

- Check-digit formula: NTA Corporate Number site, "Check Digit Calculation"
  https://www.houjin-bangou.nta.go.jp/documents/checkdigit.pdf
- Corporate number (13-digit) structure: NTA Corporate Number site, "Structure of the Corporate Number"
  https://www.houjin-bangou.nta.go.jp/documents/houjinbangounokousei.pdf
- Overview of the corporate number system (who is assigned a number; categories for national organs, local
  governments, registered corporations, etc.): NTA Corporate Number Management Office, "About the Corporate
  Number" (June 2026 edition)
  https://www.houjin-bangou.nta.go.jp/setsumei/pamphlet/images/houjinbangou_gaiyou.pdf
- Act on the Use of Numbers to Identify a Specific Individual in Administrative Procedures, Article 39:
  https://laws.e-gov.go.jp/law/425AC0000000027
- Its Cabinet Order (Cabinet Order No. 155 of 2014), Articles 35 (corporate number structure) and 36 (units for
  assigning numbers to national organs):
  https://laws.e-gov.go.jp/law/426CO0000000155
- Ordinance on the Assignment of Corporate Numbers (MOF Ordinance No. 70 of 2014), Articles 2 (check-digit
  formula) and 3 (base numbers for non-registered entities):
  https://laws.e-gov.go.jp/law/426M60000040070
- Commercial Registration Rules (Ministry of Justice Ordinance No. 23 of 1964), Article 1-2 (recording of company
  registration numbers):
  https://laws.e-gov.go.jp/law/339M50000010023
- Invoice registration number structure: NTA Qualified Invoice Issuer Publication Site, "About Registration
  Numbers"
  https://www.invoice-kohyo.nta.go.jp/about-toroku/index.html

### Items that could not be verified (disclosed honestly)

- **The specific numeric code table for the 2-digit "organization type" portion of the company registration
  number** (e.g. which digits mean "stock company" vs. "LLC") could not be confirmed. Article 1-2 of the
  Commercial Registration Rules defines three textual categories ("stock companies"; "general/limited
  partnerships, LLCs, and foreign companies"; "trade-name users, etc."), but the reviewed statutory text does not
  spell out numeric codes for them, and secondary sources (blog posts, etc.) found online disagreed with each
  other. Because of this, `parse_corporate_number` returns only the raw 2-digit code with no interpretive label.
- **What the local-government sub-codes ("20" / "30") specifically distinguish** (e.g. prefectures vs.
  municipalities) could not be confirmed.
- **The check-digit algorithm for the 13-digit invoice registration numbers issued to sole proprietors and
  unincorporated associations** could not be confirmed as publicly documented. Numbers in this category are
  therefore validated for format only, with no mathematical check-digit verification.
- The corporate-form and legacy-kanji dictionaries are not an exhaustive statutory definition; they are a
  practical, hand-curated set of commonly seen notations.

## Setup

### 1. Prerequisites

- [Node.js](https://nodejs.org/) (LTS recommended)

```bash
node --version
```

### 2. Install dependencies

```bash
npm install
```

### 3. Build

```bash
npm run build
```

On success, `build/index.js` is created.

## Using it from Claude Desktop

Add the following to your Claude Desktop config file (`claude_desktop_config.json`):

```json
{
  "mcpServers": {
    "jp-corporate-id": {
      "command": "node",
      "args": ["/absolute/path/to/mcp-jp-corporate-id/build/index.js"]
    }
  }
}
```

Config file locations:

- Windows: `%APPDATA%\Claude\claude_desktop_config.json`
- macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`

Restart Claude Desktop afterward, and tools such as `validate_corporate_number` become available.

## Running tests

```bash
npm test
```

All tests should show `✔`.

## Project layout

```
mcp-jp-corporate-id/
├── src/
│   ├── sources.ts          … list of cited primary sources
│   ├── errors.ts            … shared validation-error class
│   ├── normalize.ts         … full/half-width, hyphen, etc. input normalization
│   ├── checkDigit.ts        … the check-digit formula
│   ├── corporateNumber.ts   … 12-digit base-number structure parsing
│   ├── corporateIdCalc.ts   … logic for tools 1-4
│   ├── companyNameData.ts   … corporate-form dictionary, legacy-kanji map
│   ├── companyName.ts       … logic for tools 5-7
│   └── index.ts             … MCP server entry point (registers the 7 tools)
├── tests/                   … automated tests (node:test)
├── package.json
├── tsconfig.json
├── LICENSE
├── README.md                … this file
└── README.ja.md             … Japanese version
```

## Related tools

Other servers by the same author:

- [mcp-jp-paid-leave](https://github.com/skypier-jp-works/mcp-jp-paid-leave) — an MCP server for calculating
  statutory annual paid leave under Japan's Labor Standards Act
- [mcp-jp-calendar](https://github.com/skypier-jp-works/mcp-jp-calendar) — an MCP server for Japanese business
  days, national holidays, gotobi settlement days, and fiscal quarters

## License

[MIT](https://github.com/skypier-jp-works/mcp-jp-corporate-id/blob/HEAD/LICENSE)

