@shuji-bonji/pdf-writer-mcp 0.5.1 → 0.7.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 (66) hide show
  1. package/CHANGELOG.md +139 -17
  2. package/README.ja.md +7 -1
  3. package/README.md +7 -1
  4. package/dist/config.d.ts +12 -0
  5. package/dist/config.js +21 -0
  6. package/dist/config.js.map +1 -1
  7. package/dist/constants.d.ts +28 -0
  8. package/dist/constants.js +41 -0
  9. package/dist/constants.js.map +1 -1
  10. package/dist/errors.d.ts +64 -0
  11. package/dist/errors.js +76 -0
  12. package/dist/errors.js.map +1 -0
  13. package/dist/index.d.ts +6 -2
  14. package/dist/index.js +9 -35
  15. package/dist/index.js.map +1 -1
  16. package/dist/server.d.ts +6 -0
  17. package/dist/server.js +45 -0
  18. package/dist/server.js.map +1 -0
  19. package/dist/services/attachment.d.ts +52 -0
  20. package/dist/services/attachment.js +145 -0
  21. package/dist/services/attachment.js.map +1 -0
  22. package/dist/services/builder.js +2 -1
  23. package/dist/services/builder.js.map +1 -1
  24. package/dist/services/editor.d.ts +16 -8
  25. package/dist/services/editor.js +229 -130
  26. package/dist/services/editor.js.map +1 -1
  27. package/dist/services/font-manager.js +8 -9
  28. package/dist/services/font-manager.js.map +1 -1
  29. package/dist/services/form.d.ts +75 -0
  30. package/dist/services/form.js +253 -0
  31. package/dist/services/form.js.map +1 -0
  32. package/dist/services/output.d.ts +6 -2
  33. package/dist/services/output.js +11 -6
  34. package/dist/services/output.js.map +1 -1
  35. package/dist/services/page-number.d.ts +43 -0
  36. package/dist/services/page-number.js +79 -0
  37. package/dist/services/page-number.js.map +1 -0
  38. package/dist/services/page-ops.d.ts +15 -0
  39. package/dist/services/page-ops.js +136 -0
  40. package/dist/services/page-ops.js.map +1 -0
  41. package/dist/services/renderers/text.js +2 -3
  42. package/dist/services/renderers/text.js.map +1 -1
  43. package/dist/services/struct-append.d.ts +8 -0
  44. package/dist/services/struct-append.js +17 -1
  45. package/dist/services/struct-append.js.map +1 -1
  46. package/dist/services/watermark.d.ts +52 -0
  47. package/dist/services/watermark.js +75 -0
  48. package/dist/services/watermark.js.map +1 -0
  49. package/dist/services/xmp.js +5 -2
  50. package/dist/services/xmp.js.map +1 -1
  51. package/dist/tools/definitions.d.ts +25 -561
  52. package/dist/tools/definitions.js +100 -283
  53. package/dist/tools/definitions.js.map +1 -1
  54. package/dist/tools/handlers.d.ts +12 -4
  55. package/dist/tools/handlers.js +64 -35
  56. package/dist/tools/handlers.js.map +1 -1
  57. package/dist/types/index.d.ts +131 -0
  58. package/dist/utils/page-spec.js +10 -6
  59. package/dist/utils/page-spec.js.map +1 -1
  60. package/dist/utils/stdout-guard.d.ts +12 -0
  61. package/dist/utils/stdout-guard.js +16 -0
  62. package/dist/utils/stdout-guard.js.map +1 -0
  63. package/dist/utils/validation.d.ts +515 -22
  64. package/dist/utils/validation.js +387 -263
  65. package/dist/utils/validation.js.map +1 -1
  66. package/package.json +3 -2
package/CHANGELOG.md CHANGED
@@ -2,6 +2,145 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
4
 
