{
  "markdown": "# FieldCure MCP PublicData.Kr\n\n[![NuGet](https://img.shields.io/nuget/v/FieldCure.Mcp.PublicData.Kr)](https://www.nuget.org/packages/FieldCure.Mcp.PublicData.Kr)\n[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://github.com/fieldcure/fieldcure-mcp-publicdata/blob/main/LICENSE)\n\nKorean public data API gateway. A [Model Context Protocol (MCP)](https://modelcontextprotocol.io) server that lets any MCP client discover, inspect, and call 80,000+ APIs on [data.go.kr](https://www.data.go.kr) — weather, real estate, business registration, air quality, transit, and more. Built with C# and the official [MCP C# SDK](https://github.com/modelcontextprotocol/csharp-sdk).\n\n## Features\n\n- **3 tools** — search APIs by keyword, inspect parameters/response fields, call any data.go.kr API\n- **Automatic serviceKey injection** — the API key is added to every request; never leaked to the LLM\n- **Lazy key resolution** — env var → MCP Elicitation → soft-fail chain (no hard-fail on startup). Hosts that support [MCP Elicitation](https://modelcontextprotocol.io/specification/2025-06-18/server/elicitation) can prompt the user for the key on first use; on upstream `401/403` or `SERVICE_KEY_IS_NOT_REGISTERED` the cached key is invalidated and a re-elicit is attempted (session cap: 2 re-elicits)\n- **XML → JSON normalization** — strips the `response/header/body/items` wrapper, returns clean JSON\n- **Error code mapping** — translates data.go.kr error codes into Korean guidance messages the LLM can relay directly\n- **SSRF protection** — domain whitelist limits calls to approved government hosts\n- **EUC-KR support** — legacy encoding from older government APIs is auto-detected and converted\n- **Stateless** — no cache, no database, no local files; every call is independent\n- **Stdio transport** — standard MCP subprocess model via JSON-RPC over stdin/stdout\n\n## Installation\n\n### dotnet tool (recommended)\n\n```bash\ndotnet tool install -g FieldCure.Mcp.PublicData.Kr\n```\n\nAfter installation, the `fieldcure-mcp-publicdata-kr` command is available globally.\n\n### From source\n\n```bash\ngit clone https://github.com/fieldcure/fieldcure-mcp-publicdata.git\ncd fieldcure-mcp-publicdata\ndotnet build\n```\n\n## Prerequisites\n\n1. Sign up at [data.go.kr](https://www.data.go.kr) and get your API key\n   (data.go.kr 회원가입 후 인증키 발급)\n2. **Subscribe to [목록조회서비스](https://www.data.go.kr/data/15077093/openapi.do)** (Required)\n   — `discover_api` and `describe_api` depend on this API\n   (discover_api, describe_api 도구가 이 API를 사용합니다)\n3. Subscribe to each individual API you want to query\n   (조회하려는 개별 API도 각각 활용신청 필요)\n\n## Requirements\n\n- [.NET 8.0 Runtime](https://dotnet.microsoft.com/download/dotnet/8.0) or later\n\n## Authentication\n\nThis server requires a **data.go.kr API key** (공공데이터포털 인증키). Key resolution is\nlazy (on first tool call) and follows the [FieldCure MCP Credential ADR](https://github.com/fieldcure/fieldcure-assiststudio/blob/main/docs/ADR-001-MCP-Credential-Management.md):\n\n1. **Environment variable** — `DATA_GO_KR_API_KEY` (canonical) or `PUBLICDATA_API_KEY` (legacy alias)\n2. **MCP Elicitation** — if no env var is found, the server requests the key interactively\n   on the first tool call (requires a client that supports MCP Elicitation — e.g. Claude\n   Code ≥ 2.1.76, AssistStudio). The resolved key is cached in process memory for the\n   session lifetime and is never written to disk by the server.\n3. **Soft-fail** — if both paths fail, `tools/list` still works and tool calls return a\n   structured error message asking the user to set the env var.\n\n`--api-key <value>` is also accepted as a CLI arg but is intended for manual testing only,\nnot as a supported configuration path.\n\n### Setup by host\n\n**Claude Code / Claude Desktop** — add the key to your MCP config:\n\n```json\n{\n  \"mcpServers\": {\n    \"publicdata-kr\": {\n      \"command\": \"fieldcure-mcp-publicdata-kr\",\n      \"env\": {\n        \"DATA_GO_KR_API_KEY\": \"<your-key>\"\n      }\n    }\n  }\n}\n```\n\nOn Claude Code (≥ 2.1.76), if the env var is omitted the server prompts for the key via\nElicitation on first use.\n\n**AssistStudio** — the key is requested via Elicitation on first use and stored in Windows\nPasswordVault for subsequent launches; the host then injects it as an env var when\nstarting the server.\n\n**Docker / CI** — pass the key as a standard environment variable:\n\n```bash\ndocker run -e DATA_GO_KR_API_KEY=<your-key> ...\n```\n\n### Key validation and re-elicitation\n\nIf the server receives an HTTP 401/403 or a `resultCode=22` / `SERVICE_KEY_IS_NOT_REGISTERED_ERROR`\nbody from data.go.kr, it invalidates the cached key and re-requests via Elicitation\n(session cap: 2 re-elicits per `ApiKeyResolver` lifetime). After exhausting retries, the\ntool returns a soft-fail error message.\n\n> **Note:** On data.go.kr an HTTP 401 can mean either an invalid key *or* an API that you\n> have not applied for (활용신청). If a re-elicitation prompt appears right after calling\n> an API you haven't subscribed to, entering the same key will produce the final error\n> envelope with details — at that point visit the API's data.go.kr page and apply for access.\n\n## Configuration\n\n### Claude Desktop\n\nAdd to `claude_desktop_config.json`:\n\n```json\n{\n  \"mcpServers\": {\n    \"publicdata-kr\": {\n      \"command\": \"fieldcure-mcp-publicdata-kr\",\n      \"env\": {\n        \"DATA_GO_KR_API_KEY\": \"YOUR_DATA_GO_KR_API_KEY\"\n      }\n    }\n  }\n}\n```\n\n### Claude Code (v2.1.76+)\n\n```bash\nclaude mcp add publicdata-kr -- fieldcure-mcp-publicdata-kr\n```\n\nClaude Code supports MCP Elicitation, so `DATA_GO_KR_API_KEY` may be omitted — the\nserver will prompt for the key on first tool use.\n\n### VS Code (Copilot)\n\nAdd to `.vscode/mcp.json`:\n\n```json\n{\n  \"servers\": {\n    \"publicdata-kr\": {\n      \"command\": \"fieldcure-mcp-publicdata-kr\",\n      \"env\": {\n        \"DATA_GO_KR_API_KEY\": \"YOUR_DATA_GO_KR_API_KEY\"\n      }\n    }\n  }\n}\n```\n\n### From source (without dotnet tool)\n\n```json\n{\n  \"mcpServers\": {\n    \"publicdata-kr\": {\n      \"command\": \"dotnet\",\n      \"args\": [\n        \"run\",\n        \"--project\", \"C:\\\\path\\\\to\\\\fieldcure-mcp-publicdata\\\\src\\\\FieldCure.Mcp.PublicData.Kr\"\n      ],\n      \"env\": {\n        \"DATA_GO_KR_API_KEY\": \"YOUR_DATA_GO_KR_API_KEY\"\n      }\n    }\n  }\n}\n```\n\n### AssistStudio\n\n> **Install the dotnet tool first.** AssistStudio does not auto-install external MCP\n> servers (only built-in ones are managed via the AssistStudio auto-update path).\n> The `fieldcure-mcp-publicdata-kr` command must be on PATH before you add the server,\n> otherwise the connection fails with a generic \"server shut down unexpectedly\" message.\n>\n> ```bash\n> dotnet tool install -g FieldCure.Mcp.PublicData.Kr\n> # later, to upgrade:\n> dotnet tool update -g FieldCure.Mcp.PublicData.Kr\n> ```\n\nThen: Settings > MCP Servers > **Add Server**:\n\n| Field | Value |\n|-------|-------|\n| **Name** | `PublicData.Kr` |\n| **Command** | `fieldcure-mcp-publicdata-kr` |\n| **Arguments** | *(empty)* |\n| **Environment** | `DATA_GO_KR_API_KEY` = your data.go.kr API key *(optional — AssistStudio can prompt via Elicitation if unset)* |\n| **Description** | *(auto-filled on first connection)* |\n\n## Tools\n\n| Tool | Description |\n|------|-------------|\n| `discover_api` | Search data.go.kr APIs by keyword — returns names, providers, endpoint URLs |\n| `describe_api` | Get operations, request parameters, and response fields for a specific API |\n| `call_api` | Call any data.go.kr API with automatic serviceKey injection and response normalization |\n\n### Workflow\n\n```\n1. discover_api(\"미세먼지\")\n   → { serviceId: \"15073861\", serviceName: \"한국환경공단_에어코리아_대기오염정보\", ... }\n\n2. describe_api(\"15073861\")\n   → { operations: [{ name: \"getMsrstnAcctoRltmMesureDnsty\", url: \"...\", requestParameters: [...] }] }\n\n3. call_api(url: \"http://apis.data.go.kr/B552584/ArpltnInforInqireSvc/getMsrstnAcctoRltmMesureDnsty\",\n            params: '{\"stationName\": \"종로구\", \"dataTerm\": \"DAILY\", \"returnType\": \"json\"}')\n   → { totalCount: 24, items: [{ stationName: \"종로구\", pm10Value: \"45\", ... }] }\n```\n\n### `discover_api`\n\nSearch Korean public data APIs on data.go.kr by keyword. Results are deduplicated by service — each API appears once even if it has multiple operations.\n\n| Parameter | Type | Required | Description |\n|-----------|------|:--------:|-------------|\n| `query` | string | Yes | Search keyword (e.g., `미세먼지`, `부동산`, `사업자`) |\n| `page` | int | — | Page number (default: 1) |\n| `pageSize` | int | — | Results per page (default: 10, max: 50) |\n\n### `describe_api`\n\nGet the request parameters and response fields of a specific API. Use the `serviceId` from `discover_api` results.\n\n| Parameter | Type | Required | Description |\n|-----------|------|:--------:|-------------|\n| `serviceId` | string | Yes | Service ID (`list_id`) from `discover_api` |\n\n### `call_api`\n\nCall a Korean public data API. The serviceKey is automatically injected — never pass it yourself. If the call fails with ACCESS_DENIED, the user needs to apply for access to that specific API at data.go.kr.\n\n| Parameter | Type | Required | Description |\n|-----------|------|:--------:|-------------|\n| `url` | string | Yes | Full endpoint URL from `describe_api` results |\n| `params` | string | — | Query parameters as a JSON **string** (not a raw object), e.g. `'{\"stationName\":\"종로구\",\"dataTerm\":\"DAILY\"}'`. Parameter names must come from `describe_api`'s `request_parameters` — do not guess. |\n| `maxResults` | int | — | Max items to return (default: 20, prevents context overflow) |\n\n## Error Code Mapping\n\nWhen a data.go.kr API returns an error, the server translates it into a Korean guidance message the LLM can relay directly:\n\n| Code | Meaning | LLM receives |\n|------|---------|--------------|\n| 12 | NO_OPENAPI_SERVICE | 이 API가 존재하지 않습니다. discover_api로 다시 검색해보세요. |\n| 20 | ACCESS_DENIED | 이 API에 대한 활용신청이 필요합니다. (포털 링크 포함) |\n| 22 | KEY_NOT_REGISTERED | API 키가 등록되지 않았습니다. |\n| 30 | TRAFFIC_EXCEEDED | 일일 호출 한도를 초과했습니다. |\n| 31 | UNREGISTERED_IP | 이 IP가 등록되지 않았습니다. |\n\n## Environment Variables\n\n| Variable | Required | Default | Description |\n|----------|:--------:|---------|-------------|\n| `DATA_GO_KR_API_KEY` | — | — | data.go.kr API key (인증키). If unset, the server requests it via MCP Elicitation on first tool call. |\n| `PUBLICDATA_API_KEY` | — | — | Legacy alias for `DATA_GO_KR_API_KEY`. Still accepted; prefer the canonical name for new setups. |\n| `PUBLICDATA_TIMEOUT_SECONDS` | — | 30 | Per-request timeout |\n| `PUBLICDATA_MAX_RESPONSE_LENGTH` | — | 50000 | Maximum response body length in characters |\n\nCLI args (`--api-key`, `--timeout`, `--max-response-length`) override environment variables\nand are intended for manual testing only — `DATA_GO_KR_API_KEY` and Elicitation are the\nsupported paths.\n\n> **Naming note:** the API key follows the external service naming convention\n> (`DATA_GO_KR_API_KEY`), while server-local configuration uses the `PUBLICDATA_` prefix.\n> This keeps the key aligned with data.go.kr's own documentation so users don't have to\n> configure it twice, while local tunables stay grouped under a single package namespace.\n\n## Security\n\n- **API key masking** — the serviceKey is replaced with `***` in any error output visible to the LLM\n- **Domain whitelist** — `call_api` only allows requests to approved hosts: `api.odcloud.kr`, `apis.data.go.kr`, `api.data.go.kr`, `openapi.data.go.kr`, `www.law.go.kr`, `open.neis.go.kr`\n- **Response size limit** — configurable via `PUBLICDATA_MAX_RESPONSE_LENGTH` (default: 50,000 chars)\n- **No log leaks** — the API key is never printed to stdout or stderr\n\n## Project Structure\n\n```\nsrc/FieldCure.Mcp.PublicData.Kr/\n├── Program.cs                       # MCP server entry point (stdio); no startup hard-fail\n├── Services/\n│   ├── ApiKeyResolver.cs            # env var → MCP Elicitation → soft-fail chain + cache + retry cap\n│   ├── InvalidApiKeyException.cs    # Signals upstream auth rejection (HTTP 401/403 or body error)\n│   ├── KeyedCall.cs                 # Tool-side resolve → run → invalidate → retry helper\n│   ├── PublicDataHttpClient.cs      # HTTP proxy with serviceKey injection + auth-error detection\n│   ├── DomainWhitelist.cs           # SSRF prevention via host whitelist\n│   ├── ResponseNormalizer.cs        # XML→JSON conversion, wrapper removal\n│   └── ErrorCodeMapper.cs           # Error code → Korean guidance messages\n└── Tools/\n    ├── DiscoverApiTool.cs           # discover_api\n    ├── DescribeApiTool.cs           # describe_api\n    └── CallApiTool.cs               # call_api\n```\n\n## Development\n\n```bash\n# Build\ndotnet build\n\n# Test\ndotnet test\n\n# Pack as dotnet tool\ndotnet pack src/FieldCure.Mcp.PublicData.Kr -c Release\n```\n\n## See Also\n\nPart of the [AssistStudio ecosystem](https://github.com/fieldcure/fieldcure-assiststudio#packages).\n\n## License\n\n[MIT](LICENSE)\n",
  "bytes": 12758,
  "sha": "acde7c38b968fd66c1f6eeb96a8572b3f5c40a04d2a6102b69f016d3b2bcabb4",
  "repo_slug": "fieldcure/fieldcure-mcp-publicdata",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_fieldcure_publicdata_kr_67b886dd/readme"
}