Skip to main content
Glama

get_district_plan

Query a Korean address or PNU to retrieve district unit plan membership and development activity permit restriction overlays. District plans can override building coverage, floor area ratio, and use.

Instructions

Return 지구단위계획구역 membership and 개발행위허가제한지역 overlays. When district_plan is non-empty, 건폐율·용적률·용도 may be overridden by the plan (see 국토계획법 제52조). V-World only returns the geometric hit — actual plan text must come from 지자체 고시문.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
queryYesKorean address (e.g. '경기도 평택시 포승읍 내기리 680') or 19-digit PNU

Implementation Reference

  • The main handler function that resolves a query to a point, queries V-World overlays for 지구단위계획구역 (LT_C_UPISUQ161) and 개발행위허가제한지역 (LT_C_UPISUQ171), then returns structured JSON with district plan and development permit restriction data.
    export const getDistrictPlanTool = async ({ query }: { query: string }) => {
      const resolved = await resolveToPoint(query);
      const q = await queryOverlays(LAYERS, resolved.point_wgs84);
    
      const result = {
        query,
        pnu: resolved.pnu,
        point_wgs84: resolved.point_wgs84,
        district_plan: q.hits
          .filter((h) => h.layer === "LT_C_UPISUQ161")
          .map((h) => ({
            layer: h.layer,
            name: h.name,
            designation_year: h.designation_year,
            designation_number: h.designation_number,
            sido: h.sido,
            sigg: h.sigg,
            extra: h.properties,
          })),
        development_permit_restriction: q.hits
          .filter((h) => h.layer === "LT_C_UPISUQ171")
          .map((h) => ({
            layer: h.layer,
            name: h.name,
            designation_year: h.designation_year,
            designation_number: h.designation_number,
          })),
        layer_errors: q.errors.length > 0 ? q.errors : undefined,
        source: {
          resolved_at: new Date().toISOString(),
          layers: LAYERS.map((l) => l.id),
        },
        note:
          "When district_plan is non-empty, 건폐율/용적률 may be overridden by the 지구단위계획 (see 국토계획법 제52조). This tool returns the V-World geometric hit only — the actual plan text is NOT in V-World and must be fetched from the local 지자체 portal or 고시문.",
        disclaimer: DISCLAIMER,
      };
    
      return { content: [{ type: "text" as const, text: JSON.stringify(result, null, 2) }] };
    };
  • Layer definitions for the two V-World layers queried by this tool: 지구단위계획구역 and 개발행위허가제한지역.
    const LAYERS: LayerDef[] = [
      { id: "LT_C_UPISUQ161", label: "지구단위계획구역" },
      { id: "LT_C_UPISUQ171", label: "개발행위허가제한지역" },
    ];
  • src/server.ts:47-52 (registration)
    Registration of the 'get_district_plan' tool in the MCP server with its description and schema binding.
    server.tool(
      "get_district_plan",
      "Return 지구단위계획구역 membership and 개발행위허가제한지역 overlays. When district_plan is non-empty, 건폐율·용적률·용도 may be overridden by the plan (see 국토계획법 제52조). V-World only returns the geometric hit — actual plan text must come from 지자체 고시문.",
      QUERY_SCHEMA,
      getDistrictPlanTool
    );
  • src/server.ts:11-11 (registration)
    Import of the getDistrictPlanTool handler from the tools module.
    import { getDistrictPlanTool } from "./tools/get_district_plan.js";
  • The queryOverlays helper function used by the handler to query all layers and return hits/errors.
    export async function queryOverlays(
      layers: LayerDef[],
      point: { x: number; y: number },
      opts: QueryOverlaysOptions | number = {}
    ): Promise<OverlayQueryResult> {
      const options: QueryOverlaysOptions = typeof opts === "number" ? { perLayerSize: opts } : opts;
      const perLayerSize = options.perLayerSize ?? 5;
      const geomFilter =
        options.geomFilter ??
        (options.radius_m && options.radius_m > 0 ? pointToBox(point, options.radius_m) : undefined);
    
      const results = await Promise.all(
        layers.map(async (layer) => {
          try {
            const feats = geomFilter
              ? await getFeatures({ layer: layer.id, geomFilter, size: perLayerSize })
              : await getFeatures({ layer: layer.id, point, size: perLayerSize });
            return { layer, feats, error: null as LayerQueryError | null };
          } catch (e) {
            const err: LayerQueryError =
              e instanceof VWorldError
                ? {
                    layer: layer.id,
                    layer_label: layer.label,
                    error_code: e.code ?? "UNKNOWN",
                    error_message: e.message,
                  }
                : {
                    layer: layer.id,
                    layer_label: layer.label,
                    error_code: "UNHANDLED",
                    error_message: e instanceof Error ? e.message : String(e),
                  };
            return { layer, feats: [] as VWorldFeature[], error: err };
          }
        })
      );
    
      const hits: OverlayHit[] = [];
      const errors: LayerQueryError[] = [];
      for (const r of results) {
        if (r.error) errors.push(r.error);
        for (const f of r.feats) hits.push(featureToHit(r.layer, f));
      }
      return { hits, errors };
    }
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries full burden. It discloses the tool's limitation (only geometric hit, not plan text) and the behavioral implication of plan overriding properties. It does not mention authorization or other side effects, but the read-only nature is implied.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is three sentences with no fluff, front-loading the purpose in the first sentence. Every sentence adds value: purpose, override implication, and data source limitation.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the absence of an output schema, the description explains what is returned (membership and overlays) and the override behavior, but does not detail the response structure or error handling. It is sufficiently complete for a simple tool with one parameter.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema already fully describes the single parameter 'query' with minLength and a clear description. The description adds no additional meaning beyond what the schema provides, meeting the baseline for 100% schema coverage.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool returns '지구단위계획구역 membership and 개발행위허가제한지역 overlays' with a specific verb and resource. It further explains the implications of non-empty district plan overriding certain properties, which distinguishes it from sibling tools like get_zoning.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides context on when to use the tool by mentioning that district plan may override properties and references relevant law. It also warns that V-World only returns geometric hit and that actual plan text is external. However, it does not explicitly compare to sibling tools or state when not to use it.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

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/UrbanWatcherKr/korean-land-mcp'

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