5
+ ## [0.7.0] - 2026-07-17
6
+
7
+ コードレビュー(2026-07-17)と TASKS.md E 系(コード衛生・family 整合)への
8
+ 一括対応。**ツール名・必須フィールド・成功時の出力形式は不変**。エラー応答の
9
+ 形式のみ family 契約に揃えて変わった(minor バンプの理由)。
10
+
11
+ ### Changed
12
+
13
+ - **McpServer + Zod へ移行(E-5)** — 低レベル `Server` + 手書き JSON Schema
14
+ (definitions.ts 553 行)+ asserts 検査(validation.ts 502 行)の二重管理を解消。
15
+ Zod スキーマ(validation.ts)が公開スキーマと実行時検証の単一情報源になった。
16
+ reader / verify と同じ `registerTool` パターン。`server.ts` の `buildServer()`
17
+ はテストから `InMemoryTransport` で検証され、`registry.test.ts` が 17 ツールの
18
+ 名前・必須フィールド・annotations を外部仕様スナップショットとして固定する。
19
+ - **構造化エラー(E-2)** — `{error: message}` から reader v0.6.0 と同じ
20
+ `code` / `hint` / `next_actions` / `retryable` 形式へ。writer 固有のガードは
21
+ すべて「解除フラグ付きで再試行可能」として表現される:
22
+ `SIGNED_PDF` (allowBreakingSignatures) / `TAGGED_PDF` (allowBreakingTags) /
23
+ `FONT_REQUIRED` (fontPath) / `MISSING_GLYPH` (onMissingGlyph)。ほかに
24
+ `DOC_NOT_FOUND` / `FILE_TOO_LARGE` / `ENCRYPTED_PDF` / `INVALID_PDF` /
25
+ `UNSUPPORTED_PDF_FEATURE` (XFA) / `FONT_NOT_FOUND` / `INVALID_ARGUMENT`。
26
+ - **ページ操作を page-ops.ts へ分離** — merge / split / extract / delete /
27
+ reorder / rotate を editor.ts(20.6kB → 16.1kB)から切り出し。mergePdfs が
28
+ 文書情報の引き継ぎのために先頭ファイルを二重読込していた無駄も解消。
29
+
30
+ ### Added
31
+
32
+ - **パス検査の強化(E-1)** — すべてのパス引数(inputPath / inputPaths[] /
33
+ outputPath / outputDir / fontPath / attachmentPath)に絶対パスを強制し、
34
+ `..` セグメントを拒否。入力 PDF に 100MB のサイズ上限を新設
35
+ (verify の `MAX_FILE_SIZE` と同水準)。
36
+ - **stdout ガード(E-3)** — `marked` / `subset-font` 等の依存が `console.log`
37
+ を吐いても stdio の JSON-RPC を汚染しないよう、side-effect-first の
38
+ `stdout-guard.ts` を導入(reader / verify と同パターン)。
39
+ - **tool annotations(E-4)** — 全 17 ツールに `readOnlyHint` /
40
+ `destructiveHint` / `idempotentHint` / `openWorldHint` を付与。
41
+ `destructiveHint: true` は情報が失われる `delete_pages` と `flatten_form` のみ。
42
+ - **決定論的出力(E-6)** — 環境変数 `SOURCE_DATE_EPOCH`(UNIX 秒、
43
+ reproducible-builds.org の慣習)設定時に CreationDate / ModificationDate /
44
+ XMP の日時を固定し、同一入力 → 同一バイト列を保証。学習データ工場の
45
+ 差分検証・キャッシュ・再現テスト用。不正値は黙殺せずエラー。
46
+ - 依存に `zod ^4.4.3` を追加。
47
+
48
+ ## [0.6.0] - 2026-07-16
49
+
50
+ ### Added
51
+
52
+ - **`fill_form`** — fill AcroForm fields: text, checkbox, dropdown, optionlist,
53
+ radio. Values are validated against the field's type and, for choice fields,
54
+ against its options; both errors name what the document actually offers.
55
+ Naming a field that does not exist lists the real field names, which is how a
56
+ caller discovers the form without a separate listing tool.
57
+
58
+ - Values are rendered with an **embedded font**, so Japanese works. pdf-lib
59
+ would otherwise regenerate every appearance with Helvetica on `save()` and
60
+ fail on `WinAnsi cannot encode "山"`; the font goes through the same
61
+ font-manager as the create tools (ADR-7/8).
62
+ - `flatten: true` fills and flattens in one pass.
63
+ - Filling does **not** touch the structure tree, so a tagged PDF keeps whatever
64
+ conformance it came in with.
65
+
66
+ - **`flatten_form`** — flatten an AcroForm so the filled values become static
67
+ content, for fixing values before distribution.
68
+
69
+ - **Refuses tagged PDFs by default.** Flattening removes the Widget
70
+ annotations that the `Form` structure elements point to and bakes their
71
+ appearance in as untagged content. Measured, not assumed: veraPDF reports
72
+ `7.1-3 Content shall be marked as Artifact or tagged as real content`.
73
+ `allowBreakingTags: true` overrides and reports a warning.
74
+ - Drops the now-empty `/AcroForm` and prunes the dangling references that
75
+ pdf-lib's `flatten()` leaves behind in `/Annots` and `/Kids` (poppler
76
+ otherwise reports `Invalid XRef entry`).
77
+
78
+ - **`add_watermark`** — overlay a diagonal watermark ("社外秘" / "DRAFT" /
79
+ "COPY") at the centre of each page.
80
+
81
+ - `text`, `fontSize` (60), `color` (`#808080`), `opacity` (0.15), `angle` (45),
82
+ `behind` (true), `pages`.
83
+ - **Behind the body content by default.** pdf-lib can only append to a content
84
+ stream, so the watermark is drawn and then moved to the front of the
85
+ `/Contents` array; each stream is self-contained in `q`/`Q`, so reordering is
86
+ safe.
87
+ - **Becomes an artifact on tagged PDFs** (PDF/UA-1 7.1-3). Verified: veraPDF
88
+ `ua1` 106/106.
89
+
90
+ - **`stamp_page_numbers`** — stamp page numbers onto an existing PDF.
91
+
92
+ - `format` expands `{n}` and `{total}` (`{n} / {total}`, `- {n} -`, `{n} ページ`).
93
+ - `position` (six corners), `margin`, `fontSize`, `color`, `pages`, `startAt` —
94
+ `pages: "2-"` with `startAt: 1` numbers everything but the cover from 1.
95
+ - **Stamps become artifacts on tagged PDFs** (PDF/UA-1 7.1-3). Page numbers
96
+ carry no meaning for a screen reader, and content that is neither tagged nor
97
+ marked as an artifact breaks conformance. Verified: veraPDF `ua1` 106/106.
98
+ - Rotated pages (`/Rotate`) are compensated for, so "bottom-right" lands where
99
+ the reader sees the bottom right.
100
+ - The first editing tool that needs a font: it goes through the same
101
+ font-manager as the create tools, so harfbuzz subsetting (ADR-7/8) and the
102
+ missing-glyph check apply. Japanese formats need `fontPath` or
103
+ `PDF_WRITER_FONT`.
104
+
105
+ ### Changed
106
+
107
+ - **biome adopted** for linting and formatting, matching the rest of the family
108
+ (same `biome.json`, same scripts). `npm run check` now runs in CI and in the
109
+ publish workflow. Existing sources were reformatted; the suite is clean.
110
+ - The version is pinned to an exact `2.5.4` rather than a caret range. Biome's
111
+ formatting output changes between minor releases, so a range lets a local
112
+ `npm install` drift ahead of CI and produce spurious diffs.
113
+
114
+ ### Fixed
115
+
116
+ - `parsePageSpec` reported an open-ended chunk past the end (`"2-"` on a 1-page
117
+ document) as *reversed* rather than *out of range* — the open end collapses to
118
+ `pageCount`, which made `from > to` trigger first.
119
+ - `handleCreateTablePdf` duplicated the Latin-1 check as a regex containing
120
+ control characters; it now reuses the existing `hasNonLatin1` helper.
121
+ - `src/config.ts` imports `node:module` rather than the bare `module` specifier.
122
+
123
+
124
+ - **`attach_file`** — embed a file in a PDF (Tier B, first tool). Registers it in
125
+ `/Names /EmbeddedFiles`, references it from the catalog `/AF`, and sets
126
+ `/AFRelationship`. This is the shape PDF/A-3 (ISO 19005-3) requires, and the
127
+ one used to bundle a human-readable invoice with its machine-readable
128
+ counterpart (CSV/XML) in a single file — the 電子帳簿保存法 use case.
129
+
130
+ - `relationship`: `Data` (machine-readable counterpart), `Source` (the data the
131
+ document came from), `Alternative`, `Supplement`, `Unspecified` (default).
132
+ Omitting it produces a warning — PDF/A-3 §6.8 wants a meaningful value, and
133
+ `Unspecified` says nothing about why the file is there.
134
+ - `mimeType` is inferred from the extension when omitted (`.csv` → `text/csv`),
135
+ falling back to `application/octet-stream`.
136
+ - `name` renames the attachment inside the PDF; duplicates are rejected because
137
+ name-tree keys must be unique.
138
+ - Attaching to a tagged PDF leaves it conformant (verified: veraPDF `ua1`,
139
+ 106/106).
140
+
141
+ Descriptions and names round-trip in Japanese, and attached bytes come back
142
+ byte-identical.
143
+
5
144
  ## [0.5.1] - 2026-07-16
