@shuji-bonji/rfcxml-mcp 0.1.2 → 0.1.3

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.ja.md CHANGED
@@ -246,6 +246,66 @@ RFC 8650 (2019年12月) 以降は公式 RFCXML v3 形式で提供されていま
246
246
  }
247
247
  ```
248
248
 
249
+ ## 内部アーキテクチャ
250
+
251
+ ### モジュール構成
252
+
253
+ ```
254
+ src/
255
+ ├── index.ts # MCP サーバーエントリポイント
256
+ ├── config.ts # 設定の一元管理
257
+ ├── constants.ts # BCP 14 キーワード定義
258
+ ├── services/
259
+ │ ├── rfc-fetcher.ts # RFC 取得(並列フェッチ)
260
+ │ ├── rfcxml-parser.ts # RFCXML パーサー
261
+ │ └── rfc-text-parser.ts # テキストフォールバック
262
+ ├── tools/
263
+ │ ├── definitions.ts # MCP ツール定義
264
+ │ └── handlers.ts # ツールハンドラー
265
+ ├── types/
266
+ │ └── index.ts # 型定義
267
+ └── utils/
268
+ ├── cache.ts # LRU キャッシュ
269
+ ├── fetch.ts # 並列フェッチユーティリティ
270
+ └── text.ts # テキスト処理ユーティリティ
271
+ ```
272
+
273
+ ### RFC 取得の最適化
274
+
275
+ 複数ソース(RFC Editor、IETF Tools、Datatracker)に並列リクエストを送信し、最初に成功したレスポンスを採用:
276
+
277
+ ```
278
+ ┌─────────────────┐
279
+ │ fetchRFCXML() │
280
+ └────────┬────────┘
281
+ │ 並列リクエスト
282
+ ┌────┴────┬────────────┐
283
+ ▼ ▼ ▼
284
+ ┌────────┐ ┌────────┐ ┌────────┐
285
+ │RFC │ │IETF │ │Data- │
286
+ │Editor │ │Tools │ │tracker │
287
+ └────┬───┘ └────┬───┘ └────┬───┘
288
+ │ │ │
289
+ └────┬─────┴──────────┘
290
+ │ Promise.any(最初の成功)
291
+
292
+ ┌───────────┐
293
+ │ 成功した │ → 他のリクエストを AbortController でキャンセル
294
+ │ レスポンス│
295
+ └───────────┘
296
+ ```
297
+
298
+ ### キャッシュ戦略
299
+
300
+ LRU(Least Recently Used)キャッシュでメモリ使用量を制限:
301
+
302
+ | キャッシュ | 最大エントリ数 | 内容 |
303
+ |-----------|---------------|------|
304
+ | XML キャッシュ | 20 | 生の RFCXML |
305
+ | Text キャッシュ | 20 | 生のテキスト |
306
+ | Metadata キャッシュ | 100 | RFC メタデータ |
307
+ | Parse キャッシュ | 50 | パース済み構造 |
308
+
249
309
  ## 開発
250
310
 
251
311
  ```bash
@@ -260,6 +320,12 @@ npm run build
260
320
 
261
321
  # テスト
262
322
  npm test
323
+
324
+ # リント
325
+ npm run lint
326
+
327
+ # フォーマット
328
+ npm run format
263
329
  ```
264
330
 
265
331
  ## ライセンス
package/README.md CHANGED
@@ -244,6 +244,66 @@ Role: Client
244
244
  }
245
245
  ```
246
246
 
247
+ ## Internal Architecture
248
+
249
+ ### Module Structure
250
+
251
+ ```
252
+ src/
253
+ ├── index.ts # MCP server entry point
254
+ ├── config.ts # Centralized configuration
255
+ ├── constants.ts # BCP 14 keyword definitions
256
+ ├── services/
257
+ │ ├── rfc-fetcher.ts # RFC fetching (parallel)
258
+ │ ├── rfcxml-parser.ts # RFCXML parser
259
+ │ └── rfc-text-parser.ts # Text fallback parser
260
+ ├── tools/
261
+ │ ├── definitions.ts # MCP tool definitions
262
+ │ └── handlers.ts # Tool handlers
263
+ ├── types/
264
+ │ └── index.ts # Type definitions
265
+ └── utils/
266
+ ├── cache.ts # LRU cache
267
+ ├── fetch.ts # Parallel fetch utility
268
+ └── text.ts # Text processing utility
269
+ ```
270
+
271
+ ### RFC Fetch Optimization
272
+
273
+ Sends parallel requests to multiple sources (RFC Editor, IETF Tools, Datatracker) and uses the first successful response:
274
+
275
+ ```
276
+ ┌─────────────────┐
277
+ │ fetchRFCXML() │
278
+ └────────┬────────┘
279
+ │ Parallel requests
280
+ ┌────┴────┬────────────┐
281
+ ▼ ▼ ▼
282
+ ┌────────┐ ┌────────┐ ┌────────┐
283
+ │RFC │ │IETF │ │Data- │
284
+ │Editor │ │Tools │ │tracker │
285
+ └────┬───┘ └────┬───┘ └────┬───┘
286
+ │ │ │
287
+ └────┬─────┴──────────┘
288
+ │ Promise.any (first success)
289
+
290
+ ┌───────────┐
291
+ │ Successful│ → Cancel other requests via AbortController
292
+ │ Response │
293
+ └───────────┘
294
+ ```
295
+
296
+ ### Cache Strategy
297
+
298
+ LRU (Least Recently Used) cache with memory limits:
299
+
300
+ | Cache | Max Entries | Content |
301
+ |-------|-------------|---------|
302
+ | XML Cache | 20 | Raw RFCXML |
303
+ | Text Cache | 20 | Raw text |
304
+ | Metadata Cache | 100 | RFC metadata |
305
+ | Parse Cache | 50 | Parsed structure |
306
+
247
307
  ## Development
