autoform-mcp-server 1.2.1 → 1.3.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.
@@ -23,11 +23,15 @@ export class BatchGenerator {
23
23
  }
24
24
  const outputPaths = [];
25
25
  const errors = [];
26
+ // If merging, write individuals to temp dir (will be cleaned up)
27
+ const workingDir = mergeIntoSingle
28
+ ? fs.mkdtempSync(path.join(OUTPUT_DIR, '.tmp_batch_'))
29
+ : OUTPUT_DIR;
26
30
  for (let docNum = 0; docNum < documentsNeeded; docNum++) {
27
31
  try {
28
32
  const mappings = this.createMappings(data, template, docNum, mode);
29
33
  const docNumStr = String(docNum + 1).padStart(3, '0');
30
- const outputPath = path.join(OUTPUT_DIR, `${safeName}_${docNumStr}_${timestamp}.pdf`);
34
+ const outputPath = path.join(workingDir, `${safeName}_${docNumStr}_${timestamp}.pdf`);
31
35
  await PdfService.generateSingleDocument(basePdf, mappings, outputPath);
32
36
  outputPaths.push(outputPath);
33
37
  }
@@ -35,11 +39,28 @@ export class BatchGenerator {
35
39
  errors.push(`Doc ${docNum + 1}: ${err instanceof Error ? err.message : String(err)}`);
36
40
  }
37
41
  }
38
- // Merge if requested
42
+ // Merge if requested — and clean up individuals
39
43
  let mergedPath;
40
44
  if (mergeIntoSingle && outputPaths.length > 0) {
41
45
  mergedPath = path.join(OUTPUT_DIR, `${safeName}_merged_${timestamp}.pdf`);
42
46
  await PdfService.mergePdfs(outputPaths, mergedPath);
47
+ // Delete temp files and dir
48
+ for (const p of outputPaths) {
49
+ try {
50
+ fs.unlinkSync(p);
51
+ }
52
+ catch { /* ignore */ }
53
+ }
54
+ try {
55
+ fs.rmdirSync(workingDir);
56
+ }
57
+ catch { /* ignore */ }
58
+ return {
59
+ documentsGenerated: outputPaths.length,
60
+ outputPaths: [],
61
+ mergedPath,
62
+ errors
63
+ };
43
64
  }
44
65
  return {
45
66
  documentsGenerated: outputPaths.length,
@@ -202,11 +202,14 @@ export class PdfService {
202
202
  * Each entry in `dataRows` produces one PDF using the same field positions.
203
203
  */
204
204
  static async batchFillAtCoordinates(pdfPath, fieldDefinitions, dataRows, outputDir, baseName, merge = false) {
205
- const bytes = fs.readFileSync(pdfPath);
206
205
  const outputPaths = [];
207
206
  const errors = [];
208
207
  const timestamp = new Date().toISOString().slice(0, 10);
209
208
  fs.mkdirSync(outputDir, { recursive: true });
209
+ // If merging, write individuals to a temp dir that will be cleaned up
210
+ const workingDir = merge
211
+ ? fs.mkdtempSync(path.join(outputDir, '.tmp_batch_'))
212
+ : outputDir;
210
213
  for (let i = 0; i < dataRows.length; i++) {
211
214
  try {
212
215
  const row = dataRows[i];
@@ -221,7 +224,7 @@ export class PdfService {
221
224
  overflowMode: def.overflowMode
222
225
  })).filter(f => f.text.trim() !== '');
223
226
  const num = String(i + 1).padStart(3, '0');
224
- const outPath = path.join(outputDir, `${baseName}_${num}_${timestamp}.pdf`);
227
+ const outPath = path.join(workingDir, `${baseName}_${num}_${timestamp}.pdf`);
225
228
  await this.fillAtCoordinates(pdfPath, fields, outPath);
226
229
  outputPaths.push(outPath);
227
230
  }
@@ -233,6 +236,19 @@ export class PdfService {
233
236
  if (merge && outputPaths.length > 0) {
234
237
  mergedPath = path.join(outputDir, `${baseName}_merged_${timestamp}.pdf`);
235
238
  await this.mergePdfs(outputPaths, mergedPath);
239
+ // Clean up temp files and dir
240
+ for (const p of outputPaths) {
241
+ try {
242
+ fs.unlinkSync(p);
243
+ }
244
+ catch { /* ignore */ }
245
+ }
246
+ try {
247
+ fs.rmdirSync(workingDir);
248
+ }
249
+ catch { /* ignore */ }
250
+ // Clear individual paths from response since they no longer exist
251
+ return { outputPaths: [], mergedPath, errors };
236
252
  }
237
253
  return { outputPaths, mergedPath, errors };
238
254
  }
@@ -7,6 +7,12 @@ export const fillAtCoordinatesSchema = {
7
7
  description: `Escribe texto en posiciones exactas de un PDF usando coordenadas en puntos PDF (origen: esquina inferior-izquierda).
8
8
  Ideal cuando Claude analiza visualmente un PDF y determina dónde colocar el texto.
9
9
 
10
+ IMPORTANTE — Codificación de texto:
11
+ - El texto se pasa EXACTAMENTE como lo envías. NO simplifiques ni modifiques caracteres.
12
+ - Acentos españoles (á é í ó ú ñ Ñ ü) están soportados completamente.
13
+ - Nombres como "Sofía", "Benítez", "Peña" deben pasarse con sus tildes intactas.
14
+ - Solo se filtran: emojis, caracteres de control invisibles, y patrones de script malicioso.
15
+
10
16
  FLUJO RECOMENDADO:
11
17
  1. Primero usa autoform_get_pdf_info para obtener las dimensiones de cada página
12
18
  2. Basándote en el análisis visual del PDF, calcula las coordenadas en puntos PDF
@@ -8,6 +8,13 @@ export const fillBatchAtCoordinatesSchema = {
8
8
 
9
9
  CUANDO USAR: El usuario pasa un PDF (certificado, diploma, constancia) y una LISTA de datos (nombres, fechas, etc.) y quiere generar un PDF por cada fila de datos.
10
10
 
11
+ IMPORTANTE — Codificación de texto:
12
+ - Los datos se escriben EXACTAMENTE como los envías. NO simplifiques ni modifiques caracteres.
13
+ - Acentos españoles (á é í ó ú ñ Ñ ü) están soportados completamente.
14
+ - Nombres como "Sofía", "Benítez", "Peña" deben pasarse con sus tildes intactas.
15
+
16
+ MERGE: Si merge_into_single=true, se genera SOLO el PDF unificado (los individuales son temporales y se borran automáticamente).
17
+
11
18
  FLUJO:
12
19
  1. Usa autoform_get_pdf_info para obtener las dimensiones de la pagina
13
20
  2. Analiza visualmente el PDF para determinar donde van los campos
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "autoform-mcp-server",
3
- "version": "1.2.1",
3
+ "version": "1.3.0",
4
4
  "description": "MCP server for bulk PDF form filling. Detect fields, fill templates, and generate hundreds of PDFs from data — directly from Claude.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",