Skip to main content
Glama
kkawailab

MLIT Data Platform MCP Server

by kkawailab

normalize_codes

Standardizes Japanese prefecture and municipality names into official codes and formal names for accurate data retrieval from the MLIT Data Platform.

Instructions

入力された都道府県名・市区町村名を正規化し、正式なコードと名称を取得する。

            使用ケース:
            1. ユーザー入力('東京', 'Tokyo', '13')を正規化 → '13' + '東京都'
            2. 市区町村名から5桁コードを取得
            3. 曖昧な入力の候補一覧取得

            このツールを他の検索ツールの前に実行することで、正確なprefecture_code/municipality_codeを取得できます

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
prefectureNo都道府県の指定。以下の形式に対応: - コード: '13', '27' - 日本語: '東京都', '東京', '大阪府', '大阪' - ローマ字: 'Tokyo', 'Osaka', 'Hokkaido' 全角数字(例: '13')も自動的に正規化されます
municipalityNo市区町村の指定。以下の形式に対応: - JISコード: '13101' (千代田区) - 日本語: '千代田区', '港区' 注意: 市区町村を指定する場合、prefectureも併せて指定することを推奨します(同名の市区町村が複数存在する可能性があるため)

Implementation Reference

  • The `normalize_codes` method in `MLITClient` class handles the logic for normalizing prefecture and municipality names/codes into standardized identifiers. It uses internal caches for prefectures and municipalities and provides several strategies for matching.
    async def normalize_codes(self, params: NormalizeCodesInput) -> NormalizeCodesOutput:
        out = NormalizeCodesOutput(
            normalization_meta={
                "input_prefecture": params.prefecture,
                "input_municipality": params.municipality,
                "matched_strategy": None,
            }
        )
        pref_in = (params.prefecture or "").strip()
        pref_rows = await self._load_pref_list()
    
        pref_code: Optional[str] = None
        pref_name: Optional[str] = None
    
        if pref_in:
            pcanon = self._canon(pref_in)
            if pcanon.isdigit():
                for r in pref_rows:
                    code = str(r["code"])
                    if code == pcanon or code.lstrip("0") == pcanon.lstrip("0"):
                        pref_code, pref_name = code, r["name"]
                        out.normalization_meta["matched_strategy"] = "pref:code"
                        break
            if pref_code is None:
                for r in pref_rows:
                    nm = r["name"]
                    nm_core = self._strip_pref_suffix(nm)
                    in_core = self._strip_pref_suffix(self._nfkc(pref_in))
                    if nm == pref_in or nm_core == in_core:
                        pref_code, pref_name = str(r["code"]), nm
                        out.normalization_meta["matched_strategy"] = "pref:jp_exact"
                        break
            if pref_code is None and pcanon.isascii():
                alias = self._pref_romaji_map().get(pcanon.replace(" ", "").replace("-", ""))
                if alias:
                    for r in pref_rows:
                        if r["name"] == alias:
                            pref_code, pref_name = str(r["code"]), r["name"]
                            out.normalization_meta["matched_strategy"] = "pref:romaji"
                            break
            if pref_code is None:
                for r in pref_rows:
                    nm = r["name"]
                    if self._strip_pref_suffix(nm) in self._nfkc(pref_in):
                        pref_code, pref_name = str(r["code"]), nm
                        out.normalization_meta["matched_strategy"] = "pref:jp_contains"
                        break
    
        muni_in = (params.municipality or "").strip()
        muni_code: Optional[str] = None
        muni_name: Optional[str] = None
        candidates: List[MunicipalityCandidate] = []
    
        if muni_in:
            mcanon = self._canon(muni_in)
            if mcanon.isdigit() and len(mcanon) >= 5:
                if pref_code:
                    mlist = await self._load_muni_list(pref_code)
                    for r in mlist:
                        if str(r["code_as_string"]) == mcanon:
                            muni_code, muni_name = r["code_as_string"], r["name"]
                            out.normalization_meta["matched_strategy"] = "muni:code_in_pref"
                            break
                if muni_code is None and not pref_code:
                    out.warnings.append("municipality_code_provided_but_prefecture_unknown")
            else:
                if pref_code:
                    mlist = await self._load_muni_list(pref_code)
                    for r in mlist:
                        if r["name"] == self._nfkc(muni_in):
                            muni_code, muni_name = r["code_as_string"], r["name"]
                            out.normalization_meta["matched_strategy"] = "muni:jp_exact"
                            break
                    if muni_code is None:
                        for r in mlist:
                            if self._nfkc(muni_in) in r["name"]:
                                candidates.append(MunicipalityCandidate(
                                    municipality_code=str(r["code_as_string"]),
                                    municipality_name=str(r["name"])
                                ))
                        if len(candidates) == 1:
                            muni_code, muni_name = candidates[0].municipality_code, candidates[0].municipality_name
                            candidates = []
                            out.normalization_meta["matched_strategy"] = "muni:jp_contains_unique"
                        elif len(candidates) > 1:
                            out.normalization_meta["matched_strategy"] = "muni:jp_contains_ambiguous"
                            out.warnings.append("ambiguous_municipality: multiple candidates")
                else:
                    out.warnings.append("municipality_without_prefecture: provide prefecture for disambiguation")
    
        out.prefecture_code = pref_code
        out.prefecture_name = pref_name
        out.municipality_code = muni_code
        out.municipality_name = muni_name
        out.candidates = candidates
    
        if pref_code and not muni_code and not muni_in:
            out.warnings.append("attribute_only_hint: some MLIT attribute-only queries require term:\"\" or an additional attribute (e.g., address)")
    
        return out
  • Input and output schemas for `normalize_codes` tool.
    class NormalizeCodesInput(BaseModel):
        prefecture: Optional[str] = None
        municipality: Optional[str] = None
    
    
    class MunicipalityCandidate(BaseModel):
        municipality_code: str
        municipality_name: str
    
    
    class NormalizeCodesOutput(BaseModel):
        prefecture_code: Optional[str] = None

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/kkawailab/kklab-mlit-dpf-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server