Skip to main content
Glama
kkawailab

MLIT Data Platform MCP Server

by kkawailab

get_count_data

Count data records in Japan's MLIT Data Platform by applying keyword searches, location filters, or attribute conditions, with options to aggregate results by dataset or specific attributes.

Instructions

特定のデータセットに含まれるデータや、指定した範囲、日付など、指定した検索条件に一致するデータの件数を取得する。分類ごとの集計も可能。

            使い方:
            - キーワード / メタデータ / 空間条件を組み合わせて、件数のみを高速に把握できます。
            - 集計の切り口は `slice_type` で指定:
            - "dataset": カタログ→データセットの2段階で件数を返す(全カタログ/全データセットの分布を俯瞰)
            - "attribute": 任意属性ごとの上位出現値を `slice_size` 件まで取得(最大50)。必要なら `slice_sub_attribute_name` で下位分類も可能。
            - 空間条件(矩形/円)は `location_*` 引数により内部で `locationFilter` に変換。
            - 属性条件は `catalog_id` / `dataset_id` / `prefecture_code` / `municipality_code` / `address` などを内部で `attributeFilter` に変換。

            例:
            - キーワード「橋梁」をデータセット別に件数集計:
            term="橋梁", slice_type="dataset"

            - 都道府県別トップ10 + その下でデータセット別内訳:
            term="", slice_type="attribute",
            slice_attribute_name="DPF:prefecture_code", slice_size=10,
            slice_sub_attribute_name="DPF:dataset_id", slice_sub_size=10

            - 矩形範囲(東京都心部)× カタログIDで件数:
            term="", catalog_id="dimaps",
            location_rectangle_top_left_lat=35.80,  location_rectangle_top_left_lon=139.55,
            location_rectangle_bottom_right_lat=35.60, location_rectangle_bottom_right_lon=139.85,
            slice_type="attribute", slice_attribute_name="DPF:dataset_id", slice_size=20

            - 円範囲(東京駅 半径500m)× データセット内件数:
            term="", dataset_id="cals_construction",
            location_lat=35.681236, location_lon=139.767125, location_distance=500,
            slice_type="attribute", slice_attribute_name="DPF:title", slice_size=10

            注意:
            - 公式仕様上、`locationFilter`(空間条件)**のみでは検索不可**。必ず `term` か `attributeFilter`(本ツールでは catalog_id / dataset_id / prefecture_code / municipality_code / address 等)を併用してください。
            - `slice_size` の最大は **50**。上位出現値のみが返却され、それ以外は省略されます。上位分類の `dataCount` には下位分類で表示されない分も含まれます。
            - `attributeFilter` は `is/similar/gte/gt/lte/lt` に対応し、`AND` / `OR` でネスト結合が可能(本ツールでは単純条件を主にサポート)。
            - `locationFilter` は `rectangle` / `geoDistance` のほか `union` / `intersection` に対応。ただし **同クラス内の他メンバーと同時利用不可**、かつ **入れ子(ネスト)不可**。
            - 座標は WGS84。矩形は「北西(top_left)→南東(bottom_right)」の順で指定。
            - パフォーマンス観点から、まず `get_count_data` でボリューム見積り → 必要に応じて `get_all_data` で実データ取得が推奨。

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
termNo検索キーワード。属性フィルタのみの場合は省略可能
phrase_matchNoフレーズマッチモード
prefecture_codeNo都道府県コードで絞り込み
municipality_codeNo市区町村コードで絞り込み
addressNo住所で絞り込み
catalog_idNoカタログIDで絞り込み
dataset_idNoデータセットIDで絞り込み。集計対象の指定に必須
location_rectangle_top_left_latNo矩形範囲の左上緯度
location_rectangle_top_left_lonNo矩形範囲の左上経度
location_rectangle_bottom_right_latNo矩形範囲の右下緯度
location_rectangle_bottom_right_lonNo矩形範囲の右下経度
location_latNo中心地点の緯度(円形範囲検索用)
location_lonNo中心地点の経度(円形範囲検索用)
location_distanceNo検索半径(メートル単位、円形範囲検索用)
slice_typeNo集計タイプ: - 'attribute': 属性別に集計(最も一般的) - 'dataset': データセット別に集計 省略時は属性指定があれば自動的に'attribute'になります
slice_attribute_nameNo集計する属性名(ネームスペース付き)。 例: - 'DPF:year' → 年度別集計 - 'DPF:prefecture_code' → 都道府県別集計 - 'RSDB:tenken.nendo' → 点検年度別集計 指定すると自動的にslice_type='attribute'になります
slice_sizeNo集計結果の最大件数(1-50)。上位N件のみ取得したい場合に指定
slice_sub_attribute_nameNo2段階目の集計属性名。 例: slice_attribute_name='DPF:prefecture_code', slice_sub_attribute_name='DPF:year' → 都道府県別 × 年度別のクロス集計
slice_sub_sizeNo2段階目の集計結果の最大件数

