xlsx-for-ai 3.0.13 → 3.0.16
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/mcp.js +204 -41
- package/package.json +1 -1
package/mcp.js
CHANGED
|
@@ -39,7 +39,7 @@ const TOOLS = [
|
|
|
39
39
|
inputSchema: {
|
|
40
40
|
type: 'object',
|
|
41
41
|
properties: {
|
|
42
|
-
file_path: { type: 'string', description: 'Absolute path to the .xlsx file.' },
|
|
42
|
+
file_path: { type: 'string', description: 'Absolute path to the .xlsx file. Pass the path string AS-IS — do NOT read, open, or base64-encode the file; the client handles all file I/O. The base64 surface in this connector is OUTPUT-only (_meta.file_b64).' },
|
|
43
43
|
format: {
|
|
44
44
|
type: 'string',
|
|
45
45
|
enum: ['md', 'json', 'sql'],
|
|
@@ -64,7 +64,7 @@ const TOOLS = [
|
|
|
64
64
|
inputSchema: {
|
|
65
65
|
type: 'object',
|
|
66
66
|
properties: {
|
|
67
|
-
file_path: { type: 'string', description: 'Absolute path to the .xlsx file.' },
|
|
67
|
+
file_path: { type: 'string', description: 'Absolute path to the .xlsx file. Pass the path string AS-IS — do NOT read, open, or base64-encode the file; the client handles all file I/O. The base64 surface in this connector is OUTPUT-only (_meta.file_b64).' },
|
|
68
68
|
},
|
|
69
69
|
required: ['file_path'],
|
|
70
70
|
},
|
|
@@ -80,7 +80,7 @@ const TOOLS = [
|
|
|
80
80
|
inputSchema: {
|
|
81
81
|
type: 'object',
|
|
82
82
|
properties: {
|
|
83
|
-
file_path: { type: 'string', description: 'Absolute path to the .xlsx file.' },
|
|
83
|
+
file_path: { type: 'string', description: 'Absolute path to the .xlsx file. Pass the path string AS-IS — do NOT read, open, or base64-encode the file; the client handles all file I/O. The base64 surface in this connector is OUTPUT-only (_meta.file_b64).' },
|
|
84
84
|
sheet: { type: 'string', description: 'Limit to one sheet (default: all).' },
|
|
85
85
|
},
|
|
86
86
|
required: ['file_path'],
|
|
@@ -97,8 +97,8 @@ const TOOLS = [
|
|
|
97
97
|
inputSchema: {
|
|
98
98
|
type: 'object',
|
|
99
99
|
properties: {
|
|
100
|
-
file_path_a: { type: 'string', description: '
|
|
101
|
-
file_path_b: { type: 'string', description: '
|
|
100
|
+
file_path_a: { type: 'string', description: 'Absolute path to the base .xlsx file. Pass the path string AS-IS — do NOT base64-encode the file; the client reads it.' },
|
|
101
|
+
file_path_b: { type: 'string', description: 'Absolute path to the changed .xlsx file. Pass the path string AS-IS — do NOT base64-encode the file; the client reads it.' },
|
|
102
102
|
sheet: { type: 'string', description: 'Limit diff to one sheet (default: all).' },
|
|
103
103
|
},
|
|
104
104
|
required: ['file_path_a', 'file_path_b'],
|
|
@@ -181,7 +181,7 @@ const TOOLS = [
|
|
|
181
181
|
},
|
|
182
182
|
spec_path: {
|
|
183
183
|
type: 'string',
|
|
184
|
-
description: '
|
|
184
|
+
description: 'Absolute path to a .json file carrying the spec (alternative to inline spec for large workbooks). Pass the path string AS-IS — do NOT base64-encode; the client reads it.',
|
|
185
185
|
},
|
|
186
186
|
out_path: {
|
|
187
187
|
type: 'string',
|
|
@@ -189,7 +189,7 @@ const TOOLS = [
|
|
|
189
189
|
},
|
|
190
190
|
base_file_b64: {
|
|
191
191
|
type: 'string',
|
|
192
|
-
description: '
|
|
192
|
+
description: 'NARROW EXCEPTION — xlsx_write ONLY accepts a base64-encoded base workbook here for edit-in-place. Every OTHER tool in this connector takes a file PATH (`file_path`), not bytes. When omitted, a fresh workbook is created.',
|
|
193
193
|
},
|
|
194
194
|
},
|
|
195
195
|
// out_path is the typical caller's choice but not strictly required —
|
|
@@ -212,7 +212,7 @@ const TOOLS = [
|
|
|
212
212
|
inputSchema: {
|
|
213
213
|
type: 'object',
|
|
214
214
|
properties: {
|
|
215
|
-
file_path: { type: 'string', description: 'Absolute path to the source .xlsx file.' },
|
|
215
|
+
file_path: { type: 'string', description: 'Absolute path to the source .xlsx file. Pass the path string AS-IS — do NOT read, open, or base64-encode the file; the client handles all file I/O.' },
|
|
216
216
|
out_path: { type: 'string', description: 'Destination for the redacted .xlsx file.' },
|
|
217
217
|
},
|
|
218
218
|
required: ['file_path', 'out_path'],
|
|
@@ -238,7 +238,7 @@ const TOOLS = [
|
|
|
238
238
|
inputSchema: {
|
|
239
239
|
type: 'object',
|
|
240
240
|
properties: {
|
|
241
|
-
file_path: { type: 'string', description: 'Absolute path to the .xlsx file.' },
|
|
241
|
+
file_path: { type: 'string', description: 'Absolute path to the .xlsx file. Pass the path string AS-IS — do NOT read, open, or base64-encode the file; the client handles all file I/O. The base64 surface in this connector is OUTPUT-only (_meta.file_b64).' },
|
|
242
242
|
sheet: { type: 'string', description: 'Sheet name (default: first sheet).' },
|
|
243
243
|
header_row: { type: 'integer', description: 'Header row (1-based). 0 = treat row 1 as data, no header.' },
|
|
244
244
|
max_rows: { type: 'integer', description: 'Max data rows to scan (default 10000).' },
|
|
@@ -258,7 +258,7 @@ const TOOLS = [
|
|
|
258
258
|
inputSchema: {
|
|
259
259
|
type: 'object',
|
|
260
260
|
properties: {
|
|
261
|
-
file_path: { type: 'string', description: 'Absolute path to the .xlsx file.' },
|
|
261
|
+
file_path: { type: 'string', description: 'Absolute path to the .xlsx file. Pass the path string AS-IS — do NOT read, open, or base64-encode the file; the client handles all file I/O. The base64 surface in this connector is OUTPUT-only (_meta.file_b64).' },
|
|
262
262
|
predicates: {
|
|
263
263
|
type: 'array',
|
|
264
264
|
minItems: 1,
|
|
@@ -292,7 +292,7 @@ const TOOLS = [
|
|
|
292
292
|
inputSchema: {
|
|
293
293
|
type: 'object',
|
|
294
294
|
properties: {
|
|
295
|
-
file_path: { type: 'string', description: 'Absolute path to the .xlsx file.' },
|
|
295
|
+
file_path: { type: 'string', description: 'Absolute path to the .xlsx file. Pass the path string AS-IS — do NOT read, open, or base64-encode the file; the client handles all file I/O. The base64 surface in this connector is OUTPUT-only (_meta.file_b64).' },
|
|
296
296
|
group_by: { type: 'array', items: { type: 'string' }, minItems: 1, description: 'Columns to group by.' },
|
|
297
297
|
aggs: {
|
|
298
298
|
type: 'array',
|
|
@@ -328,7 +328,7 @@ const TOOLS = [
|
|
|
328
328
|
inputSchema: {
|
|
329
329
|
type: 'object',
|
|
330
330
|
properties: {
|
|
331
|
-
file_path: { type: 'string', description: 'Absolute path to the .xlsx file.' },
|
|
331
|
+
file_path: { type: 'string', description: 'Absolute path to the .xlsx file. Pass the path string AS-IS — do NOT read, open, or base64-encode the file; the client handles all file I/O. The base64 surface in this connector is OUTPUT-only (_meta.file_b64).' },
|
|
332
332
|
},
|
|
333
333
|
required: ['file_path'],
|
|
334
334
|
},
|
|
@@ -344,7 +344,7 @@ const TOOLS = [
|
|
|
344
344
|
inputSchema: {
|
|
345
345
|
type: 'object',
|
|
346
346
|
properties: {
|
|
347
|
-
file_path: { type: 'string', description: 'Absolute path to the .xlsx file.' },
|
|
347
|
+
file_path: { type: 'string', description: 'Absolute path to the .xlsx file. Pass the path string AS-IS — do NOT read, open, or base64-encode the file; the client handles all file I/O. The base64 surface in this connector is OUTPUT-only (_meta.file_b64).' },
|
|
348
348
|
by: {
|
|
349
349
|
type: 'array',
|
|
350
350
|
minItems: 1,
|
|
@@ -376,7 +376,7 @@ const TOOLS = [
|
|
|
376
376
|
inputSchema: {
|
|
377
377
|
type: 'object',
|
|
378
378
|
properties: {
|
|
379
|
-
file_path: { type: 'string', description: 'Absolute path to the .xlsx file.' },
|
|
379
|
+
file_path: { type: 'string', description: 'Absolute path to the .xlsx file. Pass the path string AS-IS — do NOT read, open, or base64-encode the file; the client handles all file I/O. The base64 surface in this connector is OUTPUT-only (_meta.file_b64).' },
|
|
380
380
|
column: { type: 'string', description: 'Column to count values in.' },
|
|
381
381
|
sheet: { type: 'string' },
|
|
382
382
|
header_row: { type: 'integer' },
|
|
@@ -398,7 +398,7 @@ const TOOLS = [
|
|
|
398
398
|
inputSchema: {
|
|
399
399
|
type: 'object',
|
|
400
400
|
properties: {
|
|
401
|
-
file_path: { type: 'string', description: 'Absolute path to the .xlsx file.' },
|
|
401
|
+
file_path: { type: 'string', description: 'Absolute path to the .xlsx file. Pass the path string AS-IS — do NOT read, open, or base64-encode the file; the client handles all file I/O. The base64 surface in this connector is OUTPUT-only (_meta.file_b64).' },
|
|
402
402
|
sheet: { type: 'string', description: 'Filter to one sheet (default: all sheets).' },
|
|
403
403
|
include_results: { type: 'boolean', description: 'Include cached results column (default true).' },
|
|
404
404
|
limit: { type: 'integer', description: 'Max formulas to return (default 1000, max 5000).' },
|
|
@@ -418,7 +418,7 @@ const TOOLS = [
|
|
|
418
418
|
inputSchema: {
|
|
419
419
|
type: 'object',
|
|
420
420
|
properties: {
|
|
421
|
-
file_path: { type: 'string', description: 'Absolute path to the .xlsx file.' },
|
|
421
|
+
file_path: { type: 'string', description: 'Absolute path to the .xlsx file. Pass the path string AS-IS — do NOT read, open, or base64-encode the file; the client handles all file I/O. The base64 surface in this connector is OUTPUT-only (_meta.file_b64).' },
|
|
422
422
|
sheet: { type: 'string', description: 'Filter to one sheet (default: all sheets).' },
|
|
423
423
|
include_columns: { type: 'boolean', description: 'Include column names per table (default true).' },
|
|
424
424
|
},
|
|
@@ -436,7 +436,7 @@ const TOOLS = [
|
|
|
436
436
|
inputSchema: {
|
|
437
437
|
type: 'object',
|
|
438
438
|
properties: {
|
|
439
|
-
file_path: { type: 'string', description: 'Absolute path to the .xlsx file.' },
|
|
439
|
+
file_path: { type: 'string', description: 'Absolute path to the .xlsx file. Pass the path string AS-IS — do NOT read, open, or base64-encode the file; the client handles all file I/O. The base64 surface in this connector is OUTPUT-only (_meta.file_b64).' },
|
|
440
440
|
index: { type: 'array', items: { type: 'string' }, minItems: 1, description: 'Row-axis grouping columns.' },
|
|
441
441
|
columns: { type: 'array', items: { type: 'string' }, description: 'Column-axis grouping columns (optional).' },
|
|
442
442
|
values: { type: 'array', items: { type: 'string' }, minItems: 1, description: 'Columns to aggregate.' },
|
|
@@ -460,7 +460,7 @@ const TOOLS = [
|
|
|
460
460
|
inputSchema: {
|
|
461
461
|
type: 'object',
|
|
462
462
|
properties: {
|
|
463
|
-
file_path: { type: 'string', description: 'Absolute path to the .xlsx file.' },
|
|
463
|
+
file_path: { type: 'string', description: 'Absolute path to the .xlsx file. Pass the path string AS-IS — do NOT read, open, or base64-encode the file; the client handles all file I/O. The base64 surface in this connector is OUTPUT-only (_meta.file_b64).' },
|
|
464
464
|
formulas: {
|
|
465
465
|
type: 'array',
|
|
466
466
|
items: { type: 'string' },
|
|
@@ -488,7 +488,7 @@ const TOOLS = [
|
|
|
488
488
|
inputSchema: {
|
|
489
489
|
type: 'object',
|
|
490
490
|
properties: {
|
|
491
|
-
file_path: { type: 'string', description: 'Absolute path to the source spreadsheet file (any supported format).' },
|
|
491
|
+
file_path: { type: 'string', description: 'Absolute path to the source spreadsheet file (any supported format). Pass the path string AS-IS — do NOT read, open, or base64-encode the file; the client handles all file I/O.' },
|
|
492
492
|
to: {
|
|
493
493
|
type: 'string',
|
|
494
494
|
enum: [
|
|
@@ -516,7 +516,7 @@ const TOOLS = [
|
|
|
516
516
|
inputSchema: {
|
|
517
517
|
type: 'object',
|
|
518
518
|
properties: {
|
|
519
|
-
file_path: { type: 'string', description: 'Absolute path to the .xlsx file.' },
|
|
519
|
+
file_path: { type: 'string', description: 'Absolute path to the .xlsx file. Pass the path string AS-IS — do NOT read, open, or base64-encode the file; the client handles all file I/O. The base64 surface in this connector is OUTPUT-only (_meta.file_b64).' },
|
|
520
520
|
mode: {
|
|
521
521
|
type: 'string',
|
|
522
522
|
enum: ['diagnose', 'execute'],
|
|
@@ -577,7 +577,7 @@ const TOOLS = [
|
|
|
577
577
|
inputSchema: {
|
|
578
578
|
type: 'object',
|
|
579
579
|
properties: {
|
|
580
|
-
file_path: { type: 'string', description: 'Absolute path to the .xlsx file.' },
|
|
580
|
+
file_path: { type: 'string', description: 'Absolute path to the .xlsx file. Pass the path string AS-IS — do NOT read, open, or base64-encode the file; the client handles all file I/O. The base64 surface in this connector is OUTPUT-only (_meta.file_b64).' },
|
|
581
581
|
},
|
|
582
582
|
required: ['file_path'],
|
|
583
583
|
},
|
|
@@ -594,7 +594,7 @@ const TOOLS = [
|
|
|
594
594
|
inputSchema: {
|
|
595
595
|
type: 'object',
|
|
596
596
|
properties: {
|
|
597
|
-
file_path: { type: 'string', description: 'Absolute path to the .xlsx file.' },
|
|
597
|
+
file_path: { type: 'string', description: 'Absolute path to the .xlsx file. Pass the path string AS-IS — do NOT read, open, or base64-encode the file; the client handles all file I/O. The base64 surface in this connector is OUTPUT-only (_meta.file_b64).' },
|
|
598
598
|
sheet: { type: 'string', description: 'Optional: restrict to a specific sheet.' },
|
|
599
599
|
},
|
|
600
600
|
required: ['file_path'],
|
|
@@ -612,7 +612,7 @@ const TOOLS = [
|
|
|
612
612
|
inputSchema: {
|
|
613
613
|
type: 'object',
|
|
614
614
|
properties: {
|
|
615
|
-
file_path: { type: 'string', description: 'Absolute path to the .xlsx file.' },
|
|
615
|
+
file_path: { type: 'string', description: 'Absolute path to the .xlsx file. Pass the path string AS-IS — do NOT read, open, or base64-encode the file; the client handles all file I/O. The base64 surface in this connector is OUTPUT-only (_meta.file_b64).' },
|
|
616
616
|
sheet: { type: 'string', description: 'Optional: restrict to a specific sheet.' },
|
|
617
617
|
},
|
|
618
618
|
required: ['file_path'],
|
|
@@ -630,7 +630,7 @@ const TOOLS = [
|
|
|
630
630
|
inputSchema: {
|
|
631
631
|
type: 'object',
|
|
632
632
|
properties: {
|
|
633
|
-
file_path: { type: 'string', description: 'Absolute path to the .xlsx file.' },
|
|
633
|
+
file_path: { type: 'string', description: 'Absolute path to the .xlsx file. Pass the path string AS-IS — do NOT read, open, or base64-encode the file; the client handles all file I/O. The base64 surface in this connector is OUTPUT-only (_meta.file_b64).' },
|
|
634
634
|
},
|
|
635
635
|
required: ['file_path'],
|
|
636
636
|
},
|
|
@@ -647,7 +647,7 @@ const TOOLS = [
|
|
|
647
647
|
inputSchema: {
|
|
648
648
|
type: 'object',
|
|
649
649
|
properties: {
|
|
650
|
-
file_path: { type: 'string', description: 'Absolute path to the .xlsx file.' },
|
|
650
|
+
file_path: { type: 'string', description: 'Absolute path to the .xlsx file. Pass the path string AS-IS — do NOT read, open, or base64-encode the file; the client handles all file I/O. The base64 surface in this connector is OUTPUT-only (_meta.file_b64).' },
|
|
651
651
|
sheet: { type: 'string', description: 'Optional: restrict to a specific sheet.' },
|
|
652
652
|
},
|
|
653
653
|
required: ['file_path'],
|
|
@@ -665,7 +665,7 @@ const TOOLS = [
|
|
|
665
665
|
inputSchema: {
|
|
666
666
|
type: 'object',
|
|
667
667
|
properties: {
|
|
668
|
-
file_path: { type: 'string', description: 'Absolute path to the .xlsx file.' },
|
|
668
|
+
file_path: { type: 'string', description: 'Absolute path to the .xlsx file. Pass the path string AS-IS — do NOT read, open, or base64-encode the file; the client handles all file I/O. The base64 surface in this connector is OUTPUT-only (_meta.file_b64).' },
|
|
669
669
|
sheet: { type: 'string', description: 'Optional: restrict to a specific sheet.' },
|
|
670
670
|
},
|
|
671
671
|
required: ['file_path'],
|
|
@@ -682,7 +682,7 @@ const TOOLS = [
|
|
|
682
682
|
inputSchema: {
|
|
683
683
|
type: 'object',
|
|
684
684
|
properties: {
|
|
685
|
-
file_path: { type: 'string', description: 'Absolute path to the .xlsx / .xlsm file.' },
|
|
685
|
+
file_path: { type: 'string', description: 'Absolute path to the .xlsx / .xlsm file. Pass the path string AS-IS — do NOT read, open, or base64-encode the file; the client handles all file I/O.' },
|
|
686
686
|
},
|
|
687
687
|
required: ['file_path'],
|
|
688
688
|
},
|
|
@@ -699,7 +699,7 @@ const TOOLS = [
|
|
|
699
699
|
inputSchema: {
|
|
700
700
|
type: 'object',
|
|
701
701
|
properties: {
|
|
702
|
-
file_path: { type: 'string', description: 'Absolute path to the .xlsx file.' },
|
|
702
|
+
file_path: { type: 'string', description: 'Absolute path to the .xlsx file. Pass the path string AS-IS — do NOT read, open, or base64-encode the file; the client handles all file I/O. The base64 surface in this connector is OUTPUT-only (_meta.file_b64).' },
|
|
703
703
|
sheet: { type: 'string', description: 'Optional: restrict to a specific sheet.' },
|
|
704
704
|
},
|
|
705
705
|
required: ['file_path'],
|
|
@@ -716,7 +716,7 @@ const TOOLS = [
|
|
|
716
716
|
inputSchema: {
|
|
717
717
|
type: 'object',
|
|
718
718
|
properties: {
|
|
719
|
-
file_path: { type: 'string', description: 'Absolute path to the .xlsx / .xlsm / .xlsb file.' },
|
|
719
|
+
file_path: { type: 'string', description: 'Absolute path to the .xlsx / .xlsm / .xlsb file. Pass the path string AS-IS — do NOT read, open, or base64-encode the file; the client handles all file I/O.' },
|
|
720
720
|
},
|
|
721
721
|
required: ['file_path'],
|
|
722
722
|
},
|
|
@@ -733,7 +733,7 @@ const TOOLS = [
|
|
|
733
733
|
inputSchema: {
|
|
734
734
|
type: 'object',
|
|
735
735
|
properties: {
|
|
736
|
-
file_path: { type: 'string', description: 'Absolute path to the .xlsx file.' },
|
|
736
|
+
file_path: { type: 'string', description: 'Absolute path to the .xlsx file. Pass the path string AS-IS — do NOT read, open, or base64-encode the file; the client handles all file I/O. The base64 surface in this connector is OUTPUT-only (_meta.file_b64).' },
|
|
737
737
|
sheet: { type: 'string', description: 'Optional: restrict to a specific sheet.' },
|
|
738
738
|
},
|
|
739
739
|
required: ['file_path'],
|
|
@@ -750,7 +750,7 @@ const TOOLS = [
|
|
|
750
750
|
inputSchema: {
|
|
751
751
|
type: 'object',
|
|
752
752
|
properties: {
|
|
753
|
-
file_path: { type: 'string', description: 'Absolute path to the .xlsx file.' },
|
|
753
|
+
file_path: { type: 'string', description: 'Absolute path to the .xlsx file. Pass the path string AS-IS — do NOT read, open, or base64-encode the file; the client handles all file I/O. The base64 surface in this connector is OUTPUT-only (_meta.file_b64).' },
|
|
754
754
|
sheet: { type: 'string', description: 'Optional: restrict to a specific sheet.' },
|
|
755
755
|
},
|
|
756
756
|
required: ['file_path'],
|
|
@@ -768,7 +768,7 @@ const TOOLS = [
|
|
|
768
768
|
inputSchema: {
|
|
769
769
|
type: 'object',
|
|
770
770
|
properties: {
|
|
771
|
-
file_path: { type: 'string', description: 'Absolute path to the .xlsx file.' },
|
|
771
|
+
file_path: { type: 'string', description: 'Absolute path to the .xlsx file. Pass the path string AS-IS — do NOT read, open, or base64-encode the file; the client handles all file I/O. The base64 surface in this connector is OUTPUT-only (_meta.file_b64).' },
|
|
772
772
|
sheet: { type: 'string', description: 'Optional: restrict to a specific sheet.' },
|
|
773
773
|
},
|
|
774
774
|
required: ['file_path'],
|
|
@@ -785,7 +785,7 @@ const TOOLS = [
|
|
|
785
785
|
inputSchema: {
|
|
786
786
|
type: 'object',
|
|
787
787
|
properties: {
|
|
788
|
-
file_path: { type: 'string', description: 'Absolute path to the .xlsx file.' },
|
|
788
|
+
file_path: { type: 'string', description: 'Absolute path to the .xlsx file. Pass the path string AS-IS — do NOT read, open, or base64-encode the file; the client handles all file I/O. The base64 surface in this connector is OUTPUT-only (_meta.file_b64).' },
|
|
789
789
|
},
|
|
790
790
|
required: ['file_path'],
|
|
791
791
|
},
|
|
@@ -802,7 +802,7 @@ const TOOLS = [
|
|
|
802
802
|
inputSchema: {
|
|
803
803
|
type: 'object',
|
|
804
804
|
properties: {
|
|
805
|
-
file_path: { type: 'string', description: 'Absolute path to the .xlsx file.' },
|
|
805
|
+
file_path: { type: 'string', description: 'Absolute path to the .xlsx file. Pass the path string AS-IS — do NOT read, open, or base64-encode the file; the client handles all file I/O. The base64 surface in this connector is OUTPUT-only (_meta.file_b64).' },
|
|
806
806
|
},
|
|
807
807
|
required: ['file_path'],
|
|
808
808
|
},
|
|
@@ -818,7 +818,7 @@ const TOOLS = [
|
|
|
818
818
|
inputSchema: {
|
|
819
819
|
type: 'object',
|
|
820
820
|
properties: {
|
|
821
|
-
file_path: { type: 'string', description: 'Absolute path to the .xlsx file.' },
|
|
821
|
+
file_path: { type: 'string', description: 'Absolute path to the .xlsx file. Pass the path string AS-IS — do NOT read, open, or base64-encode the file; the client handles all file I/O. The base64 surface in this connector is OUTPUT-only (_meta.file_b64).' },
|
|
822
822
|
},
|
|
823
823
|
required: ['file_path'],
|
|
824
824
|
},
|
|
@@ -834,7 +834,7 @@ const TOOLS = [
|
|
|
834
834
|
inputSchema: {
|
|
835
835
|
type: 'object',
|
|
836
836
|
properties: {
|
|
837
|
-
file_path: { type: 'string', description: 'Absolute path to the .xlsx file.' },
|
|
837
|
+
file_path: { type: 'string', description: 'Absolute path to the .xlsx file. Pass the path string AS-IS — do NOT read, open, or base64-encode the file; the client handles all file I/O. The base64 surface in this connector is OUTPUT-only (_meta.file_b64).' },
|
|
838
838
|
sheet: { type: 'string', description: 'Optional: restrict to a specific sheet.' },
|
|
839
839
|
},
|
|
840
840
|
required: ['file_path'],
|
|
@@ -851,7 +851,7 @@ const TOOLS = [
|
|
|
851
851
|
inputSchema: {
|
|
852
852
|
type: 'object',
|
|
853
853
|
properties: {
|
|
854
|
-
file_path: { type: 'string', description: 'Absolute path to the .xlsx file.' },
|
|
854
|
+
file_path: { type: 'string', description: 'Absolute path to the .xlsx file. Pass the path string AS-IS — do NOT read, open, or base64-encode the file; the client handles all file I/O. The base64 surface in this connector is OUTPUT-only (_meta.file_b64).' },
|
|
855
855
|
sheet: { type: 'string', description: 'Optional: restrict to a specific sheet.' },
|
|
856
856
|
},
|
|
857
857
|
required: ['file_path'],
|
|
@@ -868,7 +868,7 @@ const TOOLS = [
|
|
|
868
868
|
inputSchema: {
|
|
869
869
|
type: 'object',
|
|
870
870
|
properties: {
|
|
871
|
-
file_path: { type: 'string', description: 'Absolute path to the .xlsx file.' },
|
|
871
|
+
file_path: { type: 'string', description: 'Absolute path to the .xlsx file. Pass the path string AS-IS — do NOT read, open, or base64-encode the file; the client handles all file I/O. The base64 surface in this connector is OUTPUT-only (_meta.file_b64).' },
|
|
872
872
|
sheet: { type: 'string', description: 'Optional: restrict to a specific sheet.' },
|
|
873
873
|
},
|
|
874
874
|
required: ['file_path'],
|
|
@@ -885,7 +885,7 @@ const TOOLS = [
|
|
|
885
885
|
inputSchema: {
|
|
886
886
|
type: 'object',
|
|
887
887
|
properties: {
|
|
888
|
-
file_path: { type: 'string', description: 'Absolute path to the .xlsx file.' },
|
|
888
|
+
file_path: { type: 'string', description: 'Absolute path to the .xlsx file. Pass the path string AS-IS — do NOT read, open, or base64-encode the file; the client handles all file I/O. The base64 surface in this connector is OUTPUT-only (_meta.file_b64).' },
|
|
889
889
|
sheet: { type: 'string', description: 'Optional: restrict to a specific sheet.' },
|
|
890
890
|
},
|
|
891
891
|
required: ['file_path'],
|
|
@@ -903,7 +903,7 @@ const TOOLS = [
|
|
|
903
903
|
inputSchema: {
|
|
904
904
|
type: 'object',
|
|
905
905
|
properties: {
|
|
906
|
-
file_path: { type: 'string', description: 'Absolute path to the .xlsx file.' },
|
|
906
|
+
file_path: { type: 'string', description: 'Absolute path to the .xlsx file. Pass the path string AS-IS — do NOT read, open, or base64-encode the file; the client handles all file I/O. The base64 surface in this connector is OUTPUT-only (_meta.file_b64).' },
|
|
907
907
|
sheet: { type: 'string', description: 'Optional: restrict to a specific sheet.' },
|
|
908
908
|
detailed: { type: 'boolean', description: 'If true, return per-cell breakdown (capped at 1000 cells). Default false (per-sheet rollup).' },
|
|
909
909
|
},
|
|
@@ -1501,6 +1501,21 @@ function friendlyErrorMessage(toolName, err) {
|
|
|
1501
1501
|
return `${toolName}: free-tier monthly cap reached — see xlsx-for-ai.dev/pricing.`;
|
|
1502
1502
|
case 'FALLBACK_ENGINE_MISSING':
|
|
1503
1503
|
return `${toolName}: local fallback engine not installed (\`npm install @protobi/exceljs\`).`;
|
|
1504
|
+
case 'BASE64_MISREAD':
|
|
1505
|
+
// SPM SPEC base64-defensive-error-and-suggested-next-call — turn the
|
|
1506
|
+
// base64-bash-hang class into a one-turn recovery. The error names
|
|
1507
|
+
// the offending field AND restates the contract so the next call
|
|
1508
|
+
// self-corrects.
|
|
1509
|
+
return (
|
|
1510
|
+
`${toolName}: argument "${err.field || 'file_path'}" looks like base64-encoded bytes, not a file path. ` +
|
|
1511
|
+
`This tool takes a PATH STRING (e.g. "/Users/you/foo.xlsx" or "~/Desktop/foo.xlsx"); the client reads and encodes the file for you. ` +
|
|
1512
|
+
`Retry with file_path set to the path string.`
|
|
1513
|
+
);
|
|
1514
|
+
case 'MISSING_REQUIRED_ARG':
|
|
1515
|
+
return (
|
|
1516
|
+
`${toolName}: missing required argument "${err.field || ''}". ` +
|
|
1517
|
+
`Check the tool's input schema; the workhorse case is file_path as a path string (NOT bytes).`
|
|
1518
|
+
);
|
|
1504
1519
|
default:
|
|
1505
1520
|
break;
|
|
1506
1521
|
}
|
|
@@ -1559,7 +1574,148 @@ function friendlyErrorMessage(toolName, err) {
|
|
|
1559
1574
|
// Tool dispatch
|
|
1560
1575
|
// ---------------------------------------------------------------------------
|
|
1561
1576
|
|
|
1577
|
+
// ---------------------------------------------------------------------------
|
|
1578
|
+
// Defensive input-contract validation (belt-and-suspenders for SPM SPEC
|
|
1579
|
+
// base64-defensive-error-and-suggested-next-call).
|
|
1580
|
+
//
|
|
1581
|
+
// Description hardening in 3.0.14 reduces the rate at which the model
|
|
1582
|
+
// invents a base64-encoding step, but doesn't eliminate it. If a tool
|
|
1583
|
+
// call arrives with byte-shaped content where a file_path is expected,
|
|
1584
|
+
// or with file_path missing entirely, throw a crisp error code the
|
|
1585
|
+
// friendlyErrorMessage path translates into actionable text — turning
|
|
1586
|
+
// the prior indefinite hang into a one-turn recovery.
|
|
1587
|
+
// ---------------------------------------------------------------------------
|
|
1588
|
+
|
|
1589
|
+
const FILE_PATH_FIELDS = new Set(['file_path', 'file_path_a', 'file_path_b', 'spec_path']);
|
|
1590
|
+
const BASE64_ONLY_REGEX = /^[A-Za-z0-9+/]+=*$/;
|
|
1591
|
+
|
|
1592
|
+
function looksLikeBase64(value) {
|
|
1593
|
+
if (typeof value !== 'string') return false;
|
|
1594
|
+
// The trap: `/` is a base64-alphabet character AND a POSIX path
|
|
1595
|
+
// separator, so "contains slash" can't distinguish on its own. Real
|
|
1596
|
+
// file paths carry distinctive markers base64 strings don't:
|
|
1597
|
+
// - `.` for an extension (any spreadsheet path ends with .xlsx/.xls/
|
|
1598
|
+
// etc; intermediate dirs often have them too)
|
|
1599
|
+
// - `\` for Windows path separators
|
|
1600
|
+
// - `~` for home prefix
|
|
1601
|
+
// - spaces (common in Mac/Windows user dirs)
|
|
1602
|
+
// If ANY of those appear, we treat the string as a path.
|
|
1603
|
+
if (value.length < 200) return false;
|
|
1604
|
+
if (
|
|
1605
|
+
value.includes('.') ||
|
|
1606
|
+
value.includes('\\') ||
|
|
1607
|
+
value.includes('~') ||
|
|
1608
|
+
value.includes(' ')
|
|
1609
|
+
) {
|
|
1610
|
+
return false;
|
|
1611
|
+
}
|
|
1612
|
+
const trimmed = value.trim();
|
|
1613
|
+
return BASE64_ONLY_REGEX.test(trimmed);
|
|
1614
|
+
}
|
|
1615
|
+
|
|
1616
|
+
function validateToolArgs(name, args) {
|
|
1617
|
+
// Find the tool's inputSchema so we can read the `required` array. Use a
|
|
1618
|
+
// local Map lookup so a 50-tool catalog isn't re-scanned per call.
|
|
1619
|
+
if (!validateToolArgs._toolByName) {
|
|
1620
|
+
validateToolArgs._toolByName = new Map(TOOLS.map((t) => [t.name, t]));
|
|
1621
|
+
}
|
|
1622
|
+
const tool = validateToolArgs._toolByName.get(name);
|
|
1623
|
+
if (!tool || !tool.inputSchema) return; // unknown tool — server will route or fail
|
|
1624
|
+
const schema = tool.inputSchema;
|
|
1625
|
+
const required = Array.isArray(schema.required) ? schema.required : [];
|
|
1626
|
+
const argsObj = args && typeof args === 'object' ? args : {};
|
|
1627
|
+
|
|
1628
|
+
// Required-field presence check.
|
|
1629
|
+
for (const field of required) {
|
|
1630
|
+
const v = argsObj[field];
|
|
1631
|
+
if (v === undefined || v === null || (typeof v === 'string' && v.length === 0)) {
|
|
1632
|
+
const err = new Error(`${name}: missing required argument "${field}".`);
|
|
1633
|
+
err.code = 'MISSING_REQUIRED_ARG';
|
|
1634
|
+
err.field = field;
|
|
1635
|
+
throw err;
|
|
1636
|
+
}
|
|
1637
|
+
}
|
|
1638
|
+
|
|
1639
|
+
// Base64-misread check on every file_path-shaped field.
|
|
1640
|
+
for (const field of FILE_PATH_FIELDS) {
|
|
1641
|
+
if (!(field in argsObj)) continue;
|
|
1642
|
+
if (looksLikeBase64(argsObj[field])) {
|
|
1643
|
+
const err = new Error(
|
|
1644
|
+
`${name}: argument "${field}" looks like base64-encoded bytes, not a file path.`
|
|
1645
|
+
);
|
|
1646
|
+
err.code = 'BASE64_MISREAD';
|
|
1647
|
+
err.field = field;
|
|
1648
|
+
throw err;
|
|
1649
|
+
}
|
|
1650
|
+
}
|
|
1651
|
+
}
|
|
1652
|
+
|
|
1653
|
+
// ---------------------------------------------------------------------------
|
|
1654
|
+
// Suggested-next-call injection on triage tools (SPM SPEC follow-up).
|
|
1655
|
+
//
|
|
1656
|
+
// xlsx_doctor's findings reference follow-on tools by name ("Run
|
|
1657
|
+
// xlsx_workbook_views to enumerate", "Run xlsx_external_links to see
|
|
1658
|
+
// the target"). Post-process the response text to add a concrete
|
|
1659
|
+
// invocation example for each referenced tool — pre-filled with the
|
|
1660
|
+
// caller's file_path. Doubles as a correct-usage exemplar (path-shaped,
|
|
1661
|
+
// no base64) that mitigates the misread class structurally.
|
|
1662
|
+
// ---------------------------------------------------------------------------
|
|
1663
|
+
|
|
1664
|
+
// Tools that take ONLY a required file_path — safe to suggest with a
|
|
1665
|
+
// one-arg invocation.
|
|
1666
|
+
const _drillDownEligible = (() => {
|
|
1667
|
+
const map = new Map();
|
|
1668
|
+
for (const t of TOOLS) {
|
|
1669
|
+
const req = Array.isArray(t.inputSchema?.required) ? t.inputSchema.required : [];
|
|
1670
|
+
if (req.length === 1 && req[0] === 'file_path') map.set(t.name, true);
|
|
1671
|
+
}
|
|
1672
|
+
return map;
|
|
1673
|
+
})();
|
|
1674
|
+
|
|
1675
|
+
function injectDrillDownExamples(result, callerToolName, args) {
|
|
1676
|
+
if (!result || typeof result !== 'object') return result;
|
|
1677
|
+
if (!args || typeof args.file_path !== 'string' || args.file_path.length === 0) return result;
|
|
1678
|
+
const content = Array.isArray(result.content) ? result.content : null;
|
|
1679
|
+
if (!content) return result;
|
|
1680
|
+
// First text block holds the rendered findings.
|
|
1681
|
+
const firstText = content.find((c) => c && c.type === 'text' && typeof c.text === 'string');
|
|
1682
|
+
if (!firstText) return result;
|
|
1683
|
+
|
|
1684
|
+
// Scan for xlsx_FOO mentions OTHER than the caller itself.
|
|
1685
|
+
const mentioned = new Set();
|
|
1686
|
+
const re = /\bxlsx_[a-z_]+(?:_[a-z_]+)*\b/g;
|
|
1687
|
+
let m;
|
|
1688
|
+
while ((m = re.exec(firstText.text)) !== null) {
|
|
1689
|
+
const tool = m[0];
|
|
1690
|
+
if (tool === callerToolName) continue;
|
|
1691
|
+
if (_drillDownEligible.has(tool)) mentioned.add(tool);
|
|
1692
|
+
}
|
|
1693
|
+
if (mentioned.size === 0) return result;
|
|
1694
|
+
|
|
1695
|
+
const filePathJson = JSON.stringify(args.file_path);
|
|
1696
|
+
const lines = [...mentioned].sort().map(
|
|
1697
|
+
(toolName) => `- \`${toolName}({ "file_path": ${filePathJson} })\``
|
|
1698
|
+
);
|
|
1699
|
+
const footer =
|
|
1700
|
+
'\n\n---\nDrill-down suggestions — concrete invocations pre-filled with your file_path ' +
|
|
1701
|
+
'(pass the path STRING, not file bytes; the client reads the file):\n' +
|
|
1702
|
+
lines.join('\n');
|
|
1703
|
+
|
|
1704
|
+
// Return a new result object with the footer appended; do NOT mutate the
|
|
1705
|
+
// server's response.
|
|
1706
|
+
const newContent = content.map((c) => {
|
|
1707
|
+
if (c === firstText) return { ...c, text: c.text + footer };
|
|
1708
|
+
return c;
|
|
1709
|
+
});
|
|
1710
|
+
return { ...result, content: newContent };
|
|
1711
|
+
}
|
|
1712
|
+
|
|
1562
1713
|
async function dispatchTool(name, args) {
|
|
1714
|
+
// Defensive validation — runs first so a base64 misread or missing
|
|
1715
|
+
// file_path produces an actionable error instead of an opaque server
|
|
1716
|
+
// failure or a base64-bash-hang.
|
|
1717
|
+
validateToolArgs(name, args);
|
|
1718
|
+
|
|
1563
1719
|
// xlsx_read: relay to API; fallback to local on unreachable / 5xx
|
|
1564
1720
|
if (name === 'xlsx_read') {
|
|
1565
1721
|
const body = {
|
|
@@ -1954,7 +2110,14 @@ async function dispatchTool(name, args) {
|
|
|
1954
2110
|
file_b64: fileToB64(args.file_path),
|
|
1955
2111
|
options: opts,
|
|
1956
2112
|
};
|
|
1957
|
-
|
|
2113
|
+
const result = await callTool(name, body);
|
|
2114
|
+
|
|
2115
|
+
// Triage tools that mention follow-on tools in their findings get a
|
|
2116
|
+
// drill-down footer with pre-filled invocations. xlsx_doctor is the
|
|
2117
|
+
// primary triage surface; xlsx_topology and xlsx_doctor's siblings can
|
|
2118
|
+
// benefit too, so we run the injection universally — it's a no-op on
|
|
2119
|
+
// any response whose text doesn't mention other xlsx_* tools.
|
|
2120
|
+
return injectDrillDownExamples(result, name, args);
|
|
1958
2121
|
}
|
|
1959
2122
|
|
|
1960
2123
|
// ---------------------------------------------------------------------------
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "xlsx-for-ai",
|
|
3
3
|
"mcpName": "io.github.senoff/xlsx-for-ai",
|
|
4
|
-
"version": "3.0.
|
|
4
|
+
"version": "3.0.16",
|
|
5
5
|
"description": "The MCP server that makes LLMs reliable on real-world Excel spreadsheets. Thin npm client over a hosted API — read, write, diff, redact, and supervise .xlsx files from any MCP-aware agent.",
|
|
6
6
|
"main": "index.js",
|
|
7
7
|
"bin": {
|