6
145
 
7
146
  ### Added
@@ -74,23 +213,6 @@ an annotation was added.
74
213
  - XMP metadata is written as UTF-8 bytes. `context.stream(string)` writes one
75
214
  byte per character, which mangled Japanese titles.
76
215
 
77
- ## [Unreleased]
78
-
79
- ### Changed
80
-
81
- - **biome adopted** for linting and formatting, matching the rest of the family
82
- (same `biome.json`, same scripts). `npm run check` now runs in CI and in the
83
- publish workflow. Existing sources were reformatted; the suite is clean.
84
- - The version is pinned to an exact `2.5.4` rather than a caret range. Biome's
85
- formatting output changes between minor releases, so a range lets a local
86
- `npm install` drift ahead of CI and produce spurious diffs.
87
-
88
- ### Fixed
89
-
90
- - `handleCreateTablePdf` duplicated the Latin-1 check as a regex containing
91
- control characters; it now reuses the existing `hasNonLatin1` helper.
92
- - `src/config.ts` imports `node:module` rather than the bare `module` specifier.
93
-
94
216
  ## [0.4.0] - 2026-07-16
95
217
 
96
218
  ### Added
package/README.ja.md CHANGED
@@ -49,6 +49,11 @@ PDF/UA はタイトルを要求するため、`tagged: true` では `title` が
49
49
  | `rotate_pages` | 時計回りに回転(90/180/270)。既存の回転に加算 |
50
50
  | `add_bookmarks` | しおり(アウトライン)の設定。`children` で入れ子にでき、既存のしおりは置換 |
51
51
  | `add_annotation` | 付箋(`text`)/ ハイライト(`highlight`)/ 矩形(`square`)の注釈を追加。タグ付き PDF では `Annot` 構造要素に内包され PDF/UA 準拠を維持する(`alt` で説明を渡す) |
52
+ | `attach_file` | ファイルを埋め込む(`/Names /EmbeddedFiles` + catalog `/AF` + `/AFRelationship`)。PDF/A-3 が要求する形式で、機械可読データを文書に同梱する |
53
+ | `stamp_page_numbers` | ページ番号を刻む(`{n}` / `{total}`、6 箇所の配置、`pages`、`startAt`)。タグ付き PDF では Artifact になるため準拠を維持する |
54
+ | `fill_form` | AcroForm に値を記入する。日本語は埋め込みフォントで描画。同時にフラット化も可能 |
55
+ | `flatten_form` | フォームを静的な内容に焼き込む。タグ付き PDF は既定で拒否(PDF/UA が壊れるため) |
56
+ | `add_watermark` | 斜めの透かしを重ねる("社外秘" / "DRAFT")。既定で本文の背面。タグ付き PDF では Artifact になる |
52
57
 
53
58
  共通オプション: `outputPath` / `returnBase64` / `allowBreakingSignatures`。
54
59
 
@@ -146,7 +151,8 @@ TEST_FONT_PATH=/path/to/NotoSansJP-Regular.otf npm test
146
151
  - [x] 編集系 Tier A 第2波 — しおり・注釈(v0.4.0)
147
152
  - [x] タグ付き PDF / PDF/UA-1 — veraPDF で準拠を確認(v0.5.0)
148
153
  - [x] タグ付き出力での注釈の `Annot` タグ内包(v0.5.1)
149
- - [ ] 編集系 Tier B — フォーム記入 / フラット化、透かし、添付ファイル、ページ番号スタンプ
154
+ - [x] 編集系 Tier B — 添付ファイル(v0.6.0)
155
+ - [ ] 編集系 Tier B — フォーム記入 / フラット化、透かし、ページ番号スタンプ
150
156
  - [ ] 画像の代替テキスト(`Figure` + `/Alt`)
151
157
  - [ ] `.ttc` からのフェイス自動抽出
152
158
  - [ ] 見出し用と本文用のフォント分け(太字フェイス埋め込み)
