@shuji-bonji/pdf-writer-mcp 0.2.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.
- package/LICENSE +21 -0
- package/README.md +208 -0
- package/dist/config.d.ts +34 -0
- package/dist/config.js +38 -0
- package/dist/config.js.map +1 -0
- package/dist/constants.d.ts +46 -0
- package/dist/constants.js +46 -0
- package/dist/constants.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +52 -0
- package/dist/index.js.map +1 -0
- package/dist/services/builder.d.ts +10 -0
- package/dist/services/builder.js +40 -0
- package/dist/services/builder.js.map +1 -0
- package/dist/services/editor.d.ts +24 -0
- package/dist/services/editor.js +194 -0
- package/dist/services/editor.js.map +1 -0
- package/dist/services/font-manager.d.ts +18 -0
- package/dist/services/font-manager.js +59 -0
- package/dist/services/font-manager.js.map +1 -0
- package/dist/services/layout.d.ts +62 -0
- package/dist/services/layout.js +198 -0
- package/dist/services/layout.js.map +1 -0
- package/dist/services/output.d.ts +13 -0
- package/dist/services/output.js +60 -0
- package/dist/services/output.js.map +1 -0
- package/dist/services/renderers/markdown.d.ts +8 -0
- package/dist/services/renderers/markdown.js +132 -0
- package/dist/services/renderers/markdown.js.map +1 -0
- package/dist/services/renderers/table.d.ts +7 -0
- package/dist/services/renderers/table.js +89 -0
- package/dist/services/renderers/table.js.map +1 -0
- package/dist/services/renderers/text.d.ts +9 -0
- package/dist/services/renderers/text.js +29 -0
- package/dist/services/renderers/text.js.map +1 -0
- package/dist/tools/definitions.d.ts +388 -0
- package/dist/tools/definitions.js +241 -0
- package/dist/tools/definitions.js.map +1 -0
- package/dist/tools/handlers.d.ts +23 -0
- package/dist/tools/handlers.js +82 -0
- package/dist/tools/handlers.js.map +1 -0
- package/dist/types/index.d.ts +135 -0
- package/dist/types/index.js +5 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/logger.d.ts +14 -0
- package/dist/utils/logger.js +28 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/page-spec.d.ts +12 -0
- package/dist/utils/page-spec.js +55 -0
- package/dist/utils/page-spec.js.map +1 -0
- package/dist/utils/validation.d.ts +24 -0
- package/dist/utils/validation.js +187 -0
- package/dist/utils/validation.js.map +1 -0
- package/package.json +48 -0
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool ハンドラ群 + ディスパッチ用 Map
|
|
3
|
+
*
|
|
4
|
+
* 新しいツールを追加するときは:
|
|
5
|
+
* 1. handleXxx 関数を実装
|
|
6
|
+
* 2. 下の toolHandlers に 1 行追加
|
|
7
|
+
* だけでよい。引数検査は validation.ts に集約。
|
|
8
|
+
*/
|
|
9
|
+
import { validateCreateTextArgs, validateCreateMarkdownArgs, validateCreateTableArgs, validateSetMetadataArgs, validateMergePdfsArgs, validateSplitPdfArgs, validateExtractPagesArgs, validateDeletePagesArgs, validateReorderPagesArgs, validateRotatePagesArgs, } from '../utils/validation.js';
|
|
10
|
+
import { buildPdf } from '../services/builder.js';
|
|
11
|
+
import { renderText } from '../services/renderers/text.js';
|
|
12
|
+
import { renderMarkdown } from '../services/renderers/markdown.js';
|
|
13
|
+
import { renderTable } from '../services/renderers/table.js';
|
|
14
|
+
import { setMetadata, mergePdfs, splitPdf, extractPages, deletePages, reorderPages, rotatePages, } from '../services/editor.js';
|
|
15
|
+
export async function handleCreateTextPdf(args) {
|
|
16
|
+
validateCreateTextArgs(args);
|
|
17
|
+
return buildPdf(args, (engine, loaded) => renderText(engine, args.text, loaded));
|
|
18
|
+
}
|
|
19
|
+
export async function handleCreateMarkdownPdf(args) {
|
|
20
|
+
validateCreateMarkdownArgs(args);
|
|
21
|
+
return buildPdf(args, (engine, loaded) => renderMarkdown(engine, args.markdown, loaded));
|
|
22
|
+
}
|
|
23
|
+
export async function handleCreateTablePdf(args) {
|
|
24
|
+
validateCreateTableArgs(args);
|
|
25
|
+
return buildPdf(args, (engine, loaded) => {
|
|
26
|
+
// 表は標準フォントで日本語不可のため、描画前に検査
|
|
27
|
+
const flat = [...args.headers, ...args.rows.flat()].join('\n');
|
|
28
|
+
if (loaded.isStandard && /[^\x00-\xff]/.test(flat)) {
|
|
29
|
+
throw new Error('The table contains non-Latin characters (e.g. Japanese) but no embeddable font was provided. ' +
|
|
30
|
+
'Pass "fontPath" pointing to a .ttf/.otf font, or set PDF_WRITER_FONT.');
|
|
31
|
+
}
|
|
32
|
+
renderTable(engine, args.headers, args.rows);
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
// ---------------------------------------------------------------------------
|
|
36
|
+
// 編集系(Tier A)
|
|
37
|
+
// ---------------------------------------------------------------------------
|
|
38
|
+
export async function handleSetMetadata(args) {
|
|
39
|
+
validateSetMetadataArgs(args);
|
|
40
|
+
return setMetadata(args);
|
|
41
|
+
}
|
|
42
|
+
export async function handleMergePdfs(args) {
|
|
43
|
+
validateMergePdfsArgs(args);
|
|
44
|
+
return mergePdfs(args.inputPaths, args);
|
|
45
|
+
}
|
|
46
|
+
export async function handleSplitPdf(args) {
|
|
47
|
+
validateSplitPdfArgs(args);
|
|
48
|
+
return splitPdf(args.inputPath, args.ranges, args.outputDir, args.prefix, args);
|
|
49
|
+
}
|
|
50
|
+
export async function handleExtractPages(args) {
|
|
51
|
+
validateExtractPagesArgs(args);
|
|
52
|
+
return extractPages(args.inputPath, args.pages, args);
|
|
53
|
+
}
|
|
54
|
+
export async function handleDeletePages(args) {
|
|
55
|
+
validateDeletePagesArgs(args);
|
|
56
|
+
return deletePages(args.inputPath, args.pages, args);
|
|
57
|
+
}
|
|
58
|
+
export async function handleReorderPages(args) {
|
|
59
|
+
validateReorderPagesArgs(args);
|
|
60
|
+
return reorderPages(args.inputPath, args.order, args);
|
|
61
|
+
}
|
|
62
|
+
export async function handleRotatePages(args) {
|
|
63
|
+
validateRotatePagesArgs(args);
|
|
64
|
+
return rotatePages(args.inputPath, args.rotation, args.pages, args);
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Tool ハンドラの Map(引数型は各ハンドラ側で検査するため any を許容)
|
|
68
|
+
*/
|
|
69
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
70
|
+
export const toolHandlers = {
|
|
71
|
+
create_text_pdf: handleCreateTextPdf,
|
|
72
|
+
create_markdown_pdf: handleCreateMarkdownPdf,
|
|
73
|
+
create_table_pdf: handleCreateTablePdf,
|
|
74
|
+
set_metadata: handleSetMetadata,
|
|
75
|
+
merge_pdfs: handleMergePdfs,
|
|
76
|
+
split_pdf: handleSplitPdf,
|
|
77
|
+
extract_pages: handleExtractPages,
|
|
78
|
+
delete_pages: handleDeletePages,
|
|
79
|
+
reorder_pages: handleReorderPages,
|
|
80
|
+
rotate_pages: handleRotatePages,
|
|
81
|
+
};
|
|
82
|
+
//# sourceMappingURL=handlers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handlers.js","sourceRoot":"","sources":["../../src/tools/handlers.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 共有型
|
|
3
|
+
*/
|
|
4
|
+
import type { PageSizeName } from '../constants.js';
|
|
5
|
+
/**
|
|
6
|
+
* すべての生成ツールに共通するオプション
|
|
7
|
+
*/
|
|
8
|
+
export interface CommonCreateOptions {
|
|
9
|
+
/** 出力先パス。指定時はファイルに保存する */
|
|
10
|
+
outputPath?: string;
|
|
11
|
+
/** base64 文字列を結果に含めるか(outputPath 未指定なら自動的に true 相当) */
|
|
12
|
+
returnBase64?: boolean;
|
|
13
|
+
/** 埋め込むフォントファイルのパス(.ttf / .otf)。日本語には必須 */
|
|
14
|
+
fontPath?: string;
|
|
15
|
+
/** 本文フォントサイズ(pt) */
|
|
16
|
+
fontSize?: number;
|
|
17
|
+
/** ページサイズ名 */
|
|
18
|
+
pageSize?: PageSizeName;
|
|
19
|
+
/** 上下左右マージン(pt) */
|
|
20
|
+
margin?: number;
|
|
21
|
+
/** PDF メタデータ: タイトル */
|
|
22
|
+
title?: string;
|
|
23
|
+
/** PDF メタデータ: 作成者 */
|
|
24
|
+
author?: string;
|
|
25
|
+
}
|
|
26
|
+
export interface CreateTextArgs extends CommonCreateOptions {
|
|
27
|
+
/** 本文テキスト。\n で改行、空行で段落区切り */
|
|
28
|
+
text: string;
|
|
29
|
+
}
|
|
30
|
+
export interface CreateMarkdownArgs extends CommonCreateOptions {
|
|
31
|
+
/** Markdown 文字列 */
|
|
32
|
+
markdown: string;
|
|
33
|
+
}
|
|
34
|
+
export interface CreateTableArgs extends CommonCreateOptions {
|
|
35
|
+
/** ヘッダ行 */
|
|
36
|
+
headers: string[];
|
|
37
|
+
/** データ行(各行は headers と同じ列数を推奨) */
|
|
38
|
+
rows: string[][];
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* 生成結果
|
|
42
|
+
*/
|
|
43
|
+
export interface CreateResult {
|
|
44
|
+
/** 保存した場合の絶対パス */
|
|
45
|
+
path?: string;
|
|
46
|
+
/** returnBase64 時の base64 文字列 */
|
|
47
|
+
base64?: string;
|
|
48
|
+
/** 生成ページ数 */
|
|
49
|
+
pageCount: number;
|
|
50
|
+
/** バイトサイズ */
|
|
51
|
+
bytes: number;
|
|
52
|
+
/** 埋め込みフォント名(標準フォント時は 'Helvetica') */
|
|
53
|
+
font: string;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* すべての編集ツールに共通するオプション
|
|
57
|
+
*/
|
|
58
|
+
export interface CommonEditOptions {
|
|
59
|
+
/** 出力先パス。指定時はファイルに保存する */
|
|
60
|
+
outputPath?: string;
|
|
61
|
+
/** base64 文字列を結果に含めるか(outputPath 未指定なら自動的に true 相当) */
|
|
62
|
+
returnBase64?: boolean;
|
|
63
|
+
/** 署名済み PDF(/ByteRange 検知)でも編集を続行するか。既定 false */
|
|
64
|
+
allowBreakingSignatures?: boolean;
|
|
65
|
+
}
|
|
66
|
+
export interface SetMetadataArgs extends CommonEditOptions {
|
|
67
|
+
/** 編集対象の PDF パス */
|
|
68
|
+
inputPath: string;
|
|
69
|
+
title?: string;
|
|
70
|
+
author?: string;
|
|
71
|
+
subject?: string;
|
|
72
|
+
keywords?: string[];
|
|
73
|
+
creator?: string;
|
|
74
|
+
}
|
|
75
|
+
export interface MergePdfsArgs extends CommonEditOptions {
|
|
76
|
+
/** 結合する PDF のパス(結合順) */
|
|
77
|
+
inputPaths: string[];
|
|
78
|
+
}
|
|
79
|
+
export interface ExtractPagesArgs extends CommonEditOptions {
|
|
80
|
+
inputPath: string;
|
|
81
|
+
/** ページ指定("1,3-5,8-" 形式・1 始まり) */
|
|
82
|
+
pages: string;
|
|
83
|
+
}
|
|
84
|
+
export interface DeletePagesArgs extends CommonEditOptions {
|
|
85
|
+
inputPath: string;
|
|
86
|
+
pages: string;
|
|
87
|
+
}
|
|
88
|
+
export interface ReorderPagesArgs extends CommonEditOptions {
|
|
89
|
+
inputPath: string;
|
|
90
|
+
/** 新しいページ順(1 始まり・全ページを 1 回ずつ) */
|
|
91
|
+
order: number[];
|
|
92
|
+
}
|
|
93
|
+
export interface RotatePagesArgs extends CommonEditOptions {
|
|
94
|
+
inputPath: string;
|
|
95
|
+
/** 時計回りの回転角 */
|
|
96
|
+
rotation: 90 | 180 | 270;
|
|
97
|
+
/** 対象ページ指定。省略時は全ページ */
|
|
98
|
+
pages?: string;
|
|
99
|
+
}
|
|
100
|
+
export interface SplitPdfArgs extends CommonEditOptions {
|
|
101
|
+
inputPath: string;
|
|
102
|
+
/** 分割単位のページ指定の配列。各要素が 1 ファイルになる(例: ["1-3", "4-6", "7-"]) */
|
|
103
|
+
ranges: string[];
|
|
104
|
+
/** 出力先ディレクトリ */
|
|
105
|
+
outputDir: string;
|
|
106
|
+
/** 出力ファイル名の接頭辞。既定は "<入力名>-part" */
|
|
107
|
+
prefix?: string;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* 編集結果
|
|
111
|
+
*/
|
|
112
|
+
export interface EditResult {
|
|
113
|
+
path?: string;
|
|
114
|
+
base64?: string;
|
|
115
|
+
pageCount: number;
|
|
116
|
+
bytes: number;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* 分割結果
|
|
120
|
+
*/
|
|
121
|
+
export interface SplitResult {
|
|
122
|
+
files: Array<{
|
|
123
|
+
path: string;
|
|
124
|
+
pageCount: number;
|
|
125
|
+
bytes: number;
|
|
126
|
+
}>;
|
|
127
|
+
count: number;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* MCP レスポンスの content block(最小限)
|
|
131
|
+
*/
|
|
132
|
+
export interface ContentBlock {
|
|
133
|
+
type: 'text';
|
|
134
|
+
text: string;
|
|
135
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA;;GAEG"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Logger Utility
|
|
3
|
+
* MCP は stdio で JSON-RPC を喋るため console.log(stdout) は禁止。
|
|
4
|
+
* すべて stderr(console.error)へ寄せてプロトコル汚染を防ぐ。
|
|
5
|
+
*/
|
|
6
|
+
export type LogLevel = 'debug' | 'info' | 'warn' | 'error';
|
|
7
|
+
interface Logger {
|
|
8
|
+
debug(context: string, message: string): void;
|
|
9
|
+
info(context: string, message: string): void;
|
|
10
|
+
warn(context: string, message: string): void;
|
|
11
|
+
error(context: string, message: string, error?: Error): void;
|
|
12
|
+
}
|
|
13
|
+
export declare const logger: Logger;
|
|
14
|
+
export {};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Logger Utility
|
|
3
|
+
* MCP は stdio で JSON-RPC を喋るため console.log(stdout) は禁止。
|
|
4
|
+
* すべて stderr(console.error)へ寄せてプロトコル汚染を防ぐ。
|
|
5
|
+
*/
|
|
6
|
+
function formatMessage(_level, context, message) {
|
|
7
|
+
return `[${context}] ${message}`;
|
|
8
|
+
}
|
|
9
|
+
export const logger = {
|
|
10
|
+
debug(context, message) {
|
|
11
|
+
if (process.env.DEBUG) {
|
|
12
|
+
console.error(formatMessage('debug', context, message));
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
info(context, message) {
|
|
16
|
+
console.error(formatMessage('info', context, message));
|
|
17
|
+
},
|
|
18
|
+
warn(context, message) {
|
|
19
|
+
console.error(formatMessage('warn', context, message));
|
|
20
|
+
},
|
|
21
|
+
error(context, message, error) {
|
|
22
|
+
console.error(formatMessage('error', context, message));
|
|
23
|
+
if (error && process.env.DEBUG) {
|
|
24
|
+
console.error(error.stack);
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAWH,SAAS,aAAa,CAAC,MAAgB,EAAE,OAAe,EAAE,OAAe;IACvE,OAAO,IAAI,OAAO,KAAK,OAAO,EAAE,CAAC;AACnC,CAAC;AAED,MAAM,CAAC,MAAM,MAAM,GAAW;IAC5B,KAAK,CAAC,OAAO,EAAE,OAAO;QACpB,IAAI,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC;YACtB,OAAO,CAAC,KAAK,CAAC,aAAa,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;QAC1D,CAAC;IACH,CAAC;IACD,IAAI,CAAC,OAAO,EAAE,OAAO;QACnB,OAAO,CAAC,KAAK,CAAC,aAAa,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;IACzD,CAAC;IACD,IAAI,CAAC,OAAO,EAAE,OAAO;QACnB,OAAO,CAAC,KAAK,CAAC,aAAa,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;IACzD,CAAC;IACD,KAAK,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK;QAC3B,OAAO,CAAC,KAAK,CAAC,aAAa,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;QACxD,IAAI,KAAK,IAAI,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC;YAC/B,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAC7B,CAAC;IACH,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Page Spec Parser
|
|
3
|
+
* "1,3-5,8-" のような 1 始まりのページ指定文字列を解釈する。
|
|
4
|
+
*
|
|
5
|
+
* 文法:
|
|
6
|
+
* - "3" : 単一ページ
|
|
7
|
+
* - "2-5" : 範囲(両端含む)
|
|
8
|
+
* - "6-" : 6 ページから最終ページまで
|
|
9
|
+
* - "-3" : 先頭から 3 ページまで
|
|
10
|
+
* - カンマ区切りで複数指定。重複は除去し、指定順を保持する
|
|
11
|
+
*/
|
|
12
|
+
export declare function parsePageSpec(spec: string, pageCount: number, fieldName?: string): number[];
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Page Spec Parser
|
|
3
|
+
* "1,3-5,8-" のような 1 始まりのページ指定文字列を解釈する。
|
|
4
|
+
*
|
|
5
|
+
* 文法:
|
|
6
|
+
* - "3" : 単一ページ
|
|
7
|
+
* - "2-5" : 範囲(両端含む)
|
|
8
|
+
* - "6-" : 6 ページから最終ページまで
|
|
9
|
+
* - "-3" : 先頭から 3 ページまで
|
|
10
|
+
* - カンマ区切りで複数指定。重複は除去し、指定順を保持する
|
|
11
|
+
*/
|
|
12
|
+
const CHUNK_RE = /^(?:(\d+)|(\d*)-(\d*))$/;
|
|
13
|
+
export function parsePageSpec(spec, pageCount, fieldName = 'pages') {
|
|
14
|
+
if (typeof spec !== 'string' || spec.trim().length === 0) {
|
|
15
|
+
throw new Error(`${fieldName} must be a non-empty string like "1,3-5,8-"`);
|
|
16
|
+
}
|
|
17
|
+
const result = [];
|
|
18
|
+
const seen = new Set();
|
|
19
|
+
const push = (n) => {
|
|
20
|
+
if (!seen.has(n)) {
|
|
21
|
+
seen.add(n);
|
|
22
|
+
result.push(n);
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
for (const raw of spec.split(',')) {
|
|
26
|
+
const chunk = raw.trim();
|
|
27
|
+
const m = CHUNK_RE.exec(chunk);
|
|
28
|
+
if (!m) {
|
|
29
|
+
throw new Error(`${fieldName} contains an invalid chunk "${chunk}" (expected forms: "3", "2-5", "6-", "-3")`);
|
|
30
|
+
}
|
|
31
|
+
let from;
|
|
32
|
+
let to;
|
|
33
|
+
if (m[1] !== undefined) {
|
|
34
|
+
from = to = Number(m[1]);
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
// "a-b" / "a-" / "-b"("-" 単独は from/to とも空で不正)
|
|
38
|
+
if (m[2] === '' && m[3] === '') {
|
|
39
|
+
throw new Error(`${fieldName} contains an invalid chunk "${chunk}"`);
|
|
40
|
+
}
|
|
41
|
+
from = m[2] === '' ? 1 : Number(m[2]);
|
|
42
|
+
to = m[3] === '' ? pageCount : Number(m[3]);
|
|
43
|
+
}
|
|
44
|
+
if (from < 1 || to > pageCount) {
|
|
45
|
+
throw new Error(`${fieldName} chunk "${chunk}" is out of range (document has ${pageCount} page(s))`);
|
|
46
|
+
}
|
|
47
|
+
if (from > to) {
|
|
48
|
+
throw new Error(`${fieldName} chunk "${chunk}" is reversed (from > to)`);
|
|
49
|
+
}
|
|
50
|
+
for (let n = from; n <= to; n++)
|
|
51
|
+
push(n);
|
|
52
|
+
}
|
|
53
|
+
return result;
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=page-spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"page-spec.js","sourceRoot":"","sources":["../../src/utils/page-spec.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,MAAM,QAAQ,GAAG,yBAAyB,CAAC;AAE3C,MAAM,UAAU,aAAa,CAAC,IAAY,EAAE,SAAiB,EAAE,SAAS,GAAG,OAAO;IAChF,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzD,MAAM,IAAI,KAAK,CAAC,GAAG,SAAS,6CAA6C,CAAC,CAAC;IAC7E,CAAC;IAED,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAE/B,MAAM,IAAI,GAAG,CAAC,CAAS,EAAQ,EAAE;QAC/B,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;YACjB,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;YACZ,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACjB,CAAC;IACH,CAAC,CAAC;IAEF,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;QAClC,MAAM,KAAK,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;QACzB,MAAM,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC/B,IAAI,CAAC,CAAC,EAAE,CAAC;YACP,MAAM,IAAI,KAAK,CACb,GAAG,SAAS,+BAA+B,KAAK,4CAA4C,CAC7F,CAAC;QACJ,CAAC;QAED,IAAI,IAAY,CAAC;QACjB,IAAI,EAAU,CAAC;QACf,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,SAAS,EAAE,CAAC;YACvB,IAAI,GAAG,EAAE,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC3B,CAAC;aAAM,CAAC;YACN,8CAA8C;YAC9C,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC;gBAC/B,MAAM,IAAI,KAAK,CAAC,GAAG,SAAS,+BAA+B,KAAK,GAAG,CAAC,CAAC;YACvE,CAAC;YACD,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACtC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC9C,CAAC;QAED,IAAI,IAAI,GAAG,CAAC,IAAI,EAAE,GAAG,SAAS,EAAE,CAAC;YAC/B,MAAM,IAAI,KAAK,CACb,GAAG,SAAS,WAAW,KAAK,mCAAmC,SAAS,WAAW,CACpF,CAAC;QACJ,CAAC;QACD,IAAI,IAAI,GAAG,EAAE,EAAE,CAAC;YACd,MAAM,IAAI,KAAK,CAAC,GAAG,SAAS,WAAW,KAAK,2BAA2B,CAAC,CAAC;QAC3E,CAAC;QACD,KAAK,IAAI,CAAC,GAAG,IAAI,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,EAAE;YAAE,IAAI,CAAC,CAAC,CAAC,CAAC;IAC3C,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Input Validation
|
|
3
|
+
* asserts 型述語で narrowing しつつ検査。閾値は constants.ts に集約。
|
|
4
|
+
*/
|
|
5
|
+
import { type PageSizeName } from '../constants.js';
|
|
6
|
+
import type { CreateTextArgs, CreateMarkdownArgs, CreateTableArgs, CommonCreateOptions, SetMetadataArgs, MergePdfsArgs, ExtractPagesArgs, DeletePagesArgs, ReorderPagesArgs, RotatePagesArgs, SplitPdfArgs } from '../types/index.js';
|
|
7
|
+
export declare function validateNonEmptyString(value: unknown, fieldName: string): asserts value is string;
|
|
8
|
+
export declare function validateTextLength(value: unknown, fieldName: string): asserts value is string;
|
|
9
|
+
/**
|
|
10
|
+
* common オプション(すべて optional)の検査。
|
|
11
|
+
* 指定されているフィールドのみ検査する。
|
|
12
|
+
*/
|
|
13
|
+
export declare function validateCommonOptions(opts: CommonCreateOptions): void;
|
|
14
|
+
export declare function validatePageSize(value: unknown): asserts value is PageSizeName;
|
|
15
|
+
export declare function validateCreateTextArgs(args: unknown): asserts args is CreateTextArgs;
|
|
16
|
+
export declare function validateCreateMarkdownArgs(args: unknown): asserts args is CreateMarkdownArgs;
|
|
17
|
+
export declare function validateSetMetadataArgs(args: unknown): asserts args is SetMetadataArgs;
|
|
18
|
+
export declare function validateMergePdfsArgs(args: unknown): asserts args is MergePdfsArgs;
|
|
19
|
+
export declare function validateExtractPagesArgs(args: unknown): asserts args is ExtractPagesArgs;
|
|
20
|
+
export declare function validateDeletePagesArgs(args: unknown): asserts args is DeletePagesArgs;
|
|
21
|
+
export declare function validateReorderPagesArgs(args: unknown): asserts args is ReorderPagesArgs;
|
|
22
|
+
export declare function validateRotatePagesArgs(args: unknown): asserts args is RotatePagesArgs;
|
|
23
|
+
export declare function validateSplitPdfArgs(args: unknown): asserts args is SplitPdfArgs;
|
|
24
|
+
export declare function validateCreateTableArgs(args: unknown): asserts args is CreateTableArgs;
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Input Validation
|
|
3
|
+
* asserts 型述語で narrowing しつつ検査。閾値は constants.ts に集約。
|
|
4
|
+
*/
|
|
5
|
+
import { LIMITS, PAGE_SIZES, ROTATION_ANGLES } from '../constants.js';
|
|
6
|
+
export function validateNonEmptyString(value, fieldName) {
|
|
7
|
+
if (typeof value !== 'string') {
|
|
8
|
+
throw new Error(`${fieldName} must be a string, got ${typeof value}`);
|
|
9
|
+
}
|
|
10
|
+
if (value.length === 0) {
|
|
11
|
+
throw new Error(`${fieldName} must not be empty`);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
export function validateTextLength(value, fieldName) {
|
|
15
|
+
if (typeof value !== 'string') {
|
|
16
|
+
throw new Error(`${fieldName} must be a string, got ${typeof value}`);
|
|
17
|
+
}
|
|
18
|
+
if (value.length > LIMITS.TEXT_MAX_LENGTH) {
|
|
19
|
+
throw new Error(`${fieldName} is too long (${value.length} chars, max ${LIMITS.TEXT_MAX_LENGTH})`);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* common オプション(すべて optional)の検査。
|
|
24
|
+
* 指定されているフィールドのみ検査する。
|
|
25
|
+
*/
|
|
26
|
+
export function validateCommonOptions(opts) {
|
|
27
|
+
if (opts.fontSize !== undefined) {
|
|
28
|
+
if (typeof opts.fontSize !== 'number' || !Number.isFinite(opts.fontSize)) {
|
|
29
|
+
throw new Error(`fontSize must be a number, got ${String(opts.fontSize)}`);
|
|
30
|
+
}
|
|
31
|
+
if (opts.fontSize < LIMITS.FONT_SIZE_MIN || opts.fontSize > LIMITS.FONT_SIZE_MAX) {
|
|
32
|
+
throw new Error(`fontSize must be between ${LIMITS.FONT_SIZE_MIN} and ${LIMITS.FONT_SIZE_MAX}, got ${opts.fontSize}`);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
if (opts.margin !== undefined) {
|
|
36
|
+
if (typeof opts.margin !== 'number' || !Number.isFinite(opts.margin)) {
|
|
37
|
+
throw new Error(`margin must be a number, got ${String(opts.margin)}`);
|
|
38
|
+
}
|
|
39
|
+
if (opts.margin < LIMITS.MARGIN_MIN || opts.margin > LIMITS.MARGIN_MAX) {
|
|
40
|
+
throw new Error(`margin must be between ${LIMITS.MARGIN_MIN} and ${LIMITS.MARGIN_MAX}, got ${opts.margin}`);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
if (opts.pageSize !== undefined) {
|
|
44
|
+
validatePageSize(opts.pageSize);
|
|
45
|
+
}
|
|
46
|
+
if (opts.fontPath !== undefined) {
|
|
47
|
+
validateNonEmptyString(opts.fontPath, 'fontPath');
|
|
48
|
+
}
|
|
49
|
+
if (opts.outputPath !== undefined) {
|
|
50
|
+
validateNonEmptyString(opts.outputPath, 'outputPath');
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
export function validatePageSize(value) {
|
|
54
|
+
if (typeof value !== 'string' || !(value in PAGE_SIZES)) {
|
|
55
|
+
throw new Error(`pageSize must be one of ${Object.keys(PAGE_SIZES).join(', ')}, got ${String(value)}`);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
export function validateCreateTextArgs(args) {
|
|
59
|
+
if (typeof args !== 'object' || args === null) {
|
|
60
|
+
throw new Error('arguments must be an object');
|
|
61
|
+
}
|
|
62
|
+
const a = args;
|
|
63
|
+
validateTextLength(a.text, 'text');
|
|
64
|
+
validateCommonOptions(a);
|
|
65
|
+
}
|
|
66
|
+
export function validateCreateMarkdownArgs(args) {
|
|
67
|
+
if (typeof args !== 'object' || args === null) {
|
|
68
|
+
throw new Error('arguments must be an object');
|
|
69
|
+
}
|
|
70
|
+
const a = args;
|
|
71
|
+
validateTextLength(a.markdown, 'markdown');
|
|
72
|
+
validateCommonOptions(a);
|
|
73
|
+
}
|
|
74
|
+
/** 編集系共通オプションの検査 + オブジェクト形状の確認 */
|
|
75
|
+
function asEditArgs(args) {
|
|
76
|
+
if (typeof args !== 'object' || args === null) {
|
|
77
|
+
throw new Error('arguments must be an object');
|
|
78
|
+
}
|
|
79
|
+
const a = args;
|
|
80
|
+
const opts = a;
|
|
81
|
+
if (opts.outputPath !== undefined) {
|
|
82
|
+
validateNonEmptyString(opts.outputPath, 'outputPath');
|
|
83
|
+
}
|
|
84
|
+
if (opts.allowBreakingSignatures !== undefined && typeof opts.allowBreakingSignatures !== 'boolean') {
|
|
85
|
+
throw new Error('allowBreakingSignatures must be a boolean');
|
|
86
|
+
}
|
|
87
|
+
return a;
|
|
88
|
+
}
|
|
89
|
+
export function validateSetMetadataArgs(args) {
|
|
90
|
+
const a = asEditArgs(args);
|
|
91
|
+
validateNonEmptyString(a.inputPath, 'inputPath');
|
|
92
|
+
for (const f of ['title', 'author', 'subject', 'creator']) {
|
|
93
|
+
if (a[f] !== undefined && typeof a[f] !== 'string') {
|
|
94
|
+
throw new Error(`${f} must be a string`);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
if (a.keywords !== undefined) {
|
|
98
|
+
if (!Array.isArray(a.keywords) || a.keywords.some((k) => typeof k !== 'string')) {
|
|
99
|
+
throw new Error('keywords must be an array of strings');
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
if (a.title === undefined &&
|
|
103
|
+
a.author === undefined &&
|
|
104
|
+
a.subject === undefined &&
|
|
105
|
+
a.keywords === undefined &&
|
|
106
|
+
a.creator === undefined) {
|
|
107
|
+
throw new Error('set_metadata requires at least one of: title, author, subject, keywords, creator');
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
export function validateMergePdfsArgs(args) {
|
|
111
|
+
const a = asEditArgs(args);
|
|
112
|
+
if (!Array.isArray(a.inputPaths) || a.inputPaths.some((p) => typeof p !== 'string' || p.length === 0)) {
|
|
113
|
+
throw new Error('inputPaths must be an array of non-empty strings');
|
|
114
|
+
}
|
|
115
|
+
if (a.inputPaths.length < 2) {
|
|
116
|
+
throw new Error('inputPaths must contain at least 2 files to merge');
|
|
117
|
+
}
|
|
118
|
+
if (a.inputPaths.length > LIMITS.MERGE_MAX_INPUTS) {
|
|
119
|
+
throw new Error(`inputPaths has too many files (max ${LIMITS.MERGE_MAX_INPUTS})`);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
export function validateExtractPagesArgs(args) {
|
|
123
|
+
const a = asEditArgs(args);
|
|
124
|
+
validateNonEmptyString(a.inputPath, 'inputPath');
|
|
125
|
+
validateNonEmptyString(a.pages, 'pages');
|
|
126
|
+
}
|
|
127
|
+
export function validateDeletePagesArgs(args) {
|
|
128
|
+
const a = asEditArgs(args);
|
|
129
|
+
validateNonEmptyString(a.inputPath, 'inputPath');
|
|
130
|
+
validateNonEmptyString(a.pages, 'pages');
|
|
131
|
+
}
|
|
132
|
+
export function validateReorderPagesArgs(args) {
|
|
133
|
+
const a = asEditArgs(args);
|
|
134
|
+
validateNonEmptyString(a.inputPath, 'inputPath');
|
|
135
|
+
if (!Array.isArray(a.order) || a.order.length === 0 || a.order.some((n) => typeof n !== 'number')) {
|
|
136
|
+
throw new Error('order must be a non-empty array of page numbers (1-based)');
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
export function validateRotatePagesArgs(args) {
|
|
140
|
+
const a = asEditArgs(args);
|
|
141
|
+
validateNonEmptyString(a.inputPath, 'inputPath');
|
|
142
|
+
if (!ROTATION_ANGLES.includes(a.rotation)) {
|
|
143
|
+
throw new Error(`rotation must be one of ${ROTATION_ANGLES.join(', ')}, got ${String(a.rotation)}`);
|
|
144
|
+
}
|
|
145
|
+
if (a.pages !== undefined) {
|
|
146
|
+
validateNonEmptyString(a.pages, 'pages');
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
export function validateSplitPdfArgs(args) {
|
|
150
|
+
const a = asEditArgs(args);
|
|
151
|
+
validateNonEmptyString(a.inputPath, 'inputPath');
|
|
152
|
+
validateNonEmptyString(a.outputDir, 'outputDir');
|
|
153
|
+
if (!Array.isArray(a.ranges) || a.ranges.length === 0 || a.ranges.some((r) => typeof r !== 'string' || r.length === 0)) {
|
|
154
|
+
throw new Error('ranges must be a non-empty array of page-spec strings (e.g. ["1-3", "4-"])');
|
|
155
|
+
}
|
|
156
|
+
if (a.prefix !== undefined) {
|
|
157
|
+
validateNonEmptyString(a.prefix, 'prefix');
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
export function validateCreateTableArgs(args) {
|
|
161
|
+
if (typeof args !== 'object' || args === null) {
|
|
162
|
+
throw new Error('arguments must be an object');
|
|
163
|
+
}
|
|
164
|
+
const a = args;
|
|
165
|
+
if (!Array.isArray(a.headers) || a.headers.some((h) => typeof h !== 'string')) {
|
|
166
|
+
throw new Error('headers must be an array of strings');
|
|
167
|
+
}
|
|
168
|
+
if (a.headers.length === 0) {
|
|
169
|
+
throw new Error('headers must not be empty');
|
|
170
|
+
}
|
|
171
|
+
if (a.headers.length > LIMITS.TABLE_MAX_COLS) {
|
|
172
|
+
throw new Error(`headers has too many columns (max ${LIMITS.TABLE_MAX_COLS})`);
|
|
173
|
+
}
|
|
174
|
+
if (!Array.isArray(a.rows)) {
|
|
175
|
+
throw new Error('rows must be an array');
|
|
176
|
+
}
|
|
177
|
+
if (a.rows.length > LIMITS.TABLE_MAX_ROWS) {
|
|
178
|
+
throw new Error(`rows has too many rows (max ${LIMITS.TABLE_MAX_ROWS})`);
|
|
179
|
+
}
|
|
180
|
+
for (const [i, row] of a.rows.entries()) {
|
|
181
|
+
if (!Array.isArray(row) || row.some((c) => typeof c !== 'string')) {
|
|
182
|
+
throw new Error(`rows[${i}] must be an array of strings`);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
validateCommonOptions(a);
|
|
186
|
+
}
|
|
187
|
+
//# sourceMappingURL=validation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation.js","sourceRoot":"","sources":["../../src/utils/validation.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@shuji-bonji/pdf-writer-mcp",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "MCP server that generates and edits PDFs (text/Markdown/table creation, metadata & page operations) using pdf-lib, with Japanese font embedding (fontkit subset).",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"pdf-writer-mcp": "dist/index.js"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"dist"
|
|
11
|
+
],
|
|
12
|
+
"engines": {
|
|
13
|
+
"node": ">=20"
|
|
14
|
+
},
|
|
15
|
+
"scripts": {
|
|
16
|
+
"build": "tsc",
|
|
17
|
+
"dev": "tsc -w",
|
|
18
|
+
"start": "node dist/index.js",
|
|
19
|
+
"test": "vitest run",
|
|
20
|
+
"test:watch": "vitest",
|
|
21
|
+
"typecheck": "tsc --noEmit",
|
|
22
|
+
"prepublishOnly": "npm run build"
|
|
23
|
+
},
|
|
24
|
+
"keywords": [
|
|
25
|
+
"mcp",
|
|
26
|
+
"model-context-protocol",
|
|
27
|
+
"pdf",
|
|
28
|
+
"pdf-lib",
|
|
29
|
+
"markdown-to-pdf"
|
|
30
|
+
],
|
|
31
|
+
"author": "shuji-bonji",
|
|
32
|
+
"license": "MIT",
|
|
33
|
+
"repository": {
|
|
34
|
+
"type": "git",
|
|
35
|
+
"url": "git+https://github.com/shuji-bonji/pdf-writer-mcp.git"
|
|
36
|
+
},
|
|
37
|
+
"dependencies": {
|
|
38
|
+
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
39
|
+
"@pdf-lib/fontkit": "^1.1.1",
|
|
40
|
+
"marked": "^18.0.6",
|
|
41
|
+
"pdf-lib": "^1.17.1"
|
|
42
|
+
},
|
|
43
|
+
"devDependencies": {
|
|
44
|
+
"@types/node": "^26.1.1",
|
|
45
|
+
"typescript": "^7.0.2",
|
|
46
|
+
"vitest": "^4.1.10"
|
|
47
|
+
}
|
|
48
|
+
}
|