@shuji-bonji/pdf-reader-mcp 0.6.0 → 0.6.1

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/CHANGELOG.md CHANGED
@@ -5,6 +5,20 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.6.1] - 2026-05-08
9
+
10
+ ### Added
11
+
12
+ - **`read_url` の同時実行数制限 (concurrency limit)** — module-level の shared limiter を `src/services/url-fetcher.ts` に導入。LLM が複数 `read_url` を並列に呼んでも、リモートホストへの過剰負荷とレート制限の発火を防ぎます。
13
+ - 新規 `src/utils/concurrency.ts`: 軽量な FIFO ベース limit ヘルパー (`createLimit`)。houki-egov-mcp v0.2.1 の同名実装を移植 (外部依存なし、約 30 行)。
14
+ - 既定 4 並列。環境変数 `PDF_READER_CONCURRENCY` で上書き可。
15
+ - `fetchPdfFromUrl(url)` は内部で limit を経由するように変更。limit を経由しない素の実装は `fetchPdfFromUrlUnlimited(url)` として再エクスポート (テスト・特殊用途用)。
16
+ - **`tests/tier1/concurrency.test.ts`**: limit が cap を超えないこと、戻り値・順序を保つこと、エラー伝播の単体テスト 5 件。
17
+
18
+ ### Changed
19
+
20
+ - **`SERVER_VERSION` 定数を `0.6.0` → `0.6.1` へ同期**。`User-Agent` ヘッダで送信される値もこれに追従。
21
+
8
22
  ## [0.6.0] - 2026-05-07
9
23
 
10
24
  ### Added
@@ -13,7 +13,18 @@ export declare const MAX_SEARCH_RESULTS = 100;
13
13
  export declare const DEFAULT_SEARCH_CONTEXT = 80;
14
14
  /** Server info */
15
15
  export declare const SERVER_NAME = "pdf-reader-mcp";
16
- export declare const SERVER_VERSION = "0.5.0";
16
+ export declare const SERVER_VERSION = "0.6.1";
17
+ /**
18
+ * Default concurrency cap for remote PDF fetches (`read_url`).
19
+ * Can be overridden with the `PDF_READER_CONCURRENCY` environment variable.
20
+ *
21
+ * 同一プロセス内で複数の `read_url` 呼び出しが並列に走った場合、
22
+ * 同時 fetch 数をこの値に制限することでリモートホストへの過剰負荷と
23
+ * レート制限の発火を防ぐ。
24
+ */
25
+ export declare const DEFAULT_FETCH_CONCURRENCY = 4;
26
+ /** 環境変数で上書きされた fetch 同時実行数(無効値ならデフォルト) */
27
+ export declare const FETCH_CONCURRENCY: number;
17
28
  /** Response format enum */
