autoform-mcp-server 1.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.
@@ -0,0 +1,94 @@
1
+ export declare const fillAtCoordinatesSchema: {
2
+ name: string;
3
+ description: string;
4
+ inputSchema: {
5
+ type: "object";
6
+ properties: {
7
+ pdf_path: {
8
+ type: string;
9
+ description: string;
10
+ };
11
+ fields: {
12
+ type: string;
13
+ description: string;
14
+ items: {
15
+ type: string;
16
+ properties: {
17
+ text: {
18
+ type: string;
19
+ description: string;
20
+ };
21
+ page: {
22
+ type: string;
23
+ description: string;
24
+ };
25
+ x: {
26
+ type: string;
27
+ description: string;
28
+ };
29
+ y: {
30
+ type: string;
31
+ description: string;
32
+ };
33
+ width: {
34
+ type: string;
35
+ description: string;
36
+ };
37
+ height: {
38
+ type: string;
39
+ description: string;
40
+ };
41
+ fontSize: {
42
+ type: string;
43
+ description: string;
44
+ };
45
+ overflowMode: {
46
+ type: string;
47
+ enum: string[];
48
+ description: string;
49
+ };
50
+ };
51
+ required: string[];
52
+ };
53
+ };
54
+ output_path: {
55
+ type: string;
56
+ description: string;
57
+ };
58
+ };
59
+ required: string[];
60
+ };
61
+ };
62
+ export declare const getPdfInfoSchema: {
63
+ name: string;
64
+ description: string;
65
+ inputSchema: {
66
+ type: "object";
67
+ properties: {
68
+ pdf_path: {
69
+ type: string;
70
+ description: string;
71
+ };
72
+ };
73
+ required: string[];
74
+ };
75
+ };
76
+ export declare function handleFillAtCoordinates(args: any): Promise<{
77
+ content: {
78
+ type: "text";
79
+ text: string;
80
+ }[];
81
+ isError: boolean;
82
+ } | {
83
+ content: {
84
+ type: "text";
85
+ text: string;
86
+ }[];
87
+ isError?: undefined;
88
+ }>;
89
+ export declare function handleGetPdfInfo(args: any): Promise<{
90
+ content: {
91
+ type: "text";
92
+ text: string;
93
+ }[];
94
+ }>;
@@ -0,0 +1,113 @@
1
+ import * as path from 'path';
2
+ import { PdfService } from '../services/pdfService.js';
3
+ const OUTPUT_DIR = path.resolve(import.meta.dirname, '../../output');
4
+ export const fillAtCoordinatesSchema = {
5
+ name: 'autoform_fill_at_coordinates',
6
+ description: `Escribe texto en posiciones exactas de un PDF usando coordenadas en puntos PDF (origen: esquina inferior-izquierda).
7
+ Ideal cuando Claude analiza visualmente un PDF y determina dónde colocar el texto.
8
+
9
+ FLUJO RECOMENDADO:
10
+ 1. Primero usa autoform_get_pdf_info para obtener las dimensiones de cada página
11
+ 2. Basándote en el análisis visual del PDF, calcula las coordenadas en puntos PDF
12
+ 3. Recuerda: Y=0 está ABAJO, Y aumenta hacia ARRIBA
13
+
14
+ SISTEMA DE COORDENADAS:
15
+ - Origen (0,0) = esquina inferior-izquierda de la página
16
+ - X aumenta hacia la derecha
17
+ - Y aumenta hacia arriba
18
+ - Una página A4 típica mide ~595 x 842 puntos
19
+ - Una página Letter típica mide ~612 x 792 puntos`,
20
+ inputSchema: {
21
+ type: 'object',
22
+ properties: {
23
+ pdf_path: {
24
+ type: 'string',
25
+ description: 'Ruta absoluta al archivo PDF'
26
+ },
27
+ fields: {
28
+ type: 'array',
29
+ description: 'Array de campos a llenar con coordenadas exactas',
30
+ items: {
31
+ type: 'object',
32
+ properties: {
33
+ text: { type: 'string', description: 'Texto a escribir' },
34
+ page: { type: 'number', description: 'Número de página (1-indexed)' },
35
+ x: { type: 'number', description: 'Posición X en puntos desde la izquierda' },
36
+ y: { type: 'number', description: 'Posición Y en puntos desde abajo' },
37
+ width: { type: 'number', description: 'Ancho del campo en puntos' },
38
+ height: { type: 'number', description: 'Alto del campo en puntos' },
39
+ fontSize: { type: 'number', description: '(Opcional) Tamaño de fuente. Default: 12' },
40
+ overflowMode: { type: 'string', enum: ['shrink', 'wrap'], description: '(Opcional) shrink=reducir tamaño, wrap=salto de línea. Default: shrink' }
41
+ },
42
+ required: ['text', 'page', 'x', 'y', 'width', 'height']
43
+ }
44
+ },
45
+ output_path: {
46
+ type: 'string',
47
+ description: '(Opcional) Ruta donde guardar el PDF. Si no se especifica, se guarda en output/'
48
+ }
49
+ },
50
+ required: ['pdf_path', 'fields']
51
+ }
52
+ };
53
+ export const getPdfInfoSchema = {
54
+ name: 'autoform_get_pdf_info',
55
+ description: 'Obtiene información del PDF: número de páginas y dimensiones de cada página en puntos. Útil para calcular coordenadas antes de usar autoform_fill_at_coordinates.',
56
+ inputSchema: {
57
+ type: 'object',
58
+ properties: {
59
+ pdf_path: {
60
+ type: 'string',
61
+ description: 'Ruta absoluta al archivo PDF'
62
+ }
63
+ },
64
+ required: ['pdf_path']
65
+ }
66
+ };
67
+ export async function handleFillAtCoordinates(args) {
68
+ const { pdf_path, output_path } = args;
69
+ // fields puede llegar como string JSON o como array — normalizar
70
+ let fields = args.fields;
71
+ if (typeof fields === 'string') {
72
+ try {
73
+ fields = JSON.parse(fields);
74
+ }
75
+ catch { /* keep as-is */ }
76
+ }
77
+ if (!fields || !Array.isArray(fields) || fields.length === 0) {
78
+ return {
79
+ content: [{ type: 'text', text: JSON.stringify({ error: true, message: 'No se proporcionaron campos válidos.' }, null, 2) }],
80
+ isError: true
81
+ };
82
+ }
83
+ const outputFile = output_path || path.join(OUTPUT_DIR, `coords_${path.basename(pdf_path, '.pdf')}_${Date.now()}.pdf`);
84
+ const filled = await PdfService.fillAtCoordinates(pdf_path, fields, outputFile);
85
+ return {
86
+ content: [{
87
+ type: 'text',
88
+ text: JSON.stringify({
89
+ fields_filled: filled,
90
+ output_path: outputFile,
91
+ message: `${filled} campo(s) escritos en el PDF. Archivo: ${outputFile}`
92
+ }, null, 2)
93
+ }]
94
+ };
95
+ }
96
+ export async function handleGetPdfInfo(args) {
97
+ const { pdf_path } = args;
98
+ const pages = await PdfService.getPageDimensions(pdf_path);
99
+ const { fields, hasAcroform } = await PdfService.detectFields(pdf_path);
100
+ return {
101
+ content: [{
102
+ type: 'text',
103
+ text: JSON.stringify({
104
+ total_pages: pages.length,
105
+ pages,
106
+ has_acroform: hasAcroform,
107
+ acroform_fields: fields.length,
108
+ coordinate_system: 'Origen (0,0) = esquina inferior-izquierda. X→derecha, Y→arriba. Unidades: puntos PDF (1 punto = 1/72 pulgada).',
109
+ message: `PDF con ${pages.length} página(s). ${pages.map(p => `Pág ${p.page}: ${p.width} x ${p.height} pts`).join(', ')}`
110
+ }, null, 2)
111
+ }]
112
+ };
113
+ }
@@ -0,0 +1,88 @@
1
+ export declare const fillBatchAtCoordinatesSchema: {
2
+ name: string;
3
+ description: string;
4
+ inputSchema: {
5
+ type: "object";
6
+ properties: {
7
+ pdf_path: {
8
+ type: string;
9
+ description: string;
10
+ };
11
+ field_definitions: {
12
+ type: string;
13
+ description: string;
14
+ items: {
15
+ type: string;
16
+ properties: {
17
+ label: {
18
+ type: string;
19
+ description: string;
20
+ };
21
+ page: {
22
+ type: string;
23
+ description: string;
24
+ };
25
+ x: {
26
+ type: string;
27
+ description: string;
28
+ };
29
+ y: {
30
+ type: string;
31
+ description: string;
32
+ };
33
+ width: {
34
+ type: string;
35
+ description: string;
36
+ };
37
+ height: {
38
+ type: string;
39
+ description: string;
40
+ };
41
+ fontSize: {
42
+ type: string;
43
+ description: string;
44
+ };
45
+ overflowMode: {
46
+ type: string;
47
+ enum: string[];
48
+ description: string;
49
+ };
50
+ };
51
+ required: string[];
52
+ };
53
+ };
54
+ data_rows: {
55
+ type: string;
56
+ description: string;
57
+ items: {
58
+ type: string;
59
+ additionalProperties: {
60
+ type: string;
61
+ };
62
+ };
63
+ };
64
+ merge_into_single: {
65
+ type: string;
66
+ description: string;
67
+ };
68
+ output_dir: {
69
+ type: string;
70
+ description: string;
71
+ };
72
+ };
73
+ required: string[];
74
+ };
75
+ };
76
+ export declare function handleFillBatchAtCoordinates(args: any): Promise<{
77
+ content: {
78
+ type: "text";
79
+ text: string;
80
+ }[];
81
+ isError: boolean;
82
+ } | {
83
+ content: {
84
+ type: "text";
85
+ text: string;
86
+ }[];
87
+ isError?: undefined;
88
+ }>;
@@ -0,0 +1,102 @@
1
+ import * as path from 'path';
2
+ import { PdfService } from '../services/pdfService.js';
3
+ const OUTPUT_DIR = path.resolve(import.meta.dirname, '../../output');
4
+ export const fillBatchAtCoordinatesSchema = {
5
+ name: 'autoform_fill_batch_at_coordinates',
6
+ description: `Genera MULTIPLES PDFs a partir de un mismo PDF base, escribiendo datos diferentes en las mismas posiciones de cada copia.
7
+
8
+ 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.
9
+
10
+ FLUJO:
11
+ 1. Usa autoform_get_pdf_info para obtener las dimensiones de la pagina
12
+ 2. Analiza visualmente el PDF para determinar donde van los campos
13
+ 3. Define los campos con label (nombre logico) + coordenadas
14
+ 4. Pasa las filas de datos como array de objetos {label: valor}
15
+ 5. Opcionalmente unifica todo en un solo PDF con merge_into_single
16
+
17
+ SISTEMA DE COORDENADAS: Origen (0,0) = esquina inferior-izquierda. Y aumenta hacia arriba. Unidades: puntos PDF.`,
18
+ inputSchema: {
19
+ type: 'object',
20
+ properties: {
21
+ pdf_path: {
22
+ type: 'string',
23
+ description: 'Ruta absoluta al PDF base (la plantilla)'
24
+ },
25
+ field_definitions: {
26
+ type: 'array',
27
+ description: 'Definicion de los campos: donde va cada dato en el PDF. El "label" es la clave que conecta con los datos.',
28
+ items: {
29
+ type: 'object',
30
+ properties: {
31
+ label: { type: 'string', description: 'Nombre logico del campo (ej: "nombre", "fecha"). Debe coincidir con las claves de data_rows.' },
32
+ page: { type: 'number', description: 'Pagina (1-indexed)' },
33
+ x: { type: 'number', description: 'X en puntos desde la izquierda' },
34
+ y: { type: 'number', description: 'Y en puntos desde abajo' },
35
+ width: { type: 'number', description: 'Ancho en puntos' },
36
+ height: { type: 'number', description: 'Alto en puntos' },
37
+ fontSize: { type: 'number', description: '(Opcional) Tamaño de fuente. Default: 12' },
38
+ overflowMode: { type: 'string', enum: ['shrink', 'wrap'], description: '(Opcional) Default: shrink' }
39
+ },
40
+ required: ['label', 'page', 'x', 'y', 'width', 'height']
41
+ }
42
+ },
43
+ data_rows: {
44
+ type: 'array',
45
+ description: 'Array de objetos con los datos. Cada objeto es un documento. Las claves deben coincidir con los "label" de field_definitions.',
46
+ items: {
47
+ type: 'object',
48
+ additionalProperties: { type: 'string' }
49
+ }
50
+ },
51
+ merge_into_single: {
52
+ type: 'boolean',
53
+ description: '(Opcional) Si true, une todos los PDFs en uno solo. Default: false'
54
+ },
55
+ output_dir: {
56
+ type: 'string',
57
+ description: '(Opcional) Directorio de salida. Default: output/'
58
+ }
59
+ },
60
+ required: ['pdf_path', 'field_definitions', 'data_rows']
61
+ }
62
+ };
63
+ export async function handleFillBatchAtCoordinates(args) {
64
+ const { pdf_path, output_dir, merge_into_single = false } = args;
65
+ let field_definitions = args.field_definitions;
66
+ if (typeof field_definitions === 'string') {
67
+ try {
68
+ field_definitions = JSON.parse(field_definitions);
69
+ }
70
+ catch { /* keep */ }
71
+ }
72
+ let data_rows = args.data_rows;
73
+ if (typeof data_rows === 'string') {
74
+ try {
75
+ data_rows = JSON.parse(data_rows);
76
+ }
77
+ catch { /* keep */ }
78
+ }
79
+ if (!field_definitions || !Array.isArray(field_definitions) || field_definitions.length === 0) {
80
+ return { content: [{ type: 'text', text: JSON.stringify({ error: true, message: 'field_definitions es requerido (array de campos con coordenadas)' }, null, 2) }], isError: true };
81
+ }
82
+ if (!data_rows || !Array.isArray(data_rows) || data_rows.length === 0) {
83
+ return { content: [{ type: 'text', text: JSON.stringify({ error: true, message: 'data_rows es requerido (array de objetos con datos)' }, null, 2) }], isError: true };
84
+ }
85
+ const outDir = output_dir || OUTPUT_DIR;
86
+ const baseName = path.basename(pdf_path, '.pdf').replace(/[^a-zA-Z0-9_\-]/g, '_');
87
+ const result = await PdfService.batchFillAtCoordinates(pdf_path, field_definitions, data_rows, outDir, baseName, merge_into_single);
88
+ return {
89
+ content: [{
90
+ type: 'text',
91
+ text: JSON.stringify({
92
+ documents_generated: result.outputPaths.length,
93
+ output_paths: result.outputPaths,
94
+ merged_path: result.mergedPath,
95
+ errors: result.errors,
96
+ message: result.outputPaths.length > 0
97
+ ? `Generados ${result.outputPaths.length} documentos.${result.mergedPath ? ` PDF unificado: ${result.mergedPath}` : ''}`
98
+ : `Error: no se generaron documentos. ${result.errors.join(', ')}`
99
+ }, null, 2)
100
+ }]
101
+ };
102
+ }
@@ -0,0 +1,42 @@
1
+ export declare const fillPdfSchema: {
2
+ name: string;
3
+ description: string;
4
+ inputSchema: {
5
+ type: "object";
6
+ properties: {
7
+ pdf_path: {
8
+ type: string;
9
+ description: string;
10
+ };
11
+ field_values: {
12
+ type: string;
13
+ description: string;
14
+ additionalProperties: {
15
+ type: string;
16
+ };
17
+ };
18
+ output_path: {
19
+ type: string;
20
+ description: string;
21
+ };
22
+ template_name: {
23
+ type: string;
24
+ description: string;
25
+ };
26
+ };
27
+ required: string[];
28
+ };
29
+ };
30
+ export declare function handleFillPdf(args: any): Promise<{
31
+ content: {
32
+ type: "text";
33
+ text: string;
34
+ }[];
35
+ isError?: undefined;
36
+ } | {
37
+ content: {
38
+ type: "text";
39
+ text: string;
40
+ }[];
41
+ isError: boolean;
42
+ }>;
@@ -0,0 +1,97 @@
1
+ import * as path from 'path';
2
+ import { PdfService } from '../services/pdfService.js';
3
+ import { TemplateStore } from '../services/templateStore.js';
4
+ const OUTPUT_DIR = path.resolve(import.meta.dirname, '../../output');
5
+ export const fillPdfSchema = {
6
+ name: 'autoform_fill_pdf',
7
+ description: `Llena UN PDF con valores. Detecta automaticamente si tiene AcroForm o usa un template guardado.
8
+
9
+ CUANDO USAR: Quieres llenar UN SOLO documento y ya tienes AcroForm o un template guardado.
10
+ NO USAR SI: El PDF es estatico sin template → usa autoform_fill_at_coordinates.
11
+ NO USAR SI: Quieres generar MULTIPLES documentos → usa autoform_generate_batch o autoform_fill_batch_at_coordinates.`,
12
+ inputSchema: {
13
+ type: 'object',
14
+ properties: {
15
+ pdf_path: {
16
+ type: 'string',
17
+ description: 'Ruta absoluta al archivo PDF a llenar'
18
+ },
19
+ field_values: {
20
+ type: 'object',
21
+ description: 'Objeto con los valores a llenar. Claves = nombre del campo, valores = texto a insertar. Ejemplo: { "nombre": "Juan", "dni": "12345" }',
22
+ additionalProperties: { type: 'string' }
23
+ },
24
+ output_path: {
25
+ type: 'string',
26
+ description: '(Opcional) Ruta donde guardar el PDF llenado. Si no se especifica, se guarda en la carpeta output/'
27
+ },
28
+ template_name: {
29
+ type: 'string',
30
+ description: '(Opcional) Nombre del template a usar para posicionar los campos. Solo necesario si el PDF no tiene AcroForm.'
31
+ }
32
+ },
33
+ required: ['pdf_path', 'field_values']
34
+ }
35
+ };
36
+ export async function handleFillPdf(args) {
37
+ const { pdf_path, output_path, template_name } = args;
38
+ let field_values = args.field_values;
39
+ if (typeof field_values === 'string') {
40
+ try {
41
+ field_values = JSON.parse(field_values);
42
+ }
43
+ catch { /* keep as-is */ }
44
+ }
45
+ const outputFile = output_path || path.join(OUTPUT_DIR, `filled_${path.basename(pdf_path, '.pdf')}_${Date.now()}.pdf`);
46
+ // Try AcroForm first
47
+ const { fields, hasAcroform } = await PdfService.detectFields(pdf_path);
48
+ if (hasAcroform && fields.length > 0) {
49
+ const filled = await PdfService.fillAcroForm(pdf_path, field_values, outputFile);
50
+ return {
51
+ content: [{
52
+ type: 'text',
53
+ text: JSON.stringify({
54
+ method: 'acroform',
55
+ fields_filled: filled,
56
+ output_path: outputFile,
57
+ message: `PDF llenado exitosamente usando AcroForm. ${filled} campo(s) completados.`
58
+ }, null, 2)
59
+ }]
60
+ };
61
+ }
62
+ // No AcroForm — try template
63
+ let template = template_name ? TemplateStore.load(template_name) : null;
64
+ // If no template specified, try to find one matching the PDF name
65
+ if (!template) {
66
+ const allTemplates = TemplateStore.list();
67
+ const pdfBaseName = path.basename(pdf_path).toLowerCase();
68
+ const match = allTemplates.find(t => t.name.toLowerCase().includes(pdfBaseName.replace('.pdf', '')));
69
+ if (match)
70
+ template = TemplateStore.load(match.name);
71
+ }
72
+ if (!template) {
73
+ return {
74
+ content: [{
75
+ type: 'text',
76
+ text: JSON.stringify({
77
+ error: true,
78
+ message: `El PDF no tiene campos AcroForm y no se encontro un template con las coordenadas de los campos.\n\nOpciones:\n1. Abra el PDF en la app web de AutoForm, defina los campos visualmente, y exporte como template JSON\n2. Importe el template con autoform_import_template\n3. Luego use autoform_fill_pdf con template_name="nombre_del_template"`
79
+ }, null, 2)
80
+ }],
81
+ isError: true
82
+ };
83
+ }
84
+ const filled = await PdfService.fillWithTemplate(pdf_path, template.fields, field_values, outputFile);
85
+ return {
86
+ content: [{
87
+ type: 'text',
88
+ text: JSON.stringify({
89
+ method: 'template',
90
+ template_used: template.name,
91
+ fields_filled: filled,
92
+ output_path: outputFile,
93
+ message: `PDF llenado usando template "${template.name}". ${filled} campo(s) completados.`
94
+ }, null, 2)
95
+ }]
96
+ };
97
+ }
@@ -0,0 +1,46 @@
1
+ export declare const generateBatchSchema: {
2
+ name: string;
3
+ description: string;
4
+ inputSchema: {
5
+ type: "object";
6
+ properties: {
7
+ template_name: {
8
+ type: string;
9
+ description: string;
10
+ };
11
+ data: {
12
+ type: string;
13
+ description: string;
14
+ items: {
15
+ type: string;
16
+ additionalProperties: {
17
+ type: string;
18
+ };
19
+ };
20
+ };
21
+ distribution_mode: {
22
+ type: string;
23
+ enum: string[];
24
+ description: string;
25
+ };
26
+ merge_into_single: {
27
+ type: string;
28
+ description: string;
29
+ };
30
+ };
31
+ required: string[];
32
+ };
33
+ };
34
+ export declare function handleGenerateBatch(args: any): Promise<{
35
+ content: {
36
+ type: "text";
37
+ text: string;
38
+ }[];
39
+ isError: boolean;
40
+ } | {
41
+ content: {
42
+ type: "text";
43
+ text: string;
44
+ }[];
45
+ isError?: undefined;
46
+ }>;