Skip to main content
Glama
dj-oyu

GSI Vector Tile MCP App

by dj-oyu
README.md
# GSI Vector Tile MCP App

国土地理院の地理院地図Vectorを表示するMCP App。ElysiaJS + Bun で構築。

チャット内にインタラクティブな地図UIが埋め込まれ、地理院タイルの閲覧・住所検索・タイル情報取得ができます。

## Quick Start

```bash
# bunx で直接起動(npm公開後)
bunx elysiajs-gsi-gov

# または clone して起動
git clone https://github.com/dj-oyu/elysiajs-gsi-gov.git
cd elysiajs-gsi-gov
bun install
bun run start
```

サーバーは `http://localhost:3001/mcp` でMCPエンドポイントを公開します。

## Usage

```bash
# UI をビルドしてサーバー起動
bun run start

# 開発モード(UI + サーバーのホットリロード)
bun run dev

# stdio モード(Claude Desktop / Claude Code から直接接続)
bun run serve:stdio

# ビルドのみ(UI + サーバーを dist/ にバンドル)
bun run build:all

# テスト実行
bun test
```

## Claude Desktop / Claude Code から使う

### Streamable HTTP(リモート接続)

```bash
# サーバーを起動
bun run start
```

Claude の Settings > Connectors > Add custom connector で `http://localhost:3001/mcp` を追加。

### stdio(直接接続)

`claude_desktop_config.json` に追加:

```json
{
  "mcpServers": {
    "gsi-map": {
      "command": "bun",
      "args": ["run", "serve:stdio"],
      "cwd": "/path/to/elysiajs-gsi-gov"
    }
  }
}
```

または、ビルド済みバイナリを使う場合:

```json
{
  "mcpServers": {
    "gsi-map": {
      "command": "bun",
      "args": ["/path/to/elysiajs-gsi-gov/dist/index.js", "--stdio"]
    }
  }
}
```

## MCP Tools

| Tool | Type | Description |
|------|------|-------------|
| `show-gsi-map` | App (UI付き) | 地理院地図をインタラクティブに表示。レイヤー切替・ズーム・パン操作が可能 |
| `search-location` | Text | GSI住所検索APIで日本国内の住所・地名を検索 |
| `get-tile-info` | Text | 緯度経度からタイル座標(z/x/y)と全レイヤーのURLを取得 |

### show-gsi-map のパラメータ

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `lat` | number | 35.6812 | 中心緯度 |
| `lon` | number | 139.7671 | 中心経度 |
| `zoom` | number | 13 | ズームレベル (2-18) |
| `layer` | string | "std" | `std` / `pale` / `seamlessphoto` / `optimal_bvmap` |
| `label` | string | - | 地図上に表示するラベル |

## GSI Tile Layers

| Key | Name | Format | Zoom |
|-----|------|--------|------|
| `std` | 標準地図 | PNG | 2-18 |
| `pale` | 淡色地図 | PNG | 2-18 |
| `seamlessphoto` | 全国最新写真 | JPG | 2-18 |
| `optimal_bvmap` | 最適化ベクトルタイル | PBF | 4-17 |
| `blank` | 白地図 | PNG | 2-14 |

タイルURL形式: `https://cyberjapandata.gsi.go.jp/xyz/{layer_id}/{z}/{x}/{y}.{format}`

## Architecture

```
├── index.ts           # ElysiaJS HTTP エントリポイント
├── server.ts          # MCP Server(ツール・リソース登録)
├── mcp-app.html       # 地図UI ソース
├── src/mcp-app.ts     # 地図UI ロジック(Leaflet + GSIタイル)
├── vite.config.ts     # Vite で UI を単一HTMLにバンドル
├── dist/
│   ├── index.js       # バンドル済みサーバー (bun build)
│   └── mcp-app.html   # バンドル済みUI (vite-plugin-singlefile)
├── server.test.ts     # ユニットテスト (19 tests)
└── index.test.ts      # インテグレーションテスト (7 tests)
```

### 処理の流れ

1. LLMが `show-gsi-map` ツールを呼び出す
2. サーバーがツール結果 + `ui://gsi-map/mcp-app.html` リソースを返す
3. ホスト(Claude等)がHTMLをsandboxed iframeで表示
4. UIはLeafletで地理院タイルを描画し、`App` クラスでホストと双方向通信
5. ユーザーが地図を操作すると `updateModelContext()` でLLMに現在地を通知

## Scripts

| Command | Description |
|---------|-------------|
| `bun run start` | UIビルド + サーバー起動 |
| `bun run dev` | 開発モード(ホットリロード) |
| `bun run build` | UIのみビルド(Vite → dist/mcp-app.html) |
| `bun run build:all` | UI + サーバーをバンドル(dist/) |
| `bun run serve` | サーバー起動(watchモード) |
| `bun run serve:stdio` | stdioモードで起動 |
| `bun test` | テスト実行(26 tests) |

## Tech Stack

- [Bun](https://bun.sh) - Runtime & package manager
- [ElysiaJS](https://elysiajs.com) - Web framework
- [MCP SDK](https://github.com/modelcontextprotocol/typescript-sdk) - Model Context Protocol
- [MCP Apps](https://github.com/modelcontextprotocol/ext-apps) - Interactive UI extension
- [Leaflet](https://leafletjs.com) - Map library
- [Vite](https://vite.dev) + [vite-plugin-singlefile](https://github.com/nicegoodthings/vite-plugin-singlefile) - UI bundler
- [国土地理院タイル](https://maps.gsi.go.jp/development/ichiran.html) - Map data source

## License

MIT