18
29
  export declare enum ResponseFormat {
19
30
  MARKDOWN = "markdown",
@@ -1 +1 @@
1
- {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,0CAA0C;AAC1C,eAAO,MAAM,eAAe,QAAS,CAAC;AAEtC,4CAA4C;AAC5C,eAAO,MAAM,aAAa,QAAmB,CAAC;AAE9C,6CAA6C;AAC7C,eAAO,MAAM,kBAAkB,KAAK,CAAC;AAErC,iDAAiD;AACjD,eAAO,MAAM,kBAAkB,MAAM,CAAC;AAEtC,uDAAuD;AACvD,eAAO,MAAM,sBAAsB,KAAK,CAAC;AAEzC,kBAAkB;AAClB,eAAO,MAAM,WAAW,mBAAmB,CAAC;AAC5C,eAAO,MAAM,cAAc,UAAU,CAAC;AAEtC,2BAA2B;AAC3B,oBAAY,cAAc;IACxB,QAAQ,aAAa;IACrB,IAAI,SAAS;CACd"}
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,0CAA0C;AAC1C,eAAO,MAAM,eAAe,QAAS,CAAC;AAEtC,4CAA4C;AAC5C,eAAO,MAAM,aAAa,QAAmB,CAAC;AAE9C,6CAA6C;AAC7C,eAAO,MAAM,kBAAkB,KAAK,CAAC;AAErC,iDAAiD;AACjD,eAAO,MAAM,kBAAkB,MAAM,CAAC;AAEtC,uDAAuD;AACvD,eAAO,MAAM,sBAAsB,KAAK,CAAC;AAEzC,kBAAkB;AAClB,eAAO,MAAM,WAAW,mBAAmB,CAAC;AAC5C,eAAO,MAAM,cAAc,UAAU,CAAC;AAEtC;;;;;;;GAOG;AACH,eAAO,MAAM,yBAAyB,IAAI,CAAC;AAE3C,0CAA0C;AAC1C,eAAO,MAAM,iBAAiB,QAC8D,CAAC;AAE7F,2BAA2B;AAC3B,oBAAY,cAAc;IACxB,QAAQ,aAAa;IACrB,IAAI,SAAS;CACd"}
package/dist/constants.js CHANGED
@@ -13,7 +13,18 @@ export const MAX_SEARCH_RESULTS = 100;
13
13
  export const DEFAULT_SEARCH_CONTEXT = 80;
14
14
  /** Server info */
15
15
  export const SERVER_NAME = 'pdf-reader-mcp';
16
- export const SERVER_VERSION = '0.5.0';
16
+ export const SERVER_VERSION = '0.6.1';
17
+ /**
18
+ * Default concurrency cap for remote PDF fetches (`read_url`).
19
+ * Can be overridden with the `PDF_READER_CONCURRENCY` environment variable.
20
+ *
21
+ * 同一プロセス内で複数の `read_url` 呼び出しが並列に走った場合、
22
+ * 同時 fetch 数をこの値に制限することでリモートホストへの過剰負荷と
23
+ * レート制限の発火を防ぐ。
24
+ */
25
+ export const DEFAULT_FETCH_CONCURRENCY = 4;
26
+ /** 環境変数で上書きされた fetch 同時実行数(無効値ならデフォルト) */
27
+ export const FETCH_CONCURRENCY = Number.parseInt(process.env.PDF_READER_CONCURRENCY ?? '', 10) || DEFAULT_FETCH_CONCURRENCY;
17
28
  /** Response format enum */
18
29
  export var ResponseFormat;
19
30
  (function (ResponseFormat) {
@@ -1 +1 @@
1
- {"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,0CAA0C;AAC1C,MAAM,CAAC,MAAM,eAAe,GAAG,MAAM,CAAC;AAEtC,4CAA4C;AAC5C,MAAM,CAAC,MAAM,aAAa,GAAG,EAAE,GAAG,IAAI,GAAG,IAAI,CAAC;AAE9C,6CAA6C;AAC7C,MAAM,CAAC,MAAM,kBAAkB,GAAG,EAAE,CAAC;AAErC,iDAAiD;AACjD,MAAM,CAAC,MAAM,kBAAkB,GAAG,GAAG,CAAC;AAEtC,uDAAuD;AACvD,MAAM,CAAC,MAAM,sBAAsB,GAAG,EAAE,CAAC;AAEzC,kBAAkB;AAClB,MAAM,CAAC,MAAM,WAAW,GAAG,gBAAgB,CAAC;AAC5C,MAAM,CAAC,MAAM,cAAc,GAAG,OAAO,CAAC;AAEtC,2BAA2B;AAC3B,MAAM,CAAN,IAAY,cAGX;AAHD,WAAY,cAAc;IACxB,uCAAqB,CAAA;IACrB,+BAAa,CAAA;AACf,CAAC,EAHW,cAAc,KAAd,cAAc,QAGzB"}
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,0CAA0C;AAC1C,MAAM,CAAC,MAAM,eAAe,GAAG,MAAM,CAAC;AAEtC,4CAA4C;AAC5C,MAAM,CAAC,MAAM,aAAa,GAAG,EAAE,GAAG,IAAI,GAAG,IAAI,CAAC;AAE9C,6CAA6C;AAC7C,MAAM,CAAC,MAAM,kBAAkB,GAAG,EAAE,CAAC;AAErC,iDAAiD;AACjD,MAAM,CAAC,MAAM,kBAAkB,GAAG,GAAG,CAAC;AAEtC,uDAAuD;AACvD,MAAM,CAAC,MAAM,sBAAsB,GAAG,EAAE,CAAC;AAEzC,kBAAkB;AAClB,MAAM,CAAC,MAAM,WAAW,GAAG,gBAAgB,CAAC;AAC5C,MAAM,CAAC,MAAM,cAAc,GAAG,OAAO,CAAC;AAEtC;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAC,CAAC;AAE3C,0CAA0C;AAC1C,MAAM,CAAC,MAAM,iBAAiB,GAC5B,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,sBAAsB,IAAI,EAAE,EAAE,EAAE,CAAC,IAAI,yBAAyB,CAAC;AAE7F,2BAA2B;AAC3B,MAAM,CAAN,IAAY,cAGX;AAHD,WAAY,cAAc;IACxB,uCAAqB,CAAA;IACrB,+BAAa,CAAA;AACf,CAAC,EAHW,cAAc,KAAd,cAAc,QAGzB"}
@@ -1,8 +1,21 @@
1
1
  /**
2
2
  * Remote PDF fetcher service.
3
+ *
4
+ * v0.6.1+ では module-level の shared limiter で同時 fetch 数を制限する。
5
+ * 上限は `PDF_READER_CONCURRENCY` 環境変数で上書き可能(既定 4)。
6
+ *
7
+ * テスト用に制限なしで呼びたい場合は `fetchPdfFromUrlUnlimited()` を使う。
3
8
  */
4
9
  /**
5
10
  * Fetch a PDF from a URL and return it as Uint8Array.
11
+ *
12
+ * 同時実行数は `FETCH_CONCURRENCY` で制限される。LLM が複数 `read_url` を
13
+ * 並列に呼んでも、リモートホストへの過剰負荷とレート制限を防ぐ。
6
14
  */
7
15
  export declare function fetchPdfFromUrl(url: string): Promise<Uint8Array>;
16
+ /**
17
+ * Limit を経由しない素の fetch 実装。
18
+ * テスト用、または limit 経由がすでに保証されている呼び出し側用。
19
+ */
20
+ export declare function fetchPdfFromUrlUnlimited(url: string): Promise<Uint8Array>;
8
21
  //# sourceMappingURL=url-fetcher.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"url-fetcher.d.ts","sourceRoot":"","sources":["../../src/services/url-fetcher.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH;;GAEG;AACH,wBAAsB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAuDtE"}
1
+ {"version":3,"file":"url-fetcher.d.ts","sourceRoot":"","sources":["../../src/services/url-fetcher.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AASH;;;;;GAKG;AACH,wBAAsB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAEtE;AAED;;;GAGG;AACH,wBAAsB,wBAAwB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAuD/E"}
@@ -1,12 +1,30 @@
1
1
  /**
2
2
  * Remote PDF fetcher service.
3
+ *
4
+ * v0.6.1+ では module-level の shared limiter で同時 fetch 数を制限する。
5
+ * 上限は `PDF_READER_CONCURRENCY` 環境変数で上書き可能(既定 4)。
6
+ *
7
+ * テスト用に制限なしで呼びたい場合は `fetchPdfFromUrlUnlimited()` を使う。
3
8
  */
4
- import { MAX_FILE_SIZE, SERVER_NAME, SERVER_VERSION } from '../constants.js';
9
+ import { FETCH_CONCURRENCY, MAX_FILE_SIZE, SERVER_NAME, SERVER_VERSION } from '../constants.js';
10
+ import { createLimit } from '../utils/concurrency.js';
5
11
  import { PdfReaderError } from '../utils/error-handler.js';
12
+ /** module-level shared limiter — 全 read_url 呼び出しが同じ limiter を経由する */
13
+ const fetchLimit = createLimit(FETCH_CONCURRENCY);
6
14
  /**
7
15
  * Fetch a PDF from a URL and return it as Uint8Array.
16
+ *
17
+ * 同時実行数は `FETCH_CONCURRENCY` で制限される。LLM が複数 `read_url` を
18
+ * 並列に呼んでも、リモートホストへの過剰負荷とレート制限を防ぐ。
8
19
  */
9
20
  export async function fetchPdfFromUrl(url) {
21
+ return fetchLimit(() => fetchPdfFromUrlUnlimited(url));
22
+ }
23
+ /**
24
+ * Limit を経由しない素の fetch 実装。
25
+ * テスト用、または limit 経由がすでに保証されている呼び出し側用。
26
+ */
27
+ export async function fetchPdfFromUrlUnlimited(url) {
10
28
  let parsedUrl;
11
29
  try {
12
30
  parsedUrl = new URL(url);
@@ -1 +1 @@
1
- {"version":3,"file":"url-fetcher.js","sourceRoot":"","sources":["../../src/services/url-fetcher.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAC7E,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAE3D;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,GAAW;IAC/C,IAAI,SAAc,CAAC;IACnB,IAAI,CAAC;QACH,SAAS,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;IAC3B,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,cAAc,CACtB,gBAAgB,GAAG,EAAE,EACrB,aAAa,EACb,2DAA2D,CAC5D,CAAC;IACJ,CAAC;IAED,IAAI,CAAC,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE,CAAC;QACtD,MAAM,IAAI,cAAc,CACtB,yBAAyB,SAAS,CAAC,QAAQ,EAAE,EAC7C,sBAAsB,EACtB,yCAAyC,CAC1C,CAAC;IACJ,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;QAChC,OAAO,EAAE;YACP,MAAM,EAAE,iBAAiB;YACzB,YAAY,EAAE,GAAG,WAAW,IAAI,cAAc,EAAE;SACjD;QACD,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,MAAM,CAAC;KACpC,CAAC,CAAC;IAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,IAAI,cAAc,CACtB,6BAA6B,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,UAAU,EAAE,EACrE,cAAc,EACd,0CAA0C,CAC3C,CAAC;IACJ,CAAC;IAED,MAAM,aAAa,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;IAC7D,IAAI,aAAa,IAAI,QAAQ,CAAC,aAAa,EAAE,EAAE,CAAC,GAAG,aAAa,EAAE,CAAC;QACjE,MAAM,IAAI,cAAc,CACtB,oBAAoB,CAAC,QAAQ,CAAC,aAAa,EAAE,EAAE,CAAC,GAAG,IAAI,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,6BAA6B,EACvG,gBAAgB,EAChB,yBAAyB,CAC1B,CAAC;IACJ,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,WAAW,EAAE,CAAC;IAC5C,IAAI,MAAM,CAAC,UAAU,GAAG,aAAa,EAAE,CAAC;QACtC,MAAM,IAAI,cAAc,CACtB,wBAAwB,CAAC,MAAM,CAAC,UAAU,GAAG,IAAI,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,6BAA6B,EACjG,gBAAgB,EAChB,yBAAyB,CAC1B,CAAC;IACJ,CAAC;IAED,OAAO,IAAI,UAAU,CAAC,MAAM,CAAC,CAAC;AAChC,CAAC"}
1
+ {"version":3,"file":"url-fetcher.js","sourceRoot":"","sources":["../../src/services/url-fetcher.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAChG,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAE3D,qEAAqE;AACrE,MAAM,UAAU,GAAG,WAAW,CAAC,iBAAiB,CAAC,CAAC;AAElD;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,GAAW;IAC/C,OAAO,UAAU,CAAC,GAAG,EAAE,CAAC,wBAAwB,CAAC,GAAG,CAAC,CAAC,CAAC;AACzD,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAAC,GAAW;IACxD,IAAI,SAAc,CAAC;IACnB,IAAI,CAAC;QACH,SAAS,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;IAC3B,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,cAAc,CACtB,gBAAgB,GAAG,EAAE,EACrB,aAAa,EACb,2DAA2D,CAC5D,CAAC;IACJ,CAAC;IAED,IAAI,CAAC,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE,CAAC;QACtD,MAAM,IAAI,cAAc,CACtB,yBAAyB,SAAS,CAAC,QAAQ,EAAE,EAC7C,sBAAsB,EACtB,yCAAyC,CAC1C,CAAC;IACJ,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;QAChC,OAAO,EAAE;YACP,MAAM,EAAE,iBAAiB;YACzB,YAAY,EAAE,GAAG,WAAW,IAAI,cAAc,EAAE;SACjD;QACD,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,MAAM,CAAC;KACpC,CAAC,CAAC;IAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,IAAI,cAAc,CACtB,6BAA6B,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,UAAU,EAAE,EACrE,cAAc,EACd,0CAA0C,CAC3C,CAAC;IACJ,CAAC;IAED,MAAM,aAAa,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;IAC7D,IAAI,aAAa,IAAI,QAAQ,CAAC,aAAa,EAAE,EAAE,CAAC,GAAG,aAAa,EAAE,CAAC;QACjE,MAAM,IAAI,cAAc,CACtB,oBAAoB,CAAC,QAAQ,CAAC,aAAa,EAAE,EAAE,CAAC,GAAG,IAAI,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,6BAA6B,EACvG,gBAAgB,EAChB,yBAAyB,CAC1B,CAAC;IACJ,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,WAAW,EAAE,CAAC;IAC5C,IAAI,MAAM,CAAC,UAAU,GAAG,aAAa,EAAE,CAAC;QACtC,MAAM,IAAI,cAAc,CACtB,wBAAwB,CAAC,MAAM,CAAC,UAAU,GAAG,IAAI,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,6BAA6B,EACjG,gBAAgB,EAChB,yBAAyB,CAC1B,CAAC;IACJ,CAAC;IAED,OAAO,IAAI,UAAU,CAAC,MAAM,CAAC,CAAC;AAChC,CAAC"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * 軽量な並行制限ヘルパー(p-limit 相当)
3
+ *
4
+ * リモート PDF (`read_url`) の連打を防ぐため、同時実行数を制限する。
5
+ * 外部依存を増やしたくないため自前実装(30行ほど)。
6
+ *
7
+ * 使い方:
8
+ * ```ts
9
+ * const limit = createLimit(2); // 同時 2 並列まで
10
+ * const results = await Promise.all(
11
+ * urls.map((url) => limit(() => fetch(url)))
12
+ * );
13
+ * ```
14
+ *
15
+ * 設計メモ:
16
+ * - LIFO ではなく FIFO(投入順に実行)
17
+ * - 例外は呼び出し側に伝播
18
+ * - キャンセル機構は意図的に持たない(必要なら AbortController を内部で)
19
+ *
20
+ * houki-hub family の他 MCP (houki-egov-mcp v0.2.1+) と同じ実装パターン。
21
+ * 共通パッケージ依存を増やさないため各 MCP で独立実装する。
22
+ */
23
+ export type LimitFn = <T>(task: () => Promise<T>) => Promise<T>;
24
+ export declare function createLimit(concurrency: number): LimitFn;
25
+ //# sourceMappingURL=concurrency.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"concurrency.d.ts","sourceRoot":"","sources":["../../src/utils/concurrency.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,MAAM,MAAM,OAAO,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC;AAEhE,wBAAgB,WAAW,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CA+BxD"}
@@ -0,0 +1,53 @@
1
+ /**
2
+ * 軽量な並行制限ヘルパー(p-limit 相当)
3
+ *
4
+ * リモート PDF (`read_url`) の連打を防ぐため、同時実行数を制限する。
5
+ * 外部依存を増やしたくないため自前実装(30行ほど)。
6
+ *
7
+ * 使い方:
8
+ * ```ts
9
+ * const limit = createLimit(2); // 同時 2 並列まで
10
+ * const results = await Promise.all(
11
+ * urls.map((url) => limit(() => fetch(url)))
12
+ * );
13
+ * ```
14
+ *
15
+ * 設計メモ:
16
+ * - LIFO ではなく FIFO(投入順に実行)
17
+ * - 例外は呼び出し側に伝播
18
+ * - キャンセル機構は意図的に持たない(必要なら AbortController を内部で)
19
+ *
20
+ * houki-hub family の他 MCP (houki-egov-mcp v0.2.1+) と同じ実装パターン。
21
+ * 共通パッケージ依存を増やさないため各 MCP で独立実装する。
22
+ */
23
+ export function createLimit(concurrency) {
24
+ if (!Number.isFinite(concurrency) || concurrency < 1) {
25
+ throw new Error(`createLimit: concurrency must be >= 1, got ${concurrency}`);
26
+ }
27
+ let active = 0;
28
+ const queue = [];
29
+ const next = () => {
30
+ if (active >= concurrency)
31
+ return;
32
+ const run = queue.shift();
33
+ if (run) {
34
+ active++;
35
+ run();
36
+ }
37
+ };
38
+ return (task) => {
39
+ return new Promise((resolve, reject) => {
40
+ const exec = () => {
41
+ task()
42
+ .then(resolve, reject)
43
+ .finally(() => {
44
+ active--;
45
+ next();
46
+ });
47
+ };
48
+ queue.push(exec);
49
+ next();
50
+ });
51
+ };
52
+ }
53
+ //# sourceMappingURL=concurrency.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"concurrency.js","sourceRoot":"","sources":["../../src/utils/concurrency.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAIH,MAAM,UAAU,WAAW,CAAC,WAAmB;IAC7C,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,WAAW,GAAG,CAAC,EAAE,CAAC;QACrD,MAAM,IAAI,KAAK,CAAC,8CAA8C,WAAW,EAAE,CAAC,CAAC;IAC/E,CAAC;IAED,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,MAAM,KAAK,GAAsB,EAAE,CAAC;IAEpC,MAAM,IAAI,GAAG,GAAG,EAAE;QAChB,IAAI,MAAM,IAAI,WAAW;YAAE,OAAO;QAClC,MAAM,GAAG,GAAG,KAAK,CAAC,KAAK,EAAE,CAAC;QAC1B,IAAI,GAAG,EAAE,CAAC;YACR,MAAM,EAAE,CAAC;YACT,GAAG,EAAE,CAAC;QACR,CAAC;IACH,CAAC,CAAC;IAEF,OAAO,CAAI,IAAsB,EAAc,EAAE;QAC/C,OAAO,IAAI,OAAO,CAAI,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACxC,MAAM,IAAI,GAAG,GAAG,EAAE;gBAChB,IAAI,EAAE;qBACH,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC;qBACrB,OAAO,CAAC,GAAG,EAAE;oBACZ,MAAM,EAAE,CAAC;oBACT,IAAI,EAAE,CAAC;gBACT,CAAC,CAAC,CAAC;YACP,CAAC,CAAC;YACF,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACjB,IAAI,EAAE,CAAC;QACT,CAAC,CAAC,CAAC;IACL,CAAC,CAAC;AACJ,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shuji-bonji/pdf-reader-mcp",
3
- "version": "0.6.0",
3
+ "version": "0.6.1",
4
4
  "description": "MCP server for PDF structure analysis - read, inspect, and validate PDF internals",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",