package/README.md CHANGED
@@ -49,6 +49,11 @@ PDF/UA mandates a document title, so `tagged: true` requires `title`. `lang` (BC
49
49
  | `rotate_pages` | Rotate clockwise (90/180/270), accumulating over existing rotation |
50
50
  | `add_bookmarks` | Set the outline (bookmarks); nestable via `children`, replaces any existing outline |
51
51
  | `add_annotation` | Add a sticky note (`text`), `highlight`, or `square` annotation to a page. On tagged PDFs the annotation is nested in an `Annot` element and stays PDF/UA conformant — pass `alt` to describe it |
52
+ | `attach_file` | Embed a file (`/Names /EmbeddedFiles` + catalog `/AF` + `/AFRelationship`) — the PDF/A-3 shape for bundling machine-readable data with a document |
53
+ | `stamp_page_numbers` | Stamp page numbers (`{n}` / `{total}`, six positions, `pages`, `startAt`). Becomes an artifact on tagged PDFs, so conformance holds |
54
+ | `fill_form` | Fill AcroForm fields. Japanese values via an embedded font; can flatten in the same pass |
55
+ | `flatten_form` | Flatten a form into static content. Refuses tagged PDFs by default (breaks PDF/UA) |
56
+ | `add_watermark` | Overlay a diagonal watermark ("社外秘" / "DRAFT"). Behind the body content by default; artifact on tagged PDFs |
52
57
 
53
58
  Shared options: `outputPath`, `returnBase64`, `allowBreakingSignatures`.
54
59
 
@@ -146,7 +151,8 @@ TEST_FONT_PATH=/path/to/NotoSansJP-Regular.otf npm test
146
151
  - [x] Editing Tier A wave 2 — bookmarks and annotations (v0.4.0)
147
152
  - [x] Tagged PDF / PDF/UA-1 — verified by veraPDF (v0.5.0)
148
153
  - [x] Annotations nested in `Annot` tags on tagged output (v0.5.1)
149
- - [ ] Editing Tier B — form filling/flattening, watermarks, attachments, page-number stamping
154
+ - [x] Editing Tier B — file attachments (v0.6.0)
155
+ - [ ] Editing Tier B — form filling/flattening, watermarks, page-number stamping
150
156
  - [ ] Images with alt text (`Figure` + `/Alt`)
151
157
  - [ ] Automatic face extraction from `.ttc`
152
158
  - [ ] Separate faces for headings and body (bold face embedding)
package/dist/config.d.ts CHANGED
@@ -15,7 +15,19 @@ export declare const PACKAGE_INFO: {
15
15
  export declare const ENV_KEYS: {
16
16
  /** デフォルトで埋め込むフォントファイルのパス(.ttf / .otf) */
17
17
  readonly DEFAULT_FONT: 'PDF_WRITER_FONT';
18
+ /**
19
+ * 決定論的出力(E-6): reproducible-builds.org の慣習に従う UNIX 秒。
20
+ * 設定時は CreationDate / ModificationDate / XMP の各日時に固定値を使い、
21
+ * 同一入力 → 同一バイト列を保証する(学習データ工場の差分検証・キャッシュ用)。
22
+ */
23
+ readonly SOURCE_DATE_EPOCH: 'SOURCE_DATE_EPOCH';
18
24
  };
25
+ /**
26
+ * 出力に焼き込む「現在時刻」。SOURCE_DATE_EPOCH が設定されていれば固定値を返す。
27
+ * 値が不正(数値でない・負)な場合は黙って現在時刻に落とさずエラーにする —
28
+ * 再現性を期待した呼び出し側が黙って非決定的な出力を得るのが最悪のケースのため。
29
+ */
30
+ export declare function outputDate(): Date;
19
31
  /**
20
32
  * PDF 生成のデフォルト値
21
33
  * 単位はすべて pt(1pt = 1/72 inch)
package/dist/config.js CHANGED
@@ -18,7 +18,28 @@ export const PACKAGE_INFO = {
18
18
  export const ENV_KEYS = {
19
19
  /** デフォルトで埋め込むフォントファイルのパス(.ttf / .otf) */
20
20
  DEFAULT_FONT: 'PDF_WRITER_FONT',
21
+ /**
22
+ * 決定論的出力(E-6): reproducible-builds.org の慣習に従う UNIX 秒。
23
+ * 設定時は CreationDate / ModificationDate / XMP の各日時に固定値を使い、
24
+ * 同一入力 → 同一バイト列を保証する(学習データ工場の差分検証・キャッシュ用)。
25
+ */
26
+ SOURCE_DATE_EPOCH: 'SOURCE_DATE_EPOCH',
21
27
  };
28
+ /**
29
+ * 出力に焼き込む「現在時刻」。SOURCE_DATE_EPOCH が設定されていれば固定値を返す。
30
+ * 値が不正(数値でない・負)な場合は黙って現在時刻に落とさずエラーにする —
31
+ * 再現性を期待した呼び出し側が黙って非決定的な出力を得るのが最悪のケースのため。
32
+ */
33
+ export function outputDate() {
34
+ const raw = process.env[ENV_KEYS.SOURCE_DATE_EPOCH];
35
+ if (raw === undefined || raw === '')
36
+ return new Date();
37
+ const epoch = Number(raw);
38
+ if (!Number.isFinite(epoch) || epoch < 0) {
39
+ throw new Error(`${ENV_KEYS.SOURCE_DATE_EPOCH} must be a non-negative number of seconds, got "${raw}"`);
40
+ }
41
+ return new Date(epoch * 1000);
42
+ }
22
43
  /**
23
44
  * PDF 生成のデフォルト値
24
45
  * 単位はすべて pt(1pt = 1/72 inch)
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,MAAM,OAAO,GAAG,aAAa,CAAC,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC;AAC/C,MAAM,WAAW,GAAG,OAAO,CAAC,iBAAiB,CAG5C,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,IAAI,EAAE,WAAW,CAAC,IAAI;IACtB,OAAO,EAAE,WAAW,CAAC,OAAO;CACpB,CAAC;AAEX;;GAEG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG;IACtB,yCAAyC;IACzC,YAAY,EAAE,iBAAiB;CACvB,CAAC;AAEX;;;GAGG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG;IACtB,cAAc;IACd,QAAQ,EAAE,IAAI;IACd,eAAe;IACf,MAAM,EAAE,EAAE,EAAE,SAAS;IACrB,gBAAgB;IAChB,QAAQ,EAAE,EAAE;IACZ,wDAAwD;IACxD,UAAU,EAAE,IAAI;IAChB,eAAe;IACf,YAAY,EAAE,CAAC;CACP,CAAC"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,MAAM,OAAO,GAAG,aAAa,CAAC,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC;AAC/C,MAAM,WAAW,GAAG,OAAO,CAAC,iBAAiB,CAG5C,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,IAAI,EAAE,WAAW,CAAC,IAAI;IACtB,OAAO,EAAE,WAAW,CAAC,OAAO;CACpB,CAAC;AAEX;;GAEG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG;IACtB,yCAAyC;IACzC,YAAY,EAAE,iBAAiB;IAC/B;;;;OAIG;IACH,iBAAiB,EAAE,mBAAmB;CAC9B,CAAC;AAEX;;;;GAIG;AACH,MAAM,UAAU,UAAU;IACxB,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,iBAAiB,CAAC,CAAC;IACpD,IAAI,GAAG,KAAK,SAAS,IAAI,GAAG,KAAK,EAAE;QAAE,OAAO,IAAI,IAAI,EAAE,CAAC;IACvD,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;IAC1B,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;QACzC,MAAM,IAAI,KAAK,CACb,GAAG,QAAQ,CAAC,iBAAiB,mDAAmD,GAAG,GAAG,CACvF,CAAC;IACJ,CAAC;IACD,OAAO,IAAI,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC;AAChC,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG;IACtB,cAAc;IACd,QAAQ,EAAE,IAAI;IACd,eAAe;IACf,MAAM,EAAE,EAAE,EAAE,SAAS;IACrB,gBAAgB;IAChB,QAAQ,EAAE,EAAE;IACZ,wDAAwD;IACxD,UAAU,EAAE,IAAI;IAChB,eAAe;IACf,YAAY,EAAE,CAAC;CACP,CAAC"}
@@ -36,7 +36,35 @@ export declare const LIMITS: {
36
36
  /** しおりの最大総数・最大ネスト深さ */
37
37
  readonly BOOKMARK_MAX_TOTAL: 2000;
38
38
  readonly BOOKMARK_MAX_DEPTH: 8;
39
+ /** 埋め込みファイルの最大サイズ(バイト)。PDF 全体がメモリに載るため上限を設ける */
40
+ readonly ATTACHMENT_MAX_BYTES: number;
41
+ /**
42
+ * 入力 PDF の最大サイズ(バイト)。pdf-lib は全体をメモリに載せるため、
43
+ * verify(MAX_FILE_SIZE = 100MB)と同水準の上限を設ける。
44
+ */
45
+ readonly INPUT_PDF_MAX_BYTES: number;
39
46
  };