Implementation Reference

  • The tool 'get_count_data' is handled here by assembling slice settings and calling client.count_data.
    elif name == "get_count_data":
        # --- Build sub-slice (plain dict, camelCase) ---
        sub_dict = None
        if arguments.get("slice_sub_attribute_name") or arguments.get("slice_sub_size") is not None:
            sub_dict = {
                "attributeName": arguments.get("slice_sub_attribute_name") or "",
            }
            if arguments.get("slice_sub_size") is not None:
                sub_dict["size"] = int(arguments.get("slice_sub_size"))
    
        # --- Build attribute slice (plain dict, camelCase) ---
        attr_dict = None
        if (
            arguments.get("slice_attribute_name")
            or arguments.get("slice_size") is not None
            or sub_dict is not None
        ):
            attr_dict = {
                "attributeName": arguments.get("slice_attribute_name") or "",
            }
            if arguments.get("slice_size") is not None:
                attr_dict["size"] = int(arguments.get("slice_size"))
            if sub_dict is not None:
                # penting: key GraphQL adalah subSliceSetting (camelCase)
                attr_dict["subSliceSetting"] = sub_dict
    
        # --- Decide slice_type ---
        slice_type = arguments.get("slice_type")
        if slice_type is None and attr_dict is not None:
            slice_type = "attribute"
    
        # --- Assemble slice_setting (plain dict; do not use Pydantic yet) ---
        slice_setting = None
        if slice_type == "dataset":
            slice_setting = {"type": "dataset"}
        elif slice_type is not None or attr_dict is not None:
            slice_setting = {"type": slice_type or "attribute"}
            if attr_dict is not None:
                # important: GraphQL key is attributeSliceSetting (camelCase)
                slice_setting["attributeSliceSetting"] = attr_dict
    
        # --- Normalize region args (same as before) ---
        arguments = await _auto_normalize_region_args(arguments, client)
    
        # --- Build CountDataInput (PASS-THROUGH dict slice_setting already assembled) ---
        p = CountDataInput.model_validate({
            "term": arguments.get("term"),
            "phrase_match": arguments.get("phrase_match"),
            "prefecture_code": arguments.get("prefecture_code"),
            "municipality_code": arguments.get("municipality_code"),
            "address": arguments.get("address"),
            "catalog_id": arguments.get("catalog_id"),
            "dataset_id": arguments.get("dataset_id"),
            "location_rectangle_top_left_lat": arguments.get("location_rectangle_top_left_lat"),
            "location_rectangle_top_left_lon": arguments.get("location_rectangle_top_left_lon"),
            "location_rectangle_bottom_right_lat": arguments.get("location_rectangle_bottom_right_lat"),
            "location_rectangle_bottom_right_lon": arguments.get("location_rectangle_bottom_right_lon"),
            "location_lat": arguments.get("location_lat"),
            "location_lon": arguments.get("location_lon"),
            "location_distance": arguments.get("location_distance"),
            "slice_setting": slice_setting, 
        })
    
        data = await client.count_data(p)
        return {
            "content": [{"type": "text", "text": json.dumps(data)}],
            "isError": False,
        }
  • Implementation of the count_data method in MLITClient, which builds the GraphQL query for the countData API.
    async def count_data(self, params: CountDataInput) -> Dict[str, Any]:
        attr_filter = self.make_attribute_filter_for_countdata(
            prefecture_code=params.prefecture_code,
            municipality_code=params.municipality_code,
            address=params.address,
            catalog_id=params.catalog_id,
            dataset_id=params.dataset_id,
        )
    
        loc_filter = None
        if all(v is not None for v in [
            params.location_rectangle_top_left_lat,
            params.location_rectangle_top_left_lon,
            params.location_rectangle_bottom_right_lat,
            params.location_rectangle_bottom_right_lon
        ]):
            loc_filter = self.make_rectangle_filter(
                float(params.location_rectangle_top_left_lat),   # type: ignore
                float(params.location_rectangle_top_left_lon),   # type: ignore
                float(params.location_rectangle_bottom_right_lat),  # type: ignore
                float(params.location_rectangle_bottom_right_lon),  # type: ignore
            )
        elif all(v is not None for v in [
            params.location_lat, params.location_lon, params.location_distance
        ]):
            loc_filter = self.make_geodistance_filter(
                float(params.location_lat),   # type: ignore
                float(params.location_lon),   # type: ignore
                float(params.location_distance),  # type: ignore
            )
    
        effective_term: Optional[str] = params.term
        if effective_term is None and (attr_filter is not None or loc_filter is not None):
            effective_term = ""
    
        # BRIDGE: top-level slice_* → slice_setting (kalau belum ada)
        slice_setting_obj = params.slice_setting
        if slice_setting_obj is None:
            st = (getattr(params, "slice_type", None) or "").strip().lower()
            if st == "dataset":
                slice_setting_obj = {"type": "dataset"}
            elif st == "attribute":
                # Build attributeSliceSetting from top-level fields
                name = self._normalize_attr_name(getattr(params, "slice_attribute_name", "") or "")
                size = getattr(params, "slice_size", None)
                sub_name = self._normalize_attr_name(getattr(params, "slice_sub_attribute_name", "") or "")
                sub_size = getattr(params, "slice_sub_size", None)
    
                attr_block: Dict[str, Any] = {}
                if name:
                    attr_block["attributeName"] = name
                if isinstance(size, int):
                    attr_block["size"] = int(size)
    
                sub_block: Dict[str, Any] = {}
                if sub_name:
                    sub_block["attributeName"] = sub_name
                if isinstance(sub_size, int):
                    sub_block["size"] = int(sub_size)
                if sub_block:
                    attr_block["subSliceSetting"] = sub_block
    
                slice_setting_obj = (
                    {"type": "attribute", "attributeSliceSetting": attr_block}
                    if attr_block else
                    {"type": "attribute"}
                )
    
        q = self.build_count_data(
            term=effective_term,
            phrase_match=params.phrase_match,
            attribute_filter=attr_filter,
            location_filter=loc_filter,
            slice_setting=slice_setting_obj,
        )
        return await self.post_query(q)
  • src/server.py:720-851 (registration)
    Registration of the 'get_count_data' tool with its input schema definition.
    types.Tool(
        name="get_count_data",
        description="""特定のデータセットに含まれるデータや、指定した範囲、日付など、指定した検索条件に一致するデータの件数を取得する。分類ごとの集計も可能。
    
            使い方:
            - キーワード / メタデータ / 空間条件を組み合わせて、件数のみを高速に把握できます。
            - 集計の切り口は `slice_type` で指定:
            - "dataset": カタログ→データセットの2段階で件数を返す(全カタログ/全データセットの分布を俯瞰)
            - "attribute": 任意属性ごとの上位出現値を `slice_size` 件まで取得(最大50)。必要なら `slice_sub_attribute_name` で下位分類も可能。
            - 空間条件(矩形/円)は `location_*` 引数により内部で `locationFilter` に変換。
            - 属性条件は `catalog_id` / `dataset_id` / `prefecture_code` / `municipality_code` / `address` などを内部で `attributeFilter` に変換。
    
            例:
            - キーワード「橋梁」をデータセット別に件数集計:
            term="橋梁", slice_type="dataset"
    
            - 都道府県別トップ10 + その下でデータセット別内訳:
            term="", slice_type="attribute",
            slice_attribute_name="DPF:prefecture_code", slice_size=10,
            slice_sub_attribute_name="DPF:dataset_id", slice_sub_size=10
    
            - 矩形範囲(東京都心部)× カタログIDで件数:
            term="", catalog_id="dimaps",
            location_rectangle_top_left_lat=35.80,  location_rectangle_top_left_lon=139.55,
            location_rectangle_bottom_right_lat=35.60, location_rectangle_bottom_right_lon=139.85,
            slice_type="attribute", slice_attribute_name="DPF:dataset_id", slice_size=20
    
            - 円範囲(東京駅 半径500m)× データセット内件数:
            term="", dataset_id="cals_construction",
            location_lat=35.681236, location_lon=139.767125, location_distance=500,
            slice_type="attribute", slice_attribute_name="DPF:title", slice_size=10
    
            注意:
            - 公式仕様上、`locationFilter`(空間条件)**のみでは検索不可**。必ず `term` か `attributeFilter`(本ツールでは catalog_id / dataset_id / prefecture_code / municipality_code / address 等)を併用してください。
            - `slice_size` の最大は **50**。上位出現値のみが返却され、それ以外は省略されます。上位分類の `dataCount` には下位分類で表示されない分も含まれます。
            - `attributeFilter` は `is/similar/gte/gt/lte/lt` に対応し、`AND` / `OR` でネスト結合が可能(本ツールでは単純条件を主にサポート)。
            - `locationFilter` は `rectangle` / `geoDistance` のほか `union` / `intersection` に対応。ただし **同クラス内の他メンバーと同時利用不可**、かつ **入れ子(ネスト)不可**。
            - 座標は WGS84。矩形は「北西(top_left)→南東(bottom_right)」の順で指定。
            - パフォーマンス観点から、まず `get_count_data` でボリューム見積り → 必要に応じて `get_all_data` で実データ取得が推奨。""",
        inputSchema={
            "type": "object",
            "properties": {
                "term": {
                    "type": "string",
                    "description": "検索キーワード。属性フィルタのみの場合は省略可能"
                },
                "phrase_match": {
                    "type": "boolean",
                    "description": "フレーズマッチモード"
                },
                "prefecture_code": {
                    "type": "string",
                    "description": "都道府県コードで絞り込み"
                },
                "municipality_code": {
                    "type": "string",
                    "description": "市区町村コードで絞り込み"
                },
                "address": {
                    "type": "string",
                    "description": "住所で絞り込み"
                },
                "catalog_id": {
                    "type": "string",
                    "description": "カタログIDで絞り込み"
                },
                "dataset_id": {
                    "type": "string",
                    "description": "データセットIDで絞り込み。集計対象の指定に必須"
                },
                "location_rectangle_top_left_lat": {
                    "type": "number",
                    "description": "矩形範囲の左上緯度"
                },
                "location_rectangle_top_left_lon": {
                    "type": "number",
                    "description": "矩形範囲の左上経度"
                },
                "location_rectangle_bottom_right_lat": {
                    "type": "number",
                    "description": "矩形範囲の右下緯度"
                },
                "location_rectangle_bottom_right_lon": {
                    "type": "number",
                    "description": "矩形範囲の右下経度"
                },
                "location_lat": {
                    "type": "number",
                    "description": "中心地点の緯度(円形範囲検索用)"
                },
                "location_lon": {
                    "type": "number",
                    "description": "中心地点の経度(円形範囲検索用)"
                },
                "location_distance": {
                    "type": "number",
                    "description": "検索半径(メートル単位、円形範囲検索用)"
                },
                "slice_type": {
                    "type": "string",
                    "description": """集計タイプ:
                    - 'attribute': 属性別に集計(最も一般的)
                    - 'dataset': データセット別に集計
                    省略時は属性指定があれば自動的に'attribute'になります"""
                },
                "slice_attribute_name": {
                    "type": "string",
                    "description": """集計する属性名(ネームスペース付き)。
                    例:
                    - 'DPF:year' → 年度別集計
                    - 'DPF:prefecture_code' → 都道府県別集計
                    - 'RSDB:tenken.nendo' → 点検年度別集計
    
                    指定すると自動的にslice_type='attribute'になります"""
                },
                "slice_size": {
                    "type": "integer",
                    "description": "集計結果の最大件数(1-50)。上位N件のみ取得したい場合に指定"
                },
                "slice_sub_attribute_name": {
                    "type": "string",
                    "description": """2段階目の集計属性名。
                    例: slice_attribute_name='DPF:prefecture_code', slice_sub_attribute_name='DPF:year'
                    → 都道府県別 × 年度別のクロス集計"""
                },
                "slice_sub_size": {
                    "type": "integer",
                    "description": "2段階目の集計結果の最大件数"
                },
            },
        },
    ),

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