korbus-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.
Files changed (91) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +251 -0
  3. package/dist/bus/gateway.d.ts +11 -0
  4. package/dist/bus/gateway.d.ts.map +1 -0
  5. package/dist/bus/gateway.js +36 -0
  6. package/dist/bus/gateway.js.map +1 -0
  7. package/dist/bus/gyeonggi.d.ts +9 -0
  8. package/dist/bus/gyeonggi.d.ts.map +1 -0
  9. package/dist/bus/gyeonggi.js +69 -0
  10. package/dist/bus/gyeonggi.js.map +1 -0
  11. package/dist/bus/seoul.d.ts +9 -0
  12. package/dist/bus/seoul.d.ts.map +1 -0
  13. package/dist/bus/seoul.js +72 -0
  14. package/dist/bus/seoul.js.map +1 -0
  15. package/dist/db.d.ts +55 -0
  16. package/dist/db.d.ts.map +1 -0
  17. package/dist/db.js +409 -0
  18. package/dist/db.js.map +1 -0
  19. package/dist/errors.d.ts +21 -0
  20. package/dist/errors.d.ts.map +1 -0
  21. package/dist/errors.js +71 -0
  22. package/dist/errors.js.map +1 -0
  23. package/dist/index.d.ts +2 -0
  24. package/dist/index.d.ts.map +1 -0
  25. package/dist/index.js +55 -0
  26. package/dist/index.js.map +1 -0
  27. package/dist/notifier/console.d.ts +3 -0
  28. package/dist/notifier/console.d.ts.map +1 -0
  29. package/dist/notifier/console.js +4 -0
  30. package/dist/notifier/console.js.map +1 -0
  31. package/dist/notifier/dispatcher.d.ts +11 -0
  32. package/dist/notifier/dispatcher.d.ts.map +1 -0
  33. package/dist/notifier/dispatcher.js +28 -0
  34. package/dist/notifier/dispatcher.js.map +1 -0
  35. package/dist/notifier/telegram.d.ts +3 -0
  36. package/dist/notifier/telegram.d.ts.map +1 -0
  37. package/dist/notifier/telegram.js +14 -0
  38. package/dist/notifier/telegram.js.map +1 -0
  39. package/dist/notifier/webhook.d.ts +3 -0
  40. package/dist/notifier/webhook.d.ts.map +1 -0
  41. package/dist/notifier/webhook.js +6 -0
  42. package/dist/notifier/webhook.js.map +1 -0
  43. package/dist/openclaw/dispatcher.d.ts +10 -0
  44. package/dist/openclaw/dispatcher.d.ts.map +1 -0
  45. package/dist/openclaw/dispatcher.js +50 -0
  46. package/dist/openclaw/dispatcher.js.map +1 -0
  47. package/dist/openclaw/index.d.ts +21 -0
  48. package/dist/openclaw/index.d.ts.map +1 -0
  49. package/dist/openclaw/index.js +39 -0
  50. package/dist/openclaw/index.js.map +1 -0
  51. package/dist/openclaw/service.d.ts +11 -0
  52. package/dist/openclaw/service.d.ts.map +1 -0
  53. package/dist/openclaw/service.js +28 -0
  54. package/dist/openclaw/service.js.map +1 -0
  55. package/dist/openclaw/tools.d.ts +27 -0
  56. package/dist/openclaw/tools.d.ts.map +1 -0
  57. package/dist/openclaw/tools.js +318 -0
  58. package/dist/openclaw/tools.js.map +1 -0
  59. package/dist/scheduler.d.ts +15 -0
  60. package/dist/scheduler.d.ts.map +1 -0
  61. package/dist/scheduler.js +106 -0
  62. package/dist/scheduler.js.map +1 -0
  63. package/dist/tools/alarm.d.ts +3 -0
  64. package/dist/tools/alarm.d.ts.map +1 -0
  65. package/dist/tools/alarm.js +118 -0
  66. package/dist/tools/alarm.js.map +1 -0
  67. package/dist/tools/arrival.d.ts +4 -0
  68. package/dist/tools/arrival.d.ts.map +1 -0
  69. package/dist/tools/arrival.js +37 -0
  70. package/dist/tools/arrival.js.map +1 -0
  71. package/dist/tools/helpers.d.ts +14 -0
  72. package/dist/tools/helpers.d.ts.map +1 -0
  73. package/dist/tools/helpers.js +14 -0
  74. package/dist/tools/helpers.js.map +1 -0
  75. package/dist/tools/poll.d.ts +4 -0
  76. package/dist/tools/poll.d.ts.map +1 -0
  77. package/dist/tools/poll.js +17 -0
  78. package/dist/tools/poll.js.map +1 -0
  79. package/dist/tools/search.d.ts +4 -0
  80. package/dist/tools/search.d.ts.map +1 -0
  81. package/dist/tools/search.js +26 -0
  82. package/dist/tools/search.js.map +1 -0
  83. package/dist/types.d.ts +117 -0
  84. package/dist/types.d.ts.map +1 -0
  85. package/dist/types.js +16 -0
  86. package/dist/types.js.map +1 -0
  87. package/package.json +73 -0
  88. package/prisma/migrations/20260303085107_init/migration.sql +62 -0
  89. package/prisma/migrations/20260303120821_add_once_alarm_fields/migration.sql +22 -0
  90. package/prisma/migrations/migration_lock.toml +3 -0
  91. package/prisma/schema.prisma +72 -0
