norikae-mcp 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +264 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +137 -0
- package/dist/index.js.map +1 -0
- package/dist/index.test.d.ts +6 -0
- package/dist/index.test.d.ts.map +1 -0
- package/dist/index.test.js +126 -0
- package/dist/index.test.js.map +1 -0
- package/dist/test.d.ts +7 -0
- package/dist/test.d.ts.map +1 -0
- package/dist/test.js +149 -0
- package/dist/test.js.map +1 -0
- package/package.json +48 -0
package/README.md
ADDED
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
# 乗換案内MCP 🚃 / Norikae MCP
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/norikae-mcp)
|
|
4
|
+
[](https://opensource.org/licenses/MIT)
|
|
5
|
+
|
|
6
|
+
日本の電車乗り換え検索ができるMCP(Model Context Protocol)サーバーです。
|
|
7
|
+
Yahoo!乗換案内のデータを使用して、駅から駅への最適なルートを検索できます。
|
|
8
|
+
|
|
9
|
+
*An MCP (Model Context Protocol) server for searching train routes in Japan.
|
|
10
|
+
Uses Yahoo! Transit data to find optimal routes between stations.*
|
|
11
|
+
|
|
12
|
+
## 機能 / Features
|
|
13
|
+
|
|
14
|
+
- 🚉 駅から駅への乗り換えルート検索 / Station-to-station route search
|
|
15
|
+
- ⏰ 指定時刻での検索(出発・到着時刻指定)/ Departure or arrival time specification
|
|
16
|
+
- 💰 IC運賃の表示 / IC card fare display
|
|
17
|
+
- 🔄 乗り換え回数・所要時間の比較 / Transfer count and travel time comparison
|
|
18
|
+
|
|
19
|
+
## 必要条件 / Requirements
|
|
20
|
+
|
|
21
|
+
- Node.js 18以上 / Node.js 18+
|
|
22
|
+
|
|
23
|
+
## インストール / Installation
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
npm install -g norikae-mcp
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
または、npxで直接実行 / Or run directly with npx:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
npx norikae-mcp
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## 設定 / Configuration
|
|
36
|
+
|
|
37
|
+
### Claude Desktop での設定 / Claude Desktop Configuration
|
|
38
|
+
|
|
39
|
+
設定ファイルを開いて以下を追加してください:
|
|
40
|
+
|
|
41
|
+
*Open the config file and add the following:*
|
|
42
|
+
|
|
43
|
+
**macOS:** `~/Library/Application Support/Claude/claude_desktop_config.json`
|
|
44
|
+
|
|
45
|
+
**Windows:** `%APPDATA%\Claude\claude_desktop_config.json`
|
|
46
|
+
|
|
47
|
+
```json
|
|
48
|
+
{
|
|
49
|
+
"mcpServers": {
|
|
50
|
+
"norikae": {
|
|
51
|
+
"command": "npx",
|
|
52
|
+
"args": ["-y", "norikae-mcp"]
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
設定後、Claude Desktopを再起動してください。
|
|
59
|
+
|
|
60
|
+
*After saving, restart Claude Desktop.*
|
|
61
|
+
|
|
62
|
+
### Cursor での設定 / Cursor Configuration
|
|
63
|
+
|
|
64
|
+
`~/.cursor/mcp.json` または プロジェクトの `.cursor/mcp.json` に以下を追加:
|
|
65
|
+
|
|
66
|
+
*Add the following to `~/.cursor/mcp.json` or your project's `.cursor/mcp.json`:*
|
|
67
|
+
|
|
68
|
+
```json
|
|
69
|
+
{
|
|
70
|
+
"mcpServers": {
|
|
71
|
+
"norikae": {
|
|
72
|
+
"command": "npx",
|
|
73
|
+
"args": ["-y", "norikae-mcp"]
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## 使用できるツール / Available Tools
|
|
80
|
+
|
|
81
|
+
### `search_route`
|
|
82
|
+
|
|
83
|
+
駅から駅への電車ルートを検索します。
|
|
84
|
+
|
|
85
|
+
*Search for train routes between stations.*
|
|
86
|
+
|
|
87
|
+
**パラメータ / Parameters:**
|
|
88
|
+
|
|
89
|
+
| パラメータ | 型 | 必須 | 説明 / Description |
|
|
90
|
+
|-----------|------|------|---------------------|
|
|
91
|
+
| `from` | string | ✅ | 出発駅名 / Departure station (e.g., 東京, 新宿) |
|
|
92
|
+
| `to` | string | ✅ | 到着駅名 / Arrival station (e.g., 九段下, 横浜) |
|
|
93
|
+
| `year` | number | - | 出発年 / Year (default: current) |
|
|
94
|
+
| `month` | number | - | 出発月 / Month (default: current) |
|
|
95
|
+
| `day` | number | - | 出発日 / Day (default: current) |
|
|
96
|
+
| `hour` | number | - | 時 / Hour (default: current) |
|
|
97
|
+
| `minute` | number | - | 分 / Minute (default: current) |
|
|
98
|
+
|
|
99
|
+
**検索オプション / Search Options:**
|
|
100
|
+
|
|
101
|
+
| パラメータ | 型 | デフォルト | 説明 / Description |
|
|
102
|
+
|-----------|------|----------|---------------------|
|
|
103
|
+
| `timeType` | `departure` \| `arrival` | `departure` | 時刻指定タイプ / Time type |
|
|
104
|
+
| `ticket` | `ic` \| `cash` | `ic` | 運賃タイプ / Fare type |
|
|
105
|
+
| `walkSpeed` | `fast` \| `slightly_fast` \| `slightly_slow` \| `slow` | `slightly_slow` | 歩く速度 / Walking speed |
|
|
106
|
+
| `sortBy` | `time` \| `transfer` \| `fare` | `time` | 並び順 / Sort order |
|
|
107
|
+
|
|
108
|
+
**交通手段オプション / Transport Options:**
|
|
109
|
+
|
|
110
|
+
| パラメータ | 型 | デフォルト | 説明 / Description |
|
|
111
|
+
|-----------|------|----------|---------------------|
|
|
112
|
+
| `useAirline` | boolean | `true` | 空路を使う / Use airlines |
|
|
113
|
+
| `useShinkansen` | boolean | `true` | 新幹線を使う / Use Shinkansen |
|
|
114
|
+
| `useExpress` | boolean | `true` | 有料特急を使う / Use express trains |
|
|
115
|
+
| `useHighwayBus` | boolean | `true` | 高速バスを使う / Use highway buses |
|
|
116
|
+
| `useLocalBus` | boolean | `true` | 路線バスを使う / Use local buses |
|
|
117
|
+
| `useFerry` | boolean | `true` | フェリーを使う / Use ferries |
|
|
118
|
+
|
|
119
|
+
## 使用例(自然言語 → オプション)/ Usage Examples (Natural Language → Options)
|
|
120
|
+
|
|
121
|
+
AIに以下のように話しかけると、自動的に適切なオプションが設定されます。
|
|
122
|
+
|
|
123
|
+
*When you ask the AI in natural language, the appropriate options are automatically set.*
|
|
124
|
+
|
|
125
|
+
### 基本的な検索 / Basic Search
|
|
126
|
+
|
|
127
|
+
| あなたの質問 / Your Question | 認識されるオプション / Recognized Options |
|
|
128
|
+
|------------------------------|------------------------------------------|
|
|
129
|
+
| 「東京から九段下まで」 | `from: 東京`, `to: 九段下` |
|
|
130
|
+
| 「新宿から横浜への行き方」 | `from: 新宿`, `to: 横浜` |
|
|
131
|
+
| "How to get from Tokyo to Shibuya" | `from: 東京`, `to: 渋谷` |
|
|
132
|
+
| "Route from Shinjuku to Yokohama" | `from: 新宿`, `to: 横浜` |
|
|
133
|
+
|
|
134
|
+
### 時刻指定 / Time Specification
|
|
135
|
+
|
|
136
|
+
| あなたの質問 / Your Question | 認識されるオプション / Recognized Options |
|
|
137
|
+
|------------------------------|------------------------------------------|
|
|
138
|
+
| 「10時30分に出発」 | `hour: 10`, `minute: 30` |
|
|
139
|
+
| 「朝8時の電車」 | `hour: 8` |
|
|
140
|
+
| 「明日の朝9時」 | `day: (tomorrow)`, `hour: 9` |
|
|
141
|
+
| "Departing at 10:30 AM" | `hour: 10`, `minute: 30` |
|
|
142
|
+
| "Train at 8 in the morning" | `hour: 8` |
|
|
143
|
+
|
|
144
|
+
### 到着時刻指定 / Arrival Time (timeType)
|
|
145
|
+
|
|
146
|
+
| あなたの質問 / Your Question | 認識されるオプション / Recognized Options |
|
|
147
|
+
|------------------------------|------------------------------------------|
|
|
148
|
+
| 「18時に着きたい」 | `timeType: arrival`, `hour: 18` |
|
|
149
|
+
| 「9時の会議に間に合うように」 | `timeType: arrival`, `hour: 9` |
|
|
150
|
+
| "I want to arrive by 6 PM" | `timeType: arrival`, `hour: 18` |
|
|
151
|
+
| "Need to be there for a 9 AM meeting" | `timeType: arrival`, `hour: 9` |
|
|
152
|
+
|
|
153
|
+
### 運賃タイプ / Fare Type (ticket)
|
|
154
|
+
|
|
155
|
+
| あなたの質問 / Your Question | 認識されるオプション / Recognized Options |
|
|
156
|
+
|------------------------------|------------------------------------------|
|
|
157
|
+
| 「IC運賃で」 | `ticket: ic` (default) |
|
|
158
|
+
| 「きっぷの値段で」 | `ticket: cash` |
|
|
159
|
+
| 「Suicaで」 | `ticket: ic` |
|
|
160
|
+
| "Using IC card" | `ticket: ic` |
|
|
161
|
+
| "Cash fare please" | `ticket: cash` |
|
|
162
|
+
|
|
163
|
+
### 歩く速度 / Walking Speed (walkSpeed)
|
|
164
|
+
|
|
165
|
+
| あなたの質問 / Your Question | 認識されるオプション / Recognized Options |
|
|
166
|
+
|------------------------------|------------------------------------------|
|
|
167
|
+
| 「急いでるので早歩きで」 | `walkSpeed: fast` |
|
|
168
|
+
| 「ゆっくり歩きたい」 | `walkSpeed: slow` |
|
|
169
|
+
| 「足が悪いのでゆっくり」 | `walkSpeed: slow` |
|
|
170
|
+
| "I'm in a hurry, fast walking" | `walkSpeed: fast` |
|
|
171
|
+
| "Walking slowly, I have luggage" | `walkSpeed: slow` |
|
|
172
|
+
|
|
173
|
+
### 並び順 / Sort Order (sortBy)
|
|
174
|
+
|
|
175
|
+
| あなたの質問 / Your Question | 認識されるオプション / Recognized Options |
|
|
176
|
+
|------------------------------|------------------------------------------|
|
|
177
|
+
| 「一番早いルート」 | `sortBy: time` (default) |
|
|
178
|
+
| 「一番安いルート」 | `sortBy: fare` |
|
|
179
|
+
| 「乗り換え少ないのがいい」 | `sortBy: transfer` |
|
|
180
|
+
| "Fastest route" | `sortBy: time` |
|
|
181
|
+
| "Cheapest route" | `sortBy: fare` |
|
|
182
|
+
| "Fewest transfers" | `sortBy: transfer` |
|
|
183
|
+
|
|
184
|
+
### 交通手段の除外 / Excluding Transport Types
|
|
185
|
+
|
|
186
|
+
| あなたの質問 / Your Question | 認識されるオプション / Recognized Options |
|
|
187
|
+
|------------------------------|------------------------------------------|
|
|
188
|
+
| 「新幹線を使わないで」 | `useShinkansen: false` |
|
|
189
|
+
| 「在来線だけで」 | `useShinkansen: false`, `useExpress: false` |
|
|
190
|
+
| 「バスは乗りたくない」 | `useHighwayBus: false`, `useLocalBus: false` |
|
|
191
|
+
| "Without Shinkansen" | `useShinkansen: false` |
|
|
192
|
+
| "Local trains only" | `useShinkansen: false`, `useExpress: false` |
|
|
193
|
+
| "No buses please" | `useHighwayBus: false`, `useLocalBus: false` |
|
|
194
|
+
|
|
195
|
+
### 組み合わせ例 / Combined Examples
|
|
196
|
+
|
|
197
|
+
**例1 / Example 1: 出張で節約したい / Budget business trip**
|
|
198
|
+
```
|
|
199
|
+
「明日の朝10時までに東京から大阪に着きたい、新幹線なしで、一番安いルートで」
|
|
200
|
+
"I need to arrive in Osaka from Tokyo by 10 AM tomorrow, without Shinkansen, cheapest route"
|
|
201
|
+
```
|
|
202
|
+
→ `from: 東京`, `to: 大阪`, `timeType: arrival`, `hour: 10`, `useShinkansen: false`, `sortBy: fare`
|
|
203
|
+
|
|
204
|
+
**例2 / Example 2: 観光でゆっくり / Leisurely sightseeing**
|
|
205
|
+
```
|
|
206
|
+
「京都から奈良まで、ゆっくり歩きで」
|
|
207
|
+
"From Kyoto to Nara, walking slowly"
|
|
208
|
+
```
|
|
209
|
+
→ `from: 京都`, `to: 奈良`, `walkSpeed: slow`
|
|
210
|
+
|
|
211
|
+
**例3 / Example 3: 急いでいる / In a hurry**
|
|
212
|
+
```
|
|
213
|
+
「今すぐ渋谷から羽田空港、最速で、早歩きで」
|
|
214
|
+
"Right now from Shibuya to Haneda Airport, fastest route, fast walking"
|
|
215
|
+
```
|
|
216
|
+
→ `from: 渋谷`, `to: 羽田空港`, `sortBy: time`, `walkSpeed: fast`
|
|
217
|
+
|
|
218
|
+
**例4 / Example 4: 複雑な条件 / Complex conditions**
|
|
219
|
+
```
|
|
220
|
+
「来週の金曜日、18時に品川に着くように新宿から、新幹線と飛行機は使わないで、乗り換え少ない順で」
|
|
221
|
+
"Next Friday, arriving at Shinagawa by 6 PM from Shinjuku, no Shinkansen or planes, fewest transfers"
|
|
222
|
+
```
|
|
223
|
+
→ `from: 新宿`, `to: 品川`, `timeType: arrival`, `hour: 18`, `useShinkansen: false`, `useAirline: false`, `sortBy: transfer`
|
|
224
|
+
|
|
225
|
+
## 開発 / Development
|
|
226
|
+
|
|
227
|
+
```bash
|
|
228
|
+
# リポジトリをクローン / Clone the repository
|
|
229
|
+
git clone https://github.com/YOUR_USERNAME/norikae-mcp.git
|
|
230
|
+
cd norikae-mcp
|
|
231
|
+
|
|
232
|
+
# 依存関係のインストール / Install dependencies
|
|
233
|
+
npm install
|
|
234
|
+
|
|
235
|
+
# ビルド / Build
|
|
236
|
+
npm run build
|
|
237
|
+
|
|
238
|
+
# 開発モード / Development mode (watch)
|
|
239
|
+
npm run dev
|
|
240
|
+
|
|
241
|
+
# テスト実行 / Run tests
|
|
242
|
+
npm test
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
## 技術詳細 / Technical Details
|
|
246
|
+
|
|
247
|
+
- MCP SDK: `@modelcontextprotocol/sdk`
|
|
248
|
+
- データソース / Data source: Yahoo!乗換案内 (transit.yahoo.co.jp)
|
|
249
|
+
- ランタイム / Runtime: Node.js 18+
|
|
250
|
+
|
|
251
|
+
## 注意事項 / Notes
|
|
252
|
+
|
|
253
|
+
- このMCPはYahoo!乗換案内のWebページをスクレイピングしています
|
|
254
|
+
*This MCP scrapes Yahoo! Transit web pages*
|
|
255
|
+
- 個人利用を想定しています
|
|
256
|
+
*Intended for personal use*
|
|
257
|
+
- Yahoo! JAPANの利用規約をご確認ください
|
|
258
|
+
*Please check Yahoo! JAPAN's terms of service*
|
|
259
|
+
- リアルタイムの遅延情報は含まれない場合があります
|
|
260
|
+
*Real-time delay information may not be included*
|
|
261
|
+
|
|
262
|
+
## ライセンス / License
|
|
263
|
+
|
|
264
|
+
MIT
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
3
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
const server = new McpServer({
|
|
6
|
+
name: 'norikae-mcp',
|
|
7
|
+
version: '0.1.0',
|
|
8
|
+
});
|
|
9
|
+
// input schema for search_route
|
|
10
|
+
const searchRouteSchema = {
|
|
11
|
+
from: z.string().describe('出発駅名(例:東京、新宿、渋谷)'),
|
|
12
|
+
to: z.string().describe('到着駅名(例:九段下、横浜、品川)'),
|
|
13
|
+
year: z.number().optional().describe('出発年(例:2026)'),
|
|
14
|
+
month: z.number().optional().describe('出発月(1-12)'),
|
|
15
|
+
day: z.number().optional().describe('出発日(1-31)'),
|
|
16
|
+
hour: z.number().optional().describe('出発時刻の時(0-23)'),
|
|
17
|
+
minute: z.number().optional().describe('出発時刻の分(0-59)'),
|
|
18
|
+
timeType: z.enum(['departure', 'arrival']).optional().describe('時刻指定タイプ:departure=出発時刻、arrival=到着時刻'),
|
|
19
|
+
ticket: z.enum(['ic', 'cash']).optional().describe('運賃タイプ:ic=IC運賃、cash=きっぷ運賃'),
|
|
20
|
+
walkSpeed: z.enum(['fast', 'slightly_fast', 'slightly_slow', 'slow']).optional().describe('歩く速度'),
|
|
21
|
+
sortBy: z.enum(['time', 'transfer', 'fare']).optional().describe('並び順:time=到着が早い順、transfer=乗換回数順、fare=料金安い順'),
|
|
22
|
+
useAirline: z.boolean().optional().describe('空路を使う'),
|
|
23
|
+
useShinkansen: z.boolean().optional().describe('新幹線を使う'),
|
|
24
|
+
useExpress: z.boolean().optional().describe('有料特急を使う'),
|
|
25
|
+
useHighwayBus: z.boolean().optional().describe('高速バスを使う'),
|
|
26
|
+
useLocalBus: z.boolean().optional().describe('路線バスを使う'),
|
|
27
|
+
useFerry: z.boolean().optional().describe('フェリーを使う'),
|
|
28
|
+
};
|
|
29
|
+
// register search_route tool
|
|
30
|
+
server.registerTool('search_route', {
|
|
31
|
+
title: '乗り換え検索',
|
|
32
|
+
description: '駅から駅への電車ルートを検索します(Yahoo!乗換案内使用)',
|
|
33
|
+
inputSchema: searchRouteSchema,
|
|
34
|
+
annotations: {
|
|
35
|
+
readOnlyHint: true, // data is only read, not modified
|
|
36
|
+
openWorldHint: true, // interacts with external service (Yahoo)
|
|
37
|
+
},
|
|
38
|
+
}, async (args) => {
|
|
39
|
+
const { from, to, year, month, day, hour, minute, timeType, ticket, walkSpeed, sortBy, useAirline, useShinkansen, useExpress, useHighwayBus, useLocalBus, useFerry, } = args;
|
|
40
|
+
// default to current time if not specified
|
|
41
|
+
const now = new Date();
|
|
42
|
+
const y = year ?? now.getFullYear();
|
|
43
|
+
const m = month ?? now.getMonth() + 1;
|
|
44
|
+
const d = day ?? now.getDate();
|
|
45
|
+
const hh = hour ?? now.getHours();
|
|
46
|
+
const mm = minute ?? now.getMinutes();
|
|
47
|
+
const options = {
|
|
48
|
+
timeType: timeType ?? 'departure',
|
|
49
|
+
ticket: ticket ?? 'ic',
|
|
50
|
+
walkSpeed: walkSpeed ?? 'slightly_slow',
|
|
51
|
+
sortBy: sortBy ?? 'time',
|
|
52
|
+
useAirline: useAirline ?? true,
|
|
53
|
+
useShinkansen: useShinkansen ?? true,
|
|
54
|
+
useExpress: useExpress ?? true,
|
|
55
|
+
useHighwayBus: useHighwayBus ?? true,
|
|
56
|
+
useLocalBus: useLocalBus ?? true,
|
|
57
|
+
useFerry: useFerry ?? true,
|
|
58
|
+
};
|
|
59
|
+
const url = buildYahooTransitUrl(from, to, y, m, d, hh, mm, options);
|
|
60
|
+
try {
|
|
61
|
+
const response = await fetch(url);
|
|
62
|
+
const html = await response.text();
|
|
63
|
+
const content = extractMainContent(html);
|
|
64
|
+
return {
|
|
65
|
+
content: [{ type: 'text', text: content }],
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
catch (error) {
|
|
69
|
+
return {
|
|
70
|
+
content: [{ type: 'text', text: `エラーが発生しました: ${error}` }],
|
|
71
|
+
isError: true,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
function buildYahooTransitUrl(from, to, year, month, day, hour, minute, options) {
|
|
76
|
+
// map options to Yahoo URL parameters
|
|
77
|
+
const timeTypeMap = { departure: '1', arrival: '2' };
|
|
78
|
+
const walkSpeedMap = { fast: '1', slightly_fast: '2', slightly_slow: '3', slow: '4' };
|
|
79
|
+
const sortByMap = { time: '0', transfer: '1', fare: '2' };
|
|
80
|
+
const params = new URLSearchParams({
|
|
81
|
+
from: from,
|
|
82
|
+
to: to,
|
|
83
|
+
y: year.toString(),
|
|
84
|
+
m: month.toString().padStart(2, '0'),
|
|
85
|
+
d: day.toString().padStart(2, '0'),
|
|
86
|
+
hh: hour.toString(),
|
|
87
|
+
m1: Math.floor(minute / 10).toString(),
|
|
88
|
+
m2: (minute % 10).toString(),
|
|
89
|
+
type: timeTypeMap[options.timeType],
|
|
90
|
+
ticket: options.ticket,
|
|
91
|
+
expkind: '1',
|
|
92
|
+
ws: walkSpeedMap[options.walkSpeed],
|
|
93
|
+
s: sortByMap[options.sortBy],
|
|
94
|
+
al: options.useAirline ? '1' : '0',
|
|
95
|
+
shin: options.useShinkansen ? '1' : '0',
|
|
96
|
+
ex: options.useExpress ? '1' : '0',
|
|
97
|
+
hb: options.useHighwayBus ? '1' : '0',
|
|
98
|
+
lb: options.useLocalBus ? '1' : '0',
|
|
99
|
+
sr: options.useFerry ? '1' : '0',
|
|
100
|
+
});
|
|
101
|
+
return `https://transit.yahoo.co.jp/search/result?${params.toString()}`;
|
|
102
|
+
}
|
|
103
|
+
function extractMainContent(html) {
|
|
104
|
+
// remove noise: scripts, styles, comments
|
|
105
|
+
let content = html.replace(/<script[^>]*>[\s\S]*?<\/script>/gi, '');
|
|
106
|
+
content = content.replace(/<style[^>]*>[\s\S]*?<\/style>/gi, '');
|
|
107
|
+
content = content.replace(/<!--[\s\S]*?-->/g, '');
|
|
108
|
+
// remove common noise elements (ads, nav, header, footer)
|
|
109
|
+
content = content.replace(/<nav[^>]*>[\s\S]*?<\/nav>/gi, '');
|
|
110
|
+
content = content.replace(/<header[^>]*>[\s\S]*?<\/header>/gi, '');
|
|
111
|
+
content = content.replace(/<footer[^>]*>[\s\S]*?<\/footer>/gi, '');
|
|
112
|
+
content = content.replace(/<aside[^>]*>[\s\S]*?<\/aside>/gi, '');
|
|
113
|
+
// extract route section (keep HTML structure)
|
|
114
|
+
const routeStartMatch = content.match(/(<div[^>]*class="[^"]*routeDetail[^"]*"[^>]*>)/i);
|
|
115
|
+
const routeEndMatch = content.indexOf('条件を変更して検索');
|
|
116
|
+
if (routeStartMatch && routeEndMatch !== -1) {
|
|
117
|
+
const routeStart = content.indexOf(routeStartMatch[0]);
|
|
118
|
+
return content.substring(routeStart, routeEndMatch);
|
|
119
|
+
}
|
|
120
|
+
// fallback: convert to text if structure not found
|
|
121
|
+
content = content.replace(/<[^>]+>/g, '\n');
|
|
122
|
+
content = content.replace(/\n\s*\n/g, '\n');
|
|
123
|
+
content = content.trim();
|
|
124
|
+
const textRouteStart = content.indexOf('ルート1');
|
|
125
|
+
const textRouteEnd = content.indexOf('条件を変更して検索');
|
|
126
|
+
if (textRouteStart !== -1 && textRouteEnd !== -1) {
|
|
127
|
+
return content.substring(textRouteStart, textRouteEnd);
|
|
128
|
+
}
|
|
129
|
+
return content;
|
|
130
|
+
}
|
|
131
|
+
async function main() {
|
|
132
|
+
const transport = new StdioServerTransport();
|
|
133
|
+
await server.connect(transport);
|
|
134
|
+
console.error('norikae-mcp server started');
|
|
135
|
+
}
|
|
136
|
+
main().catch(console.error);
|
|
137
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.test.d.ts","sourceRoot":"","sources":["../src/index.test.ts"],"names":[],"mappings":"AAAA;;;GAGG"}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unit tests for norikae-mcp
|
|
3
|
+
* Run: npm test
|
|
4
|
+
*/
|
|
5
|
+
import { describe, it, expect } from 'vitest';
|
|
6
|
+
function buildYahooTransitUrl(from, to, year, month, day, hour, minute, options) {
|
|
7
|
+
const timeTypeMap = { departure: '1', arrival: '2' };
|
|
8
|
+
const walkSpeedMap = { fast: '1', slightly_fast: '2', slightly_slow: '3', slow: '4' };
|
|
9
|
+
const sortByMap = { time: '0', transfer: '1', fare: '2' };
|
|
10
|
+
const params = new URLSearchParams({
|
|
11
|
+
from: from,
|
|
12
|
+
to: to,
|
|
13
|
+
y: year.toString(),
|
|
14
|
+
m: month.toString().padStart(2, '0'),
|
|
15
|
+
d: day.toString().padStart(2, '0'),
|
|
16
|
+
hh: hour.toString(),
|
|
17
|
+
m1: Math.floor(minute / 10).toString(),
|
|
18
|
+
m2: (minute % 10).toString(),
|
|
19
|
+
type: timeTypeMap[options.timeType],
|
|
20
|
+
ticket: options.ticket,
|
|
21
|
+
expkind: '1',
|
|
22
|
+
ws: walkSpeedMap[options.walkSpeed],
|
|
23
|
+
s: sortByMap[options.sortBy],
|
|
24
|
+
al: options.useAirline ? '1' : '0',
|
|
25
|
+
shin: options.useShinkansen ? '1' : '0',
|
|
26
|
+
ex: options.useExpress ? '1' : '0',
|
|
27
|
+
hb: options.useHighwayBus ? '1' : '0',
|
|
28
|
+
lb: options.useLocalBus ? '1' : '0',
|
|
29
|
+
sr: options.useFerry ? '1' : '0',
|
|
30
|
+
});
|
|
31
|
+
return `https://transit.yahoo.co.jp/search/result?${params.toString()}`;
|
|
32
|
+
}
|
|
33
|
+
const defaultOptions = {
|
|
34
|
+
timeType: 'departure',
|
|
35
|
+
ticket: 'ic',
|
|
36
|
+
walkSpeed: 'slightly_slow',
|
|
37
|
+
sortBy: 'time',
|
|
38
|
+
useAirline: true,
|
|
39
|
+
useShinkansen: true,
|
|
40
|
+
useExpress: true,
|
|
41
|
+
useHighwayBus: true,
|
|
42
|
+
useLocalBus: true,
|
|
43
|
+
useFerry: true,
|
|
44
|
+
};
|
|
45
|
+
describe('buildYahooTransitUrl', () => {
|
|
46
|
+
it('should build basic URL with from and to', () => {
|
|
47
|
+
const url = buildYahooTransitUrl('東京', '九段下', 2026, 1, 22, 10, 30, defaultOptions);
|
|
48
|
+
expect(url).toContain('from=%E6%9D%B1%E4%BA%AC'); // 東京 encoded
|
|
49
|
+
expect(url).toContain('to=%E4%B9%9D%E6%AE%B5%E4%B8%8B'); // 九段下 encoded
|
|
50
|
+
});
|
|
51
|
+
it('should set correct time parameters', () => {
|
|
52
|
+
const url = buildYahooTransitUrl('東京', '大阪', 2026, 1, 22, 10, 35, defaultOptions);
|
|
53
|
+
expect(url).toContain('y=2026');
|
|
54
|
+
expect(url).toContain('m=01');
|
|
55
|
+
expect(url).toContain('d=22');
|
|
56
|
+
expect(url).toContain('hh=10');
|
|
57
|
+
expect(url).toContain('m1=3'); // 35 / 10 = 3
|
|
58
|
+
expect(url).toContain('m2=5'); // 35 % 10 = 5
|
|
59
|
+
});
|
|
60
|
+
it('should set departure type by default', () => {
|
|
61
|
+
const url = buildYahooTransitUrl('東京', '大阪', 2026, 1, 22, 10, 30, defaultOptions);
|
|
62
|
+
expect(url).toContain('type=1'); // departure
|
|
63
|
+
});
|
|
64
|
+
it('should set arrival type when specified', () => {
|
|
65
|
+
const url = buildYahooTransitUrl('東京', '大阪', 2026, 1, 22, 18, 0, {
|
|
66
|
+
...defaultOptions,
|
|
67
|
+
timeType: 'arrival',
|
|
68
|
+
});
|
|
69
|
+
expect(url).toContain('type=2'); // arrival
|
|
70
|
+
});
|
|
71
|
+
it('should disable shinkansen when specified', () => {
|
|
72
|
+
const url = buildYahooTransitUrl('東京', '大阪', 2026, 1, 22, 10, 30, {
|
|
73
|
+
...defaultOptions,
|
|
74
|
+
useShinkansen: false,
|
|
75
|
+
});
|
|
76
|
+
expect(url).toContain('shin=0');
|
|
77
|
+
});
|
|
78
|
+
it('should set sort by fare', () => {
|
|
79
|
+
const url = buildYahooTransitUrl('東京', '大阪', 2026, 1, 22, 10, 30, {
|
|
80
|
+
...defaultOptions,
|
|
81
|
+
sortBy: 'fare',
|
|
82
|
+
});
|
|
83
|
+
expect(url).toContain('s=2'); // fare
|
|
84
|
+
});
|
|
85
|
+
it('should set walk speed to fast', () => {
|
|
86
|
+
const url = buildYahooTransitUrl('東京', '大阪', 2026, 1, 22, 10, 30, {
|
|
87
|
+
...defaultOptions,
|
|
88
|
+
walkSpeed: 'fast',
|
|
89
|
+
});
|
|
90
|
+
expect(url).toContain('ws=1'); // fast
|
|
91
|
+
});
|
|
92
|
+
it('should set cash ticket type', () => {
|
|
93
|
+
const url = buildYahooTransitUrl('東京', '大阪', 2026, 1, 22, 10, 30, {
|
|
94
|
+
...defaultOptions,
|
|
95
|
+
ticket: 'cash',
|
|
96
|
+
});
|
|
97
|
+
expect(url).toContain('ticket=cash');
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
describe('extractMainContent', () => {
|
|
101
|
+
// simple mock test for HTML extraction
|
|
102
|
+
it('should extract route section from HTML', () => {
|
|
103
|
+
const mockHtml = `
|
|
104
|
+
<html>
|
|
105
|
+
<script>var x = 1;</script>
|
|
106
|
+
<style>.foo { color: red; }</style>
|
|
107
|
+
<nav>Navigation</nav>
|
|
108
|
+
<div>ルート1のルート情報</div>
|
|
109
|
+
<div>条件を変更して検索</div>
|
|
110
|
+
</html>
|
|
111
|
+
`;
|
|
112
|
+
// basic extraction test - just verify it doesn't crash
|
|
113
|
+
expect(mockHtml).toContain('ルート1');
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
describe('SearchOptions defaults', () => {
|
|
117
|
+
it('should have correct default values', () => {
|
|
118
|
+
expect(defaultOptions.timeType).toBe('departure');
|
|
119
|
+
expect(defaultOptions.ticket).toBe('ic');
|
|
120
|
+
expect(defaultOptions.walkSpeed).toBe('slightly_slow');
|
|
121
|
+
expect(defaultOptions.sortBy).toBe('time');
|
|
122
|
+
expect(defaultOptions.useShinkansen).toBe(true);
|
|
123
|
+
expect(defaultOptions.useAirline).toBe(true);
|
|
124
|
+
});
|
|
125
|
+
});
|
|
126
|
+
//# sourceMappingURL=index.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.test.js","sourceRoot":"","sources":["../src/index.test.ts"],"names":[],"mappings":"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"}
|
package/dist/test.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test.d.ts","sourceRoot":"","sources":["../src/test.ts"],"names":[],"mappings":";AAEA;;;GAGG"}
|
package/dist/test.js
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
#!/usr/bin/env npx ts-node
|
|
2
|
+
/**
|
|
3
|
+
* Test script for core logic (without MCP)
|
|
4
|
+
* Run: npx ts-node src/test.ts
|
|
5
|
+
*/
|
|
6
|
+
function buildYahooTransitUrl(from, to, year, month, day, hour, minute, options) {
|
|
7
|
+
const timeTypeMap = { departure: '1', arrival: '2' };
|
|
8
|
+
const walkSpeedMap = { fast: '1', slightly_fast: '2', slightly_slow: '3', slow: '4' };
|
|
9
|
+
const sortByMap = { time: '0', transfer: '1', fare: '2' };
|
|
10
|
+
const params = new URLSearchParams({
|
|
11
|
+
from: from,
|
|
12
|
+
to: to,
|
|
13
|
+
y: year.toString(),
|
|
14
|
+
m: month.toString().padStart(2, '0'),
|
|
15
|
+
d: day.toString().padStart(2, '0'),
|
|
16
|
+
hh: hour.toString(),
|
|
17
|
+
m1: Math.floor(minute / 10).toString(),
|
|
18
|
+
m2: (minute % 10).toString(),
|
|
19
|
+
type: timeTypeMap[options.timeType],
|
|
20
|
+
ticket: options.ticket,
|
|
21
|
+
expkind: '1',
|
|
22
|
+
ws: walkSpeedMap[options.walkSpeed],
|
|
23
|
+
s: sortByMap[options.sortBy],
|
|
24
|
+
al: options.useAirline ? '1' : '0',
|
|
25
|
+
shin: options.useShinkansen ? '1' : '0',
|
|
26
|
+
ex: options.useExpress ? '1' : '0',
|
|
27
|
+
hb: options.useHighwayBus ? '1' : '0',
|
|
28
|
+
lb: options.useLocalBus ? '1' : '0',
|
|
29
|
+
sr: options.useFerry ? '1' : '0',
|
|
30
|
+
});
|
|
31
|
+
return `https://transit.yahoo.co.jp/search/result?${params.toString()}`;
|
|
32
|
+
}
|
|
33
|
+
function extractMainContent(html) {
|
|
34
|
+
// remove noise: scripts, styles, comments
|
|
35
|
+
let content = html.replace(/<script[^>]*>[\s\S]*?<\/script>/gi, '');
|
|
36
|
+
content = content.replace(/<style[^>]*>[\s\S]*?<\/style>/gi, '');
|
|
37
|
+
content = content.replace(/<!--[\s\S]*?-->/g, '');
|
|
38
|
+
// remove common noise elements (ads, nav, header, footer)
|
|
39
|
+
content = content.replace(/<nav[^>]*>[\s\S]*?<\/nav>/gi, '');
|
|
40
|
+
content = content.replace(/<header[^>]*>[\s\S]*?<\/header>/gi, '');
|
|
41
|
+
content = content.replace(/<footer[^>]*>[\s\S]*?<\/footer>/gi, '');
|
|
42
|
+
content = content.replace(/<aside[^>]*>[\s\S]*?<\/aside>/gi, '');
|
|
43
|
+
// extract route section (keep HTML structure)
|
|
44
|
+
const routeStartMatch = content.match(/(<div[^>]*class="[^"]*routeDetail[^"]*"[^>]*>)/i);
|
|
45
|
+
const routeEndMatch = content.indexOf('条件を変更して検索');
|
|
46
|
+
if (routeStartMatch && routeEndMatch !== -1) {
|
|
47
|
+
const routeStart = content.indexOf(routeStartMatch[0]);
|
|
48
|
+
return content.substring(routeStart, routeEndMatch);
|
|
49
|
+
}
|
|
50
|
+
// fallback: convert to text if structure not found
|
|
51
|
+
content = content.replace(/<[^>]+>/g, '\n');
|
|
52
|
+
content = content.replace(/\n\s*\n/g, '\n');
|
|
53
|
+
content = content.trim();
|
|
54
|
+
const textRouteStart = content.indexOf('ルート1');
|
|
55
|
+
const textRouteEnd = content.indexOf('条件を変更して検索');
|
|
56
|
+
if (textRouteStart !== -1 && textRouteEnd !== -1) {
|
|
57
|
+
return content.substring(textRouteStart, textRouteEnd);
|
|
58
|
+
}
|
|
59
|
+
return content;
|
|
60
|
+
}
|
|
61
|
+
// ========== TESTS ==========
|
|
62
|
+
async function testUrlBuilder() {
|
|
63
|
+
console.log('=== Test: URL Builder ===\n');
|
|
64
|
+
const defaultOptions = {
|
|
65
|
+
timeType: 'departure',
|
|
66
|
+
ticket: 'ic',
|
|
67
|
+
walkSpeed: 'slightly_slow',
|
|
68
|
+
sortBy: 'time',
|
|
69
|
+
useAirline: true,
|
|
70
|
+
useShinkansen: true,
|
|
71
|
+
useExpress: true,
|
|
72
|
+
useHighwayBus: true,
|
|
73
|
+
useLocalBus: true,
|
|
74
|
+
useFerry: true,
|
|
75
|
+
};
|
|
76
|
+
// test 1: basic route
|
|
77
|
+
const url1 = buildYahooTransitUrl('東京', '九段下', 2026, 1, 22, 10, 30, defaultOptions);
|
|
78
|
+
console.log('Test 1 - Basic route:');
|
|
79
|
+
console.log(` From: 東京 → To: 九段下`);
|
|
80
|
+
console.log(` URL: ${url1}\n`);
|
|
81
|
+
// test 2: arrival time + no shinkansen
|
|
82
|
+
const url2 = buildYahooTransitUrl('東京', '大阪', 2026, 1, 22, 18, 0, {
|
|
83
|
+
...defaultOptions,
|
|
84
|
+
timeType: 'arrival',
|
|
85
|
+
useShinkansen: false,
|
|
86
|
+
});
|
|
87
|
+
console.log('Test 2 - Arrival time, no shinkansen:');
|
|
88
|
+
console.log(` From: 東京 → To: 大阪 (arrive by 18:00)`);
|
|
89
|
+
console.log(` URL: ${url2}\n`);
|
|
90
|
+
// test 3: sort by fare
|
|
91
|
+
const url3 = buildYahooTransitUrl('新宿', '横浜', 2026, 1, 22, 12, 0, {
|
|
92
|
+
...defaultOptions,
|
|
93
|
+
sortBy: 'fare',
|
|
94
|
+
});
|
|
95
|
+
console.log('Test 3 - Sort by fare:');
|
|
96
|
+
console.log(` From: 新宿 → To: 横浜`);
|
|
97
|
+
console.log(` URL: ${url3}\n`);
|
|
98
|
+
}
|
|
99
|
+
async function testFetchAndParse() {
|
|
100
|
+
console.log('=== Test: Fetch and Parse ===\n');
|
|
101
|
+
const defaultOptions = {
|
|
102
|
+
timeType: 'departure',
|
|
103
|
+
ticket: 'ic',
|
|
104
|
+
walkSpeed: 'slightly_slow',
|
|
105
|
+
sortBy: 'time',
|
|
106
|
+
useAirline: true,
|
|
107
|
+
useShinkansen: true,
|
|
108
|
+
useExpress: true,
|
|
109
|
+
useHighwayBus: true,
|
|
110
|
+
useLocalBus: true,
|
|
111
|
+
useFerry: true,
|
|
112
|
+
};
|
|
113
|
+
const url = buildYahooTransitUrl('東京', '九段下', 2026, 1, 22, 10, 30, defaultOptions);
|
|
114
|
+
console.log(`Fetching: ${url}\n`);
|
|
115
|
+
try {
|
|
116
|
+
const response = await fetch(url);
|
|
117
|
+
const html = await response.text();
|
|
118
|
+
console.log(`Response status: ${response.status}`);
|
|
119
|
+
console.log(`HTML length: ${html.length} chars\n`);
|
|
120
|
+
const content = extractMainContent(html);
|
|
121
|
+
console.log('=== Extracted Content ===\n');
|
|
122
|
+
console.log(content);
|
|
123
|
+
console.log('\n=== End of Content ===');
|
|
124
|
+
}
|
|
125
|
+
catch (error) {
|
|
126
|
+
console.error('Fetch error:', error);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
// run tests
|
|
130
|
+
async function main() {
|
|
131
|
+
const args = process.argv.slice(2);
|
|
132
|
+
if (args.includes('--url')) {
|
|
133
|
+
await testUrlBuilder();
|
|
134
|
+
}
|
|
135
|
+
else if (args.includes('--fetch')) {
|
|
136
|
+
await testFetchAndParse();
|
|
137
|
+
}
|
|
138
|
+
else {
|
|
139
|
+
console.log('Usage:');
|
|
140
|
+
console.log(' npx ts-node src/test.ts --url # Test URL builder');
|
|
141
|
+
console.log(' npx ts-node src/test.ts --fetch # Test fetch and parse');
|
|
142
|
+
console.log('\nRunning all tests...\n');
|
|
143
|
+
await testUrlBuilder();
|
|
144
|
+
await testFetchAndParse();
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
main().catch(console.error);
|
|
148
|
+
export {};
|
|
149
|
+
//# sourceMappingURL=test.js.map
|
package/dist/test.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test.js","sourceRoot":"","sources":["../src/test.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "norikae-mcp",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Yahoo!乗換案内を使った日本の電車乗り換え検索MCP",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"norikae-mcp": "dist/index.js"
|
|
9
|
+
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"build": "tsc",
|
|
12
|
+
"dev": "tsc --watch",
|
|
13
|
+
"start": "node dist/index.js",
|
|
14
|
+
"test": "vitest run",
|
|
15
|
+
"test:watch": "vitest",
|
|
16
|
+
"test:manual": "npx ts-node src/test.ts",
|
|
17
|
+
"test:url": "npx ts-node src/test.ts --url",
|
|
18
|
+
"test:fetch": "npx ts-node src/test.ts --fetch",
|
|
19
|
+
"prepublishOnly": "npm run build"
|
|
20
|
+
},
|
|
21
|
+
"keywords": [
|
|
22
|
+
"mcp",
|
|
23
|
+
"model-context-protocol",
|
|
24
|
+
"transit",
|
|
25
|
+
"japan",
|
|
26
|
+
"train",
|
|
27
|
+
"乗り換え",
|
|
28
|
+
"yahoo"
|
|
29
|
+
],
|
|
30
|
+
"author": "",
|
|
31
|
+
"license": "MIT",
|
|
32
|
+
"dependencies": {
|
|
33
|
+
"@modelcontextprotocol/sdk": "^1.0.0",
|
|
34
|
+
"zod": "^3.23.0"
|
|
35
|
+
},
|
|
36
|
+
"devDependencies": {
|
|
37
|
+
"@types/node": "^20.0.0",
|
|
38
|
+
"ts-node": "^10.9.0",
|
|
39
|
+
"typescript": "^5.0.0",
|
|
40
|
+
"vitest": "^2.0.0"
|
|
41
|
+
},
|
|
42
|
+
"engines": {
|
|
43
|
+
"node": ">=18.0.0"
|
|
44
|
+
},
|
|
45
|
+
"files": [
|
|
46
|
+
"dist"
|
|
47
|
+
]
|
|
48
|
+
}
|