47
+ /** stamp_page_numbers の配置 */
48
+ export declare const STAMP_POSITIONS: readonly ['bottom-left', 'bottom-center', 'bottom-right', 'top-left', 'top-center', 'top-right'];
49
+ /** stamp_page_numbers の既定値 */
50
+ export declare const STAMP_DEFAULTS: {
51
+ readonly format: '{n}';
52
+ readonly position: 'bottom-center';
53
+ readonly margin: 24;
54
+ readonly fontSize: 9;
55
+ readonly color: '#666666';
56
+ readonly startAt: 1;
57
+ };
58
+ /** add_watermark の既定値 */
59
+ export declare const WATERMARK_DEFAULTS: {
60
+ readonly fontSize: 60;
61
+ readonly color: '#808080';
62
+ readonly opacity: 0.15;
63
+ readonly angle: 45;
64
+ readonly behind: true;
65
+ };
66
+ /** attach_file が受け付ける AFRelationship(PDF/A-3 §6.8) */
67
+ export declare const ATTACHMENT_RELATIONSHIPS: readonly ['Source', 'Data', 'Alternative', 'Supplement', 'Unspecified'];
40
68
  /** add_annotation が受け付ける注釈種別 */
41
69
  export declare const ANNOTATION_TYPES: readonly ['text', 'highlight', 'square'];
42
70
  /** text 注釈のアイコン名(ISO 32000-1 Table 172 の一般的な値) */
package/dist/constants.js CHANGED
@@ -35,7 +35,48 @@ export const LIMITS = {
35
35
  /** しおりの最大総数・最大ネスト深さ */
36
36
  BOOKMARK_MAX_TOTAL: 2_000,
37
37
  BOOKMARK_MAX_DEPTH: 8,
38
+ /** 埋め込みファイルの最大サイズ(バイト)。PDF 全体がメモリに載るため上限を設ける */
39
+ ATTACHMENT_MAX_BYTES: 100 * 1024 * 1024,
40
+ /**
41
+ * 入力 PDF の最大サイズ(バイト)。pdf-lib は全体をメモリに載せるため、
42
+ * verify(MAX_FILE_SIZE = 100MB)と同水準の上限を設ける。
43
+ */
44
+ INPUT_PDF_MAX_BYTES: 100 * 1024 * 1024,
38
45
  };
46
+ /** stamp_page_numbers の配置 */
47
+ export const STAMP_POSITIONS = [
48
+ 'bottom-left',
49
+ 'bottom-center',
50
+ 'bottom-right',
51
+ 'top-left',
52
+ 'top-center',
53
+ 'top-right',
54
+ ];
55
+ /** stamp_page_numbers の既定値 */
56
+ export const STAMP_DEFAULTS = {
57
+ format: '{n}',
58
+ position: 'bottom-center',
59
+ margin: 24,
60
+ fontSize: 9,
61
+ color: '#666666',
62
+ startAt: 1,
63
+ };
64
+ /** add_watermark の既定値 */
65
+ export const WATERMARK_DEFAULTS = {
66
+ fontSize: 60,
67
+ color: '#808080',
68
+ opacity: 0.15,
69
+ angle: 45,
70
+ behind: true,
71
+ };
72
+ /** attach_file が受け付ける AFRelationship(PDF/A-3 §6.8) */
73
+ export const ATTACHMENT_RELATIONSHIPS = [
74
+ 'Source',
75
+ 'Data',
76
+ 'Alternative',
77
+ 'Supplement',
78
+ 'Unspecified',
79
+ ];
39
80
  /** add_annotation が受け付ける注釈種別 */
40
81
  export const ANNOTATION_TYPES = ['text', 'highlight', 'square'];
41
82
  /** text 注釈のアイコン名(ISO 32000-1 Table 172 の一般的な値) */
