Content
# Tool List
## KOSIS/NABO Natural Language MCP Server
KOSIS and NABOSTATS provide a MCP server that allows chatbots to safely search and use data.
Users can ask questions in natural language, such as "Tell me about Seoul's population", "Compare economic growth rate and birth rate trends", or "Find NABO fiscal balance statistics". The chatbot uses this server to find the relevant statistical tables, confirm the necessary codes and periods, and retrieve the actual raw data.
The core goal of this project is to **reduce seemingly correct but incorrect statistical answers**. The MCP server does not generate the final answer but passes the verifiable raw data and warning signals to the chatbot. The final sentence is created by an LLM like Gemma, which is designed to report the basis, including values, units, periods, denominators, estimation status, and providing institutions.
## Summary for Beginners
- **What does it do?**
Searches KOSIS and NABO statistical tables, finds the codes for regions, genders, ages, and items within the tables, and retrieves the actual raw statistical data.
- **Why is it necessary?**
Statistical questions require important details such as which table to choose, whether the period matches, what the unit is, and what the denominator is. This server helps by revealing these verification processes in the response, preventing chatbots from quietly providing incorrect answers.
- **Who can use it?**
Suitable for those creating local LLM chatbots like Gemma, Claude Desktop/Cursor/Windsurf MCP clients, and analytical tools that automatically query public statistics.
- **What is the recommended usage?**
First, analyze the question with `plan_query`, then proceed with `select_table_for_query` → `resolve_concepts` → `query_table` → `compute_indicator` if necessary.
## Key Features
- Divide natural language questions into statistical inquiry procedures.
Example: "Tell me Seoul's per capita GRDP" → Decompose into indicators, regions, necessary denominators, and subsequent tool calls.
- Preserve questions with multiple indicators.
Example: "Economic growth rate, population change rate, and total fertility rate trends" → Leave each indicator in `metrics[]` to find separate tables.
- Verify with KOSIS metadata first.
Check if statistical tables actually contain regional, age, and item codes before retrieving values.
- Return raw data as is.
`query_table` returns KOSIS raw data with periods, values, units, and classification information without performing aggregation, averaging, or interpretation.
- Indicate limitations even for required calculations.
Calculations like per capita values, proportions, and change rates are performed by `compute_indicator`, but unit conversions or additivity judgments are marked with `mcp_output_contract` for caller responsibility.
- Do not hide failures or ambiguities.
States like no data, period mismatch, incorrect codes, estimated data, or need for unit interpretation are revealed in the response.
## Support Status
- Tier A direct query statistics: 189 items, all verified
- Tier B natural language search routing: 219 items
- Synonym/mundane word mapping: 90 items
- Topic browsing: 16 topics
- Intent labels: 23 items
- Default router: `NaturalLanguageRouter`
Representative questions:
```text
Tell me about Korea's population
Analyze the unemployment rate trend over the past 5 years
Compare the number of small and medium-sized enterprises and small business establishments
Compare economic growth rate, population change rate, and total fertility rate trends
Find AI-related statistics
Find wind power generation capacity statistics
Explain the formula for the shutdown rate and necessary statistics
```
## Glossary
- **KOSIS**: The National Statistical Office's national statistics portal. It aggregates official statistical tables from various institutions.
- **NABO / NABOSTATS**: The National Assembly Budget Office's fiscal and economic statistics system. It provides statistical tables and term dictionaries related to finance and economy.
- **MCP**: A connection method that allows chatbots to call external tools.
- **Statistical table**: A data table within KOSIS. Even the same "population" can have multiple tables, such as registered population, estimated population, and census population.
- **Code mapping**: The process of converting expressions like "Seoul", "female", and "30s" into actual codes within KOSIS tables.
- **Raw rows / raw data**: KOSIS query results before MCP interpretation.
- **Marker**: Attention signals like "unit interpretation needed", "estimated data", or "no data".
## 0. API Key Preparation
A KOSIS OpenAPI authentication key is required for KOSIS inquiries. This server receives the authentication key as an environment variable `KOSIS_API_KEY`.
To use NABOSTATS as well, set `NABO_API_KEY`. If you do not use NABO tools, you can skip this.
```powershell
$env:KOSIS_API_KEY="YOUR_KOSIS_API_KEY"
$env:NABO_API_KEY="YOUR_NABO_API_KEY"
```
macOS/Linux:
```bash
export KOSIS_API_KEY="YOUR_KOSIS_API_KEY"
export NABO_API_KEY="YOUR_NABO_API_KEY"
```
## Determining MCP Connection Method
There are two main MCP connection methods.
| Method | Recommended for | Advantages | Requirements |
| --- | --- | --- | --- |
| Local stdio MCP | For Claude Desktop, Cursor, Windsurf, or Claude Code on your PC | Simple setup, API key not leaving your PC | Python, `KOSIS_API_KEY`, optional `NABO_API_KEY` |
| Remote HTTP MCP | For Claude.ai web connector or multiple users sharing the same server | Connects with one URL | Render/Docker deployment environment, server `KOSIS_API_KEY`, optional `NABO_API_KEY`, optional access token |
For beginners, **Method 1: Simple installation and short config** is recommended. If you are already developing with Git clone, use **Method 2: Git Clone and connect with local path**.
MCP settings typically follow this structure:
```json
{
"mcpServers": {
"kosis-analysis": {
"command": "Command to run the server",
"args": ["Arguments if needed"],
"env": {
"KOSIS_API_KEY": "YOUR_KOSIS_API_KEY",
"NABO_API_KEY": "YOUR_NABO_API_KEY"
}
}
}
}
```
Important points:
- `command` is the command to run the MCP server.
- `args` are arguments appended to the execution file. Usually not needed if using an installed command like `kosis-analysis-mcp`.
- `env` includes the KOSIS API key. If using NABO statistics, include `NABO_API_KEY` as well. Do not write API keys directly in questions.
- In the JSON file, if there is an existing MCP server, add only the `"kosis-analysis"` block.
## Method 1: Simple Installation and Short Config
To use a short command like `kosis-analysis-mcp`, install the execution command first.
This command is executed **not in the chat window of Claude or Cursor but in your computer's terminal**.
How to open the terminal:
| OS | Where to execute? |
| --- | --- |
| Windows | Open Start menu, search for `PowerShell` or `Windows Terminal`, and execute |
| macOS | Go to `Applications` → `Utilities` → `Terminal` and execute |
| Linux | Open the terminal app for your distribution and execute |
The execution location can be any folder. This method installs a package from GitHub into your Python environment, so there's no need to navigate to a specific project folder.
Windows PowerShell example:
```powershell
pip install "git+https://github.com/jaykim429/korea-statistic-MCP-cginside.git"
```
macOS/Linux terminal example:
```bash
pip install "git+https://github.com/jaykim429/korea-statistic-MCP-cginside.git"
```
If `pip` is not found, execute using Python:
Windows:
```powershell
python -m pip install "git+https://github.com/jaykim429/korea-statistic-MCP-cginside.git"
```
macOS/Linux:
```bash
python3 -m pip install "git+https://github.com/jaykim429/korea-statistic-MCP-cginside.git"
```
Verification:
```powershell
kosis-analysis-mcp
```
This command runs the MCP stdio server, so a general CLI-like output is not expected. Confirm and terminate with `Ctrl+C`.
Add to Claude Desktop, Cursor, Windsurf settings like this:
```json
{
"mcpServers": {
"kosis-analysis": {
"command": "kosis-analysis-mcp",
"env": {
"KOSIS_API_KEY": "YOUR_KOSIS_API_KEY",
"NABO_API_KEY": "YOUR_NABO_API_KEY"
}
}
}
```
Add only the block above to `"mcpServers"` if another MCP server exists.
If `kosis-analysis-mcp` is not found, confirm the installation location and use the full path in `command`.
```powershell
where kosis-analysis-mcp
```
macOS/Linux:
```bash
which kosis-analysis-mcp
```
## Method 2: Git Clone and Connect with Local Path
This method involves cloning the code, downloading it to your computer, and connecting directly.
First, move to the working folder in the terminal:
Windows PowerShell:
```powershell
cd "$HOME\Documents"
```
macOS/Linux:
```bash
cd ~
```
Then execute:
Windows PowerShell:
```powershell
git clone https://github.com/jaykim429/korea-statistic-MCP-cginside.git
cd korea-statistic-MCP-cginside
python -m venv .venv
.\.venv\Scripts\Activate.ps1
pip install -e .
```
macOS/Linux:
```bash
git clone https://github.com/jaykim429/korea-statistic-MCP-cginside.git
cd korea-statistic-MCP-cginside
python3 -m venv .venv
source .venv/bin/activate
pip install -e .
```
Confirm the server file path:
```powershell
Resolve-Path .\kosis_mcp_server.py
```
Claude Desktop config file location:
| OS | Config file |
| --- | --- |
| Windows | `%APPDATA%\Claude\claude_desktop_config.json` |
| macOS | `~/Library/Application Support/Claude/claude_desktop_config.json` |
Open in Windows:
```powershell
notepad "$env:APPDATA\Claude\claude_desktop_config.json"
```
Open in macOS:
```bash
open -a TextEdit "$HOME/Library/Application Support/Claude/claude_desktop_config.json"
```
Create the file if it does not exist. Add settings like this:
```json
{
"mcpServers": {
"kosis-analysis": {
"command": "C:\\path\\to\\korea-statistic-MCP-cginside\\.venv\\Scripts\\python.exe",
"args": [
"C:\\path\\to\\korea-statistic-MCP-cginside\\kosis_mcp_server.py"
],
"env": {
"KOSIS_API_KEY": "YOUR_KOSIS_API_KEY",
"NABO_API_KEY": "YOUR_NABO_API_KEY"
}
}
}
}
```
Save and completely restart Claude Desktop.
## Method 3: If MCP Settings Already Exist
If another MCP server exists in your settings, add the block below. A comma is required after the previous item.
```json
"kosis-analysis": {
"command": "C:\\path\\to\\korea-statistic-MCP-cginside\\.venv\\Scripts\\python.exe",
"args": [
"C:\\path\\to\\korea-statistic-MCP-cginside\\kosis_mcp_server.py"
],
"env": {
"KOSIS_API_KEY": "YOUR_KOSIS_API_KEY",
"NABO_API_KEY": "YOUR_NABO_API_KEY"
}
}
```
If not using a virtual environment, you can change `command` to `"python"`. Ensure the Python version has installed dependencies.
The most common mistake is incorrect comma placement. For example, if one server already exists:
```json
{
"mcpServers": {
"other-server": {
"command": "other-command"
},
"kosis-analysis": {
"command": "kosis-analysis-mcp",
"env": {
"KOSIS_API_KEY": "YOUR_KOSIS_API_KEY",
"NABO_API_KEY": "YOUR_NABO_API_KEY"
}
}
}
}
```
## Method 4: Usage in Cursor / Windsurf
Cursor and Windsurf use the same MCP JSON structure.
| App | Config file |
| --- | --- |
| Cursor | `.cursor/mcp.json` in the project folder |
| Windsurf | `.windsurf/mcp.json` in the project folder |
Example:
```json
{
"mcpServers": {
"kosis-analysis": {
"command": "python",
"args": [
"/path/to/korea-statistic-MCP-cginside/kosis_mcp_server.py"
],
"env": {
"KOSIS_API_KEY": "YOUR_KOSIS_API_KEY",
"NABO_API_KEY": "YOUR_NABO_API_KEY"
}
}
}
}
```
For Windows, use the path format `C:\\path\\to\\...\\kosis_mcp_server.py`.
Each project can have separate MCP settings. If you want to use it across all projects, use the global MCP setting location supported by each app.
## Method 5. Using Local MCP with Claude Code
In Claude Code, you can choose one of two methods. The simplest way is to install the `kosis-analysis-mcp` execution command using `pip install` and then register it as a local MCP server.
```json
{
"mcpServers": {
"kosis-analysis": {
"command": "kosis-analysis-mcp",
"env": {
"KOSIS_API_KEY": "YOUR_KOSIS_API_KEY",
"NABO_API_KEY": "YOUR_NABO_API_KEY"
}
}
}
}
```
The Claude Code plugin method is described in **Method 9** below. This repository includes the `.claude-plugin/`, `.mcp.json`, and `skills/` configurations.
## Method 6. Running the Server Directly in the Terminal
Used to check if the server can be imported before connecting to the MCP client.
```powershell
kosis-analysis-mcp
```
This command runs the MCP stdio server, so it's normal for there to be no output in the terminal. To exit, use `Ctrl+C`.
Syntax/import check:
```powershell
python -m py_compile kosis_mcp_server.py kosis_curation.py kosis_charts_extra.py
```
When run directly, it's normal for there to be no output and for the process to wait. The MCP stdio server is not a CLI like a regular terminal command; it's a server that communicates with MCP clients like Claude/Cursor through standard input/output.
## Method 7. Remote URL Connector Method
To use the custom connector on Claude.ai web or `mcp-remote`, deploy a remote HTTP MCP server. This repository includes `kosis_http_server.py`, which provides a Streamable HTTP endpoint at `/mcp`.
Render Deployment:
1. Connect this GitHub repository as a Web Service on Render.
2. Use the `render.yaml` Blueprint.
3. Add the environment variable `KOSIS_API_KEY` as a Secret on the Render dashboard. If you also use the NABO tool, add `NABO_API_KEY` as a Secret.
4. If exposing the URL publicly, add `KOSIS_MCP_AUTH_TOKEN` as a Secret to protect `/mcp` calls.
5. `render.yaml` also configures metadata caching and fan-out safety features (`KOSIS_MCP_META_CACHE_TTL`, `KOSIS_MCP_QUERY_TABLE_MAX_FANOUT`, `KOSIS_MCP_QUERY_TABLE_CONCURRENCY`, `KOSIS_MCP_QUERY_TABLE_CALL_TIMEOUT`).
6. The URL after deployment will be in the form `https://<your-service>.onrender.com/mcp`.
Docker/Fly.io Deployment:
```bash
docker build -t kosis-analysis-mcp .
docker run -p 8000:8000 \
-e KOSIS_API_KEY=YOUR_KOSIS_API_KEY \
-e NABO_API_KEY=YOUR_NABO_API_KEY \
-e KOSIS_MCP_AUTH_TOKEN=YOUR_CONNECTOR_TOKEN \
kosis-analysis-mcp
```
Local HTTP Execution:
```powershell
kosis-analysis-mcp-http
```
Connecting with `mcp-remote` on Claude Desktop:
```json
{
"mcpServers": {
"kosis-analysis": {
"command": "npx",
"args": [
"-y",
"mcp-remote",
"https://your-kosis-mcp.example.com/mcp"
]
}
}
}
```
For clients that directly receive the HTTP URL:
```json
{
"mcpServers": {
"kosis-analysis": {
"url": "https://your-kosis-mcp.example.com/mcp",
"headers": {
"Authorization": "Bearer YOUR_CONNECTOR_TOKEN"
}
}
}
}
```
In the remote server method, do not include the KOSIS/NABO authentication keys in the URL; instead, set them as environment variables `KOSIS_API_KEY` and `NABO_API_KEY`. Servers with `KOSIS_MCP_AUTH_TOKEN` set require the client to send an `Authorization: Bearer ...` or `x-kosis-mcp-token` header to receive `/mcp` requests.
Remote Connection Check:
- When directly opening `/mcp` in a browser, it's not unusual for there to be no readable page. MCP endpoints are not regular web pages.
- The Render free plan may sleep, causing the first request to be slow.
- Check the server logs to ensure `uvicorn` started normally and that the environment variables `KOSIS_API_KEY` and, if necessary, `NABO_API_KEY` are included.
## Method 8. One-Line Execution with npx
This repository can be executed directly like an npm package. This method attempts to install Python dependencies during installation.
```powershell
npx -y github:jaykim429/korea-statistic-MCP-cginside
```
MCP Settings:
```json
{
"mcpServers": {
"kosis-analysis": {
"command": "npx",
"args": [
"-y",
"github:jaykim429/korea-statistic-MCP-cginside"
],
"env": {
"KOSIS_API_KEY": "YOUR_KOSIS_API_KEY",
"NABO_API_KEY": "YOUR_NABO_API_KEY"
}
}
}
}
```
If officially distributed on npm, it can be shortened further:
```json
{
"mcpServers": {
"kosis-analysis": {
"command": "npx",
"args": [
"-y",
"kosis-analysis-mcp"
],
"env": {
"KOSIS_API_KEY": "YOUR_KOSIS_API_KEY",
"NABO_API_KEY": "YOUR_NABO_API_KEY"
}
}
}
}
```
## Things to Check When the Connection Fails
1. Is `KOSIS_API_KEY` included?
- Check if it's included in the `env` of the MCP settings.
- When running directly in the terminal, ensure the environment variable is set in the current shell.
- If `missing_api_key` appears in the NABO tool, add `NABO_API_KEY` in the same manner.
2. Is the `command` path correct?
- Windows: `where kosis-analysis-mcp`
- macOS/Linux: `which kosis-analysis-mcp`
- If not found, execute `pip install "git+https://github.com/jaykim429/korea-statistic-MCP-cginside.git"` again.
3. Is the JSON syntax correct?
- Ensure that the braces `{}` and brackets `[]` are closed.
- A comma is required when adding a new server after an existing MCP server.
4. Have you restarted Claude Desktop completely?
- After changing the settings file, you need to restart the app.
5. Does the server show no output when run directly?
- This can be normal. `kosis-analysis-mcp` is an MCP stdio server and does not output results like a regular CLI.
6. Does `ModuleNotFoundError` appear?
- If using the Git clone method, ensure the virtual environment is activated and `pip install -e .` is executed.
- Check if the `command` in the settings points to the Python in that virtual environment.
7. Does a 401 appear in the remote URL method?
- If `KOSIS_MCP_AUTH_TOKEN` is set on the server, the client must send an `Authorization: Bearer YOUR_CONNECTOR_TOKEN` or `x-kosis-mcp-token` header.
8. Does the KOSIS query fail?
- Check if the API key is correct and if there is permission to use the KOSIS OpenAPI.
- If markers like `missing_api_key`, `unsupported`, `validation_errors`, `search_empty` appear in the response, follow their descriptions.
9. Does the NABO query fail?
- Check if `NABO_API_KEY` is set.
- NABO statistical tables require `STATBL_ID` and `DTACYCLE_CD`. First, find the table using `search_nabo_tables` or `search_stats`, confirm the item code using `explore_nabo_table`, and then call `query_nabo_table`.
If you need to specify a Python executable file directly, add the `KOSIS_PYTHON` environment variable.
## Method 9. Claude Code Plugin
This repository also includes the Claude Code plugin structure.
```text
/plugin marketplace add jaykim429/korea-statistic-MCP-cginside
/plugin install kosis-analysis@kosis-analysis-marketplace
```
The plugin MCP server is started through `.mcp.json` in the repository. Before use, ensure `KOSIS_API_KEY` is set in the terminal environment or Claude Code execution environment. If you also use the NABO tool, set `NABO_API_KEY`.
```bash
export KOSIS_API_KEY="YOUR_KOSIS_API_KEY"
export NABO_API_KEY="YOUR_NABO_API_KEY"
```
Windows PowerShell:
```powershell
$env:KOSIS_API_KEY="YOUR_KOSIS_API_KEY"
$env:NABO_API_KEY="YOUR_NABO_API_KEY"
```
## Supported Methods Summary
| Method | Current Status | Notes |
| --- | --- | --- |
| `kosis-analysis-mcp` command | Supported | Use after `pip install git+...` |
| Git clone + Python stdio | Supported | Current default method |
| Claude Desktop config | Supported | `command` + `args` + `env` |
| Cursor / Windsurf config | Supported | Same MCP JSON structure |
| Claude Code local MCP | Supported | Use local MCP settings |
| Claude Code plugin marketplace | Supported | Includes `.claude-plugin`, `.mcp.json` |
| Claude.ai web URL connector | Supported after deployment | Includes `kosis_http_server.py`, Render/Docker files |
| npx execution | Supported | Uses GitHub package spec, before official npm distribution |
## Recommended Call Order in Chatbot
When using local LLMs like Gemma 4 26B as MCP clients, instead of creating answers all at once, it's recommended to follow a step-by-step confirmation approach. The reason is simple: statistical questions require not just the value but also **table, period, unit, denominator, and region code** to match.
1. `plan_query`
Read the user's question first and plan “what indicators are desired,” “what region, period, and classification are needed,” and “which tools to call next.” This step does not retrieve actual values.
2. `select_table_for_query`
Select candidate KOSIS statistical tables that match the question. For example, if the user asks about “semiconductor exports,” tables without an industrial axis can be rejected.
3. `resolve_concepts`
Convert terms like “Seoul,” “30s,” “female,” and “metropolitan city” into actual code candidates within the selected statistical table.
4. `query_table`
Query the raw KOSIS data using verified codes. This tool returns raw data without performing aggregation, averaging, or ratio calculations.
5. `compute_indicator`
Perform calculations like per capita values, proportions, rate of change, or CAGR if necessary. Unit conversion or interpretation, such as whether a value can be summed, is left to the caller with response markers.
Fast paths are also maintained. The difference lies in “how much MCP can handle on behalf of the user.”
- Simple Tier A queries use `quick_stat`, and time series use `quick_trend`.
- Regional comparisons use `quick_region_compare`.
- Natural language convenience responses are handled by `answer_query`, which defaults to `verbose=false`, returning thin responses centered on `data`, `metadata`, `notes`, and `diagnostics`.
- Composite analysis materials use `analyze_trend`, `stat_time_compare`, `correlate_stats`, `forecast_stat`, and `detect_outliers`.
- Charts use `chart_line`, `chart_compare_regions`, `chart_correlation`, `chart_heatmap`, `chart_distribution`, `chart_dual_axis`, and `chart_dashboard`.
## Example
You can ask the chatbot in natural language as follows:
```text
plan_query("2020 Seoul women in their 30s population")
plan_query("Seoul per capita GRDP")
plan_query("The city with the fastest aging population among metropolitan cities")
plan_query("Trend of economic growth rate, population change rate, and total fertility rate")
query_table("101", "DT_1DA7004S", filters={"ITEM": ["T80"], "A": ["00"]}, period_range=["2025", "2025"])
```
You can also ask directly. If you want to see detailed diagnostic fields, add `verbose=true`.
```text
answer_query("Show the recent number of small and medium-sized enterprises and small business establishments")
answer_query("Compare the number of small and medium-sized enterprises by region")
answer_query("Seoul's small and medium-sized enterprise sales in 2020")
answer_query("Month-over-month change rate of Seoul housing prices")
answer_query("Increase rate of small and medium-sized enterprise sales from 2019 to 2023")
answer_query("Top 5 places with the most small and medium-sized enterprises")
answer_query("Proportion of Seoul's small and medium-sized enterprise sales in the country")
answer_query("Sum of small and medium-sized enterprises in Seoul and Gyeonggi")
answer_query("Find AI-related statistics")
answer_query("Analyze the trend of unemployment rate over the past 5 years")
answer_query("Seoul population", verbose=true)
quick_region_compare("Number of small and medium-sized enterprises")
quick_stat("Housing sales price index", region="Seoul", period="2026.03")
detect_outliers("Total fertility rate", method="detrended_zscore")
indicator_dependency_map("Business closure rate")
chart_line("Elderly population", region="Nationwide", years=5)
```
The response of `plan_query` does not return actual values but returns a procedural plan as follows:
- `status: "planned"`
- `intent`: `single_value`, `trend`, `comparison`, `computed_indicator`, etc.
- `analysis_mode`: `simple_lookup`, `analytical_single_metric`, `composite_analysis`, `needs_clarification`
- `intended_dimensions`: Detected dimensions such as `region`, `age`, `sex`, `time`, `industry`, etc.
- `table_required_dimensions`: KOSIS meta-axis meanings that candidate statistical tables must have (`year`, `month`, `quarter`, etc.)
- `semantic_dimensions`: Semantic dimensions that LLM needs to understand (`regions`, `region_group`, `industry`, etc.)
- `concepts`: Natural language concepts that will be converted to code by `resolve_concepts`
- `metrics`: Candidate indicators requested in the question. Availability is `unknown` until `select_table_for_query` verifies with KOSIS meta.
- `indicator_candidates`: Preserves indicator candidates for each segment in explicit multi-indicator questions. Not attached to single-indicator questions.
- `quarantined_metrics`: Candidates excluded from execution plans due to potential router contamination (e.g., `R&D investment scale` mixed in `GRDP` question)
- `analysis_tasks`: Subsequent analysis intentions such as `trend`, `rank`, `per_capita`, `share_by_group`, `growth_rate`, `compare_metrics`
- `evidence_workflow`: Workflow such as `select_table_for_query` → `resolve_concepts` → `query_table` → `compute_indicator` if needed
- `next_call`: Template for the next tool call that Gemma can follow
- `mcp_output_contract`: Exposes failure/warning markers and machine-readable signals. This field is for internal diagnostics and does not enforce final answer phrases.
In simple terms, `plan_query` is a "plan to find the answer," not the answer itself. It's normal for `answer` to be `null`.
If `mcp_output_contract.current_signals.markers_present` contains `multi_metric_request` in multi-indicator questions, Gemma processes each metric through a separate `select_table_for_query` path. Only when KOSIS meta proves the same table, it shares one table.
The response of `query_table` is for raw extraction:
- `verification_level: "explored_raw"`
- `confidence`: Verification level of code mapping and call conditions, not the quality of the value
- `aggregation: "none"`
- `metadata_source`: Used KOSIS meta endpoint, query time, and original URL
- `rows[]`: Returns KOSIS raw rows with period, value, unit, and dimension. Non-numeric and non-public values like `"*"`, `"-"` are separated into `value: null`, `value_raw`, `value_numeric`, and `missing_reason`.
- `data_nature`, `period_nature`: Indicate projection data like future estimates with a marker
The default of `query_table` is `include_raw=false`. Therefore, each row includes only normalized fields necessary for analysis like `period`, `value`, `unit`, `dimensions`, `value_raw`, and `missing_reason`. If you need all KOSIS original response fields, pass `include_raw=true`.
If incorrect `OBJ_ID` or `ITM_ID` is provided, it returns `status: "unsupported"`, `validation_errors`, and `suggested_codes` without calling KOSIS values.
This server prioritizes providing facts like "This code does not exist in this table," "This period is not supported," or "This data is an estimate" over generating seemingly correct values.
Environment variables for operational stability:
- `KOSIS_MCP_META_CACHE_TTL`: TTL seconds for `getMeta` response cache. Default is `3600`.
- `KOSIS_MCP_QUERY_TABLE_MAX_FANOUT`: Maximum fan-out calls for `query_table`. Default is `80`.
- `KOSIS_MCP_QUERY_TABLE_CONCURRENCY`: Concurrent fan-out calls. Default is `8`.
- `KOSIS_MCP_QUERY_TABLE_CALL_TIMEOUT`: Timeout seconds for individual fan-out calls. Default is `15`.
- `KOSIS_MCP_DATA_FRESHNESS_WARNING_YEARS`: Years threshold for data freshness warning. Default is `2.0`.
- `KOSIS_MCP_VERBOSE_OUTPUT_CONTRACT`: Default is `false`. If set to `true`, includes full `llm_rules` and `failure_markers` catalog in `mcp_output_contract`.
`plan_query` also exposes failures:
- If unable to extract metrics, returns `status: "needs_clarification"` and `markers_present: ["needs_clarification", "missing_metrics"]`
- If multiple indicators are detected, adds `multi_metric_request` to `markers_present` and synchronizes `metrics[]`, `concepts`, and `analysis_tasks[].metrics`.
- Heuristically extracted indicators, industries, and region groups are marked with `heuristic_extraction` and `caller_must_verify_with_kosis_meta` to indicate the need for KOSIS meta verification.
- Simple lookups have `analysis_mode: "simple_lookup"` and empty `analysis_tasks`.
- Single-indicator trends/ranks/formulas have `analysis_mode: "analytical_single_metric"`.
- Multi-indicator, multi-task, and multi-region comparisons have `analysis_mode: "composite_analysis"` and `evidence_bundle: true`.
- Expressions like `monthly`, `quarterly`, and `annually` are preserved as time granularity, not KOSIS axes.
`answer_query` response status:
- `EXECUTED`: Actual KOSIS API query or calculation completed
- `NEEDS_TABLE_SELECTION`: Needs candidate statistical table selection for high-level or complex questions
- `STAT_NOT_FOUND`: Failed to map or query API
- `PERIOD_NOT_FOUND`: Requested comparison period not found
- `DENOMINATOR_REQUIRED`: Needs denominator confirmation for ratios or proportions
`answer_query` response types:
- `tier_a_value`, `tier_a_trend`, `tier_a_growth_rate`: Single value, time series, and growth rate
- `tier_a_region_comparison`: Comparison of 17 regions
- `tier_a_top_n`: Ranked responses like "Top N places" or "Top N items"
- `tier_a_share_ratio`: Regional value / national value × 100
- `tier_a_region_sum`: Sum of multiple regions
- `tier_a_composite_share_ratio`: National proportion of composite regions
- `tier_a_composite`, `tier_a_composite_calculation`, `tier_a_composite_comparison`: Precisely mapped composite formulas
- `search_and_plan`: Needs candidate statistical table selection (Tier B fallback)
All `EXECUTED` responses expose:
- `used_period`: Actual KOSIS period used (e.g., `"2023"`, `"202603"`)
- `period_age_years`: Years elapsed since the current period (float)
- `검증_주의`: Automatic warnings for data freshness, intent and response type mismatch, non-compliance with specified years, missing regional intent, etc.
Direct calls like `quick_stat`, `quick_trend`, and `quick_region_compare` also expose `used_period`, `period_age_years`, and `⚠️ 데이터_신선도` fields from version 0.4.0.
Unsupported parameters (e.g., `industry`, `scale`, `aggregation`, `group_by`) are exposed in the `⚠️ 무시된_파라미터` field to prevent silent drops.
The `period` parameter recognizes:
- Absolute: `"2023"`, `"2023.04"`, `"2023년 4월"`, `"2025Q1"`, `"2025년 1분기"`
- Relative: `"last year"`, `"this year"`, `"two years ago"`
If requested period precision is finer than the statistical table's compilation cycle, `⚠️ 정밀도_다운그레이드` is automatically attached.
`search_kosis` responses indicate if there's a verified Tier A statistical table for the same keyword through the `Tier_A_직접_매핑` field.
If `STAT_CORRELATION`, `STAT_OUTLIER_DETECTION`, or `STAT_FORECAST` intentions are detected, `answer_query` exposes related tool names and candidate statistical tables.
Queries for time-cohort-based dynamic indicators (e.g., "5-year survival rate of restaurants") are directed to `dynamic_ratio_advisory` and return the formula specification and KOSIS statistical table candidates.
KOSIS standard units in response text (e.g., `thousand`, `100 million`, `hundred million`, `thousand dollars`) are automatically supplemented with human-readable formats.
The `period` expression recognizes more patterns from version 0.5.0:
- `올해 1분기` / `last year's 4th quarter` / `this quarter` / `last quarter`
- `올해 4월` / `last month` / `this month`
- `상반기` / `하반기` — Not in KOSIS standard cycle, so `⚠️ 상하반기` is exposed
`search_and_plan` responses automatically enhance search queries with extracted `industry`, `scale`, and `target` (`검색어_슬롯보강` field).
Multi-region sum and composite region handlers (`_answer_composite_aggregate`, `_answer_region_sum`) use parallel calls for all components from version 0.5.0, applying a 12-second per-call and 60-second overall budget.
Version 0.6.0 introduces meta and raw data tools directly using KOSIS `getMeta` endpoint:
- `explore_table(org_id, tbl_id, industry_term?)` — Retrieves `TBL`, `ITM`, `PRD`, and `SOURCE` meta for a statistical table in parallel, returning classification axis item catalog, storage period, and institution contact information. If `industry_term` is provided, dynamically resolves `ITM_ID` via `ITM_NM` matching.
- `check_stat_availability(query, live_period_check=True)` — Queries not only Tier A curation notes but also the actual latest recording period from KOSIS meta API. If the memo snapshot and live recording period mismatch, exposes `⚠️ 메모_vs_KOSIS_drift`. If data has been stagnant for over 2 years, adds `⚠️ 데이터_신선도`.
- `check_variable_compatibility(variables, regions?)` — Checks common recording periods, unit consistency, and regional support for multiple indicators before regression or correlation analysis. This tool provides diagnostic materials without executing regression.
- `query_table(org_id, tbl_id, filters, period_range?)` — Queries KOSIS raw rows using classification axis codes verified by `explore_table`. Even if multiple codes are provided, the server returns individual rows without aggregation and rejects incorrect codes with `suggested_codes`.
NABOSTATS (National Assembly Budget Office's fiscal and economic statistics system) OpenAPI is also accessible through the same MCP. NABO tools are provided by a separate provider, so the response must preserve `source_system: "NABO"` and `provider`.
Tool List
- `search_nabo_tables(query, limit?)` — Searches for NABO statistical table candidates. The results include `STATBL_ID`, table name, period information, and searchable `dtacycle_cd_suggestion`.
- `explore_nabo_table(statbl_id)` — Checks the classification codes, and period candidates for the selected NABO table. Used for code mapping before querying values. The response's `dtacycle_cd_suggestions` and `dtacycle_guidance` help determine the period for querying, such as yearly (`YY`), quarterly (`QY`), or monthly (`MM`).
- `query_nabo_table(statbl_id, dtacycle_cd="auto", period?, period_range?, filters?)` — Returns normalized raw NABO data in `period`, `value`, `unit`, `dimensions`, and `raw` formats. If `dtac="auto"`, itYY`/`QYMM` based on the and records the basis inacycle_resolution`. The `filters` can use keys like`, `CLASS`, `GROUP`,period`.
- `search_terms(term, limit?)` — Searches the N statistical term dictionary.
- `search_stats(query, source="all")` — An integrated search entry that finds both KOSIS and NABO table candidates. The integrated search shows combined candidates but does not assume the statistics from the two providers have the same definition.
The search tool returns the reliability of the candidates. `match_quality` includes how well the query matches the candidate table name and metadata (`coverage_ratio`, `weighted_coverage_ratio`) and the query's focus in the table title (`title_focus_ratio`). If there are perfect match candidates, partial matches are demoted to `low_confidence_results` with a `partial_candidates_demoted` marker. Candidates with all query terms but low title focus are separated into `low_confidence_results` withunfocused_full_match_demoted`For example, `search_stats("전기", source="all")` prioritizes high-focus candidates like `에너지용도별 전기요금 및 발전량` and separates long, less focused candidates like "전기 요금 절약을 수집..." into secondary results. This processing is based on query coverage and title focus ratios, not a specific dictionary.
Examples:
```text
search_stats("GDP", source="all")
search_nabo_tables("재정수지")
explore_nabo_table("T192213006109866")
query_nabo_table("T192213006109866", period="latest", filters={"ITEM": ["10001"]})
query_nabo_table("T192213006109866",=["2010", "2024"], filters={"ITEM": ["10001"]})
query_nabo_table192213006109866", period="2010:2024", filters={"ITEM": ["10001"]})
```
NABO period inputs points (`"2024"`), latest (`"latest"`), array ranges (`period_range=["2010", "2024"]`), string ranges (`"2010:2024"`, `"2010-2024"`), and object ranges (`{"start": "2010", "end": "2024"}`). Range queries apply period filters after MCP receives the raw the NABO not support it records the process in `period_request` and `period_filtered_row_count`.
`dtacycle_cd_suggestions` includes periods confirmed in theO table metadata. See `dtacycle_supported_values` for all possible enum values. For example, requesting `dtacycle_cd="QY"` for a yearly table results in a rejection with `period_type_incompatible` and `dtacycle_mismatch`, not an emptyNABO raw data may have the same `ITEM.label` repeated across different codes. `query_nabo_table` joins item metadata to include the full path in each row's `item_full_name` and `dimensions.ITEM.full_label`, such as `임금근로실업급여계정>수입`. In the prioritize `full_label short `label`.
When the question specifies “NABO 기준”, “국회예산정책처”, “재정계시스템”, `` suggests using the `search_tables` → `explore_nabo_table` →_nabo_table` flow instead of selecting a KOSIS table. Check `source_preference: "NABO"` and `nabo_indicator_normalization` to see which candidate phrases and NABO metadata were used for metric extraction.
A procedural entry for chatbots, `plan_query(query)`, is provided. It returns only the intent, dimensions, concepts, and the next tool call template, without determining the statistical table ID, code mapping, value querying, or arithmetic.
The tool manifest for chatbot exposure is in [docs/chatbot_integration.md](docs/chatbot_integration.md [docs/gemma_manifest.default.json/gemma_manifest.default.json). `answer_query` is no longer deprecated and is a convenience tool for natural language. For precise verification, combine `plan_query` → `select_table_for_query` → `resolve_concepts` → `query_table` → `compute_indicator` or analysis tools as needed.
The analysis layer prioritizes providing reproducible materials over generating conclusions since version 0.9.x.
`chain_full_analysis` remains a legacy entry point but no longer automatically runs regression, prediction, outlier detection, or chart generation. Instead, it returns a workflow for collecting analysis materials, such as `plan_query` → `select_table_for_query` → `resolve_concepts` → `query_table` → `check_variable_compatibility`. Actual modeling and visualization are chosen by the LLM in/R code execution environment.
- `end`: Returns `input `input.y`, `model_parameters`, `formula`, `fitted_values`, and `residuals`. Natural language not included by default.
- `forecast_stat`:data_characteristics`, `model_options`, and `.linear.forecast_path` instead of forecast conclusions. The legacy `forecast` field is included onlyinclude_legacy_forecast=true`.
- `correlate_stats Pearson/Spearman/Kendall coefficients and aligned data arrays. “Correlation does not imply causation” is structured in `must_know` and `common_pitfalls`.
- `detect_outliers`: The default is `detrended_zscore`, with options for `zscore`, `iqr`, `stl`, and `all`. The the raw data array and data characteristics.
`decode_error` has been extended to recognize the official KOSIS code `42` ("사용자별 이용 제한") in addition to unofficial codes.
Chart tools (`chart_line`, `chart_compare_regions`, `chart_correlation`, `chart_heatmap`, `chart_distribution`, `chart_dual_axischart_dashboard`) return SVG in fenced ``` ```svg ``` ``` blocks as `TextContent` to avoid content format issues.
`answer` natural language text undergoes post-processing:
- `X은(는)` placeholder → selects `은` or `는` based on Korean endings
- `YYYY.MM` monthly point raw notation → `YYYY년 M월` (only for 1900~2099 names are normalized to one of 17 official administrative names or abbreviations in English:
- `Seoul`, `서울특별시`, `서울시`, `seoul` → `서울`
- `경기도`, `Gyeonggi`, `gyeonggi-do` → `경기`
- `대한민국`, `한국`, `korea` → `전국`
Synthetic regions (`수도권`,수도권`, `영남권`, `호남권`, `충청권`) are automatically expanded into their constituent 17 regions:
- `수도권 사업체수` → sum of 서울, and 인천 (`_region_sum`)
- `수도권 사업체수 비중` → (서울+경기+인천) / 전국 × 100 (`tier_a_composite_share_ratio`)
## Statistical Interpretation Notes
Even official statistics can yield different numbers if the table definitions and compilation standards differ. When generating answers with a chatbot, it's to hide the following points from the user:
- of companies, establishments, and self-employed individuals refer to different populations.
- Ratios, closure rates, startup rates, and survival rates require checking the denominators and formulas.
- Correlation, regression, and policy effect analyses do not automatically imply causation.
Latest” questions are based on the latest recorded time in KOS tables.
- Questions with specified periods “2020년”, “2026년 3월”, “전”, or “전월 대비”, are processed as period comparisons and not replaced with the latest values if data is missing.
For example, theDid Korea's GDP increase?” is not just about number; it requires GDP table to use period, and the unit.
## Verification Scripts
IS API regression```powershell
$IS_API_KEY="YOUR_KOSIS_APIpython scripts\regression_smoke.py
python scripts\eval_plan_query_pipeline.py
python scripts\eval_gemma_workflow.py
python scripts\comprehensive.py
python scripts\temporal_edge_cases.py
python scripts\natural_language_battery.py --summary-only
```
To test NABO tools, set `NABO_API_KEY` in the same terminal and run `scripts_tool_contracts.py`. This script tests contracts with mock external calls, so it can pass even without a key.
```powershell
$env:NABO_API_KEY="YOUR_NABO_API_KEY"
python scripts\eval_tool.py
```
`eval_plan_query_pipeline.py` is a local regression test for Gemma's `plan_query includes that cover:
- Metric absence / clarification state `mcp_output_contract.current_signals` false negatives
- Ensuring `year`, `month`, and `quarter` do not flow intoIS table axes
- Consistency of `` / `_single_metric` / `composite_analysis` modes and `evidence_bundle`
- Queries with abbreviations like `P `GRDP`, `CPI`, and everyday language
- Isolation of `GRDP` ↔ `R&D 투자 규모` router contamination
tests for top/bottom rankings, period ranges, multi-region comparisons, and formula + ranking combinations
`eval_gemma_workflow.py` is an evaluation set for Gemma's procedural workflow centered on `plan_query`. It checks necessary dimensions, concepts, and tool sequences through seed cases like slicing, perDP, and English queries.
`natural_language.py` is a battery that calls `answer_query` only, testing10 intent categories at once. Filtering is possible with `--group <name>` or `--case>`.
## File Structure
- `kosis_mcp_server.py`: MCP server and tool definitions
- `kosis.py`: Streamable HTTP MCP point
- `kosis_curation Natural language router, Tier A/B c and concept graph
- `kosis_charts_extra.py`: Additional SVG chart helpers
- `docs/chatbot_integration.md`: Gemma chatbot MCP tool manifest and consistency rules
- `scripts/regression_smoke.py`, `scripts/eval_gemflow.pyscripts/comprehensive.py`, `scripts/temporal_edge_cases.py`, `scripts/natural_language_battery Live API/workflow regression
pyproject.toml`: `k-mcp` and package metadata
- `package.json`, `bin/`, `scripts/`: npx/npm wrapper
- `.claude-plugin/`, `.mcp.json`, `skills/`: Claude Code plugin configuration
- `render.yaml`, `Dockerfile`, `fly.toml.example`: Remote deployment examples
- `requirements.txt`: Execution dependencies
- `mcp_config.example.json`: MCP client configuration example
- `.env.example`: Environment variable example
-ifacts/source_docs/nabo_openapi/`: Locally stored NABO/OpenAPI Excel/PDF original reference materials. `artifacts/` is excluded from deployment and packages due to `.gitignore`.
MCP Config
Below is the configuration for this MCP Server. You can copy it directly to Cursor or other MCP clients.
mcp.json
Connection Info
You Might Also Like
No recommendations available