npb-mcp-server 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 (50) hide show
  1. package/README.md +301 -0
  2. package/dist/constants/teams.d.ts +14 -0
  3. package/dist/constants/teams.d.ts.map +1 -0
  4. package/dist/constants/teams.js +104 -0
  5. package/dist/constants/teams.js.map +1 -0
  6. package/dist/constants/teams.test.d.ts +2 -0
  7. package/dist/constants/teams.test.d.ts.map +1 -0
  8. package/dist/constants/teams.test.js +93 -0
  9. package/dist/constants/teams.test.js.map +1 -0
  10. package/dist/index.d.ts +3 -0
  11. package/dist/index.d.ts.map +1 -0
  12. package/dist/index.js +268 -0
  13. package/dist/index.js.map +1 -0
  14. package/dist/scrapers/players.d.ts +14 -0
  15. package/dist/scrapers/players.d.ts.map +1 -0
  16. package/dist/scrapers/players.js +151 -0
  17. package/dist/scrapers/players.js.map +1 -0
  18. package/dist/tools/get-team-players.d.ts +13 -0
  19. package/dist/tools/get-team-players.d.ts.map +1 -0
  20. package/dist/tools/get-team-players.js +28 -0
  21. package/dist/tools/get-team-players.js.map +1 -0
  22. package/dist/tools/list-teams.d.ts +13 -0
  23. package/dist/tools/list-teams.d.ts.map +1 -0
  24. package/dist/tools/list-teams.js +22 -0
  25. package/dist/tools/list-teams.js.map +1 -0
  26. package/dist/tools/list-teams.test.d.ts +2 -0
  27. package/dist/tools/list-teams.test.d.ts.map +1 -0
  28. package/dist/tools/list-teams.test.js +46 -0
  29. package/dist/tools/list-teams.test.js.map +1 -0
  30. package/dist/tools/search-players.d.ts +16 -0
  31. package/dist/tools/search-players.d.ts.map +1 -0
  32. package/dist/tools/search-players.js +41 -0
  33. package/dist/tools/search-players.js.map +1 -0
  34. package/dist/types/npb.d.ts +51 -0
  35. package/dist/types/npb.d.ts.map +1 -0
  36. package/dist/types/npb.js +2 -0
  37. package/dist/types/npb.js.map +1 -0
  38. package/dist/utils/cache.d.ts +37 -0
  39. package/dist/utils/cache.d.ts.map +1 -0
  40. package/dist/utils/cache.js +75 -0
  41. package/dist/utils/cache.js.map +1 -0
  42. package/dist/utils/cache.test.d.ts +2 -0
  43. package/dist/utils/cache.test.d.ts.map +1 -0
  44. package/dist/utils/cache.test.js +62 -0
  45. package/dist/utils/cache.test.js.map +1 -0
  46. package/dist/utils/http.d.ts +9 -0
  47. package/dist/utils/http.d.ts.map +1 -0
  48. package/dist/utils/http.js +50 -0
  49. package/dist/utils/http.js.map +1 -0
  50. package/package.json +72 -0