248
308
 
249
309
  ```bash
@@ -0,0 +1,91 @@
1
+ /**
2
+ * アプリケーション設定
3
+ * すべての設定値を一箇所で管理
4
+ */
5
+ /**
6
+ * パッケージ情報
7
+ */
8
+ export declare const PACKAGE_INFO: {
9
+ readonly name: "rfcxml-mcp";
10
+ readonly version: "0.1.2";
11
+ };
12
+ /**
13
+ * HTTP リクエスト設定
14
+ */
15
+ export declare const HTTP_CONFIG: {
16
+ /** User-Agent ヘッダー */
17
+ readonly userAgent: "rfcxml-mcp/0.1.2";
18
+ /** タイムアウト(ミリ秒) */
19
+ readonly timeout: 30000;
20
+ /** リトライ回数 */
21
+ readonly maxRetries: 3;
22
+ };
23
+ /**
24
+ * キャッシュ設定
25
+ */
26
+ export declare const CACHE_CONFIG: {
27
+ /** XML 生データキャッシュ(小さめ:パース済みがメイン) */
28
+ readonly xml: {
29
+ readonly maxSize: 20;
30
+ readonly name: "XMLCache";
31
+ };
32
+ /** テキスト生データキャッシュ */
33
+ readonly text: {
34
+ readonly maxSize: 20;
35
+ readonly name: "TextCache";
36
+ };
37
+ /** メタデータキャッシュ(軽量なので多め) */
38
+ readonly metadata: {
39
+ readonly maxSize: 100;
40
+ readonly name: "MetadataCache";
41
+ };
42
+ /** パース済み RFC キャッシュ(メインキャッシュ) */
43
+ readonly parsed: {
44
+ readonly maxSize: 50;
45
+ readonly name: "ParseCache";
46
+ };
47
+ };
48
+ /**
49
+ * RFC 関連の設定
50
+ */
51
+ export declare const RFC_CONFIG: {
52
+ /**
53
+ * RFCXML v3 が確実に利用可能な最小 RFC 番号
54
+ * RFC 8650 (2019年12月) 以降は公式に RFCXML v3 形式
55
+ */
56
+ readonly xmlAvailableFrom: 8650;
57
+ };
58
+ /**
59
+ * RFC XML ソースの取得元
60
+ * 優先順位順に定義
61
+ */
62
+ export declare const RFC_XML_SOURCES: {
63
+ /** RFC Editor 公式 */
64
+ readonly rfcEditor: (num: number) => string;
65
+ /** IETF Tools */
66
+ readonly ietfTools: (num: number) => string;
67
+ /** Datatracker */
68
+ readonly datatracker: (num: number) => string;
69
+ };
70
+ /**
71
+ * RFC テキストソースの取得元
72
+ * 優先順位順に定義
73
+ */
74
+ export declare const RFC_TEXT_SOURCES: {
75
+ /** RFC Editor 公式(テキスト) */
76
+ readonly rfcEditor: (num: number) => string;
77
+ /** IETF Tools */
78
+ readonly ietfTools: (num: number) => string;
79
+ };
80
+ /**
81
+ * IETF Datatracker API
82
+ */
83
+ export declare const DATATRACKER_API: {
84
+ /** RFC ドキュメント情報 */
85
+ readonly document: (num: number) => string;
86
+ };
87
+ /**
88
+ * RFC が XML 形式で利用可能か確認
89
+ */
90
+ export declare function isRFCXMLLikelyAvailable(rfcNumber: number): boolean;
91
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;GAEG;AACH,eAAO,MAAM,YAAY;;;CAGf,CAAC;AAEX;;GAEG;AACH,eAAO,MAAM,WAAW;IACtB,sBAAsB;;IAEtB,kBAAkB;;IAElB,aAAa;;CAEL,CAAC;AAEX;;GAEG;AACH,eAAO,MAAM,YAAY;IACvB,mCAAmC;;;;;IAKnC,oBAAoB;;;;;IAKpB,0BAA0B;;;;;IAK1B,gCAAgC;;;;;CAKxB,CAAC;AAEX;;GAEG;AACH,eAAO,MAAM,UAAU;IACrB;;;OAGG;;CAEK,CAAC;AAEX;;;GAGG;AACH,eAAO,MAAM,eAAe;IAC1B,oBAAoB;8BACH,MAAM;IACvB,iBAAiB;8BACA,MAAM;IACvB,kBAAkB;gCACC,MAAM;CACjB,CAAC;AAEX;;;GAGG;AACH,eAAO,MAAM,gBAAgB;IAC3B,0BAA0B;8BACT,MAAM;IACvB,iBAAiB;8BACA,MAAM;CACf,CAAC;AAEX;;GAEG;AACH,eAAO,MAAM,eAAe;IAC1B,mBAAmB;6BACH,MAAM;CACd,CAAC;AAEX;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAElE"}
package/dist/config.js ADDED
@@ -0,0 +1,93 @@
1
+ /**
2
+ * アプリケーション設定
3
+ * すべての設定値を一箇所で管理
4
+ */
5
+ /**
6
+ * パッケージ情報
7
+ */
8
+ export const PACKAGE_INFO = {
9
+ name: 'rfcxml-mcp',
10
+ version: '0.1.2',
11
+ };
12
+ /**
13
+ * HTTP リクエスト設定
14
+ */
15
+ export const HTTP_CONFIG = {
16
+ /** User-Agent ヘッダー */
17
+ userAgent: `${PACKAGE_INFO.name}/${PACKAGE_INFO.version}`,
18
+ /** タイムアウト(ミリ秒) */
19
+ timeout: 30000,
20
+ /** リトライ回数 */
21
+ maxRetries: 3,
22
+ };
23
+ /**
24
+ * キャッシュ設定
25
+ */
26
+ export const CACHE_CONFIG = {
27
+ /** XML 生データキャッシュ(小さめ:パース済みがメイン) */
28
+ xml: {
29
+ maxSize: 20,
30
+ name: 'XMLCache',
31
+ },
32
+ /** テキスト生データキャッシュ */
33
+ text: {
34
+ maxSize: 20,
35
+ name: 'TextCache',
36
+ },
37
+ /** メタデータキャッシュ(軽量なので多め) */
38
+ metadata: {
39
+ maxSize: 100,
40
+ name: 'MetadataCache',
41
+ },
42
+ /** パース済み RFC キャッシュ(メインキャッシュ) */
43
+ parsed: {
44
+ maxSize: 50,
45
+ name: 'ParseCache',
46
+ },
47
+ };
48
+ /**
49
+ * RFC 関連の設定
50
+ */
51
+ export const RFC_CONFIG = {
52
+ /**
53
+ * RFCXML v3 が確実に利用可能な最小 RFC 番号
54
+ * RFC 8650 (2019年12月) 以降は公式に RFCXML v3 形式
55
+ */
56
+ xmlAvailableFrom: 8650,
57
+ };
58
+ /**
59
+ * RFC XML ソースの取得元
60
+ * 優先順位順に定義
61
+ */
62
+ export const RFC_XML_SOURCES = {
63
+ /** RFC Editor 公式 */
64
+ rfcEditor: (num) => `https://www.rfc-editor.org/rfc/rfc${num}.xml`,
65
+ /** IETF Tools */
66
+ ietfTools: (num) => `https://xml2rfc.ietf.org/public/rfc/rfc${num}.xml`,
67
+ /** Datatracker */
68
+ datatracker: (num) => `https://datatracker.ietf.org/doc/rfc${num}/xml/`,
69
+ };
70
+ /**
71
+ * RFC テキストソースの取得元
72
+ * 優先順位順に定義
73
+ */
74
+ export const RFC_TEXT_SOURCES = {
75
+ /** RFC Editor 公式(テキスト) */
76
+ rfcEditor: (num) => `https://www.rfc-editor.org/rfc/rfc${num}.txt`,
77
+ /** IETF Tools */
78
+ ietfTools: (num) => `https://tools.ietf.org/rfc/rfc${num}.txt`,
79
+ };
80
+ /**
81
+ * IETF Datatracker API
82
+ */
83
+ export const DATATRACKER_API = {
84
+ /** RFC ドキュメント情報 */
85
+ document: (num) => `https://datatracker.ietf.org/api/v1/doc/document/rfc${num}/`,
86
+ };
87
+ /**
88
+ * RFC が XML 形式で利用可能か確認
89
+ */
90
+ export function isRFCXMLLikelyAvailable(rfcNumber) {
91
+ return rfcNumber >= RFC_CONFIG.xmlAvailableFrom;
92
+ }
93
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;GAEG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,IAAI,EAAE,YAAY;IAClB,OAAO,EAAE,OAAO;CACR,CAAC;AAEX;;GAEG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,sBAAsB;IACtB,SAAS,EAAE,GAAG,YAAY,CAAC,IAAI,IAAI,YAAY,CAAC,OAAO,EAAE;IACzD,kBAAkB;IAClB,OAAO,EAAE,KAAK;IACd,aAAa;IACb,UAAU,EAAE,CAAC;CACL,CAAC;AAEX;;GAEG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,mCAAmC;IACnC,GAAG,EAAE;QACH,OAAO,EAAE,EAAE;QACX,IAAI,EAAE,UAAU;KACjB;IACD,oBAAoB;IACpB,IAAI,EAAE;QACJ,OAAO,EAAE,EAAE;QACX,IAAI,EAAE,WAAW;KAClB;IACD,0BAA0B;IAC1B,QAAQ,EAAE;QACR,OAAO,EAAE,GAAG;QACZ,IAAI,EAAE,eAAe;KACtB;IACD,gCAAgC;IAChC,MAAM,EAAE;QACN,OAAO,EAAE,EAAE;QACX,IAAI,EAAE,YAAY;KACnB;CACO,CAAC;AAEX;;GAEG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB;;;OAGG;IACH,gBAAgB,EAAE,IAAI;CACd,CAAC;AAEX;;;GAGG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,oBAAoB;IACpB,SAAS,EAAE,CAAC,GAAW,EAAE,EAAE,CAAC,qCAAqC,GAAG,MAAM;IAC1E,iBAAiB;IACjB,SAAS,EAAE,CAAC,GAAW,EAAE,EAAE,CAAC,0CAA0C,GAAG,MAAM;IAC/E,kBAAkB;IAClB,WAAW,EAAE,CAAC,GAAW,EAAE,EAAE,CAAC,uCAAuC,GAAG,OAAO;CACvE,CAAC;AAEX;;;GAGG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,0BAA0B;IAC1B,SAAS,EAAE,CAAC,GAAW,EAAE,EAAE,CAAC,qCAAqC,GAAG,MAAM;IAC1E,iBAAiB;IACjB,SAAS,EAAE,CAAC,GAAW,EAAE,EAAE,CAAC,iCAAiC,GAAG,MAAM;CAC9D,CAAC;AAEX;;GAEG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,mBAAmB;IACnB,QAAQ,EAAE,CAAC,GAAW,EAAE,EAAE,CAAC,uDAAuD,GAAG,GAAG;CAChF,CAAC;AAEX;;GAEG;AACH,MAAM,UAAU,uBAAuB,CAAC,SAAiB;IACvD,OAAO,SAAS,IAAI,UAAU,CAAC,gBAAgB,CAAC;AAClD,CAAC"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * 共通定数
3
+ * BCP 14 / RFC 2119 キーワードとパターン
4
+ */
5
+ import type { RequirementLevel } from './types/index.js';
6
+ /**
7
+ * BCP 14 / RFC 2119 キーワード
8
+ * 長いキーワードから順に並べる("MUST NOT" を "MUST" より先にマッチさせるため)
9
+ */
10
+ export declare const REQUIREMENT_KEYWORDS: RequirementLevel[];
11
+ /**
12
+ * キーワードの正規表現(長い順にマッチ)
13
+ */
14
+ export declare const REQUIREMENT_REGEX: RegExp;
15
+ //# sourceMappingURL=constants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAEzD;;;GAGG;AACH,eAAO,MAAM,oBAAoB,EAAE,gBAAgB,EAYlD,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,iBAAiB,QAA+D,CAAC"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * 共通定数
3
+ * BCP 14 / RFC 2119 キーワードとパターン
4
+ */
5
+ /**
6
+ * BCP 14 / RFC 2119 キーワード
7
+ * 長いキーワードから順に並べる("MUST NOT" を "MUST" より先にマッチさせるため)
8
+ */
9
+ export const REQUIREMENT_KEYWORDS = [
10
+ 'MUST NOT',
11
+ 'MUST',
12
+ 'REQUIRED',
13
+ 'SHALL NOT',
14
+ 'SHALL',
15
+ 'SHOULD NOT',
16
+ 'SHOULD',
17
+ 'RECOMMENDED',
18
+ 'NOT RECOMMENDED',
19
+ 'MAY',
20
+ 'OPTIONAL',
21
+ ];
22
+ /**
23
+ * キーワードの正規表現(長い順にマッチ)
24
+ */
25
+ export const REQUIREMENT_REGEX = new RegExp(`\\b(${REQUIREMENT_KEYWORDS.join('|')})\\b`, 'g');
26
+ // RFC 関連の設定は config.ts に集約されています
27
+ // - RFC_CONFIG.xmlAvailableFrom
28
+ // - isRFCXMLLikelyAvailable()
29
+ //# sourceMappingURL=constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH;;;GAGG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAuB;IACtD,UAAU;IACV,MAAM;IACN,UAAU;IACV,WAAW;IACX,OAAO;IACP,YAAY;IACZ,QAAQ;IACR,aAAa;IACb,iBAAiB;IACjB,KAAK;IACL,UAAU;CACX,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,IAAI,MAAM,CAAC,OAAO,oBAAoB,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;AAE9F,iCAAiC;AACjC,gCAAgC;AAChC,8BAA8B"}
@@ -4,7 +4,8 @@
4
4
  */