@@ -1 +1 @@
1
- {"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;GAGG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,EAAE,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC;IACpB,EAAE,EAAE,CAAC,MAAM,EAAE,OAAO,CAAC;IACrB,EAAE,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,CAAC,GAAG,EAAE,GAAG,CAAC;IAClB,KAAK,EAAE,CAAC,GAAG,EAAE,IAAI,CAAC;CACV,CAAC;AAIX;;GAEG;AACH,MAAM,CAAC,MAAM,MAAM,GAAG;IACpB,qBAAqB;IACrB,aAAa,EAAE,CAAC;IAChB,aAAa,EAAE,EAAE;IACjB,sCAAsC;IACtC,UAAU,EAAE,CAAC;IACb,UAAU,EAAE,GAAG;IACf,6CAA6C;IAC7C,eAAe,EAAE,OAAO;IACxB,+BAA+B;IAC/B,cAAc,EAAE,EAAE;IAClB,cAAc,EAAE,KAAK;IACrB,4BAA4B;IAC5B,gBAAgB,EAAE,EAAE;IACpB,wBAAwB;IACxB,eAAe,EAAE,GAAG;IACpB,uBAAuB;IACvB,kBAAkB,EAAE,KAAK;IACzB,kBAAkB,EAAE,CAAC;CACb,CAAC;AAEX,gCAAgC;AAChC,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,MAAM,EAAE,WAAW,EAAE,QAAQ,CAAU,CAAC;AAEzE,kDAAkD;AAClD,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,MAAM;IACN,SAAS;IACT,KAAK;IACL,MAAM;IACN,cAAc;IACd,WAAW;IACX,QAAQ;CACA,CAAC;AAEX,qCAAqC;AACrC,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,EAAE,EAAE,GAAG,EAAE,GAAG,CAAU,CAAC;AAEvD;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG,eAAe,CAAC;AAExD;;;GAGG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,mCAAmC;IACnC,GAAG,EAAE,MAAM;CACH,CAAC"}
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;GAGG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,EAAE,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC;IACpB,EAAE,EAAE,CAAC,MAAM,EAAE,OAAO,CAAC;IACrB,EAAE,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,CAAC,GAAG,EAAE,GAAG,CAAC;IAClB,KAAK,EAAE,CAAC,GAAG,EAAE,IAAI,CAAC;CACV,CAAC;AAIX;;GAEG;AACH,MAAM,CAAC,MAAM,MAAM,GAAG;IACpB,qBAAqB;IACrB,aAAa,EAAE,CAAC;IAChB,aAAa,EAAE,EAAE;IACjB,sCAAsC;IACtC,UAAU,EAAE,CAAC;IACb,UAAU,EAAE,GAAG;IACf,6CAA6C;IAC7C,eAAe,EAAE,OAAO;IACxB,+BAA+B;IAC/B,cAAc,EAAE,EAAE;IAClB,cAAc,EAAE,KAAK;IACrB,4BAA4B;IAC5B,gBAAgB,EAAE,EAAE;IACpB,wBAAwB;IACxB,eAAe,EAAE,GAAG;IACpB,uBAAuB;IACvB,kBAAkB,EAAE,KAAK;IACzB,kBAAkB,EAAE,CAAC;IACrB,gDAAgD;IAChD,oBAAoB,EAAE,GAAG,GAAG,IAAI,GAAG,IAAI;IACvC;;;OAGG;IACH,mBAAmB,EAAE,GAAG,GAAG,IAAI,GAAG,IAAI;CAC9B,CAAC;AAEX,6BAA6B;AAC7B,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,aAAa;IACb,eAAe;IACf,cAAc;IACd,UAAU;IACV,YAAY;IACZ,WAAW;CACH,CAAC;AAEX,8BAA8B;AAC9B,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,MAAM,EAAE,KAAK;IACb,QAAQ,EAAE,eAAe;IACzB,MAAM,EAAE,EAAE;IACV,QAAQ,EAAE,CAAC;IACX,KAAK,EAAE,SAAS;IAChB,OAAO,EAAE,CAAC;CACF,CAAC;AAEX,yBAAyB;AACzB,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAChC,QAAQ,EAAE,EAAE;IACZ,KAAK,EAAE,SAAS;IAChB,OAAO,EAAE,IAAI;IACb,KAAK,EAAE,EAAE;IACT,MAAM,EAAE,IAAI;CACJ,CAAC;AAEX,sDAAsD;AACtD,MAAM,CAAC,MAAM,wBAAwB,GAAG;IACtC,QAAQ;IACR,MAAM;IACN,aAAa;IACb,YAAY;IACZ,aAAa;CACL,CAAC;AAEX,gCAAgC;AAChC,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,MAAM,EAAE,WAAW,EAAE,QAAQ,CAAU,CAAC;AAEzE,kDAAkD;AAClD,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,MAAM;IACN,SAAS;IACT,KAAK;IACL,MAAM;IACN,cAAc;IACd,WAAW;IACX,QAAQ;CACA,CAAC;AAEX,qCAAqC;AACrC,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,EAAE,EAAE,GAAG,EAAE,GAAG,CAAU,CAAC;AAEvD;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG,eAAe,CAAC;AAExD;;;GAGG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,mCAAmC;IACnC,GAAG,EAAE,MAAM;CACH,CAAC"}
@@ -0,0 +1,64 @@
1
+ /**
2
+ * family-compatible 構造化エラー応答(E-2) — pdf-writer-mcp 実装
3
+ *
4
+ * 設計指針:
5
+ * - pdf-reader-mcp v0.6.0 の error contract に準拠(`code` 文字列を共有)
6
+ * - 共通パッケージ依存を持たない独立実装
7
+ * - writer 固有のコード(SIGNED_PDF / TAGGED_PDF / FONT_REQUIRED /
8
+ * MISSING_GLYPH)を追加。いずれも「明示フラグや引数の追加で再試行できる」
9
+ * ガード系で、`retryable: true` + `next_actions` により出力パイプライン
10
+ * Skill / LLM エージェントが自律的に分岐できる。
11
+ *
12
+ * family contract 仕様:
13
+ * @see https://github.com/shuji-bonji/houki-research-skill/blob/main/docs/ERROR-CODES.md
14
+ */
15
+ /** family 共通コードの部分集合 + writer 固有拡張 */
16
+ export type WriterErrorCode = 'INVALID_ARGUMENT' | 'DOC_NOT_FOUND' | 'FONT_NOT_FOUND' | 'INVALID_PDF' | 'ENCRYPTED_PDF' | 'UNSUPPORTED_PDF_FEATURE' | 'FILE_TOO_LARGE' | 'SIGNED_PDF' | 'TAGGED_PDF' | 'FONT_REQUIRED' | 'MISSING_GLYPH' | 'INTERNAL_ERROR';
17
+ /** 次に取るべきアクションの提案。LLM が読んで自律的に再試行することを想定 */
18
+ export interface NextAction {
19
+ /** 推奨アクション(tool 名 or 自然言語) */
20
+ action: string;
21
+ /** どんなときに有効か */
22
+ reason: string;
23
+ /** 具体的な引数例(任意) */
24
+ example?: Record<string, unknown>;
25
+ }
26
+ /** family-compatible 共通エラー応答 */
27
+ export interface WriterServiceError {
28
+ /** 1文の人間可読メッセージ(LLM もここを読む) */
29
+ error: string;
30
+ /** プログラム判定用の安定したコード */
31
+ code: WriterErrorCode;
32
+ /** 追加情報(任意) */
33
+ hint?: string;
34
+ /** LLM が次に取るべき手段の候補 */
35
+ next_actions?: NextAction[];
36
+ /** フラグや引数を変えれば再試行できるか */
37
+ retryable?: boolean;
38
+ }
39
+ /** コード・ヒント・next_actions を運ぶ writer 固有の Error */
40
+ export declare class PdfWriterError extends Error {
41
+ readonly code: WriterErrorCode;
42
+ readonly options: {
43
+ hint?: string;
44
+ next_actions?: NextAction[];
45
+ retryable?: boolean;
46
+ };
47
+ constructor(message: string, code: WriterErrorCode, options?: {
48
+ hint?: string;
49
+ next_actions?: NextAction[];
50
+ retryable?: boolean;
51
+ });
52
+ }
53
+ /** 引数エラーの短縮形(validation.ts / page-spec.ts の大量の検査で使う) */
54
+ export declare function invalidArg(message: string): PdfWriterError;
55
+ /** 投げられた値を family 形式のエラー応答へ変換する */
56
+ export declare function toStructuredError(error: unknown): WriterServiceError;
57
+ /** よく使う next_actions のプリセット(writer のガード解除フラグ群) */
58
+ export declare const NEXT_ACTIONS: {
59
+ readonly allowBreakingSignatures: () => NextAction;
60
+ readonly allowBreakingTags: () => NextAction;
61
+ readonly provideFontPath: () => NextAction;
62
+ readonly changeMissingGlyphPolicy: () => NextAction;
63
+ readonly checkFilePath: (path?: string) => NextAction;
64
+ };
package/dist/errors.js ADDED
@@ -0,0 +1,76 @@
1
+ /**
2
+ * family-compatible 構造化エラー応答(E-2) — pdf-writer-mcp 実装
3
+ *
4
+ * 設計指針:
5
+ * - pdf-reader-mcp v0.6.0 の error contract に準拠(`code` 文字列を共有)
6
+ * - 共通パッケージ依存を持たない独立実装
7
+ * - writer 固有のコード(SIGNED_PDF / TAGGED_PDF / FONT_REQUIRED /
8
+ * MISSING_GLYPH)を追加。いずれも「明示フラグや引数の追加で再試行できる」
9
+ * ガード系で、`retryable: true` + `next_actions` により出力パイプライン
10
+ * Skill / LLM エージェントが自律的に分岐できる。
11
+ *
12
+ * family contract 仕様:
13
+ * @see https://github.com/shuji-bonji/houki-research-skill/blob/main/docs/ERROR-CODES.md
14
+ */
15
+ /** コード・ヒント・next_actions を運ぶ writer 固有の Error */
16
+ export class PdfWriterError extends Error {
17
+ code;
18
+ options;
19
+ constructor(message, code, options = {}) {
20
+ super(message);
21
+ this.code = code;
22
+ this.options = options;
23
+ this.name = 'PdfWriterError';
24
+ }
25
+ }
26
+ /** 引数エラーの短縮形(validation.ts / page-spec.ts の大量の検査で使う) */
27
+ export function invalidArg(message) {
28
+ return new PdfWriterError(message, 'INVALID_ARGUMENT');
29
+ }
30
+ /** 投げられた値を family 形式のエラー応答へ変換する */
31
+ export function toStructuredError(error) {
32
+ if (error instanceof PdfWriterError) {
33
+ const out = { error: error.message, code: error.code };
34
+ if (error.options.hint)
35
+ out.hint = error.options.hint;
36
+ if (error.options.next_actions && error.options.next_actions.length > 0) {
37
+ out.next_actions = error.options.next_actions;
38
+ }
39
+ if (error.options.retryable !== undefined)
40
+ out.retryable = error.options.retryable;
41
+ return out;
42
+ }
43
+ if (error instanceof Error) {
44
+ return { error: error.message, code: 'INTERNAL_ERROR' };
45
+ }
46
+ return { error: String(error), code: 'INTERNAL_ERROR' };
47
+ }
48
+ /** よく使う next_actions のプリセット(writer のガード解除フラグ群) */
49
+ export const NEXT_ACTIONS = {
50
+ allowBreakingSignatures: () => ({
51
+ action: 'retry_with_allowBreakingSignatures',
52
+ reason: '署名を無効化してよい場合のみ、同じ引数に "allowBreakingSignatures": true を足して再試行してください',
53
+ example: { allowBreakingSignatures: true },
54
+ }),
55
+ allowBreakingTags: () => ({
56
+ action: 'retry_with_allowBreakingTags',
57
+ reason: 'PDF/UA 適合を壊してよい場合のみ、"allowBreakingTags": true を足して再試行してください',
58
+ example: { allowBreakingTags: true },
59
+ }),
60
+ provideFontPath: () => ({
61
+ action: 'retry_with_fontPath',
62
+ reason: '非 Latin 文字(日本語等)には埋め込みフォントが必要です。"fontPath" に .ttf/.otf を指定するか、環境変数 PDF_WRITER_FONT を設定してください',
63
+ example: { fontPath: '/path/to/NotoSansJP-Regular.otf' },
64
+ }),
65
+ changeMissingGlyphPolicy: () => ({
66
+ action: 'retry_with_onMissingGlyph',
67
+ reason: 'フォントに無い文字が本文に含まれます。別のフォントを指定するか、"onMissingGlyph": "replace"(豆腐で置換)/ "ignore"(黙って除去)を指定してください',
68
+ example: { onMissingGlyph: 'replace' },
69
+ }),
70
+ checkFilePath: (path) => ({
71
+ action: 'verify_file_path',
72
+ reason: 'ファイルパスが正しいか、絶対パスで指定されているか確認してください',
73
+ example: path ? { inputPath: path } : undefined,
74
+ }),
75
+ };
76
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AA8CH,gDAAgD;AAChD,MAAM,OAAO,cAAe,SAAQ,KAAK;IAGrB,IAAI;IACJ,OAAO;IAHzB,YACE,OAAe,EACC,IAAqB,EACrB,OAAO,GAInB,EAAE;QAEN,KAAK,CAAC,OAAO,CAAC,CAAC;oBAPC,IAAI;uBACJ,OAAO;QAOvB,IAAI,CAAC,IAAI,GAAG,gBAAgB,CAAC;IAC/B,CAAC;CACF;AAED,wDAAwD;AACxD,MAAM,UAAU,UAAU,CAAC,OAAe;IACxC,OAAO,IAAI,cAAc,CAAC,OAAO,EAAE,kBAAkB,CAAC,CAAC;AACzD,CAAC;AAED,mCAAmC;AACnC,MAAM,UAAU,iBAAiB,CAAC,KAAc;IAC9C,IAAI,KAAK,YAAY,cAAc,EAAE,CAAC;QACpC,MAAM,GAAG,GAAuB,EAAE,KAAK,EAAE,KAAK,CAAC,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC;QAC3E,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI;YAAE,GAAG,CAAC,IAAI,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC;QACtD,IAAI,KAAK,CAAC,OAAO,CAAC,YAAY,IAAI,KAAK,CAAC,OAAO,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACxE,GAAG,CAAC,YAAY,GAAG,KAAK,CAAC,OAAO,CAAC,YAAY,CAAC;QAChD,CAAC;QACD,IAAI,KAAK,CAAC,OAAO,CAAC,SAAS,KAAK,SAAS;YAAE,GAAG,CAAC,SAAS,GAAG,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC;QACnF,OAAO,GAAG,CAAC;IACb,CAAC;IACD,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;QAC3B,OAAO,EAAE,KAAK,EAAE,KAAK,CAAC,OAAO,EAAE,IAAI,EAAE,gBAAgB,EAAE,CAAC;IAC1D,CAAC;IACD,OAAO,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,gBAAgB,EAAE,CAAC;AAC1D,CAAC;AAED,kDAAkD;AAClD,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,uBAAuB,EAAE,GAAe,EAAE,CAAC,CAAC;QAC1C,MAAM,EAAE,oCAAoC;QAC5C,MAAM,EACJ,oEAAoE;QACtE,OAAO,EAAE,EAAE,uBAAuB,EAAE,IAAI,EAAE;KAC3C,CAAC;IACF,iBAAiB,EAAE,GAAe,EAAE,CAAC,CAAC;QACpC,MAAM,EAAE,8BAA8B;QACtC,MAAM,EAAE,6DAA6D;QACrE,OAAO,EAAE,EAAE,iBAAiB,EAAE,IAAI,EAAE;KACrC,CAAC;IACF,eAAe,EAAE,GAAe,EAAE,CAAC,CAAC;QAClC,MAAM,EAAE,qBAAqB;QAC7B,MAAM,EACJ,8FAA8F;QAChG,OAAO,EAAE,EAAE,QAAQ,EAAE,iCAAiC,EAAE;KACzD,CAAC;IACF,wBAAwB,EAAE,GAAe,EAAE,CAAC,CAAC;QAC3C,MAAM,EAAE,2BAA2B;QACnC,MAAM,EACJ,8FAA8F;QAChG,OAAO,EAAE,EAAE,cAAc,EAAE,SAAS,EAAE;KACvC,CAAC;IACF,aAAa,EAAE,CAAC,IAAa,EAAc,EAAE,CAAC,CAAC;QAC7C,MAAM,EAAE,kBAAkB;QAC1B,MAAM,EAAE,mCAAmC;QAC3C,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,SAAS;KAChD,CAAC;CACM,CAAC"}
package/dist/index.d.ts CHANGED
@@ -1,6 +1,10 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
3
  * pdf-writer-mcp — MCP server entry