@@ -0,0 +1,41 @@
1
+ import { TEAMS } from '../constants/teams.js';
2
+ import { getAllPlayers } from '../scrapers/players.js';
3
+ /**
4
+ * search_players ツールの実装
5
+ * 選手名やその他の条件で選手を検索
6
+ */
7
+ export async function searchPlayers(args) {
8
+ const { name, team_id, position, number } = args;
9
+ // 対象の球団を決定
10
+ const targetTeams = team_id ? TEAMS.filter((t) => t.id === team_id) : TEAMS;
11
+ // すべての選手を取得
12
+ const rostersMap = await getAllPlayers(targetTeams);
13
+ let allPlayers = [];
14
+ for (const roster of rostersMap.values()) {
15
+ allPlayers = allPlayers.concat(roster.players);
16
+ }
17
+ // フィルタリング
18
+ let results = allPlayers;
19
+ if (name) {
20
+ const searchName = name.toLowerCase();
21
+ results = results.filter((p) => p.name.toLowerCase().includes(searchName));
22
+ }
23
+ if (position) {
24
+ results = results.filter((p) => p.position === position);
25
+ }
26
+ if (number) {
27
+ results = results.filter((p) => p.number === number);
28
+ }
29
+ return {
30
+ content: [
31
+ {
32
+ type: 'text',
33
+ text: JSON.stringify({
34
+ resultCount: results.length,
35
+ players: results,
36
+ }, null, 2),
37
+ },
38
+ ],
39
+ };
40
+ }
41
+ //# sourceMappingURL=search-players.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search-players.js","sourceRoot":"","sources":["../../src/tools/search-players.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAGvD;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,IAKnC;IACC,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IAEjD,WAAW;IACX,MAAM,WAAW,GAAG,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;IAE5E,YAAY;IACZ,MAAM,UAAU,GAAG,MAAM,aAAa,CAAC,WAAW,CAAC,CAAC;IACpD,IAAI,UAAU,GAAa,EAAE,CAAC;IAE9B,KAAK,MAAM,MAAM,IAAI,UAAU,CAAC,MAAM,EAAE,EAAE,CAAC;QACzC,UAAU,GAAG,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IACjD,CAAC;IAED,UAAU;IACV,IAAI,OAAO,GAAG,UAAU,CAAC;IAEzB,IAAI,IAAI,EAAE,CAAC;QACT,MAAM,UAAU,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;QACtC,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC;IAC7E,CAAC;IAED,IAAI,QAAQ,EAAE,CAAC;QACb,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC;IAC3D,CAAC;IAED,IAAI,MAAM,EAAE,CAAC;QACX,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC;IACvD,CAAC;IAED,OAAO;QACL,OAAO,EAAE;YACP;gBACE,IAAI,EAAE,MAAM;gBACZ,IAAI,EAAE,IAAI,CAAC,SAAS,CAClB;oBACE,WAAW,EAAE,OAAO,CAAC,MAAM;oBAC3B,OAAO,EAAE,OAAO;iBACjB,EACD,IAAI,EACJ,CAAC,CACF;aACF;SACF;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * NPB球団のリーグ
3
+ */
4
+ export type League = 'central' | 'pacific';
5
+ /**
6
+ * 選手のポジション
7
+ */
8
+ export type Position = 'pitcher' | 'catcher' | 'infielder' | 'outfielder';
9
+ /**
10
+ * 選手の投打
11
+ */
12
+ export type Hand = '右' | '左' | '両';
13
+ /**
14
+ * 選手の分類
15
+ */
16
+ export type PlayerCategory = 'registered' | 'development';
17
+ /**
18
+ * NPB球団情報
19
+ */
20
+ export interface Team {
21
+ id: string;
22
+ name: string;
23
+ fullName: string;
24
+ league: League;
25
+ rosterUrl: string;
26
+ }
27
+ /**
28
+ * 選手情報
29
+ */
30
+ export interface Player {
31
+ number: string;
32
+ name: string;
33
+ birthDate: string;
34
+ height: number;
35
+ weight: number;
36
+ pitchingHand: Hand;
37
+ battingHand: Hand;
38
+ position: Position;
39
+ category: PlayerCategory;
40
+ note?: string;
41
+ teamId: string;
42
+ }
43
+ /**
44
+ * 球団別選手一覧
45
+ */
46
+ export interface TeamRoster {
47
+ team: Team;
48
+ players: Player[];
49
+ lastUpdated: Date;
50
+ }
51
+ //# sourceMappingURL=npb.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"npb.d.ts","sourceRoot":"","sources":["../../src/types/npb.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,MAAM,MAAM,GAAG,SAAS,GAAG,SAAS,CAAC;AAE3C;;GAEG;AACH,MAAM,MAAM,QAAQ,GAAG,SAAS,GAAG,SAAS,GAAG,WAAW,GAAG,YAAY,CAAC;AAE1E;;GAEG;AACH,MAAM,MAAM,IAAI,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;AAEnC;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG,YAAY,GAAG,aAAa,CAAC;AAE1D;;GAEG;AACH,MAAM,WAAW,IAAI;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,MAAM;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,IAAI,CAAC;IACnB,WAAW,EAAE,IAAI,CAAC;IAClB,QAAQ,EAAE,QAAQ,CAAC;IACnB,QAAQ,EAAE,cAAc,CAAC;IACzB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,IAAI,CAAC;IACX,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,WAAW,EAAE,IAAI,CAAC;CACnB"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=npb.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"npb.js","sourceRoot":"","sources":["../../src/types/npb.ts"],"names":[],"mappings":""}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * シンプルなインメモリキャッシュ
3
+ */
4
+ export declare class Cache {
5
+ private store;
6
+ private defaultTTL;
7
+ /**
8
+ * @param defaultTTL デフォルトのTTL(ミリ秒)、デフォルトは1時間
9
+ */
10
+ constructor(defaultTTL?: number);
11
+ /**
12
+ * キャッシュからデータを取得
13
+ */
14
+ get<T>(key: string): T | null;
15
+ /**
16
+ * キャッシュにデータを保存
17
+ */
18
+ set<T>(key: string, data: T, ttl?: number): void;
19
+ /**
20
+ * キャッシュからデータを削除
21
+ */
22
+ delete(key: string): boolean;
23
+ /**
24
+ * すべてのキャッシュをクリア
25
+ */
26
+ clear(): void;
27
+ /**
28
+ * 期限切れのエントリーを削除
29
+ */
30
+ cleanup(): void;
31
+ /**
32
+ * キャッシュサイズを取得
33
+ */
34
+ size(): number;
35
+ }
36
+ export declare const globalCache: Cache;
37
+ //# sourceMappingURL=cache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../src/utils/cache.ts"],"names":[],"mappings":"AASA;;GAEG;AACH,qBAAa,KAAK;IAChB,OAAO,CAAC,KAAK,CAAmC;IAChD,OAAO,CAAC,UAAU,CAAS;IAE3B;;OAEG;gBACS,UAAU,GAAE,MAAgB;IAKxC;;OAEG;IACH,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,GAAG,IAAI;IAmB7B;;OAEG;IACH,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI;IAUhD;;OAEG;IACH,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAI5B;;OAEG;IACH,KAAK,IAAI,IAAI;IAIb;;OAEG;IACH,OAAO,IAAI,IAAI;IAWf;;OAEG;IACH,IAAI,IAAI,MAAM;CAGf;AAGD,eAAO,MAAM,WAAW,OAAc,CAAC"}
@@ -0,0 +1,75 @@
1
+ /**
2
+ * シンプルなインメモリキャッシュ
3
+ */
4
+ export class Cache {
5
+ store;
6
+ defaultTTL;
7
+ /**
8
+ * @param defaultTTL デフォルトのTTL(ミリ秒)、デフォルトは1時間
9
+ */
10
+ constructor(defaultTTL = 3600000) {
11
+ this.store = new Map();
12
+ this.defaultTTL = defaultTTL;
13
+ }
14
+ /**
15
+ * キャッシュからデータを取得
16
+ */
17
+ get(key) {
18
+ const entry = this.store.get(key);
19
+ if (!entry) {
20
+ return null;
21
+ }
22
+ const now = Date.now();
23
+ const age = now - entry.timestamp;
24
+ // TTLを超えている場合は削除して null を返す
25
+ if (age > entry.ttl) {
26
+ this.store.delete(key);
27
+ return null;
28
+ }
29
+ return entry.data;
30
+ }
31
+ /**
32
+ * キャッシュにデータを保存
33
+ */
34
+ set(key, data, ttl) {
35
+ const entry = {
36
+ data,
37
+ timestamp: Date.now(),
38
+ ttl: ttl ?? this.defaultTTL,
39
+ };
40
+ this.store.set(key, entry);
41
+ }
42
+ /**
43
+ * キャッシュからデータを削除
44
+ */
45
+ delete(key) {
46
+ return this.store.delete(key);
47
+ }
48
+ /**
49
+ * すべてのキャッシュをクリア
50
+ */
51
+ clear() {
52
+ this.store.clear();
53
+ }
54
+ /**
55
+ * 期限切れのエントリーを削除
56
+ */
57
+ cleanup() {
58
+ const now = Date.now();
59
+ for (const [key, entry] of this.store.entries()) {
60
+ const age = now - entry.timestamp;
61
+ if (age > entry.ttl) {
62
+ this.store.delete(key);
63
+ }
64
+ }
65
+ }
66
+ /**
67
+ * キャッシュサイズを取得
68
+ */
69
+ size() {
70
+ return this.store.size;
71
+ }
72
+ }
73
+ // グローバルキャッシュインスタンス
74
+ export const globalCache = new Cache();
75
+ //# sourceMappingURL=cache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.js","sourceRoot":"","sources":["../../src/utils/cache.ts"],"names":[],"mappings":"AASA;;GAEG;AACH,MAAM,OAAO,KAAK;IACR,KAAK,CAAmC;IACxC,UAAU,CAAS;IAE3B;;OAEG;IACH,YAAY,aAAqB,OAAO;QACtC,IAAI,CAAC,KAAK,GAAG,IAAI,GAAG,EAAE,CAAC;QACvB,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;IAC/B,CAAC;IAED;;OAEG;IACH,GAAG,CAAI,GAAW;QAChB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAElC,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,MAAM,GAAG,GAAG,GAAG,GAAG,KAAK,CAAC,SAAS,CAAC;QAElC,4BAA4B;QAC5B,IAAI,GAAG,GAAG,KAAK,CAAC,GAAG,EAAE,CAAC;YACpB,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACvB,OAAO,IAAI,CAAC;QACd,CAAC;QAED,OAAO,KAAK,CAAC,IAAS,CAAC;IACzB,CAAC;IAED;;OAEG;IACH,GAAG,CAAI,GAAW,EAAE,IAAO,EAAE,GAAY;QACvC,MAAM,KAAK,GAAkB;YAC3B,IAAI;YACJ,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;YACrB,GAAG,EAAE,GAAG,IAAI,IAAI,CAAC,UAAU;SAC5B,CAAC;QAEF,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IAC7B,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,GAAW;QAChB,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAChC,CAAC;IAED;;OAEG;IACH,KAAK;QACH,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;IACrB,CAAC;IAED;;OAEG;IACH,OAAO;QACL,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAEvB,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,EAAE,CAAC;YAChD,MAAM,GAAG,GAAG,GAAG,GAAG,KAAK,CAAC,SAAS,CAAC;YAClC,IAAI,GAAG,GAAG,KAAK,CAAC,GAAG,EAAE,CAAC;gBACpB,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACzB,CAAC;QACH,CAAC;IACH,CAAC;IAED;;OAEG;IACH,IAAI;QACF,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;IACzB,CAAC;CACF;AAED,mBAAmB;AACnB,MAAM,CAAC,MAAM,WAAW,GAAG,IAAI,KAAK,EAAE,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=cache.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.test.d.ts","sourceRoot":"","sources":["../../src/utils/cache.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,62 @@
1
+ import { describe, it, expect, beforeEach } from 'vitest';
2
+ import { Cache } from './cache.js';
3
+ describe('Cache', () => {
4
+ let cache;
5
+ beforeEach(() => {
6
+ cache = new Cache(1000); // 1秒のTTL
7
+ });
8
+ it('データを保存して取得できる', () => {
9
+ cache.set('key1', 'value1');
10
+ expect(cache.get('key1')).toBe('value1');
11
+ });
12
+ it('存在しないキーはnullを返す', () => {
13
+ expect(cache.get('nonexistent')).toBeNull();
14
+ });
15
+ it('TTLが切れたデータはnullを返す', async () => {
16
+ cache.set('key1', 'value1', 100); // 100msのTTL
17
+ expect(cache.get('key1')).toBe('value1');
18
+ // 150ms待つ
19
+ await new Promise((resolve) => setTimeout(resolve, 150));
20
+ expect(cache.get('key1')).toBeNull();
21
+ });
22
+ it('データを削除できる', () => {
23
+ cache.set('key1', 'value1');
24
+ expect(cache.delete('key1')).toBe(true);
25
+ expect(cache.get('key1')).toBeNull();
26
+ });
27
+ it('存在しないキーの削除はfalseを返す', () => {
28
+ expect(cache.delete('nonexistent')).toBe(false);
29
+ });
30
+ it('すべてのデータをクリアできる', () => {
31
+ cache.set('key1', 'value1');
32
+ cache.set('key2', 'value2');
33
+ cache.clear();
34
+ expect(cache.get('key1')).toBeNull();
35
+ expect(cache.get('key2')).toBeNull();
36
+ expect(cache.size()).toBe(0);
37
+ });
38
+ it('キャッシュサイズを取得できる', () => {
39
+ expect(cache.size()).toBe(0);
40
+ cache.set('key1', 'value1');
41
+ cache.set('key2', 'value2');
42
+ expect(cache.size()).toBe(2);
43
+ });
44
+ it('期限切れエントリーをクリーンアップできる', async () => {
45
+ cache.set('key1', 'value1', 100); // 100msのTTL
46
+ cache.set('key2', 'value2', 5000); // 5秒のTTL
47
+ expect(cache.size()).toBe(2);
48
+ // 150ms待つ
49
+ await new Promise((resolve) => setTimeout(resolve, 150));
50
+ cache.cleanup();
51
+ expect(cache.size()).toBe(1);
52
+ expect(cache.get('key1')).toBeNull();
53
+ expect(cache.get('key2')).toBe('value2');
54
+ });
55
+ it('複雑なオブジェクトを保存できる', () => {
56
+ const obj = { name: 'test', values: [1, 2, 3] };
57
+ cache.set('obj', obj);
58
+ const retrieved = cache.get('obj');
59
+ expect(retrieved).toEqual(obj);
60
+ });
61
+ });
62
+ //# sourceMappingURL=cache.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.test.js","sourceRoot":"","sources":["../../src/utils/cache.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * URLからHTMLを取得
3
+ */
4
+ export declare function fetchHTML(url: string): Promise<string>;
5
+ /**
6
+ * 複数のURLから並列でHTMLを取得
7
+ */
8
+ export declare function fetchMultipleHTML(urls: string[]): Promise<Map<string, string>>;
9
+ //# sourceMappingURL=http.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../src/utils/http.ts"],"names":[],"mappings":"AAWA;;GAEG;AACH,wBAAsB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAmB5D;AAED;;GAEG;AACH,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAepF"}
@@ -0,0 +1,50 @@
1
+ import fetch from 'node-fetch';
2
+ /**
3
+ * HTTPクライアント設定
4
+ */
5
+ const DEFAULT_HEADERS = {
6
+ 'User-Agent': 'NPB-MCP-Server/0.1.0',
7
+ Accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
8
+ 'Accept-Language': 'ja,en;q=0.9',
9
+ };
10
+ /**
11
+ * URLからHTMLを取得
12
+ */
13
+ export async function fetchHTML(url) {
14
+ try {
15
+ const response = await fetch(url, {
16
+ headers: DEFAULT_HEADERS,
17
+ redirect: 'follow',
18
+ });
19
+ if (!response.ok) {
20
+ throw new Error(`HTTP error! status: ${response.status}`);
21
+ }
22
+ const html = await response.text();
23
+ return html;
24
+ }
25
+ catch (error) {
26
+ if (error instanceof Error) {
27
+ throw new Error(`Failed to fetch ${url}: ${error.message}`);
28
+ }
29
+ throw error;
30
+ }
31
+ }
32
+ /**
33
+ * 複数のURLから並列でHTMLを取得
34
+ */
35
+ export async function fetchMultipleHTML(urls) {
36
+ const results = new Map();
37
+ const promises = urls.map(async (url) => {
38
+ try {
39
+ const html = await fetchHTML(url);
40
+ results.set(url, html);
41
+ }
42
+ catch (error) {
43
+ console.error(`Error fetching ${url}:`, error);
44
+ // エラーの場合は結果に含めない
45
+ }
46
+ });
47
+ await Promise.all(promises);
48
+ return results;
49
+ }
50
+ //# sourceMappingURL=http.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.js","sourceRoot":"","sources":["../../src/utils/http.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,YAAY,CAAC;AAE/B;;GAEG;AACH,MAAM,eAAe,GAAG;IACtB,YAAY,EAAE,sBAAsB;IACpC,MAAM,EAAE,iEAAiE;IACzE,iBAAiB,EAAE,aAAa;CACjC,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,GAAW;IACzC,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;YAChC,OAAO,EAAE,eAAe;YACxB,QAAQ,EAAE,QAAQ;SACnB,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,uBAAuB,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;QAC5D,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;QACnC,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;YAC3B,MAAM,IAAI,KAAK,CAAC,mBAAmB,GAAG,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;QAC9D,CAAC;QACD,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,IAAc;IACpD,MAAM,OAAO,GAAG,IAAI,GAAG,EAAkB,CAAC;IAE1C,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;QACtC,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,MAAM,SAAS,CAAC,GAAG,CAAC,CAAC;YAClC,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QACzB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,kBAAkB,GAAG,GAAG,EAAE,KAAK,CAAC,CAAC;YAC/C,iBAAiB;QACnB,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,MAAM,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAC5B,OAAO,OAAO,CAAC;AACjB,CAAC"}
package/package.json ADDED
@@ -0,0 +1,72 @@
1
+ {
2
+ "name": "npb-mcp-server",
3
+ "version": "0.1.0",
4
+ "description": "MCP Server for NPB (Nippon Professional Baseball) player and team information",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "bin": {
8
+ "npb-mcp-server": "dist/index.js"
9
+ },
10
+ "scripts": {
11
+ "build": "tsc",
12
+ "dev": "tsc --watch",
13
+ "start": "node dist/index.js",
14
+ "start:http": "MCP_TRANSPORT=http node dist/index.js",
15
+ "test": "vitest run",
16
+ "test:watch": "vitest",
17
+ "test:coverage": "vitest run --coverage",
18
+ "lint": "eslint . --ext .ts,.tsx",
19
+ "lint:fix": "eslint . --ext .ts,.tsx --fix",
20
+ "format": "prettier --write \"src/**/*.{ts,tsx,json,md}\"",
21
+ "format:check": "prettier --check \"src/**/*.{ts,tsx,json,md}\"",
22
+ "fix": "run-s format lint:fix",
23
+ "check": "run-p lint format:check test",
24
+ "prepare": "npm run build",
25
+ "release:patch": "npm version patch && git push --follow-tags",
26
+ "release:minor": "npm version minor && git push --follow-tags",
27
+ "release:major": "npm version major && git push --follow-tags"
28
+ },
29
+ "keywords": [
30
+ "mcp",
31
+ "npb",
32
+ "baseball",
33
+ "japan",
34
+ "model-context-protocol",
35
+ "scraping"
36
+ ],
37
+ "author": "MITSUBOSHI <yuya.mitsuboshi@gmail.com> (https://github.com/MITSUBOSHI)",
38
+ "license": "MIT",
39
+ "repository": {
40
+ "type": "git",
41
+ "url": "git+https://github.com/MITSUBOSHI/npb-mcp-server.git"
42
+ },
43
+ "homepage": "https://github.com/MITSUBOSHI/npb-mcp-server#readme",
44
+ "bugs": {
45
+ "url": "https://github.com/MITSUBOSHI/npb-mcp-server/issues"
46
+ },
47
+ "files": [
48
+ "dist",
49
+ "README.md"
50
+ ],
51
+ "dependencies": {
52
+ "@modelcontextprotocol/sdk": "^1.0.4",
53
+ "cheerio": "^1.0.0",
54
+ "hono": "^4.6.14",
55
+ "@hono/node-server": "^1.13.7",
56
+ "node-fetch": "^3.3.2"
57
+ },
58
+ "devDependencies": {
59
+ "@types/node": "^20.11.0",
60
+ "@typescript-eslint/eslint-plugin": "^8.21.0",
61
+ "@typescript-eslint/parser": "^8.21.0",
62
+ "@vitest/coverage-v8": "^2.1.8",
63
+ "eslint": "^9.18.0",
64
+ "eslint-config-prettier": "^9.1.0",
65
+ "eslint-plugin-prettier": "^5.2.1",
66
+ "globals": "^15.13.0",
67
+ "npm-run-all": "^4.1.5",
68
+ "prettier": "^3.4.2",
69
+ "typescript": "^5.3.3",
70
+ "vitest": "^2.1.8"
71
+ }
72
+ }