5
5
  import type { RFCMetadata } from '../types/index.js';
6
6
  /**
7
- * RFCXML を取得
7
+ * RFCXML を取得(並列フェッチ)
8
+ * 複数ソースに同時リクエストし、最初に成功したものを返す
8
9
  */
9
10
  export declare function fetchRFCXML(rfcNumber: number): Promise<string>;
10
11
  /**
@@ -12,7 +13,8 @@ export declare function fetchRFCXML(rfcNumber: number): Promise<string>;
12
13
  */
13
14
  export declare function fetchRFCMetadata(rfcNumber: number): Promise<RFCMetadata>;
14
15
  /**
15
- * RFC テキストを取得
16
+ * RFC テキストを取得(並列フェッチ)
17
+ * 複数ソースに同時リクエストし、最初に成功したものを返す
16
18
  */
17
19
  export declare function fetchRFCText(rfcNumber: number): Promise<string>;
18
20
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"rfc-fetcher.d.ts","sourceRoot":"","sources":["../../src/services/rfc-fetcher.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AA6BrD;;GAEG;AACH,wBAAsB,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAwCpE;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAoD9E;AAED;;GAEG;AACH,wBAAsB,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAwCrE;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAI5D;AAED;;GAEG;AACH,qBAAa,uBAAwB,SAAQ,KAAK;IAChD,SAAgB,SAAS,EAAE,MAAM,CAAC;IAClC,SAAgB,QAAQ,EAAE,OAAO,CAAC;IAClC,SAAgB,UAAU,EAAE,MAAM,CAAC;gBAEvB,SAAS,EAAE,MAAM,EAAE,cAAc,GAAE,MAAM,EAAO;CAmB7D;AAED;;GAEG;AACH,wBAAgB,UAAU,IAAI,IAAI,CAIjC"}
1
+ {"version":3,"file":"rfc-fetcher.d.ts","sourceRoot":"","sources":["../../src/services/rfc-fetcher.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAiBrD;;;GAGG;AACH,wBAAsB,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CA6BpE;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAoD9E;AAED;;;GAGG;AACH,wBAAsB,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CA8BrE;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAE5D;AAED;;GAEG;AACH,qBAAa,uBAAwB,SAAQ,KAAK;IAChD,SAAgB,SAAS,EAAE,MAAM,CAAC;IAClC,SAAgB,QAAQ,EAAE,OAAO,CAAC;IAClC,SAAgB,UAAU,EAAE,MAAM,CAAC;gBAEvB,SAAS,EAAE,MAAM,EAAE,cAAc,GAAE,MAAM,EAAO;CAoB7D;AAED;;GAEG;AACH,wBAAgB,UAAU,IAAI,IAAI,CAIjC"}
@@ -2,32 +2,16 @@
2
2
  * RFC 取得サービス
3
3
  * RFCXML ソースの取得とキャッシュ管理
4
4
  */
5
- // キャッシュ(メモリ内)
6
- const xmlCache = new Map();
7
- const textCache = new Map();
8
- const metadataCache = new Map();
5
+ import { LRUCache } from '../utils/cache.js';
6
+ import { fetchFromMultipleSources } from '../utils/fetch.js';
7
+ import { CACHE_CONFIG, RFC_XML_SOURCES, RFC_TEXT_SOURCES, DATATRACKER_API, HTTP_CONFIG, RFC_CONFIG, } from '../config.js';
8
+ // LRU キャッシュ(設定は config.ts から)
9
+ const xmlCache = new LRUCache(CACHE_CONFIG.xml);
10
+ const textCache = new LRUCache(CACHE_CONFIG.text);
11
+ const metadataCache = new LRUCache(CACHE_CONFIG.metadata);
9
12
  /**
10
- * RFC XML ソースの取得元
11
- */
12
- const RFC_XML_SOURCES = {
13
- // RFC Editor 公式
14
- rfcEditor: (num) => `https://www.rfc-editor.org/rfc/rfc${num}.xml`,
15
- // IETF Tools
16
- ietfTools: (num) => `https://xml2rfc.ietf.org/public/rfc/rfc${num}.xml`,
17
- // Datatracker
18
- datatracker: (num) => `https://datatracker.ietf.org/doc/rfc${num}/xml/`,
19
- };
20
- /**
21
- * RFC テキストソースの取得元
22
- */
23
- const RFC_TEXT_SOURCES = {
24
- // RFC Editor 公式(テキスト)
25
- rfcEditor: (num) => `https://www.rfc-editor.org/rfc/rfc${num}.txt`,
26
- // IETF Tools
27
- ietfTools: (num) => `https://tools.ietf.org/rfc/rfc${num}.txt`,
28
- };
29
- /**
30
- * RFCXML を取得
13
+ * RFCXML を取得(並列フェッチ)
14
+ * 複数ソースに同時リクエストし、最初に成功したものを返す
31
15
  */
32
16
  export async function fetchRFCXML(rfcNumber) {
33
17
  // キャッシュチェック
@@ -35,33 +19,27 @@ export async function fetchRFCXML(rfcNumber) {
35
19
  if (cached) {
36
20
  return cached;
37
21
  }
38
- // 複数ソースを試行
39
- const errors = [];
40
- for (const [sourceName, urlFn] of Object.entries(RFC_XML_SOURCES)) {
41
- try {
42
- const url = urlFn(rfcNumber);
43
- const response = await fetch(url, {
44
- headers: {
45
- Accept: 'application/xml, text/xml',
46
- 'User-Agent': 'rfcxml-mcp/0.1.0',
47
- },
48
- });
49
- if (response.ok) {
50
- const xml = await response.text();
51
- // 基本的な XML 検証
52
- if (xml.includes('<?xml') || xml.includes('<rfc')) {
53
- xmlCache.set(rfcNumber, xml);
54
- console.error(`[RFC ${rfcNumber}] Fetched from ${sourceName}`);
55
- return xml;
56
- }
57
- }
58
- }
59
- catch (error) {
60
- errors.push(error);
61
- }
22
+ // ソースリストを作成
23
+ const sources = Object.entries(RFC_XML_SOURCES).map(([name, urlFn]) => ({
24
+ name,
25
+ url: urlFn(rfcNumber),
26
+ }));
27
+ try {
28
+ // 並列フェッチ(最初に成功したものを返す)
29
+ const { text: xml, source } = await fetchFromMultipleSources(sources, {
30
+ headers: { Accept: 'application/xml, text/xml' },
31
+ validate: (text) => text.includes('<?xml') || text.includes('<rfc'),
32
+ });
33
+ xmlCache.set(rfcNumber, xml);
34
+ console.error(`[RFC ${rfcNumber}] Fetched from ${source}`);
35
+ return xml;
36
+ }
37
+ catch (error) {
38
+ // すべて失敗した場合
39
+ throw new RFCXMLNotAvailableError(rfcNumber, [
40
+ error instanceof Error ? error.message : String(error),
41
+ ]);
62
42
  }
63
- // すべて失敗した場合
64
- throw new RFCXMLNotAvailableError(rfcNumber, errors.map((e) => e.message));
65
43
  }
66
44
  /**
67
45
  * RFC メタデータを取得(IETF Datatracker API)
@@ -72,12 +50,12 @@ export async function fetchRFCMetadata(rfcNumber) {
72
50
  if (cached) {
73
51
  return cached;
74
52
  }
75
- const url = `https://datatracker.ietf.org/api/v1/doc/document/rfc${rfcNumber}/`;
53
+ const url = DATATRACKER_API.document(rfcNumber);
76
54
  try {
77
55
  const response = await fetch(url, {
78
56
  headers: {
79
57
  Accept: 'application/json',
80
- 'User-Agent': 'rfcxml-mcp/0.1.0',
58
+ 'User-Agent': HTTP_CONFIG.userAgent,
81
59
  },
82
60
  });
83
61
  if (!response.ok) {
@@ -109,7 +87,8 @@ export async function fetchRFCMetadata(rfcNumber) {
109
87
  }
110
88
  }
111
89
  /**
112
- * RFC テキストを取得
90
+ * RFC テキストを取得(並列フェッチ)
91
+ * 複数ソースに同時リクエストし、最初に成功したものを返す
113
92
  */
114
93
  export async function fetchRFCText(rfcNumber) {
115
94
  // キャッシュチェック
@@ -117,43 +96,33 @@ export async function fetchRFCText(rfcNumber) {
117
96
  if (cached) {
118
97
  return cached;
119
98
  }
120
- // 複数ソースを試行
121
- const errors = [];
122
- for (const [sourceName, urlFn] of Object.entries(RFC_TEXT_SOURCES)) {
123
- try {
124
- const url = urlFn(rfcNumber);
125
- const response = await fetch(url, {
126
- headers: {
127
- Accept: 'text/plain',
128
- 'User-Agent': 'rfcxml-mcp/0.1.0',
129
- },
130
- });
131
- if (response.ok) {
132
- const text = await response.text();
133
- // 基本的な検証(RFCテキストの特徴を確認)
134
- if (text.includes('Request for Comments') || text.includes('RFC ')) {
135
- textCache.set(rfcNumber, text);
136
- console.error(`[RFC ${rfcNumber}] Text fetched from ${sourceName}`);
137
- return text;
138
- }
139
- }
140
- }
141
- catch (error) {
142
- errors.push(error);
143
- }
99
+ // ソースリストを作成
100
+ const sources = Object.entries(RFC_TEXT_SOURCES).map(([name, urlFn]) => ({
101
+ name,
102
+ url: urlFn(rfcNumber),
103
+ }));
104
+ try {
105
+ // 並列フェッチ(最初に成功したものを返す)
106
+ const { text, source } = await fetchFromMultipleSources(sources, {
107
+ headers: { Accept: 'text/plain' },
108
+ validate: (t) => t.includes('Request for Comments') || t.includes('RFC '),
109
+ });
110
+ textCache.set(rfcNumber, text);
111
+ console.error(`[RFC ${rfcNumber}] Text fetched from ${source}`);
112
+ return text;
113
+ }
114
+ catch (error) {
115
+ // すべて失敗
116
+ throw new Error(`Failed to fetch RFC ${rfcNumber} text from all sources. ` +
117
+ `Error: ${error instanceof Error ? error.message : String(error)}`);
144
118
  }
145
- // すべて失敗
146
- throw new Error(`Failed to fetch RFC ${rfcNumber} text from all sources. ` +
147
- `Errors: ${errors.map((e) => e.message).join(', ')}`);
148
119
  }
149
120
  /**
150
121
  * RFC が XML 形式で利用可能か確認
151
122
  * 注: RFC 8650 (2019年12月) 以降は公式に RFCXML v3
152
123
  */
153
124
  export function isRFCXMLAvailable(rfcNumber) {
154
- // RFC 8650 以降は確実に RFCXML v3 が利用可能
155
- // それ以前は一部のみ利用可能
156
- return rfcNumber >= 8650;
125
+ return rfcNumber >= RFC_CONFIG.xmlAvailableFrom;
157
126
  }
158
127
  /**
159
128
  * RFC XML 取得エラー
@@ -163,13 +132,14 @@ export class RFCXMLNotAvailableError extends Error {
163
132
  isOldRFC;
164
133
  suggestion;
165
134
  constructor(rfcNumber, originalErrors = []) {
166
- const isOldRFC = rfcNumber < 8650;
135
+ const threshold = RFC_CONFIG.xmlAvailableFrom;
136
+ const isOldRFC = rfcNumber < threshold;
167
137
  const suggestion = isOldRFC
168
138
  ? `RFC ${rfcNumber} は RFCXML v3 より前の形式で公開されているため、XML が利用できない可能性があります。` +
169
139
  `テキスト形式での取得を検討してください(ietf MCP の get_ietf_doc を使用)。`
170
140
  : `RFC ${rfcNumber} の XML 取得に失敗しました。ネットワーク接続を確認してください。`;
171
141
  super(`RFC ${rfcNumber} XML を取得できませんでした。\n` +
172
- `理由: ${isOldRFC ? '古い RFC (< 8650) のため XML が利用できない可能性があります' : 'ネットワークエラー'}\n` +
142
+ `理由: ${isOldRFC ? `古い RFC (< ${threshold}) のため XML が利用できない可能性があります` : 'ネットワークエラー'}\n` +
173
143
  `提案: ${suggestion}` +
174
144
  (originalErrors.length > 0 ? `\n詳細: ${originalErrors.join(', ')}` : ''));
175
145
  this.name = 'RFCXMLNotAvailableError';
@@ -1 +1 @@
1
- {"version":3,"file":"rfc-fetcher.js","sourceRoot":"","sources":["../../src/services/rfc-fetcher.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"rfc-fetcher.js","sourceRoot":"","sources":["../../src/services/rfc-fetcher.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC7C,OAAO,EAAE,wBAAwB,EAAE,MAAM,mBAAmB,CAAC;AAC7D,OAAO,EACL,YAAY,EACZ,eAAe,EACf,gBAAgB,EAChB,eAAe,EACf,WAAW,EACX,UAAU,GACX,MAAM,cAAc,CAAC;AAEtB,8BAA8B;AAC9B,MAAM,QAAQ,GAAG,IAAI,QAAQ,CAAiB,YAAY,CAAC,GAAG,CAAC,CAAC;AAChE,MAAM,SAAS,GAAG,IAAI,QAAQ,CAAiB,YAAY,CAAC,IAAI,CAAC,CAAC;AAClE,MAAM,aAAa,GAAG,IAAI,QAAQ,CAAsB,YAAY,CAAC,QAAQ,CAAC,CAAC;AAE/E;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,SAAiB;IACjD,YAAY;IACZ,MAAM,MAAM,GAAG,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IACvC,IAAI,MAAM,EAAE,CAAC;QACX,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,YAAY;IACZ,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC;QACtE,IAAI;QACJ,GAAG,EAAE,KAAK,CAAC,SAAS,CAAC;KACtB,CAAC,CAAC,CAAC;IAEJ,IAAI,CAAC;QACH,uBAAuB;QACvB,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,MAAM,wBAAwB,CAAC,OAAO,EAAE;YACpE,OAAO,EAAE,EAAE,MAAM,EAAE,2BAA2B,EAAE;YAChD,QAAQ,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC;SACpE,CAAC,CAAC;QAEH,QAAQ,CAAC,GAAG,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;QAC7B,OAAO,CAAC,KAAK,CAAC,QAAQ,SAAS,kBAAkB,MAAM,EAAE,CAAC,CAAC;QAC3D,OAAO,GAAG,CAAC;IACb,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,YAAY;QACZ,MAAM,IAAI,uBAAuB,CAAC,SAAS,EAAE;YAC3C,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;SACvD,CAAC,CAAC;IACL,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,SAAiB;IACtD,YAAY;IACZ,MAAM,MAAM,GAAG,aAAa,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IAC5C,IAAI,MAAM,EAAE,CAAC;QACX,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,MAAM,GAAG,GAAG,eAAe,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;IAEhD,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;YAChC,OAAO,EAAE;gBACP,MAAM,EAAE,kBAAkB;gBAC1B,YAAY,EAAE,WAAW,CAAC,SAAS;aACpC;SACF,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,QAAQ,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;QAC7C,CAAC;QAED,MAAM,IAAI,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAMlC,CAAC;QAEF,MAAM,QAAQ,GAAgB;YAC5B,MAAM,EAAE,SAAS;YACjB,KAAK,EAAE,IAAI,CAAC,KAAK,IAAI,OAAO,SAAS,EAAE;YACvC,OAAO,EAAE,EAAE,EAAE,mBAAmB;YAChC,IAAI,EAAE,IAAI,CAAC,IAAI,IAAI,EAAE;YACrB,QAAQ,EAAE,WAAW,CAAC,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC;YAC7C,MAAM,EAAE,SAAS,CAAC,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC;YACtC,QAAQ,EAAE,IAAI,CAAC,QAAQ,IAAI,SAAS;SACrC,CAAC;QAEF,aAAa,CAAC,GAAG,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;QACvC,OAAO,QAAQ,CAAC;IAClB,CAAC;IAAC,OAAO,MAAM,EAAE,CAAC;QAChB,qBAAqB;QACrB,OAAO;YACL,MAAM,EAAE,SAAS;YACjB,KAAK,EAAE,OAAO,SAAS,EAAE;YACzB,OAAO,EAAE,EAAE;YACX,IAAI,EAAE,EAAE;YACR,QAAQ,EAAE,MAAM;YAChB,MAAM,EAAE,MAAM;SACf,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,SAAiB;IAClD,YAAY;IACZ,MAAM,MAAM,GAAG,SAAS,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IACxC,IAAI,MAAM,EAAE,CAAC;QACX,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,YAAY;IACZ,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC;QACvE,IAAI;QACJ,GAAG,EAAE,KAAK,CAAC,SAAS,CAAC;KACtB,CAAC,CAAC,CAAC;IAEJ,IAAI,CAAC;QACH,uBAAuB;QACvB,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,wBAAwB,CAAC,OAAO,EAAE;YAC/D,OAAO,EAAE,EAAE,MAAM,EAAE,YAAY,EAAE;YACjC,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,sBAAsB,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC;SAC1E,CAAC,CAAC;QAEH,SAAS,CAAC,GAAG,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;QAC/B,OAAO,CAAC,KAAK,CAAC,QAAQ,SAAS,uBAAuB,MAAM,EAAE,CAAC,CAAC;QAChE,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,QAAQ;QACR,MAAM,IAAI,KAAK,CACb,uBAAuB,SAAS,0BAA0B;YACxD,UAAU,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CACrE,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,SAAiB;IACjD,OAAO,SAAS,IAAI,UAAU,CAAC,gBAAgB,CAAC;AAClD,CAAC;AAED;;GAEG;AACH,MAAM,OAAO,uBAAwB,SAAQ,KAAK;IAChC,SAAS,CAAS;IAClB,QAAQ,CAAU;IAClB,UAAU,CAAS;IAEnC,YAAY,SAAiB,EAAE,iBAA2B,EAAE;QAC1D,MAAM,SAAS,GAAG,UAAU,CAAC,gBAAgB,CAAC;QAC9C,MAAM,QAAQ,GAAG,SAAS,GAAG,SAAS,CAAC;QACvC,MAAM,UAAU,GAAG,QAAQ;YACzB,CAAC,CAAC,OAAO,SAAS,oDAAoD;gBACpE,mDAAmD;YACrD,CAAC,CAAC,OAAO,SAAS,qCAAqC,CAAC;QAE1D,KAAK,CACH,OAAO,SAAS,qBAAqB;YACnC,OAAO,QAAQ,CAAC,CAAC,CAAC,aAAa,SAAS,2BAA2B,CAAC,CAAC,CAAC,WAAW,IAAI;YACrF,OAAO,UAAU,EAAE;YACnB,CAAC,cAAc,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAC1E,CAAC;QAEF,IAAI,CAAC,IAAI,GAAG,yBAAyB,CAAC;QACtC,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;QAC3B,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;IAC/B,CAAC;CACF;AAED;;GAEG;AACH,MAAM,UAAU,UAAU;IACxB,QAAQ,CAAC,KAAK,EAAE,CAAC;IACjB,SAAS,CAAC,KAAK,EAAE,CAAC;IAClB,aAAa,CAAC,KAAK,EAAE,CAAC;AACxB,CAAC;AAED,SAAS;AAET,SAAS,WAAW,CAAC,QAAuB;IAC1C,QAAQ,QAAQ,EAAE,WAAW,EAAE,EAAE,CAAC;QAChC,KAAK,mBAAmB,CAAC;QACzB,KAAK,gBAAgB,CAAC;QACtB,KAAK,mBAAmB;YACtB,OAAO,KAAK,CAAC;QACf,KAAK,uBAAuB;YAC1B,OAAO,KAAK,CAAC;QACf,KAAK,cAAc;YACjB,OAAO,KAAK,CAAC;QACf,KAAK,UAAU;YACb,OAAO,UAAU,CAAC;QACpB;YACE,OAAO,MAAM,CAAC;IAClB,CAAC;AACH,CAAC;AAED,SAAS,SAAS,CAAC,MAAqB;IACtC,QAAQ,MAAM,EAAE,WAAW,EAAE,EAAE,CAAC;QAC9B,KAAK,MAAM;YACT,OAAO,MAAM,CAAC;QAChB,KAAK,KAAK;YACR,OAAO,KAAK,CAAC;QACf,KAAK,MAAM;YACT,OAAO,MAAM,CAAC;QAChB,KAAK,KAAK;YACR,OAAO,aAAa,CAAC;QACvB;YACE,OAAO,MAAM,CAAC;IAClB,CAAC;AACH,CAAC"}