4
- * テキスト / Markdown / 表データから PDF を生成する。
4
+ * テキスト / Markdown / 表データから PDF を生成し、既存 PDF を編集する。
5
+ *
6
+ * E-5: reader / verify と同じ McpServer + registerTool + Zod 構成。
7
+ * ツール定義(説明・スキーマ・annotations)は tools/definitions.ts の
8
+ * レジストリ、実装は tools/handlers.ts、スキーマは utils/validation.ts。
5
9
  */
6
- export {};
10
+ import './utils/stdout-guard.js';
package/dist/index.js CHANGED
@@ -1,46 +1,20 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
3
  * pdf-writer-mcp — MCP server entry
4
- * テキスト / Markdown / 表データから PDF を生成する。
4
+ * テキスト / Markdown / 表データから PDF を生成し、既存 PDF を編集する。
5
+ *
6
+ * E-5: reader / verify と同じ McpServer + registerTool + Zod 構成。
7
+ * ツール定義(説明・スキーマ・annotations)は tools/definitions.ts の
8
+ * レジストリ、実装は tools/handlers.ts、スキーマは utils/validation.ts。
5
9
  */
6
- import { Server } from '@modelcontextprotocol/sdk/server/index.js';
10
+ // stdout ガードは他のあらゆる import より先(side-effect first)
11
+ import './utils/stdout-guard.js';
7
12
  import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
