Skip to main content
Glama
README.md
# korea-mcp ๐Ÿ‡ฐ๐Ÿ‡ท

**English** ยท [ํ•œ๊ตญ์–ด](#ํ•œ๊ตญ์–ด)

**Let your AI agent get you around Korea.** Subway routes in English, fares, public holidays and practical tips, as an [MCP](https://modelcontextprotocol.io) server for Claude, Cursor, ChatGPT and any MCP client.

**No API key. No Korean phone number. Works offline.**

![korea-mcp answering subway routes from Myeongdong to Seongsu and from Gangnam to Gyeongbokgung](https://raw.githubusercontent.com/Leegwangwoon/korea-mcp/main/docs/demo.gif)

```
You:    How do I get from Myeongdong to Seongsu by subway?

Agent:  Take Line 4 from Myeongdong (๋ช…๋™) on the platform whose next stop is
        Chungmuro (์ถฉ๋ฌด๋กœ). Ride 2 stops to Dongdaemun History & Culture Park.
        Transfer to Line 2 towards Sindang (์‹ ๋‹น) and ride 6 stops to Seongsu (์„ฑ์ˆ˜).
        About 22 minutes, โ‚ฉ1,550 with a T-money card.
```

## Why Google Maps fails in Korea

If you have visited Korea, you know: **Google Maps can't give you walking or driving directions here**, and its transit results are often incomplete. Korea restricts exporting map data, so locals use Naver Map and KakaoMap instead.

That's fine for people, but bad for AI agents. Naver and Kakao **don't offer a public transit-routing API**, and their other APIs need a Korean developer account. So when you ask an AI "how do I get to Seongsu?", it guesses.

`korea-mcp` fixes the basics with **open data bundled in the package**:

- 660 stations on 25 lines across Seoul, Incheon and Gyeonggi, with names in English, Korean, Japanese and Chinese
- a route planner that knows transfers, platform direction and estimated time
- the official distance-based fare formula
- Korean public holidays, including substitute holidays
- short, practical guides on T-money, airport transfers, emergency numbers and the apps that work

## Install

**Claude Code**

```bash
claude mcp add korea -- npx -y korea-mcp
```

**Claude Desktop, one click.** Download [korea-mcp.mcpb](https://github.com/Leegwangwoon/korea-mcp/releases/latest/download/korea-mcp.mcpb) and open it. Claude Desktop installs it as an extension.

**Claude Desktop (manual), Cursor and other MCP clients.** Add this to your MCP config (`claude_desktop_config.json`, `.cursor/mcp.json`, โ€ฆ):

```json
{
  "mcpServers": {
    "korea": {
      "command": "npx",
      "args": ["-y", "korea-mcp"]
    }
  }
}
```

Requires Node.js 20+.

## Tools

| Tool | What it does |
|---|---|
| `subway_route` | Route between two stations: lines, transfers, the platform to use, stops, minutes and fare. Accepts English, ํ•œ๊ตญ์–ด, ๆ—ฅๆœฌ่ชž, ไธญๆ–‡ and landmarks ("Hongdae", "COEX", "Incheon Airport T1"). Tolerates typos. |
| `subway_station` | Look up and translate a station name. Returns every language, the lines that serve it and coordinates. |
| `korea_holidays` | Public holidays in a date range, or "is this date a holiday?". Includes substitute holidays and the 2026 additions (Labour Day, Constitution Day). |
| `korea_guide` | Practical guides: `transit-card`, `airport`, `emergency`, `apps`. |

**Things to ask**

- *"I land at Incheon T2 at 9pm. How do I get to my hotel near Hongdae?"*
- *"What's the fastest way from Gangnam to Gyeongbokgung, and how much is it?"*
- *"Is anything closed in Korea the week of September 24, 2026?"*
- *"How do I top up a T-money card?"*
- *"What does ์„์ง€๋กœ์ž…๊ตฌ mean in English, and which lines stop there?"*

## Accuracy

Here is what this server knows, and what it only estimates:

- **Station order and transfers** come from OpenStreetMap and are reliable.
- **Ride times are estimates.** They're based on distance, line speed and about 7 minutes per transfer, calibrated against published journey times. There is no live timetable.
- **Fares** use the official integrated distance formula for adults (โ‚ฉ1,550 base with a card, effective 2025-06-28). Lines with their own surcharges (Shinbundang, AREX, GTX-A) are flagged in the response, not added to the total.
- **Express trains** are off by default because express stopping patterns in OSM are incomplete. Turn them on with `allow_express`.

Found a wrong route? [Open an issue](../../issues) with the two stations. That's the most useful bug report there is.

## Roadmap

These are planned **optional** extras that need free API keys. Everything above keeps working without them.

- [ ] Real-time train arrivals (Seoul Open Data)
- [ ] Place search ("cafรฉs near Seongsu", "pharmacy open now") via the Kakao Local API
- [ ] Bus and door-to-door routing via ODsay
- [ ] A hosted remote server, so there is nothing to install
- [ ] Busan, Daegu, Daejeon and Gwangju metros
- [ ] Guides for longer stays: ARC, bank accounts, phone plans, health insurance

See [docs/api-keys.md](docs/api-keys.md) for how keys will work.

## Development

```bash
npm install
npm test              # route, fare and holiday tests
npm run dev           # run the server with tsx
npm run data:subway   # rebuild data/subway.json from OpenStreetMap
```

The subway dataset is generated by [`scripts/build-subway.mjs`](scripts/build-subway.mjs) from OpenStreetMap route relations. Line definitions and name overrides are in that script. The speed model is in [`src/subway/route.ts`](src/subway/route.ts).

Contributions in any language are welcome. Issues and PRs in Korean are fine too.

## Credits & related projects

These projects explored parts of this space first. Go give them a star:

- [naeryeo](https://github.com/GyeongHoKim/naeryeo): Korean transit routing CLI and MCP using ODsay
- [seoul-essentials](https://github.com/do-droid/seoul-essentials): public facilities for foreign visitors in Seoul
- [kakao-navigation-mcp-server](https://github.com/CaChiJ/kakao-navigation-mcp-server), [mcp-server-kakao-map](https://github.com/cgoinglove/mcp-server-kakao-map), and the Naver Maps MCP servers
- [awesome-mcp-korea](https://github.com/darjeeling/awesome-mcp-korea): a list of Korean MCP servers

## License

The code is [MIT](LICENSE). The subway data is ยฉ OpenStreetMap contributors, under [ODbL 1.0](DATA_LICENSE.md).

---

## ํ•œ๊ตญ์–ด

[English](#korea-mcp-) ยท **ํ•œ๊ตญ์–ด**

**์™ธ๊ตญ์ธ ์นœ๊ตฌ๊ฐ€ AIํ•œํ…Œ "๋ช…๋™์—์„œ ์„ฑ์ˆ˜ ์–ด๋–ป๊ฒŒ ๊ฐ€?"๋ผ๊ณ  ๋ฌผ์œผ๋ฉด, ์ œ๋Œ€๋กœ ๋œ ๋‹ต์ด ๋‚˜์˜ค๊ฒŒ ํ•˜๋Š” MCP ์„œ๋ฒ„์ž…๋‹ˆ๋‹ค.**

์ง€ํ•˜์ฒ  ๊ฒฝ๋กœ์™€ ์š”๊ธˆ, ๊ณตํœด์ผ, ์ƒํ™œ ์ •๋ณด๋ฅผ ์˜์–ดยทํ•œ๊ตญ์–ดยท์ผ๋ณธ์–ดยท์ค‘๊ตญ์–ด๋กœ ์•Œ๋ ค์ค๋‹ˆ๋‹ค. Claude, Cursor, ChatGPT ๋“ฑ MCP๋ฅผ ์ง€์›ํ•˜๋Š” ๋ชจ๋“  AI ์—์ด์ „ํŠธ์—์„œ ์“ธ ์ˆ˜ ์žˆ์–ด์š”.

**API ํ‚ค ์—†์ด, ํ•œ๊ตญ ํœด๋Œ€ํฐ ๋ฒˆํ˜ธ ์—†์ด, ์˜คํ”„๋ผ์ธ์—์„œ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค.**

### ์™œ ๋งŒ๋“ค์—ˆ๋‚˜

ํ•œ๊ตญ์—์„œ๋Š” ๊ตฌ๊ธ€ ์ง€๋„๋กœ ๋„๋ณดยท์ž๋™์ฐจ ๊ธธ์ฐพ๊ธฐ๋ฅผ ํ•  ์ˆ˜ ์—†๊ณ , ๋Œ€์ค‘๊ตํ†ต ์ •๋ณด๋„ ๋ถ€์ •ํ™•ํ•œ ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์Šต๋‹ˆ๋‹ค. ์ง€๋„ ๋ฐ์ดํ„ฐ์˜ ๊ตญ์™ธ ๋ฐ˜์ถœ ์ œํ•œ ๋•Œ๋ฌธ์ด์—์š”. ๊ทธ๋ž˜์„œ ํ•œ๊ตญ ์‚ฌ๋žŒ๋“ค์€ ๋„ค์ด๋ฒ„ ์ง€๋„์™€ ์นด์นด์˜ค๋งต์„ ์”๋‹ˆ๋‹ค.

๊ทธ๋Ÿฐ๋ฐ AI ์—์ด์ „ํŠธ์—๊ฒŒ๋Š” ์ด๊ฒŒ ๋ฌธ์ œ์ž…๋‹ˆ๋‹ค. ๋„ค์ด๋ฒ„์™€ ์นด์นด์˜ค๋Š” **๋Œ€์ค‘๊ตํ†ต ๊ธธ์ฐพ๊ธฐ API๋ฅผ ์™ธ๋ถ€์— ๊ณต๊ฐœํ•˜์ง€ ์•Š๊ณ **, ๋‹ค๋ฅธ API๋„ ํ•œ๊ตญ ๊ฐœ๋ฐœ์ž ๊ณ„์ •์ด ์žˆ์–ด์•ผ ์“ธ ์ˆ˜ ์žˆ์–ด์š”. ๊ฒฐ๊ตญ AI๊ฐ€ ๊ฒฝ๋กœ๋ฅผ ์ง€์–ด๋‚ด๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

`korea-mcp`๋Š” **๊ณต๊ฐœ ๋ฐ์ดํ„ฐ๋ฅผ ํŒจํ‚ค์ง€์— ๋‚ด์žฅํ•ด์„œ** ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•ฉ๋‹ˆ๋‹ค.

- ์ˆ˜๋„๊ถŒ(์„œ์šธยท์ธ์ฒœยท๊ฒฝ๊ธฐ) 25๊ฐœ ๋…ธ์„ , 660๊ฐœ ์—ญ๊ณผ 4๊ฐœ ๊ตญ์–ด ์—ญ๋ช…
- ํ™˜์Šน, ํƒˆ ์Šน๊ฐ•์žฅ ๋ฐฉํ–ฅ, ์˜ˆ์ƒ ์†Œ์š” ์‹œ๊ฐ„์„ ์•Œ๋ ค์ฃผ๋Š” ๊ฒฝ๋กœ ํƒ์ƒ‰
- ๊ณต์‹ ๊ฑฐ๋ฆฌ๋น„๋ก€ ์š”๊ธˆ ๊ณ„์‚ฐ
- ๋Œ€์ฒด๊ณตํœด์ผ๊นŒ์ง€ ํฌํ•จํ•œ ํ•œ๊ตญ ๊ณตํœด์ผ
- ํ‹ฐ๋จธ๋‹ˆ, ๊ณตํ•ญ ์ด๋™, ๊ธด๊ธ‰์ „ํ™”, ํ•œ๊ตญ์—์„œ ์“ธ ๋งŒํ•œ ์•ฑ ์•ˆ๋‚ด

### ์„ค์น˜

**Claude Code**

```bash
claude mcp add korea -- npx -y korea-mcp
```

**Claude Desktop ์›ํด๋ฆญ ์„ค์น˜.** [korea-mcp.mcpb](https://github.com/Leegwangwoon/korea-mcp/releases/latest/download/korea-mcp.mcpb)๋ฅผ ๋‚ด๋ ค๋ฐ›์•„ ์—ด๋ฉด Claude Desktop์— ํ™•์žฅ ํ”„๋กœ๊ทธ๋žจ์œผ๋กœ ์„ค์น˜๋ฉ๋‹ˆ๋‹ค.

**Claude Desktop(์ง์ ‘ ์„ค์ •), Cursor ๋“ฑ.** MCP ์„ค์ • ํŒŒ์ผ์— ์•„๋ž˜ ๋‚ด์šฉ์„ ์ถ”๊ฐ€ํ•˜์„ธ์š”.

```json
{
  "mcpServers": {
    "korea": {
      "command": "npx",
      "args": ["-y", "korea-mcp"]
    }
  }
}
```

Node.js 20 ์ด์ƒ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

### ๋„๊ตฌ

| ๋„๊ตฌ | ๊ธฐ๋Šฅ |
|---|---|
| `subway_route` | ๋‘ ์—ญ ์‚ฌ์ด ๊ฒฝ๋กœ: ๋…ธ์„ , ํ™˜์Šน์—ญ, ํƒˆ ์Šน๊ฐ•์žฅ, ์ •๊ฑฐ์žฅ ์ˆ˜, ์˜ˆ์ƒ ์‹œ๊ฐ„, ์š”๊ธˆ. ์˜์–ดยทํ•œ๊ตญ์–ดยท์ผ๋ณธ์–ดยท์ค‘๊ตญ์–ด ์—ญ๋ช…๊ณผ ๋žœ๋“œ๋งˆํฌ("Hongdae", "COEX")๋ฅผ ์•Œ์•„๋“ฃ๊ณ , ์˜คํƒ€๋„ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค. |
| `subway_station` | ์—ญ ๊ฒ€์ƒ‰๊ณผ ์—ญ๋ช… ๋ฒˆ์—ญ. ์–ธ์–ด๋ณ„ ์ด๋ฆ„, ์ง€๋‚˜๋Š” ๋…ธ์„ , ์ขŒํ‘œ๋ฅผ ์•Œ๋ ค์ค๋‹ˆ๋‹ค. |
| `korea_holidays` | ๊ธฐ๊ฐ„ ๋‚ด ๊ณตํœด์ผ ์กฐํšŒ, ํŠน์ • ๋‚ ์งœ๊ฐ€ ๊ณตํœด์ผ์ธ์ง€ ํ™•์ธ. ๋Œ€์ฒด๊ณตํœด์ผ๊ณผ 2026๋…„์— ์ƒˆ๋กœ ์ƒ๊ธด ๋…ธ๋™์ ˆยท์ œํ—Œ์ ˆ๋„ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค. |
| `korea_guide` | ์ƒํ™œ ๊ฐ€์ด๋“œ: `transit-card`(๊ตํ†ต์นด๋“œ), `airport`(๊ณตํ•ญ), `emergency`(๊ธด๊ธ‰์ „ํ™”), `apps`(์•ฑ) |

### ์ •ํ™•๋„

- **์—ญ ์ˆœ์„œ์™€ ํ™˜์Šน ์ •๋ณด**๋Š” OpenStreetMap ๊ธฐ๋ฐ˜์ด๋ผ ์‹ ๋ขฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
- **์†Œ์š” ์‹œ๊ฐ„์€ ์ถ”์ •์น˜์ž…๋‹ˆ๋‹ค.** ์—ญ ๊ฐ„ ๊ฑฐ๋ฆฌ, ๋…ธ์„ ๋ณ„ ์†๋„, ํ™˜์Šน ์•ฝ 7๋ถ„์œผ๋กœ ๊ณ„์‚ฐํ•˜๊ณ  ๊ณต๊ฐœ๋œ ์†Œ์š” ์‹œ๊ฐ„์— ๋งž์ถฐ ๋ณด์ •ํ–ˆ์–ด์š”. ์‹ค์‹œ๊ฐ„ ์‹œ๊ฐ„ํ‘œ๋Š” ์•„๋‹™๋‹ˆ๋‹ค.
- **์š”๊ธˆ**์€ 2025๋…„ 6์›” 28์ผ๋ถ€ํ„ฐ ์ ์šฉ๋œ ์ˆ˜๋„๊ถŒ ํ†ตํ•ฉ ๊ฑฐ๋ฆฌ๋น„๋ก€์ œ(๊ตํ†ต์นด๋“œ ์„ฑ์ธ ๊ธฐ๋ณธ 1,550์›)๋ฅผ ๋”ฐ๋ฆ…๋‹ˆ๋‹ค. ์‹ ๋ถ„๋‹น์„ , ๊ณตํ•ญ์ฒ ๋„, GTX-A์ฒ˜๋Ÿผ ๋ณ„๋„ ์š”๊ธˆ์ด ๋ถ™๋Š” ๋…ธ์„ ์€ ์‘๋‹ต์— ์•ˆ๋‚ด๋งŒ ํ•˜๊ณ  ํ•ฉ๊ณ„์—๋Š” ๋„ฃ์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
- **๊ธ‰ํ–‰์€ ๊ธฐ๋ณธ์œผ๋กœ ๊บผ์ ธ ์žˆ์Šต๋‹ˆ๋‹ค.** OSM์˜ ๊ธ‰ํ–‰ ์ •์ฐจ ์ •๋ณด๊ฐ€ ๋ถˆ์™„์ „ํ•˜๊ธฐ ๋•Œ๋ฌธ์ด์—์š”. ์“ฐ๋ ค๋ฉด `allow_express` ์˜ต์…˜์„ ์ผœ์„ธ์š”.

ํ‹€๋ฆฐ ๊ฒฝ๋กœ๋ฅผ ๋ฐœ๊ฒฌํ•˜๋ฉด ์ถœ๋ฐœ์—ญ๊ณผ ๋„์ฐฉ์—ญ์„ ์ ์–ด์„œ [์ด์Šˆ](../../issues)๋กœ ์•Œ๋ ค์ฃผ์„ธ์š”. ๊ฐ€์žฅ ๋„์›€์ด ๋˜๋Š” ์ œ๋ณด์ž…๋‹ˆ๋‹ค.

### ๋กœ๋“œ๋งต

์•„๋ž˜ ๊ธฐ๋Šฅ์€ ๋ฌด๋ฃŒ API ํ‚ค๊ฐ€ ์žˆ์œผ๋ฉด ์“ธ ์ˆ˜ ์žˆ๋Š” **์„ ํƒ ๊ธฐ๋Šฅ**์œผ๋กœ ์ถ”๊ฐ€ํ•  ์˜ˆ์ •์ž…๋‹ˆ๋‹ค. ํ‚ค๊ฐ€ ์—†์–ด๋„ ๊ธฐ์กด ๊ธฐ๋Šฅ์€ ๊ทธ๋Œ€๋กœ ๋™์ž‘ํ•ด์š”.

- [ ] ์‹ค์‹œ๊ฐ„ ์ง€ํ•˜์ฒ  ๋„์ฐฉ ์ •๋ณด (์„œ์šธ ์—ด๋ฆฐ๋ฐ์ดํ„ฐ๊ด‘์žฅ)
- [ ] ์žฅ์†Œ ๊ฒ€์ƒ‰ ("์„ฑ์ˆ˜ ๊ทผ์ฒ˜ ์นดํŽ˜", "์ง€๊ธˆ ๋ฌธ ์—ฐ ์•ฝ๊ตญ"), ์นด์นด์˜ค ๋กœ์ปฌ API ์‚ฌ์šฉ
- [ ] ๋ฒ„์Šค๋ฅผ ํฌํ•จํ•œ ์ถœ๋ฐœ์ง€โ†’๋„์ฐฉ์ง€ ๊ฒฝ๋กœ (ODsay)
- [ ] ์„ค์น˜ ์—†์ด ์“ฐ๋Š” ์›๊ฒฉ ์„œ๋ฒ„
- [ ] ๋ถ€์‚ฐยท๋Œ€๊ตฌยท๋Œ€์ „ยท๊ด‘์ฃผ ๋„์‹œ์ฒ ๋„
- [ ] ์žฅ๊ธฐ ์ฒด๋ฅ˜์ž์šฉ ๊ฐ€์ด๋“œ: ์™ธ๊ตญ์ธ๋“ฑ๋ก์ฆ, ์€ํ–‰ ๊ณ„์ขŒ, ํœด๋Œ€ํฐ ๊ฐœํ†ต, ๊ฑด๊ฐ•๋ณดํ—˜

ํ‚ค ์‚ฌ์šฉ ๋ฐฉ์‹์€ [docs/api-keys.md](docs/api-keys.md)๋ฅผ ์ฐธ๊ณ ํ•˜์„ธ์š”.

### ๊ฐœ๋ฐœ

```bash
npm install
npm test              # ๊ฒฝ๋กœยท์š”๊ธˆยท๊ณตํœด์ผ ํ…Œ์ŠคํŠธ
npm run dev           # tsx๋กœ ์„œ๋ฒ„ ์‹คํ–‰
npm run data:subway   # OpenStreetMap์—์„œ data/subway.json ๋‹ค์‹œ ์ƒ์„ฑ
```

์ด์Šˆ์™€ PR์€ ํ•œ๊ตญ์–ด๋กœ ๋‚จ๊ธฐ์…”๋„ ๋ฉ๋‹ˆ๋‹ค. ์˜์–ด ์—ญ๋ช… ์˜ค๋ฅ˜, ๋น ์ง„ ๋…ธ์„ , ๊ฐ€์ด๋“œ ๋‚ด์šฉ ๋ณด์™„ ๊ฐ™์€ ๊ธฐ์—ฌ๋ฅผ ํŠนํžˆ ํ™˜์˜ํ•ด์š”.

### ์ฐธ๊ณ  ํ”„๋กœ์ ํŠธ

์ด ๋ถ„์•ผ๋ฅผ ๋จผ์ € ๋‹ค๋ฃฌ ํ”„๋กœ์ ํŠธ๋“ค์ž…๋‹ˆ๋‹ค. ์œ„์˜ [Credits](#credits--related-projects) ๋ชฉ๋ก์„ ์ฐธ๊ณ ํ•˜์„ธ์š”.

### ๋ผ์ด์„ ์Šค

์ฝ”๋“œ๋Š” [MIT](LICENSE), ์ง€ํ•˜์ฒ  ๋ฐ์ดํ„ฐ๋Š” ยฉ OpenStreetMap contributors์ด๋ฉฐ [ODbL 1.0](DATA_LICENSE.md)์„ ๋”ฐ๋ฆ…๋‹ˆ๋‹ค.

TDQS

A4.1/5.0

Scored across 4 tools

Disambiguation5/5

Each tool targets a clearly distinct purpose: subway_route plans a trip, subway_station retrieves station metadata, korea_holidays handles public holiday queries, and korea_guide provides topical guides. There is no overlap in intent, so an agent can easily select the right tool.

Naming Consistency5/5

All tool names follow a consistent snake_case pattern with a domain prefix and a noun (subway_route, subway_station, korea_holidays, korea_guide). The convention is predictable and readable throughout.

Tool Count5/5

Four tools fall comfortably within the ideal 3โ€“15 range, and each earns its place by covering a distinct aspect of the Korea travel domain. The set is focused without feeling thin or bloated.

Completeness4/5

The surface covers core subway navigation, station lookup, holidays, and practical guide topics, which handles many visitor needs. However, broader Korea coverage (e.g., buses, intercity rail, weather) is absent, leaving minor gaps that agents may need to work around.

Maintenance

ActivityMaintained
ResponsivenessNo issues