package/dist/db.js ADDED
@@ -0,0 +1,409 @@
1
+ import { execSync } from 'node:child_process';
2
+ import { existsSync, mkdirSync } from 'node:fs';
3
+ import os from 'node:os';
4
+ import path from 'node:path';
5
+ import { createRequire } from 'node:module';
6
+ import { fileURLToPath } from 'node:url';
7
+ import { PrismaClient } from '@prisma/client';
8
+ // ---------------------------------------------------------------------------
9
+ // Singleton
10
+ // ---------------------------------------------------------------------------
11
+ let prisma = null;
12
+ /**
13
+ * Initialise PrismaClient singleton.
14
+ * Automatically runs `prisma migrate deploy` so the DB schema is up-to-date.
15
+ */
16
+ export async function initDb() {
17
+ if (prisma)
18
+ return prisma;
19
+ const currentDir = path.dirname(fileURLToPath(import.meta.url));
20
+ const repoRoot = path.resolve(currentDir, '..');
21
+ const schemaPath = path.resolve(repoRoot, 'prisma/schema.prisma');
22
+ const defaultDbDir = path.resolve(os.homedir(), '.korbus-mcp');
23
+ mkdirSync(defaultDbDir, { recursive: true });
24
+ const defaultDbUrl = `file:${path.resolve(defaultDbDir, 'korbus.db')}`;
25
+ const databaseUrl = process.env.DATABASE_URL ?? defaultDbUrl;
26
+ if (existsSync(schemaPath)) {
27
+ try {
28
+ const require = createRequire(import.meta.url);
29
+ const prismaPkg = path.dirname(require.resolve('prisma/package.json'));
30
+ const prismaBin = path.resolve(prismaPkg, 'build', 'index.js');
31
+ execSync(`node "${prismaBin}" migrate deploy --schema "${schemaPath}"`, {
32
+ cwd: repoRoot,
33
+ stdio: 'pipe',
34
+ env: { ...process.env, DATABASE_URL: databaseUrl },
35
+ });
36
+ }
37
+ catch {
38
+ // Ignore migrate errors — the DB may already be up-to-date
39
+ }
40
+ }
41
+ prisma = new PrismaClient({ datasourceUrl: databaseUrl });
42
+ await prisma.$connect();
43
+ console.error('[db] connected');
44
+ return prisma;
45
+ }
46
+ /** Return the initialised PrismaClient. Throws if `initDb()` has not been called. */
47
+ export function getDb() {
48
+ if (!prisma) {
49
+ throw new Error('Database not initialised. Call initDb() first.');
50
+ }
51
+ return prisma;
52
+ }
53
+ /** Disconnect PrismaClient and reset the singleton. */
54
+ export async function closeDb() {
55
+ if (prisma) {
56
+ await prisma.$disconnect();
57
+ prisma = null;
58
+ console.error('[db] disconnected');
59
+ }
60
+ }
61
+ function mapAlarmWithRelations(row) {
62
+ const schedules = row.schedules.map((s) => ({
63
+ dayOfWeek: s.dayOfWeek.split(','),
64
+ startTime: s.startTime,
65
+ endTime: s.endTime,
66
+ }));
67
+ const channels = row.channels.map((c) => ({
68
+ type: c.type,
69
+ config: c.config,
70
+ }));
71
+ return {
72
+ id: row.id,
73
+ label: row.label,
74
+ stationId: row.stationId,
75
+ routeId: row.routeId,
76
+ alertMinutes: row.alertMinutes,
77
+ type: row.type,
78
+ activeUntil: row.activeUntil,
79
+ firedAt: row.firedAt,
80
+ enabled: row.enabled,
81
+ schedules,
82
+ channels,
83
+ createdAt: row.createdAt,
84
+ station: {
85
+ id: row.station.id,
86
+ name: row.station.name,
87
+ region: row.station.region,
88
+ arsId: row.station.arsId,
89
+ posX: row.station.posX ?? undefined,
90
+ posY: row.station.posY ?? undefined,
91
+ },
92
+ route: {
93
+ id: row.route.id,
94
+ name: row.route.name,
95
+ region: row.route.region,
96
+ },
97
+ };
98
+ }
99
+ /** Standard Prisma `include` clause used for every alarm query. */
100
+ const ALARM_INCLUDE = {
101
+ station: true,
102
+ route: true,
103
+ schedules: true,
104
+ channels: true,
105
+ };
106
+ // ---------------------------------------------------------------------------
107
+ // Station helpers
108
+ // ---------------------------------------------------------------------------
109
+ function mapStation(row) {
110
+ return {
111
+ id: row.id,
112
+ name: row.name,
113
+ region: row.region,
114
+ arsId: row.arsId,
115
+ posX: row.posX ?? undefined,
116
+ posY: row.posY ?? undefined,
117
+ };
118
+ }
119
+ function mapRoute(row) {
120
+ return {
121
+ id: row.id,
122
+ name: row.name,
123
+ region: row.region,
124
+ };
125
+ }
126
+ // ---------------------------------------------------------------------------
127
+ // CRUD — Stations & Routes
128
+ // ---------------------------------------------------------------------------
129
+ /** Upsert an array of stations, returning the mapped results. */
130
+ export async function upsertStations(stations) {
131
+ const db = getDb();
132
+ const results = [];
133
+ for (const s of stations) {
134
+ const row = await db.station.upsert({
135
+ where: { id: s.id },
136
+ create: {
137
+ id: s.id,
138
+ name: s.name,
139
+ region: s.region,
140
+ arsId: s.arsId ?? null,
141
+ posX: s.posX ?? null,
142
+ posY: s.posY ?? null,
143
+ },
144
+ update: {
145
+ name: s.name,
146
+ region: s.region,
147
+ arsId: s.arsId ?? null,
148
+ posX: s.posX ?? null,
149
+ posY: s.posY ?? null,
150
+ },
151
+ });
152
+ results.push(mapStation(row));
153
+ }
154
+ return results;
155
+ }
156
+ /** Upsert an array of routes, returning the mapped results. */
157
+ export async function upsertRoutes(routes) {
158
+ const db = getDb();
159
+ const results = [];
160
+ for (const r of routes) {
161
+ const row = await db.route.upsert({
162
+ where: { id: r.id },
163
+ create: {
164
+ id: r.id,
165
+ name: r.name,
166
+ region: r.region,
167
+ },
168
+ update: {
169
+ name: r.name,
170
+ region: r.region,
171
+ },
172
+ });
173
+ results.push(mapRoute(row));
174
+ }
175
+ return results;
176
+ }
177
+ /** Find a station by id and return a lightweight StationRef. */
178
+ export async function findStationById(stationId) {
179
+ const db = getDb();
180
+ const row = await db.station.findUnique({ where: { id: stationId } });
181
+ if (!row)
182
+ return null;
183
+ return {
184
+ id: row.id,
185
+ region: row.region,
186
+ arsId: row.arsId,
187
+ };
188
+ }
189
+ // ---------------------------------------------------------------------------
190
+ // CRUD — Alarms
191
+ // ---------------------------------------------------------------------------
192
+ /** Create an alarm with nested schedules and channels. */
193
+ export async function createAlarm(input) {
194
+ const db = getDb();
195
+ const row = await db.alarm.create({
196
+ data: {
197
+ stationId: input.stationId,
198
+ routeId: input.routeId,
199
+ label: input.label ?? null,
200
+ alertMinutes: input.alertMinutes,
201
+ schedules: {
202
+ create: input.schedules.map((s) => ({
203
+ dayOfWeek: s.dayOfWeek.join(','),
204
+ startTime: s.startTime,
205
+ endTime: s.endTime,
206
+ })),
207
+ },
208
+ channels: {
209
+ create: input.channels.map((c) => ({
210
+ type: c.type,
211
+ config: JSON.stringify(c.config ?? {}),
212
+ })),
213
+ },
214
+ },
215
+ include: ALARM_INCLUDE,
216
+ });
217
+ return mapAlarmWithRelations(row);
218
+ }
219
+ /** List all alarms with their station, route, schedules, and channels. */
220
+ export async function listAlarms() {
221
+ const db = getDb();
222
+ const rows = await db.alarm.findMany({ include: ALARM_INCLUDE });
223
+ return rows.map((r) => mapAlarmWithRelations(r));
224
+ }
225
+ /** Find a single alarm by id, or return null. */
226
+ export async function findAlarm(alarmId) {
227
+ const db = getDb();
228
+ const row = await db.alarm.findUnique({
229
+ where: { id: alarmId },
230
+ include: ALARM_INCLUDE,
231
+ });
232
+ if (!row)
233
+ return null;
234
+ return mapAlarmWithRelations(row);
235
+ }
236
+ /**
237
+ * Update an alarm. If `schedules` or `channels` are provided in the input
238
+ * the existing child rows are deleted and recreated.
239
+ */
240
+ export async function updateAlarm(alarmId, input) {
241
+ const db = getDb();
242
+ // Delete existing children when replacements are provided
243
+ const deleteOps = [];
244
+ if (input.schedules) {
245
+ deleteOps.push(db.alarmSchedule.deleteMany({ where: { alarmId } }));
246
+ }
247
+ if (input.channels) {
248
+ deleteOps.push(db.alarmChannel.deleteMany({ where: { alarmId } }));
249
+ }
250
+ if (deleteOps.length > 0) {
251
+ await Promise.all(deleteOps);
252
+ }
253
+ const row = await db.alarm.update({
254
+ where: { id: alarmId },
255
+ data: {
256
+ ...(input.label !== undefined && { label: input.label }),
257
+ ...(input.alertMinutes !== undefined && {
258
+ alertMinutes: input.alertMinutes,
259
+ }),
260
+ ...(input.enabled !== undefined && { enabled: input.enabled }),
261
+ ...(input.schedules && {
262
+ schedules: {
263
+ create: input.schedules.map((s) => ({
264
+ dayOfWeek: s.dayOfWeek.join(','),
265
+ startTime: s.startTime,
266
+ endTime: s.endTime,
267
+ })),
268
+ },
269
+ }),
270
+ ...(input.channels && {
271
+ channels: {
272
+ create: input.channels.map((c) => ({
273
+ type: c.type,
274
+ config: JSON.stringify(c.config ?? {}),
275
+ })),
276
+ },
277
+ }),
278
+ },
279
+ include: ALARM_INCLUDE,
280
+ });
281
+ return mapAlarmWithRelations(row);
282
+ }
283
+ /** Delete an alarm by id. Cascading deletes handle children. */
284
+ export async function deleteAlarm(alarmId) {
285
+ const db = getDb();
286
+ await db.alarm.delete({ where: { id: alarmId } });
287
+ }
288
+ /** Create a one-time alarm (no schedules). */
289
+ export async function createOnceAlarm(input) {
290
+ const db = getDb();
291
+ let activeUntil = null;
292
+ if (input.activeUntil) {
293
+ if (/^\d{2}:\d{2}$/.test(input.activeUntil)) {
294
+ const [hh, mm] = input.activeUntil.split(':').map(Number);
295
+ const d = new Date();
296
+ d.setHours(hh, mm, 0, 0);
297
+ activeUntil = d;
298
+ }
299
+ else {
300
+ activeUntil = new Date(input.activeUntil);
301
+ }
302
+ }
303
+ const row = await db.alarm.create({
304
+ data: {
305
+ stationId: input.stationId,
306
+ routeId: input.routeId,
307
+ label: input.label ?? null,
308
+ alertMinutes: input.alertMinutes,
309
+ type: 'ONCE',
310
+ activeUntil,
311
+ channels: {
312
+ create: input.channels.map((c) => ({
313
+ type: c.type,
314
+ config: JSON.stringify(c.config ?? {}),
315
+ })),
316
+ },
317
+ },
318
+ include: ALARM_INCLUDE,
319
+ });
320
+ return mapAlarmWithRelations(row);
321
+ }
322
+ /** Mark a one-time alarm as fired. */
323
+ export async function markAlarmFired(alarmId) {
324
+ const db = getDb();
325
+ await db.alarm.update({
326
+ where: { id: alarmId },
327
+ data: { firedAt: new Date() },
328
+ });
329
+ }
330
+ // ---------------------------------------------------------------------------
331
+ // Scheduling helpers
332
+ // ---------------------------------------------------------------------------
333
+ /**
334
+ * List all *active* alarms whose schedule matches the given `now` timestamp.
335
+ *
336
+ * "Active" means:
337
+ * - RECURRING: `enabled` is true and at least one schedule row matches now.
338
+ * - ONCE: `enabled` is true, `firedAt` is null, and `activeUntil` is null or >= now.
339
+ */
340
+ export async function listActiveAlarms(now) {
341
+ const db = getDb();
342
+ const dayNames = [
343
+ 'SUN',
344
+ 'MON',
345
+ 'TUE',
346
+ 'WED',
347
+ 'THU',
348
+ 'FRI',
349
+ 'SAT',
350
+ ];
351
+ const currentDay = dayNames[now.getDay()];
352
+ const hh = String(now.getHours()).padStart(2, '0');
353
+ const mm = String(now.getMinutes()).padStart(2, '0');
354
+ const currentTime = `${hh}:${mm}`;
355
+ // RECURRING alarms: match by schedule
356
+ const recurringRows = await db.alarm.findMany({
357
+ where: {
358
+ enabled: true,
359
+ type: 'RECURRING',
360
+ schedules: {
361
+ some: {
362
+ dayOfWeek: { contains: currentDay },
363
+ startTime: { lte: currentTime },
364
+ endTime: { gte: currentTime },
365
+ },
366
+ },
367
+ },
368
+ include: ALARM_INCLUDE,
369
+ });
370
+ // ONCE alarms: not yet fired, within activeUntil window
371
+ const onceRows = await db.alarm.findMany({
372
+ where: {
373
+ enabled: true,
374
+ type: 'ONCE',
375
+ firedAt: null,
376
+ OR: [
377
+ { activeUntil: null },
378
+ { activeUntil: { gte: now } },
379
+ ],
380
+ },
381
+ include: ALARM_INCLUDE,
382
+ });
383
+ const allRows = [...recurringRows, ...onceRows];
384
+ return allRows.map((r) => mapAlarmWithRelations(r));
385
+ }
386
+ // ---------------------------------------------------------------------------
387
+ // Notification log
388
+ // ---------------------------------------------------------------------------
389
+ /**
390
+ * Check whether a notification log exists for the given alarm + vehicle
391
+ * combination since the provided timestamp.
392
+ */
393
+ export async function hasRecentNotification(alarmId, vehicleId, since) {
394
+ const db = getDb();
395
+ const count = await db.notificationLog.count({
396
+ where: {
397
+ alarmId,
398
+ vehicleId,
399
+ sentAt: { gte: since },
400
+ },
401
+ });
402
+ return count > 0;
403
+ }
404
+ /** Create a notification log entry. */
405
+ export async function createNotificationLog(input) {
406
+ const db = getDb();
407
+ await db.notificationLog.create({ data: input });
408
+ }
409
+ //# sourceMappingURL=db.js.map
package/dist/db.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"db.js","sourceRoot":"","sources":["../src/db.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ export type ErrorCode = 'VALIDATION_ERROR' | 'NOT_FOUND' | 'API_KEY_ERROR' | 'RATE_LIMIT' | 'UPSTREAM_TIMEOUT' | 'INTERNAL_ERROR';
2
+ export interface CoreErrorShape {
3
+ code: ErrorCode;
4
+ message: string;
5
+ hint?: string;
6
+ details?: unknown;
7
+ retryable: boolean;
8
+ }
9
+ export declare class CoreError extends Error {
10
+ readonly code: ErrorCode;
11
+ readonly hint?: string;
12
+ readonly details?: unknown;
13
+ readonly retryable: boolean;
14
+ constructor(shape: CoreErrorShape);
15
+ toJSON(): CoreErrorShape;
16
+ }
17
+ export declare function apiKeyError(region: string, rawMessage?: string): CoreError;
18
+ export declare function apiKeyExpiredError(region: string): CoreError;
19
+ export declare function rateLimitError(region: string): CoreError;
20
+ export declare function toCoreError(error: unknown): CoreError;
21
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,SAAS,GACjB,kBAAkB,GAClB,WAAW,GACX,eAAe,GACf,YAAY,GACZ,kBAAkB,GAClB,gBAAgB,CAAC;AAErB,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,SAAS,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,qBAAa,SAAU,SAAQ,KAAK;IAClC,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IACzB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;gBAEhB,KAAK,EAAE,cAAc;IAQjC,MAAM,IAAI,cAAc;CASzB;AAID,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAQ1E;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAO5D;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAOxD;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,SAAS,CAsBrD"}
package/dist/errors.js ADDED
@@ -0,0 +1,71 @@
1
+ import { isAxiosError } from 'axios';
2
+ export class CoreError extends Error {
3
+ code;
4
+ hint;
5
+ details;
6
+ retryable;
7
+ constructor(shape) {
8
+ super(shape.message);
9
+ this.code = shape.code;
10
+ this.hint = shape.hint;
11
+ this.details = shape.details;
12
+ this.retryable = shape.retryable;
13
+ }
14
+ toJSON() {
15
+ return {
16
+ code: this.code,
17
+ message: this.message,
18
+ ...(this.hint && { hint: this.hint }),
19
+ ...(this.details !== undefined && { details: this.details }),
20
+ retryable: this.retryable,
21
+ };
22
+ }
23
+ }
24
+ const SETUP_GUIDE = 'https://github.com/BearMett/korbus-mcp#api-키-발급';
25
+ export function apiKeyError(region, rawMessage) {
26
+ return new CoreError({
27
+ code: 'API_KEY_ERROR',
28
+ message: `[${region}] API 키가 등록되지 않았거나 해당 서비스가 활용 신청되지 않았습니다.`,
29
+ hint: `data.go.kr에서 ${region} 버스 관련 서비스 3개의 활용 신청을 확인하세요. 가이드: ${SETUP_GUIDE}`,
30
+ details: rawMessage,
31
+ retryable: false,
32
+ });
33
+ }
34
+ export function apiKeyExpiredError(region) {
35
+ return new CoreError({
36
+ code: 'API_KEY_ERROR',
37
+ message: `[${region}] API 키가 만료되었습니다.`,
38
+ hint: `data.go.kr 마이페이지에서 인증키 갱신 후 환경변수를 업데이트하세요. 가이드: ${SETUP_GUIDE}`,
39
+ retryable: false,
40
+ });
41
+ }
42
+ export function rateLimitError(region) {
43
+ return new CoreError({
44
+ code: 'RATE_LIMIT',
45
+ message: `[${region}] API 호출 한도를 초과했습니다.`,
46
+ hint: '잠시 후 다시 시도해주세요. 공공데이터포털 기본 한도는 일 1,000건입니다.',
47
+ retryable: true,
48
+ });
49
+ }
50
+ export function toCoreError(error) {
51
+ if (error instanceof CoreError) {
52
+ return error;
53
+ }
54
+ if (isAxiosError(error)) {
55
+ if (error.code === 'ECONNABORTED' || error.code === 'ETIMEDOUT') {
56
+ return new CoreError({
57
+ code: 'UPSTREAM_TIMEOUT',
58
+ message: '공공데이터 API 서버 응답 시간이 초과되었습니다.',
59
+ hint: '잠시 후 다시 시도해주세요.',
60
+ retryable: true,
61
+ });
62
+ }
63
+ }
64
+ return new CoreError({
65
+ code: 'INTERNAL_ERROR',
66
+ message: error instanceof Error ? error.message : 'Unknown internal error',
67
+ details: error,
68
+ retryable: false,
69
+ });
70
+ }
71
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAkBrC,MAAM,OAAO,SAAU,SAAQ,KAAK;IACzB,IAAI,CAAY;IAChB,IAAI,CAAU;IACd,OAAO,CAAW;IAClB,SAAS,CAAU;IAE5B,YAAY,KAAqB;QAC/B,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACrB,IAAI,CAAC,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC;QACvB,IAAI,CAAC,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC;QACvB,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC;QAC7B,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC,SAAS,CAAC;IACnC,CAAC;IAED,MAAM;QACJ,OAAO;YACL,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,GAAG,CAAC,IAAI,CAAC,IAAI,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC;YACrC,GAAG,CAAC,IAAI,CAAC,OAAO,KAAK,SAAS,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC;YAC5D,SAAS,EAAE,IAAI,CAAC,SAAS;SAC1B,CAAC;IACJ,CAAC;CACF;AAED,MAAM,WAAW,GAAG,iDAAiD,CAAC;AAEtE,MAAM,UAAU,WAAW,CAAC,MAAc,EAAE,UAAmB;IAC7D,OAAO,IAAI,SAAS,CAAC;QACnB,IAAI,EAAE,eAAe;QACrB,OAAO,EAAE,IAAI,MAAM,2CAA2C;QAC9D,IAAI,EAAE,gBAAgB,MAAM,qCAAqC,WAAW,EAAE;QAC9E,OAAO,EAAE,UAAU;QACnB,SAAS,EAAE,KAAK;KACjB,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,MAAc;IAC/C,OAAO,IAAI,SAAS,CAAC;QACnB,IAAI,EAAE,eAAe;QACrB,OAAO,EAAE,IAAI,MAAM,mBAAmB;QACtC,IAAI,EAAE,mDAAmD,WAAW,EAAE;QACtE,SAAS,EAAE,KAAK;KACjB,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,MAAc;IAC3C,OAAO,IAAI,SAAS,CAAC;QACnB,IAAI,EAAE,YAAY;QAClB,OAAO,EAAE,IAAI,MAAM,sBAAsB;QACzC,IAAI,EAAE,6CAA6C;QACnD,SAAS,EAAE,IAAI;KAChB,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,KAAc;IACxC,IAAI,KAAK,YAAY,SAAS,EAAE,CAAC;QAC/B,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC;QACxB,IAAI,KAAK,CAAC,IAAI,KAAK,cAAc,IAAI,KAAK,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;YAChE,OAAO,IAAI,SAAS,CAAC;gBACnB,IAAI,EAAE,kBAAkB;gBACxB,OAAO,EAAE,8BAA8B;gBACvC,IAAI,EAAE,iBAAiB;gBACvB,SAAS,EAAE,IAAI;aAChB,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,OAAO,IAAI,SAAS,CAAC;QACnB,IAAI,EAAE,gBAAgB;QACtB,OAAO,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,wBAAwB;QAC1E,OAAO,EAAE,KAAK;QACd,SAAS,EAAE,KAAK;KACjB,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=index.d.ts.map
@@ -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,55 @@
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 { initDb, closeDb } from './db.js';
5
+ import { createBusGateway } from './bus/gateway.js';
6
+ import { createDispatcher } from './notifier/dispatcher.js';
7
+ import { startScheduler } from './scheduler.js';
8
+ import { registerSearchTools } from './tools/search.js';
9
+ import { registerArrivalTools } from './tools/arrival.js';
10
+ import { registerAlarmTools } from './tools/alarm.js';
11
+ import { registerPollTools } from './tools/poll.js';
12
+ async function main() {
13
+ // 1. Initialize database (auto-migrate)
14
+ await initDb();
15
+ // 2. Create bus gateway
16
+ const apiKey = process.env.KORBUS_DATA_API_KEY ?? '';
17
+ const gateway = createBusGateway({
18
+ seoulApiKey: apiKey,
19
+ gyeonggiApiKey: apiKey,
20
+ });
21
+ // 3. Create notification dispatcher
22
+ const dispatcher = createDispatcher({
23
+ telegramBotToken: process.env.TELEGRAM_BOT_TOKEN,
24
+ });
25
+ // 4. Create MCP server
26
+ const server = new McpServer({
27
+ name: 'korbus-mcp',
28
+ version: '0.1.0',
29
+ });
30
+ // 5. Register tools
31
+ registerSearchTools(server, gateway);
32
+ registerArrivalTools(server, gateway);
33
+ registerAlarmTools(server);
34
+ registerPollTools(server, { gateway, dispatcher });
35
+ // 6. Connect via stdio
36
+ const transport = new StdioServerTransport();
37
+ await server.connect(transport);
38
+ console.error('[korbus-mcp] server started');
39
+ // 7. Start scheduler
40
+ const stopScheduler = startScheduler({ gateway, dispatcher });
41
+ // 8. Graceful shutdown
42
+ const shutdown = async () => {
43
+ console.error('[korbus-mcp] shutting down...');
44
+ stopScheduler();
45
+ await closeDb();
46
+ process.exit(0);
47
+ };
48
+ process.on('SIGINT', shutdown);
49
+ process.on('SIGTERM', shutdown);
50
+ }
51
+ main().catch((err) => {
52
+ console.error('[korbus-mcp] fatal:', err);
53
+ process.exit(1);
54
+ });
55
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAC1C,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAEpD,KAAK,UAAU,IAAI;IACjB,wCAAwC;IACxC,MAAM,MAAM,EAAE,CAAC;IAEf,wBAAwB;IACxB,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,mBAAmB,IAAI,EAAE,CAAC;IACrD,MAAM,OAAO,GAAG,gBAAgB,CAAC;QAC/B,WAAW,EAAE,MAAM;QACnB,cAAc,EAAE,MAAM;KACvB,CAAC,CAAC;IAEH,oCAAoC;IACpC,MAAM,UAAU,GAAG,gBAAgB,CAAC;QAClC,gBAAgB,EAAE,OAAO,CAAC,GAAG,CAAC,kBAAkB;KACjD,CAAC,CAAC;IAEH,uBAAuB;IACvB,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;QAC3B,IAAI,EAAE,YAAY;QAClB,OAAO,EAAE,OAAO;KACjB,CAAC,CAAC;IAEH,oBAAoB;IACpB,mBAAmB,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,oBAAoB,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACtC,kBAAkB,CAAC,MAAM,CAAC,CAAC;IAC3B,iBAAiB,CAAC,MAAM,EAAE,EAAE,OAAO,EAAE,UAAU,EAAE,CAAC,CAAC;IAEnD,uBAAuB;IACvB,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAChC,OAAO,CAAC,KAAK,CAAC,6BAA6B,CAAC,CAAC;IAE7C,qBAAqB;IACrB,MAAM,aAAa,GAAG,cAAc,CAAC,EAAE,OAAO,EAAE,UAAU,EAAE,CAAC,CAAC;IAE9D,uBAAuB;IACvB,MAAM,QAAQ,GAAG,KAAK,IAAI,EAAE;QAC1B,OAAO,CAAC,KAAK,CAAC,+BAA+B,CAAC,CAAC;QAC/C,aAAa,EAAE,CAAC;QAChB,MAAM,OAAO,EAAE,CAAC;QAChB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC;IAEF,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IAC/B,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;AAClC,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IACnB,OAAO,CAAC,KAAK,CAAC,qBAAqB,EAAE,GAAG,CAAC,CAAC;IAC1C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { NotificationPayload } from '../types.js';
2
+ export declare function sendConsole(payload: NotificationPayload): void;
3
+ //# sourceMappingURL=console.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"console.d.ts","sourceRoot":"","sources":["../../src/notifier/console.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAEvD,wBAAgB,WAAW,CAAC,OAAO,EAAE,mBAAmB,GAAG,IAAI,CAI9D"}
@@ -0,0 +1,4 @@
1
+ export function sendConsole(payload) {
2
+ console.error(`[KorBus] ${payload.routeName} → ${payload.stationName}: ${payload.arrivalMsg} (vehicle: ${payload.vehicleId})`);
3
+ }
4
+ //# sourceMappingURL=console.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"console.js","sourceRoot":"","sources":["../../src/notifier/console.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,WAAW,CAAC,OAA4B;IACtD,OAAO,CAAC,KAAK,CACX,YAAY,OAAO,CAAC,SAAS,MAAM,OAAO,CAAC,WAAW,KAAK,OAAO,CAAC,UAAU,cAAc,OAAO,CAAC,SAAS,GAAG,CAChH,CAAC;AACJ,CAAC"}
@@ -0,0 +1,11 @@
1
+ import type { NotificationPayload } from '../types.js';
2
+ export interface Dispatcher {
3
+ dispatch(channel: {
4
+ type: string;
5
+ config: string;
6
+ }, payload: NotificationPayload): Promise<void>;
7
+ }
8
+ export declare function createDispatcher(config?: {
9
+ telegramBotToken?: string;
10
+ }): Dispatcher;
11
+ //# sourceMappingURL=dispatcher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dispatcher.d.ts","sourceRoot":"","sources":["../../src/notifier/dispatcher.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAKvD,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,EAAE,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAClG;AAED,wBAAgB,gBAAgB,CAAC,MAAM,CAAC,EAAE;IAAE,gBAAgB,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,UAAU,CAwBnF"}
@@ -0,0 +1,28 @@
1
+ import { sendConsole } from './console.js';
2
+ import { sendWebhook } from './webhook.js';
3
+ import { sendTelegram } from './telegram.js';
4
+ export function createDispatcher(config) {
5
+ const telegramBotToken = config?.telegramBotToken ?? process.env.TELEGRAM_BOT_TOKEN ?? '';
6
+ return {
7
+ async dispatch(channel, payload) {
8
+ if (channel.type === 'CONSOLE') {
9
+ sendConsole(payload);
10
+ return;
11
+ }
12
+ if (channel.type === 'WEBHOOK') {
13
+ const cfg = JSON.parse(channel.config || '{}');
14
+ if (!cfg.url)
15
+ return;
16
+ await sendWebhook(cfg.url, payload);
17
+ return;
18
+ }
19
+ if (channel.type === 'TELEGRAM') {
20
+ const cfg = JSON.parse(channel.config || '{}');
21
+ if (!cfg.chatId || !telegramBotToken)
22
+ return;
23
+ await sendTelegram(telegramBotToken, cfg.chatId, payload);
24
+ }
25
+ },
26
+ };
27
+ }
28
+ //# sourceMappingURL=dispatcher.js.map