8
- import { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js';
9
13
  import { PACKAGE_INFO } from './config.js';
10
- import { tools } from './tools/definitions.js';
11
- import { toolHandlers } from './tools/handlers.js';
14
+ import { buildServer } from './server.js';
12
15
  import { logger } from './utils/logger.js';
13
- const server = new Server({
14
- name: PACKAGE_INFO.name,
15
- version: PACKAGE_INFO.version,
16
- }, {
17
- capabilities: { tools: {} },
18
- });
19
- server.setRequestHandler(ListToolsRequestSchema, async () => ({
20
- tools,
21
- }));
22
- server.setRequestHandler(CallToolRequestSchema, async (request) => {
23
- const { name, arguments: args } = request.params;
24
- try {
25
- const handler = toolHandlers[name];
26
- if (!handler) {
27
- throw new Error(`Unknown tool: ${name}`);
28
- }
29
- const result = await handler(args);
30
- return {
31
- content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
32
- };
33
- }
34
- catch (error) {
35
- const message = error instanceof Error ? error.message : String(error);
36
- logger.error(name, message, error instanceof Error ? error : undefined);
37
- return {
38
- content: [{ type: 'text', text: JSON.stringify({ error: message }, null, 2) }],
39
- isError: true,
40
- };
41
- }
42
- });
43
16
  async function main() {
17
+ const server = buildServer();
44
18
  const transport = new StdioServerTransport();
45
19
  await server.connect(transport);
46
20
  logger.info(PACKAGE_INFO.name, `v${PACKAGE_INFO.version} started (stdio)`);
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;GAGG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AACnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,oCAAoC,CAAC;AACnG,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,KAAK,EAAE,MAAM,wBAAwB,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAE3C,MAAM,MAAM,GAAG,IAAI,MAAM,CACvB;IACE,IAAI,EAAE,YAAY,CAAC,IAAI;IACvB,OAAO,EAAE,YAAY,CAAC,OAAO;CAC9B,EACD;IACE,YAAY,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE;CAC5B,CACF,CAAC;AAEF,MAAM,CAAC,iBAAiB,CAAC,sBAAsB,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC;IAC5D,KAAK;CACN,CAAC,CAAC,CAAC;AAEJ,MAAM,CAAC,iBAAiB,CAAC,qBAAqB,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE;IAChE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC;IAEjD,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;QACnC,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CAAC,iBAAiB,IAAI,EAAE,CAAC,CAAC;QAC3C,CAAC;QACD,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;QACnC,OAAO;YACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;SACnE,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACvE,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;QACxE,OAAO;YACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;YAC9E,OAAO,EAAE,IAAI;SACd,CAAC;IACJ,CAAC;AACH,CAAC,CAAC,CAAC;AAEH,KAAK,UAAU,IAAI;IACjB,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAChC,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,IAAI,YAAY,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAC7E,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACrB,MAAM,CAAC,KAAK,CAAC,SAAS,EAAE,wBAAwB,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IAC9F,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;;;;;GAOG;AAEH,kDAAkD;AAClD,OAAO,yBAAyB,CAAC;AAEjC,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAE3C,KAAK,UAAU,IAAI;IACjB,MAAM,MAAM,GAAG,WAAW,EAAE,CAAC;IAC7B,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAChC,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,IAAI,YAAY,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAC7E,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACrB,MAAM,CAAC,KAAK,CAAC,SAAS,EAAE,wBAAwB,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IAC9F,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * McpServer の構築(E-5)。
3
+ * index.ts(stdio 接続)とテスト(InMemoryTransport)の両方から使う。
4
+ */
5
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
6
+ export declare function buildServer(): McpServer;