pptx-viewer-mcp 2.1.7 → 2.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.
@@ -2,7 +2,7 @@
2
2
  import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
3
3
  import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
4
4
  import { z } from 'zod';
5
- import { validatePptx, repairPptx, PptxHandler, hasTextProperties, cloneElement as cloneElement$1, isTemplateElementId, makeStoreAwareId, reassignDescendantIds, groupElements as groupElements$1, ungroupElements as ungroupElements$1, PptxMarkdownConverter, ThemePresets, getThemePreset, setChartType, setChartTitle, setChartGrouping, setChartLegend, setChartDataLabels, setChartAxis, setChartCategories, addChartSeries, removeChartSeries, updateChartSeriesValues, ChartBuilder, decomposeSmartArt, demoteSmartArtNode, promoteSmartArtNode, reorderSmartArtNode, updateSmartArtNodeText, removeSmartArtNode, addSmartArtNode, findPlaceholders, applyTemplate, getSectionForSlide, moveSlidesToSection, reorderSections, removeSection, addSection, SvgExporter, buildPptxJsonDocument, deserializePptxFromJson, applyImportedPptxData, replaceWithCustomGeometry, replaceShapeGeometry, setElementLocked, findLayoutByName, findLayoutByType } from 'pptx-viewer-core';
5
+ import { validatePptx, repairPptx, PptxHandler, hasTextProperties, resolveThemeColorRef, cloneElement as cloneElement$1, isTemplateElementId, makeStoreAwareId, reassignDescendantIds, groupElements as groupElements$1, ungroupElements as ungroupElements$1, TABLE_STYLE_PART_SEQUENCE, normalizeTableStyleGuid, createTableStyleEntry, addTableStyleToMap, deleteTableStyleFromMap, PptxMarkdownConverter, ThemePresets, getThemePreset, setChartType, setChartTitle, setChartGrouping, setChartLegend, setChartDataLabels, setChartAxis, setChartCategories, addChartSeries, removeChartSeries, updateChartSeriesValues, ChartBuilder, setChartDataPointStyle, setChartDataPointExplosion, setChartDataPointMarker, setChartDataPointLabel, setChartSeriesMarker, setChartSeriesTrendline, setChartSeriesErrorBars, setChartHelperLine, setChartColorMapOverride, listChartUserShapes, addChartUserShape, updateChartUserShape, removeChartUserShape, decomposeSmartArt, demoteSmartArtNode, promoteSmartArtNode, reorderSmartArtNode, updateSmartArtNodeText, removeSmartArtNode, addSmartArtNode, findPlaceholders, applyTemplate, getSectionForSlide, moveSlidesToSection, reorderSections, removeSection, addSection, SvgExporter, buildPptxJsonDocument, deserializePptxFromJson, applyImportedPptxData, replaceWithCustomGeometry, replaceShapeGeometry, setElementLocked, findLayoutByName, findLayoutByType } from 'pptx-viewer-core';
6
6
  import { writeFile, readFile } from 'fs/promises';
7
7
  import { resolve, isAbsolute, sep } from 'path';
8
8
 
@@ -66,6 +66,32 @@ var ConvertToMarkdownSchema = z.object({
66
66
  var AccessibilityCheckSchema = z.object({
67
67
  filePath: z.string().describe("Path to the PPTX file")
68
68
  });
69
+ var ThemeColorRefSchema = z.object({
70
+ scheme: z.enum([
71
+ "dk1",
72
+ "lt1",
73
+ "dk2",
74
+ "lt2",
75
+ "accent1",
76
+ "accent2",
77
+ "accent3",
78
+ "accent4",
79
+ "accent5",
80
+ "accent6",
81
+ "hlink",
82
+ "folHlink",
83
+ "bg1",
84
+ "tx1",
85
+ "bg2",
86
+ "tx2",
87
+ "phClr"
88
+ ]),
89
+ lumMod: z.number().optional().describe("Multiply HSL luminance (0..1)"),
90
+ lumOff: z.number().optional().describe("Add to HSL luminance after lumMod (0..1)"),
91
+ tint: z.number().optional().describe("Blend towards white (0..1)"),
92
+ shade: z.number().optional().describe("Blend towards black (0..1)"),
93
+ alpha: z.number().optional().describe("Opacity fraction, 1 = opaque")
94
+ });
69
95
  var AddElementSchema = z.object({
70
96
  filePath: z.string().describe("Path to the PPTX file"),
71
97
  slideIndex: z.number().int().min(0).describe("Zero-based slide index"),
@@ -110,6 +136,12 @@ var UpdateElementSchema = z.object({
110
136
  fontSize: z.number().optional(),
111
137
  fontFamily: z.string().optional(),
112
138
  fontColor: z.string().optional(),
139
+ /**
140
+ * A theme colour for the run text. Wins on save; resolves `fontColor`
141
+ * immediately when `fontColor` was not also given. Passing `fontColor`
142
+ * alone clears a previously-set text theme colour.
143
+ */
144
+ fontThemeColor: ThemeColorRefSchema.optional(),
113
145
  bold: z.boolean().optional(),
114
146
  italic: z.boolean().optional(),
115
147
  underline: z.boolean().optional(),
@@ -182,6 +214,32 @@ var BatchUpdateElementsSchema = z.object({
182
214
  opacity: z.number().min(0).max(1).optional(),
183
215
  hidden: z.boolean().optional()
184
216
  });
217
+ var ThemeColorRefSchema2 = z.object({
218
+ scheme: z.enum([
219
+ "dk1",
220
+ "lt1",
221
+ "dk2",
222
+ "lt2",
223
+ "accent1",
224
+ "accent2",
225
+ "accent3",
226
+ "accent4",
227
+ "accent5",
228
+ "accent6",
229
+ "hlink",
230
+ "folHlink",
231
+ "bg1",
232
+ "tx1",
233
+ "bg2",
234
+ "tx2",
235
+ "phClr"
236
+ ]),
237
+ lumMod: z.number().optional().describe("Multiply HSL luminance (0..1)"),
238
+ lumOff: z.number().optional().describe("Add to HSL luminance after lumMod (0..1)"),
239
+ tint: z.number().optional().describe("Blend towards white (0..1)"),
240
+ shade: z.number().optional().describe("Blend towards black (0..1)"),
241
+ alpha: z.number().optional().describe("Opacity fraction, 1 = opaque")
242
+ });
185
243
  var UpdateTableCellsSchema = z.object({
186
244
  filePath: z.string().describe("Path to the PPTX file"),
187
245
  slideIndex: z.number().int().min(0),
@@ -208,6 +266,14 @@ var UpdateElementStyleSchema = z.object({
208
266
  slideIndex: z.number().int().min(0),
209
267
  elementId: z.string(),
210
268
  fillColor: z.string().optional(),
269
+ /**
270
+ * A theme colour for the fill (e.g. `{ scheme: 'accent1', lumMod: 0.8 }`
271
+ * for "Accent 1, Lighter 80%"). When set, the shape saves as
272
+ * `<a:schemeClr>` and keeps following the theme after a later theme
273
+ * change, instead of freezing today's resolved hex. Setting `fillColor`
274
+ * without this clears any previously-set fill theme colour.
275
+ */
276
+ fillThemeColor: ThemeColorRefSchema2.optional(),
211
277
  fillMode: z.string().optional(),
212
278
  fillGradientStops: z.array(
213
279
  z.object({
@@ -220,6 +286,8 @@ var UpdateElementStyleSchema = z.object({
220
286
  fillGradientType: z.string().optional(),
221
287
  fillOpacity: z.number().optional(),
222
288
  strokeColor: z.string().optional(),
289
+ /** A theme colour for the outline; see `fillThemeColor` above. */
290
+ strokeThemeColor: ThemeColorRefSchema2.optional(),
223
291
  strokeWidth: z.number().optional(),
224
292
  strokeDash: z.string().optional(),
225
293
  strokeOpacity: z.number().optional(),
@@ -266,6 +334,116 @@ var ManageCommentsSchema = z.object({
266
334
  resolved: z.boolean().optional(),
267
335
  includeResolved: z.boolean().optional()
268
336
  });
337
+ var TABLE_STYLE_SECTIONS = [
338
+ "wholeTbl",
339
+ "band1H",
340
+ "band2H",
341
+ "band1V",
342
+ "band2V",
343
+ "lastCol",
344
+ "firstCol",
345
+ "lastRow",
346
+ "seCell",
347
+ "swCell",
348
+ "firstRow",
349
+ "neCell",
350
+ "nwCell"
351
+ ];
352
+ var TableStyleSimpleColorSchema = z.object({
353
+ schemeColor: z.string().describe('Theme colour key (e.g. "accent1"), or "" for a non-scheme fill'),
354
+ tint: z.number().optional().describe("0-100000"),
355
+ shade: z.number().optional().describe("0-100000"),
356
+ color: z.string().optional().describe('Explicit hex colour, e.g. "#FF8800"')
357
+ });
358
+ var TableStyleFillSchema = z.object({
359
+ schemeColor: z.string(),
360
+ tint: z.number().optional(),
361
+ shade: z.number().optional(),
362
+ color: z.string().optional(),
363
+ noFill: z.boolean().optional(),
364
+ gradient: z.object({
365
+ type: z.enum(["linear", "radial"]),
366
+ angle: z.number().optional(),
367
+ stops: z.array(z.object({ position: z.number(), fill: TableStyleSimpleColorSchema }))
368
+ }).optional(),
369
+ pattern: z.object({
370
+ preset: z.string(),
371
+ foreground: TableStyleSimpleColorSchema.optional(),
372
+ background: TableStyleSimpleColorSchema.optional()
373
+ }).optional(),
374
+ image: z.object({ path: z.string().optional(), data: z.string().optional() }).optional()
375
+ });
376
+ var TableStyleTextSchema = z.object({
377
+ bold: z.boolean().optional(),
378
+ italic: z.boolean().optional(),
379
+ underline: z.boolean().optional(),
380
+ fontSchemeColor: z.string().optional(),
381
+ fontTint: z.number().optional(),
382
+ fontShade: z.number().optional(),
383
+ fontColor: z.string().optional(),
384
+ fontFace: z.string().optional(),
385
+ fontRefIdx: z.string().optional()
386
+ });
387
+ var TableStyleBorderSideSchema = z.object({
388
+ width: z.number().optional(),
389
+ dash: z.string().optional(),
390
+ fill: TableStyleSimpleColorSchema.optional(),
391
+ color: z.string().optional(),
392
+ noFill: z.boolean().optional()
393
+ });
394
+ var TableStyleBordersSchema = z.object({
395
+ left: TableStyleBorderSideSchema.optional(),
396
+ right: TableStyleBorderSideSchema.optional(),
397
+ top: TableStyleBorderSideSchema.optional(),
398
+ bottom: TableStyleBorderSideSchema.optional(),
399
+ insideH: TableStyleBorderSideSchema.optional(),
400
+ insideV: TableStyleBorderSideSchema.optional(),
401
+ tl2br: TableStyleBorderSideSchema.optional(),
402
+ tr2bl: TableStyleBorderSideSchema.optional()
403
+ });
404
+ var TableStyleCell3DSchema = z.object({
405
+ bevelWidth: z.number().optional(),
406
+ bevelHeight: z.number().optional(),
407
+ bevelPreset: z.string().optional(),
408
+ material: z.string().optional(),
409
+ lightRig: z.string().optional(),
410
+ lightRigDirection: z.string().optional()
411
+ });
412
+ var SetTableStyleSectionSchema = z.object({
413
+ filePath: z.string().describe("Path to the PPTX file"),
414
+ styleId: z.string().describe('Table style GUID, e.g. "{5C22544A-7EE6-4342-B048-85BDC9FD1C3A}"'),
415
+ section: z.enum(TABLE_STYLE_SECTIONS).describe("Which of the 13 CT_TableStyle parts to patch"),
416
+ styleName: z.string().optional().describe("Rename the style"),
417
+ fill: TableStyleFillSchema.optional(),
418
+ text: TableStyleTextSchema.optional(),
419
+ borders: TableStyleBordersSchema.optional(),
420
+ cell3D: TableStyleCell3DSchema.optional()
421
+ });
422
+ var CreateTableStyleSchema = z.object({
423
+ filePath: z.string().describe("Path to the PPTX file"),
424
+ styleName: z.string().describe("Display name for the new style"),
425
+ basedOnStyleId: z.string().optional().describe("Deep-clone every section from this existing style GUID as the starting point"),
426
+ setAsDefault: z.boolean().optional().describe("Repoint ppt/tableStyles.xml's default style at the new one")
427
+ });
428
+ var DeleteTableStyleSchema = z.object({
429
+ filePath: z.string().describe("Path to the PPTX file"),
430
+ styleId: z.string().describe("Table style GUID to remove"),
431
+ force: z.boolean().optional().describe("Delete even though a table on this deck still references the style")
432
+ });
433
+ var AssignTableStyleSchema = z.object({
434
+ filePath: z.string().describe("Path to the PPTX file"),
435
+ slideIndex: z.number().int().min(0),
436
+ elementId: z.string().describe("Table element ID"),
437
+ styleId: z.string().optional().describe(
438
+ "Table style GUID to assign. Defaults to the presentation's current default table style when omitted."
439
+ ),
440
+ bandedRows: z.boolean().optional(),
441
+ bandedColumns: z.boolean().optional(),
442
+ firstRowHeader: z.boolean().optional(),
443
+ lastRow: z.boolean().optional(),
444
+ firstCol: z.boolean().optional(),
445
+ lastCol: z.boolean().optional()
446
+ });
269
447
  var GetThemeInfoSchema = z.object({
270
448
  filePath: z.string().describe("Path to the PPTX file")
271
449
  });
@@ -295,6 +473,139 @@ var UpdateThemeFontsSchema = z.object({
295
473
  majorFont: z.string().optional().describe("Heading (major) font family"),
296
474
  minorFont: z.string().optional().describe("Body (minor) font family")
297
475
  });
476
+ var MarkerSymbolSchema = z.enum([
477
+ "circle",
478
+ "dash",
479
+ "diamond",
480
+ "dot",
481
+ "none",
482
+ "picture",
483
+ "plus",
484
+ "square",
485
+ "star",
486
+ "triangle",
487
+ "x",
488
+ "auto"
489
+ ]);
490
+ var DataLabelPositionSchema = z.enum([
491
+ "bestFit",
492
+ "b",
493
+ "ctr",
494
+ "inBase",
495
+ "inEnd",
496
+ "l",
497
+ "outEnd",
498
+ "r",
499
+ "t"
500
+ ]);
501
+ var FormatChartDataPointSchema = z.object({
502
+ filePath: z.string().describe("Path to the PPTX file"),
503
+ slideIndex: z.number().int().min(0).describe("Zero-based slide index"),
504
+ elementId: z.string().describe("Chart element ID"),
505
+ seriesIndex: z.number().int().min(0).describe("Zero-based series index"),
506
+ pointIndex: z.number().int().min(0).describe("Zero-based data point (category) index"),
507
+ fillColor: z.string().optional().describe("Fill colour (hex) for this point only"),
508
+ strokeColor: z.string().optional().describe("Outline colour (hex) for this point only"),
509
+ strokeWidth: z.number().optional().describe("Outline width in points"),
510
+ strokeDashStyle: z.string().optional().describe("Outline dash style, e.g. solid, dash, dashDot, sysDot"),
511
+ clearStyle: z.boolean().optional().describe("Remove all per-point shape formatting"),
512
+ explosion: z.number().nullable().optional().describe("Pie/doughnut slice pull-out distance 0-100; null clears it"),
513
+ marker: z.object({
514
+ symbol: MarkerSymbolSchema.optional(),
515
+ size: z.number().optional(),
516
+ fillColor: z.string().optional()
517
+ }).nullable().optional().describe("Per-point marker override (line/scatter/bubble); null clears it")
518
+ });
519
+ var FormatChartDataLabelSchema = z.object({
520
+ filePath: z.string().describe("Path to the PPTX file"),
521
+ slideIndex: z.number().int().min(0).describe("Zero-based slide index"),
522
+ elementId: z.string().describe("Chart element ID"),
523
+ seriesIndex: z.number().int().min(0).describe("Zero-based series index"),
524
+ pointIndex: z.number().int().min(0).describe("Zero-based data point (category) index"),
525
+ remove: z.boolean().optional().describe("Remove the per-point label override entirely"),
526
+ showValue: z.boolean().optional(),
527
+ showCategory: z.boolean().optional(),
528
+ showSeriesName: z.boolean().optional(),
529
+ showPercent: z.boolean().optional(),
530
+ showLegendKey: z.boolean().optional(),
531
+ position: DataLabelPositionSchema.optional(),
532
+ text: z.string().optional().describe("Custom label text override; '' clears it"),
533
+ spPr: z.object({
534
+ fillColor: z.string().optional(),
535
+ strokeColor: z.string().optional(),
536
+ strokeWidth: z.number().optional(),
537
+ strokeDashStyle: z.string().optional()
538
+ }).nullable().optional().describe("This label's own fill/line formatting; null removes it"),
539
+ txPr: z.object({
540
+ fontFamily: z.string().optional(),
541
+ fontSize: z.number().optional(),
542
+ bold: z.boolean().optional(),
543
+ italic: z.boolean().optional(),
544
+ color: z.string().optional()
545
+ }).nullable().optional().describe("This label's own font; null removes it")
546
+ });
547
+ var FormatChartSeriesSchema = z.object({
548
+ filePath: z.string().describe("Path to the PPTX file"),
549
+ slideIndex: z.number().int().min(0).describe("Zero-based slide index"),
550
+ elementId: z.string().describe("Chart element ID"),
551
+ seriesIndex: z.number().int().min(0).describe("Zero-based series index"),
552
+ marker: z.object({
553
+ symbol: MarkerSymbolSchema.optional(),
554
+ size: z.number().optional(),
555
+ fillColor: z.string().optional(),
556
+ strokeColor: z.string().optional(),
557
+ strokeWidth: z.number().optional(),
558
+ strokeDashStyle: z.string().optional()
559
+ }).nullable().optional().describe("Series marker (line/scatter/bubble/radar); null removes it"),
560
+ trendline: z.object({
561
+ trendlineType: z.enum([
562
+ "linear",
563
+ "exponential",
564
+ "logarithmic",
565
+ "polynomial",
566
+ "power",
567
+ "movingAvg"
568
+ ]),
569
+ color: z.string().optional(),
570
+ lineWidth: z.number().optional().describe("Trendline width in points"),
571
+ lineDashStyle: z.string().optional(),
572
+ order: z.number().optional().describe("Polynomial order, 2-6"),
573
+ period: z.number().optional().describe("Moving-average period"),
574
+ displayEq: z.boolean().optional(),
575
+ displayRSq: z.boolean().optional()
576
+ }).nullable().optional().describe("Series trendline; null removes it"),
577
+ errorBars: z.object({
578
+ direction: z.enum(["x", "y"]),
579
+ barType: z.enum(["both", "minus", "plus"]),
580
+ valType: z.enum(["cust", "fixedVal", "percentage", "stdDev", "stdErr"]),
581
+ val: z.number().optional(),
582
+ customPlus: z.array(z.number()).optional(),
583
+ customMinus: z.array(z.number()).optional(),
584
+ noEndCap: z.boolean().optional(),
585
+ color: z.string().optional(),
586
+ width: z.number().optional().describe("Error-bar line width in points"),
587
+ dashStyle: z.string().optional()
588
+ }).nullable().optional().describe("Series error bars; null removes them")
589
+ });
590
+ var SetChartHelperLineSchema = z.object({
591
+ filePath: z.string().describe("Path to the PPTX file"),
592
+ slideIndex: z.number().int().min(0).describe("Zero-based slide index"),
593
+ elementId: z.string().describe("Chart element ID"),
594
+ line: z.enum(["dropLines", "hiLowLines"]).describe("Which helper line to set"),
595
+ style: z.object({
596
+ color: z.string().optional(),
597
+ width: z.number().optional(),
598
+ dashStyle: z.string().optional()
599
+ }).nullable().describe("Line colour/width/dash; {} shows the line with defaults, null removes it")
600
+ });
601
+ var SetChartColorMapOverrideSchema = z.object({
602
+ filePath: z.string().describe("Path to the PPTX file"),
603
+ slideIndex: z.number().int().min(0).describe("Zero-based slide index"),
604
+ elementId: z.string().describe("Chart element ID"),
605
+ overrides: z.record(z.string(), z.string()).nullable().describe(
606
+ 'Theme colour role remap (bg1/tx1/bg2/tx2/accent1-6/hlink/folHlink -> role), e.g. { "accent1": "accent2" }; null removes the override'
607
+ )
608
+ });
298
609
  var UpdateChartSchema = z.object({
299
610
  filePath: z.string().describe("Path to the PPTX file"),
300
611
  slideIndex: z.number().int().min(0).describe("Zero-based slide index"),
@@ -374,6 +685,50 @@ var CreateChartSchema = z.object({
374
685
  position: z.string().optional()
375
686
  }).optional().describe("Legend configuration")
376
687
  });
688
+ var PointSchema = z.object({ x: z.number(), y: z.number() });
689
+ var ExtentSchema = z.object({ cx: z.number(), cy: z.number() });
690
+ var ChartUserShapeInputSchema = z.object({
691
+ kind: z.enum(["sp", "cxnSp"]).optional().describe('Overlay shape kind: "sp" (text/preset shape, default) or "cxnSp" (connector).'),
692
+ anchor: z.enum(["rel", "abs"]).optional().describe(
693
+ 'Anchor kind: "rel" (default, resizes with the chart; needs `to`) or "abs" (fixed EMU size; needs `ext`).'
694
+ ),
695
+ from: PointSchema.describe("Top-left corner as chart-relative fractions (0-1 each)."),
696
+ to: PointSchema.optional().describe(
697
+ "Bottom-right corner as chart-relative fractions; rel anchors only."
698
+ ),
699
+ ext: ExtentSchema.optional().describe("Width/height in EMU; abs anchors only."),
700
+ prst: z.string().optional().describe('Preset geometry name (e.g. "rect", "roundRect"); default "rect".'),
701
+ fill: z.string().optional().describe('Solid fill colour, hex (e.g. "#FFFF00").'),
702
+ stroke: z.string().optional().describe("Line colour, hex."),
703
+ strokeWidth: z.number().optional().describe("Line width in points."),
704
+ text: z.string().optional().describe("Plain text content, centred in the shape.")
705
+ });
706
+ var ListChartUserShapesSchema = z.object({
707
+ filePath: z.string().describe("Path to the PPTX file"),
708
+ slideIndex: z.number().int().min(0).describe("Zero-based slide index"),
709
+ elementId: z.string().describe("Chart element ID")
710
+ });
711
+ var AddChartUserShapeSchema = z.object({
712
+ filePath: z.string().describe("Path to the PPTX file"),
713
+ slideIndex: z.number().int().min(0).describe("Zero-based slide index"),
714
+ elementId: z.string().describe("Chart element ID"),
715
+ shape: ChartUserShapeInputSchema.describe("The overlay shape to add.")
716
+ });
717
+ var UpdateChartUserShapeSchema = z.object({
718
+ filePath: z.string().describe("Path to the PPTX file"),
719
+ slideIndex: z.number().int().min(0).describe("Zero-based slide index"),
720
+ elementId: z.string().describe("Chart element ID"),
721
+ index: z.number().int().min(0).describe("Zero-based overlay-shape index (from chart_user_shape_list)"),
722
+ patch: ChartUserShapeInputSchema.partial().describe(
723
+ "Fields to overwrite; anything omitted is left as-is."
724
+ )
725
+ });
726
+ var RemoveChartUserShapeSchema = z.object({
727
+ filePath: z.string().describe("Path to the PPTX file"),
728
+ slideIndex: z.number().int().min(0).describe("Zero-based slide index"),
729
+ elementId: z.string().describe("Chart element ID"),
730
+ index: z.number().int().min(0).describe("Zero-based overlay-shape index to remove")
731
+ });
377
732
  var ManageSmartArtSchema = z.object({
378
733
  filePath: z.string().describe("Path to the PPTX file"),
379
734
  slideIndex: z.number().int().min(0).describe("Zero-based slide index"),
@@ -513,39 +868,6 @@ var ApplyLayoutSchema = z.object({
513
868
  layoutName: z.string().optional().describe("Layout name to apply"),
514
869
  layoutType: z.string().optional().describe("Layout type to apply (alternative to name)")
515
870
  });
516
-
517
- // src/tools/chart-pareto.ts
518
- function cumulativePercent(values) {
519
- const total = values.reduce((sum, value) => sum + value, 0);
520
- if (total === 0) {
521
- return values.map(() => 0);
522
- }
523
- let running = 0;
524
- return values.map((value) => {
525
- running += value;
526
- return Math.round(running / total * 1e4) / 100;
527
- });
528
- }
529
- function applyParetoChartTypeAlias(chart, requestedType) {
530
- if (requestedType.trim().toLowerCase() !== "pareto" || !chart.chartData) {
531
- return;
532
- }
533
- const data = chart.chartData;
534
- data.chartType = "histogram";
535
- const [frequency] = data.series;
536
- if (!frequency) {
537
- return;
538
- }
539
- frequency.histogramOptions = { ...frequency.histogramOptions, layout: "histogram" };
540
- const hasParetoLine = data.series.some((s) => s.histogramOptions?.layout === "pareto");
541
- if (!hasParetoLine) {
542
- data.series.push({
543
- name: "Cumulative %",
544
- values: cumulativePercent(frequency.values),
545
- histogramOptions: { layout: "pareto" }
546
- });
547
- }
548
- }
549
871
  function generateElementId() {
550
872
  return `el-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
551
873
  }
@@ -653,6 +975,133 @@ function validateSlideIndex(slideIndex, slideCount) {
653
975
  return null;
654
976
  }
655
977
 
978
+ // src/tools/chart-formatting-tools.ts
979
+ function findChartElement(ctx, slideIndex, elementId) {
980
+ const err = validateSlideIndex(slideIndex, ctx.pptxData.slides.length);
981
+ if (err) {
982
+ throw new Error(err);
983
+ }
984
+ const slide = ctx.pptxData.slides[slideIndex];
985
+ const el = slide.elements.find((e) => e.id === elementId);
986
+ if (!el) {
987
+ throw new Error(`Element '${elementId}' not found on slide ${slideIndex}.`);
988
+ }
989
+ if (el.type !== "chart") {
990
+ throw new Error(`Element '${elementId}' is not a chart.`);
991
+ }
992
+ return el;
993
+ }
994
+ function formatChartDataPoint(ctx, params) {
995
+ const chart = findChartElement(ctx, params.slideIndex, params.elementId);
996
+ if (params.clearStyle) {
997
+ setChartDataPointStyle(chart, params.seriesIndex, params.pointIndex, null);
998
+ } else if (params.fillColor !== void 0 || params.strokeColor !== void 0 || params.strokeWidth !== void 0 || params.strokeDashStyle !== void 0) {
999
+ setChartDataPointStyle(chart, params.seriesIndex, params.pointIndex, {
1000
+ ...params.fillColor !== void 0 ? { fillColor: params.fillColor } : {},
1001
+ ...params.strokeColor !== void 0 ? { strokeColor: params.strokeColor } : {},
1002
+ ...params.strokeWidth !== void 0 ? { strokeWidth: params.strokeWidth } : {},
1003
+ ...params.strokeDashStyle !== void 0 ? { strokeDashStyle: params.strokeDashStyle } : {}
1004
+ });
1005
+ }
1006
+ if (params.explosion !== void 0) {
1007
+ setChartDataPointExplosion(chart, params.seriesIndex, params.pointIndex, params.explosion);
1008
+ }
1009
+ if (params.marker !== void 0) {
1010
+ setChartDataPointMarker(chart, params.seriesIndex, params.pointIndex, params.marker);
1011
+ }
1012
+ return { pptxData: ctx.pptxData, dirty: true, result: { elementId: params.elementId } };
1013
+ }
1014
+ function formatChartDataLabel(ctx, params) {
1015
+ const chart = findChartElement(ctx, params.slideIndex, params.elementId);
1016
+ if (params.remove) {
1017
+ setChartDataPointLabel(chart, params.seriesIndex, params.pointIndex, null);
1018
+ return { pptxData: ctx.pptxData, dirty: true, result: { elementId: params.elementId } };
1019
+ }
1020
+ setChartDataPointLabel(chart, params.seriesIndex, params.pointIndex, {
1021
+ ...params.showValue !== void 0 ? { showValue: params.showValue } : {},
1022
+ ...params.showCategory !== void 0 ? { showCategory: params.showCategory } : {},
1023
+ ...params.showSeriesName !== void 0 ? { showSeriesName: params.showSeriesName } : {},
1024
+ ...params.showPercent !== void 0 ? { showPercent: params.showPercent } : {},
1025
+ ...params.showLegendKey !== void 0 ? { showLegendKey: params.showLegendKey } : {},
1026
+ ...params.position !== void 0 ? { position: params.position } : {},
1027
+ ...params.text !== void 0 ? { text: params.text } : {},
1028
+ ...params.spPr !== void 0 ? { spPr: params.spPr } : {},
1029
+ ...params.txPr !== void 0 ? { txPr: params.txPr } : {}
1030
+ });
1031
+ return { pptxData: ctx.pptxData, dirty: true, result: { elementId: params.elementId } };
1032
+ }
1033
+ function formatChartSeries(ctx, params) {
1034
+ const chart = findChartElement(ctx, params.slideIndex, params.elementId);
1035
+ if (params.marker !== void 0) {
1036
+ if (params.marker === null) {
1037
+ setChartSeriesMarker(chart, params.seriesIndex, null);
1038
+ } else if (params.marker.strokeColor !== void 0 || params.marker.strokeWidth !== void 0 || params.marker.strokeDashStyle !== void 0) {
1039
+ setChartSeriesMarker(chart, params.seriesIndex, {
1040
+ symbol: params.marker.symbol ?? "circle",
1041
+ ...params.marker.size !== void 0 ? { size: params.marker.size } : {},
1042
+ spPr: {
1043
+ ...params.marker.fillColor !== void 0 ? { fillColor: params.marker.fillColor } : {},
1044
+ ...params.marker.strokeColor !== void 0 ? { strokeColor: params.marker.strokeColor } : {},
1045
+ ...params.marker.strokeWidth !== void 0 ? { strokeWidth: params.marker.strokeWidth } : {},
1046
+ ...params.marker.strokeDashStyle !== void 0 ? { strokeDashStyle: params.marker.strokeDashStyle } : {}
1047
+ }
1048
+ });
1049
+ } else {
1050
+ setChartSeriesMarker(chart, params.seriesIndex, params.marker);
1051
+ }
1052
+ }
1053
+ if (params.trendline !== void 0) {
1054
+ setChartSeriesTrendline(chart, params.seriesIndex, params.trendline);
1055
+ }
1056
+ if (params.errorBars !== void 0) {
1057
+ setChartSeriesErrorBars(chart, params.seriesIndex, params.errorBars);
1058
+ }
1059
+ return { pptxData: ctx.pptxData, dirty: true, result: { elementId: params.elementId } };
1060
+ }
1061
+ function setChartHelperLineT(ctx, params) {
1062
+ const chart = findChartElement(ctx, params.slideIndex, params.elementId);
1063
+ setChartHelperLine(chart, params.line, params.style);
1064
+ return { pptxData: ctx.pptxData, dirty: true, result: { elementId: params.elementId } };
1065
+ }
1066
+ function setChartColorMapOverrideT(ctx, params) {
1067
+ const chart = findChartElement(ctx, params.slideIndex, params.elementId);
1068
+ setChartColorMapOverride(chart, params.overrides);
1069
+ return { pptxData: ctx.pptxData, dirty: true, result: { elementId: params.elementId } };
1070
+ }
1071
+
1072
+ // src/tools/chart-pareto.ts
1073
+ function cumulativePercent(values) {
1074
+ const total = values.reduce((sum, value) => sum + value, 0);
1075
+ if (total === 0) {
1076
+ return values.map(() => 0);
1077
+ }
1078
+ let running = 0;
1079
+ return values.map((value) => {
1080
+ running += value;
1081
+ return Math.round(running / total * 1e4) / 100;
1082
+ });
1083
+ }
1084
+ function applyParetoChartTypeAlias(chart, requestedType) {
1085
+ if (requestedType.trim().toLowerCase() !== "pareto" || !chart.chartData) {
1086
+ return;
1087
+ }
1088
+ const data = chart.chartData;
1089
+ data.chartType = "histogram";
1090
+ const [frequency] = data.series;
1091
+ if (!frequency) {
1092
+ return;
1093
+ }
1094
+ frequency.histogramOptions = { ...frequency.histogramOptions, layout: "histogram" };
1095
+ const hasParetoLine = data.series.some((s) => s.histogramOptions?.layout === "pareto");
1096
+ if (!hasParetoLine) {
1097
+ data.series.push({
1098
+ name: "Cumulative %",
1099
+ values: cumulativePercent(frequency.values),
1100
+ histogramOptions: { layout: "pareto" }
1101
+ });
1102
+ }
1103
+ }
1104
+
656
1105
  // src/tools/chart-tools.ts
657
1106
  function updateChart(ctx, params) {
658
1107
  const err = validateSlideIndex(params.slideIndex, ctx.pptxData.slides.length);
@@ -793,6 +1242,67 @@ function createChart(ctx, params) {
793
1242
  result: { elementId: chart.id, slideIndex: params.slideIndex }
794
1243
  };
795
1244
  }
1245
+ function findChartElement2(ctx, slideIndex, elementId) {
1246
+ const err = validateSlideIndex(slideIndex, ctx.pptxData.slides.length);
1247
+ if (err) {
1248
+ throw new Error(err);
1249
+ }
1250
+ const slide = ctx.pptxData.slides[slideIndex];
1251
+ const el = slide.elements.find((e) => e.id === elementId);
1252
+ if (!el) {
1253
+ throw new Error(`Element '${elementId}' not found on slide ${slideIndex}.`);
1254
+ }
1255
+ if (el.type !== "chart") {
1256
+ throw new Error(`Element '${elementId}' is not a chart.`);
1257
+ }
1258
+ return el;
1259
+ }
1260
+ function buildShape(input) {
1261
+ return {
1262
+ kind: input.kind ?? "sp",
1263
+ anchor: input.anchor ?? "rel",
1264
+ from: input.from,
1265
+ ...input.to ? { to: input.to } : {},
1266
+ ...input.ext ? { ext: input.ext } : {},
1267
+ ...input.prst ? { prst: input.prst } : {},
1268
+ ...input.fill ? { fill: input.fill } : {},
1269
+ ...input.stroke ? { stroke: input.stroke } : {},
1270
+ ...input.strokeWidth !== void 0 ? { strokeWidth: input.strokeWidth } : {},
1271
+ ...input.text ? { paragraphs: [{ text: input.text, align: "ctr" }] } : {}
1272
+ };
1273
+ }
1274
+ function listChartUserShapesT(ctx, params) {
1275
+ const chart = findChartElement2(ctx, params.slideIndex, params.elementId);
1276
+ return { pptxData: ctx.pptxData, dirty: false, result: { shapes: listChartUserShapes(chart) } };
1277
+ }
1278
+ function addChartUserShapeT(ctx, params) {
1279
+ const chart = findChartElement2(ctx, params.slideIndex, params.elementId);
1280
+ addChartUserShape(chart, buildShape(params.shape));
1281
+ const index = (chart.chartData?.userShapes?.length ?? 1) - 1;
1282
+ return { pptxData: ctx.pptxData, dirty: true, result: { elementId: params.elementId, index } };
1283
+ }
1284
+ function updateChartUserShapeT(ctx, params) {
1285
+ const chart = findChartElement2(ctx, params.slideIndex, params.elementId);
1286
+ const patch = {
1287
+ ...params.patch.kind ? { kind: params.patch.kind } : {},
1288
+ ...params.patch.anchor ? { anchor: params.patch.anchor } : {},
1289
+ ...params.patch.from ? { from: params.patch.from } : {},
1290
+ ...params.patch.to ? { to: params.patch.to } : {},
1291
+ ...params.patch.ext ? { ext: params.patch.ext } : {},
1292
+ ...params.patch.prst ? { prst: params.patch.prst } : {},
1293
+ ...params.patch.fill ? { fill: params.patch.fill } : {},
1294
+ ...params.patch.stroke ? { stroke: params.patch.stroke } : {},
1295
+ ...params.patch.strokeWidth !== void 0 ? { strokeWidth: params.patch.strokeWidth } : {},
1296
+ ...params.patch.text !== void 0 ? { paragraphs: [{ text: params.patch.text, align: "ctr" }] } : {}
1297
+ };
1298
+ updateChartUserShape(chart, params.index, patch);
1299
+ return { pptxData: ctx.pptxData, dirty: true, result: { elementId: params.elementId } };
1300
+ }
1301
+ function removeChartUserShapeT(ctx, params) {
1302
+ const chart = findChartElement2(ctx, params.slideIndex, params.elementId);
1303
+ removeChartUserShape(chart, params.index);
1304
+ return { pptxData: ctx.pptxData, dirty: true, result: { elementId: params.elementId } };
1305
+ }
796
1306
  var MAX_REGEX_LEN = 200;
797
1307
  function hasNestedUnboundedQuantifier(pattern) {
798
1308
  return /\([^)]*[+*]\)[+*]/u.test(pattern);
@@ -1317,8 +1827,17 @@ function updateElement(ctx, params) {
1317
1827
  if (params.fontFamily !== void 0) {
1318
1828
  textEl.textStyle.fontFamily = params.fontFamily;
1319
1829
  }
1320
- if (params.fontColor !== void 0) {
1830
+ if (params.fontThemeColor !== void 0) {
1831
+ textEl.textStyle.colorRef = params.fontThemeColor;
1832
+ const resolved = resolveThemeColorRef(params.fontThemeColor, ctx.pptxData.themeColorMap);
1833
+ if (params.fontColor !== void 0) {
1834
+ textEl.textStyle.color = params.fontColor;
1835
+ } else if (resolved) {
1836
+ textEl.textStyle.color = resolved;
1837
+ }
1838
+ } else if (params.fontColor !== void 0) {
1321
1839
  textEl.textStyle.color = params.fontColor;
1840
+ textEl.textStyle.colorRef = void 0;
1322
1841
  }
1323
1842
  if (params.bold !== void 0) {
1324
1843
  textEl.textStyle.bold = params.bold;
@@ -2558,8 +3077,17 @@ function updateElementStyle(ctx, params) {
2558
3077
  el.shapeStyle = {};
2559
3078
  }
2560
3079
  const ss = el.shapeStyle;
2561
- if (params.fillColor !== void 0) {
3080
+ if (params.fillThemeColor !== void 0) {
3081
+ ss.fillColorRef = params.fillThemeColor;
3082
+ const resolved = resolveThemeColorRef(params.fillThemeColor, ctx.pptxData.themeColorMap);
3083
+ if (params.fillColor !== void 0) {
3084
+ ss.fillColor = params.fillColor;
3085
+ } else if (resolved) {
3086
+ ss.fillColor = resolved;
3087
+ }
3088
+ } else if (params.fillColor !== void 0) {
2562
3089
  ss.fillColor = params.fillColor;
3090
+ ss.fillColorRef = void 0;
2563
3091
  }
2564
3092
  if (params.fillMode !== void 0) {
2565
3093
  ss.fillMode = params.fillMode;
@@ -2576,8 +3104,17 @@ function updateElementStyle(ctx, params) {
2576
3104
  if (params.fillOpacity !== void 0) {
2577
3105
  ss.fillOpacity = params.fillOpacity;
2578
3106
  }
2579
- if (params.strokeColor !== void 0) {
3107
+ if (params.strokeThemeColor !== void 0) {
3108
+ ss.strokeColorRef = params.strokeThemeColor;
3109
+ const resolved = resolveThemeColorRef(params.strokeThemeColor, ctx.pptxData.themeColorMap);
3110
+ if (params.strokeColor !== void 0) {
3111
+ ss.strokeColor = params.strokeColor;
3112
+ } else if (resolved) {
3113
+ ss.strokeColor = resolved;
3114
+ }
3115
+ } else if (params.strokeColor !== void 0) {
2580
3116
  ss.strokeColor = params.strokeColor;
3117
+ ss.strokeColorRef = void 0;
2581
3118
  }
2582
3119
  if (params.strokeWidth !== void 0) {
2583
3120
  ss.strokeWidth = params.strokeWidth;
@@ -2727,6 +3264,142 @@ function runAccessibilityCheck(ctx) {
2727
3264
  }
2728
3265
  };
2729
3266
  }
3267
+ function findTableElement(ctx, slideIndex, elementId) {
3268
+ const err = validateSlideIndex(slideIndex, ctx.pptxData.slides.length);
3269
+ if (err) {
3270
+ throw new Error(err);
3271
+ }
3272
+ const slide = ctx.pptxData.slides[slideIndex];
3273
+ const el = slide.elements.find((e) => e.id === elementId);
3274
+ if (!el) {
3275
+ throw new Error(`Element '${elementId}' not found on slide ${slideIndex}.`);
3276
+ }
3277
+ if (el.type !== "table") {
3278
+ throw new Error(`Element '${elementId}' is not a table.`);
3279
+ }
3280
+ return el;
3281
+ }
3282
+ function tableStyleIdsInUse(ctx) {
3283
+ const used = /* @__PURE__ */ new Set();
3284
+ for (const slide of ctx.pptxData.slides) {
3285
+ for (const el of slide.elements) {
3286
+ if (el.type === "table" && el.tableData?.tableStyleId) {
3287
+ used.add(normalizeTableStyleGuid(el.tableData.tableStyleId));
3288
+ }
3289
+ }
3290
+ }
3291
+ return used;
3292
+ }
3293
+ function setTableStyleSection(ctx, params) {
3294
+ if (!TABLE_STYLE_PART_SEQUENCE.includes(params.section)) {
3295
+ throw new Error(
3296
+ `Unknown table style section '${params.section}'. Valid sections: ${TABLE_STYLE_PART_SEQUENCE.join(", ")}.`
3297
+ );
3298
+ }
3299
+ const map = ctx.pptxData.tableStyleMap ?? {};
3300
+ ctx.pptxData.tableStyleMap = map;
3301
+ const normalizedId = normalizeTableStyleGuid(params.styleId);
3302
+ const entry = map[normalizedId];
3303
+ if (!entry) {
3304
+ throw new Error(
3305
+ `Table style '${params.styleId}' is not loaded in this presentation. Use create_table_style to add a new one.`
3306
+ );
3307
+ }
3308
+ if (params.styleName !== void 0) {
3309
+ entry.styleName = params.styleName;
3310
+ }
3311
+ const mutableEntry = entry;
3312
+ if (params.fill !== void 0) {
3313
+ mutableEntry[`${params.section}Fill`] = params.fill;
3314
+ }
3315
+ if (params.text !== void 0) {
3316
+ mutableEntry[`${params.section}Text`] = params.text;
3317
+ }
3318
+ if (params.borders !== void 0) {
3319
+ mutableEntry[`${params.section}Borders`] = params.borders;
3320
+ }
3321
+ if (params.cell3D !== void 0) {
3322
+ mutableEntry[`${params.section}Cell3D`] = params.cell3D;
3323
+ }
3324
+ return {
3325
+ pptxData: ctx.pptxData,
3326
+ dirty: true,
3327
+ result: { styleId: normalizedId, section: params.section }
3328
+ };
3329
+ }
3330
+ function createTableStyle(ctx, params) {
3331
+ const map = ctx.pptxData.tableStyleMap ?? {};
3332
+ ctx.pptxData.tableStyleMap = map;
3333
+ const basedOn = params.basedOnStyleId ? map[normalizeTableStyleGuid(params.basedOnStyleId)] : void 0;
3334
+ if (params.basedOnStyleId && !basedOn) {
3335
+ throw new Error(`basedOnStyleId '${params.basedOnStyleId}' is not a loaded table style.`);
3336
+ }
3337
+ const entry = createTableStyleEntry(map, { styleName: params.styleName, basedOn });
3338
+ addTableStyleToMap(map, entry);
3339
+ return {
3340
+ pptxData: ctx.pptxData,
3341
+ dirty: true,
3342
+ result: { styleId: entry.styleId },
3343
+ ...params.setAsDefault ? { saveOptions: { tableStylesDefaultId: entry.styleId } } : {}
3344
+ };
3345
+ }
3346
+ function deleteTableStyle(ctx, params) {
3347
+ const normalizedId = normalizeTableStyleGuid(params.styleId);
3348
+ if (!params.force) {
3349
+ const used = tableStyleIdsInUse(ctx);
3350
+ if (used.has(normalizedId)) {
3351
+ throw new Error(
3352
+ `Table style '${params.styleId}' is assigned to at least one table on this deck. Reassign those tables first, or pass force: true.`
3353
+ );
3354
+ }
3355
+ }
3356
+ const map = ctx.pptxData.tableStyleMap ?? {};
3357
+ ctx.pptxData.tableStyleMap = map;
3358
+ deleteTableStyleFromMap(map, normalizedId);
3359
+ return {
3360
+ pptxData: ctx.pptxData,
3361
+ dirty: true,
3362
+ result: { deleted: true },
3363
+ saveOptions: { tableStylesToDelete: [normalizedId] }
3364
+ };
3365
+ }
3366
+ function assignTableStyle(ctx, params) {
3367
+ const el = findTableElement(ctx, params.slideIndex, params.elementId);
3368
+ if (!el.tableData) {
3369
+ throw new Error(`Table '${params.elementId}' has no tableData.`);
3370
+ }
3371
+ const styleId = params.styleId ?? ctx.pptxData.tableStylesDefaultId;
3372
+ if (!styleId) {
3373
+ throw new Error(
3374
+ "styleId was not provided and this presentation has no tableStylesDefaultId to fall back to."
3375
+ );
3376
+ }
3377
+ const normalizedId = normalizeTableStyleGuid(styleId);
3378
+ el.tableData.tableStyleId = normalizedId;
3379
+ if (params.bandedRows !== void 0) {
3380
+ el.tableData.bandedRows = params.bandedRows;
3381
+ }
3382
+ if (params.bandedColumns !== void 0) {
3383
+ el.tableData.bandedColumns = params.bandedColumns;
3384
+ }
3385
+ if (params.firstRowHeader !== void 0) {
3386
+ el.tableData.firstRowHeader = params.firstRowHeader;
3387
+ }
3388
+ if (params.lastRow !== void 0) {
3389
+ el.tableData.lastRow = params.lastRow;
3390
+ }
3391
+ if (params.firstCol !== void 0) {
3392
+ el.tableData.firstCol = params.firstCol;
3393
+ }
3394
+ if (params.lastCol !== void 0) {
3395
+ el.tableData.lastCol = params.lastCol;
3396
+ }
3397
+ return {
3398
+ pptxData: ctx.pptxData,
3399
+ dirty: true,
3400
+ result: { elementId: params.elementId, styleId: normalizedId }
3401
+ };
3402
+ }
2730
3403
 
2731
3404
  // src/tools/table-tools.ts
2732
3405
  function updateTableCells(ctx, params) {
@@ -3006,11 +3679,17 @@ async function loadPresentation(filePath, execCtx) {
3006
3679
  const pptxData = await handler.load(rawBytes.buffer);
3007
3680
  return { pptxData, rawBytes };
3008
3681
  }
3009
- async function savePresentation(filePath, pptxData, rawBytes, execCtx) {
3682
+ async function savePresentation(filePath, pptxData, rawBytes, execCtx, tableStyleSaveOptions) {
3010
3683
  const handler = new PptxHandler();
3011
3684
  await handler.load(rawBytes.buffer);
3012
3685
  const outputBytes = await handler.save(pptxData.slides, {
3013
- headerFooter: pptxData.headerFooter
3686
+ headerFooter: pptxData.headerFooter,
3687
+ // `pptxData.tableStyleMap` carries any in-memory table-style edits a
3688
+ // tool made (e.g. `set_table_style_section`, `create_table_style`);
3689
+ // without forwarding it here those edits were silently dropped on
3690
+ // save even though the core save pipeline already supports them.
3691
+ tableStyles: pptxData.tableStyleMap,
3692
+ ...tableStyleSaveOptions
3014
3693
  });
3015
3694
  if (execCtx.collaboration) {
3016
3695
  const room = execCtx.collaboration.getRoom(filePath);
@@ -3042,7 +3721,13 @@ async function executeToolWithContext(filePath, execCtx, toolFn) {
3042
3721
  const { pptxData, rawBytes } = await loadPresentation(filePath, execCtx);
3043
3722
  const toolResult = await toolFn({ pptxData });
3044
3723
  if (toolResult.dirty) {
3045
- const saveResult = await savePresentation(filePath, toolResult.pptxData, rawBytes, execCtx);
3724
+ const saveResult = await savePresentation(
3725
+ filePath,
3726
+ toolResult.pptxData,
3727
+ rawBytes,
3728
+ execCtx,
3729
+ toolResult.saveOptions
3730
+ );
3046
3731
  return { ...toolResult.result, ...saveResult };
3047
3732
  }
3048
3733
  return toolResult.result;
@@ -3522,6 +4207,70 @@ function createServer() {
3522
4207
  };
3523
4208
  }
3524
4209
  );
4210
+ server2.registerTool(
4211
+ "set_table_style_section",
4212
+ {
4213
+ description: "Patch the fill, text, borders, or cell3D of one section (wholeTbl, banding, first/last row/col, or a corner cell) of an existing loaded table style",
4214
+ inputSchema: SetTableStyleSectionSchema.shape
4215
+ },
4216
+ async (params) => {
4217
+ const result = await runMcpTool(
4218
+ params.filePath,
4219
+ (ctx) => setTableStyleSection(ctx, params)
4220
+ );
4221
+ return {
4222
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
4223
+ };
4224
+ }
4225
+ );
4226
+ server2.registerTool(
4227
+ "create_table_style",
4228
+ {
4229
+ description: "Create a new table style (optionally cloned from an existing one) and optionally set it as the default",
4230
+ inputSchema: CreateTableStyleSchema.shape
4231
+ },
4232
+ async (params) => {
4233
+ const result = await runMcpTool(
4234
+ params.filePath,
4235
+ (ctx) => createTableStyle(ctx, params)
4236
+ );
4237
+ return {
4238
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
4239
+ };
4240
+ }
4241
+ );
4242
+ server2.registerTool(
4243
+ "delete_table_style",
4244
+ {
4245
+ description: "Remove a table style from the presentation",
4246
+ inputSchema: DeleteTableStyleSchema.shape
4247
+ },
4248
+ async (params) => {
4249
+ const result = await runMcpTool(
4250
+ params.filePath,
4251
+ (ctx) => deleteTableStyle(ctx, params)
4252
+ );
4253
+ return {
4254
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
4255
+ };
4256
+ }
4257
+ );
4258
+ server2.registerTool(
4259
+ "assign_table_style",
4260
+ {
4261
+ description: "Assign a table style (and row/column emphasis flags) to an existing table",
4262
+ inputSchema: AssignTableStyleSchema.shape
4263
+ },
4264
+ async (params) => {
4265
+ const result = await runMcpTool(
4266
+ params.filePath,
4267
+ (ctx) => assignTableStyle(ctx, params)
4268
+ );
4269
+ return {
4270
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
4271
+ };
4272
+ }
4273
+ );
3525
4274
  server2.registerTool(
3526
4275
  "update_element_style",
3527
4276
  {
@@ -3768,6 +4517,132 @@ function createServer() {
3768
4517
  return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
3769
4518
  }
3770
4519
  );
4520
+ server2.registerTool(
4521
+ "format_chart_data_point",
4522
+ {
4523
+ description: "Set per-data-point chart formatting: fill/stroke colour, stroke width, dash style (c:dPt/c:spPr), explosion, and marker override",
4524
+ inputSchema: FormatChartDataPointSchema.shape
4525
+ },
4526
+ async (params) => {
4527
+ const result = await runMcpTool(
4528
+ params.filePath,
4529
+ (ctx) => formatChartDataPoint(ctx, params)
4530
+ );
4531
+ return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
4532
+ }
4533
+ );
4534
+ server2.registerTool(
4535
+ "format_chart_data_label",
4536
+ {
4537
+ description: "Set a per-data-point data-label override (c:dLbl): show flags, position, custom text, and the label's own fill/line formatting (c:spPr) and font (c:txPr)",
4538
+ inputSchema: FormatChartDataLabelSchema.shape
4539
+ },
4540
+ async (params) => {
4541
+ const result = await runMcpTool(
4542
+ params.filePath,
4543
+ (ctx) => formatChartDataLabel(ctx, params)
4544
+ );
4545
+ return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
4546
+ }
4547
+ );
4548
+ server2.registerTool(
4549
+ "format_chart_series",
4550
+ {
4551
+ description: "Set a chart series marker (c:marker), trendline (c:trendline, incl. line width/dash), or error bars (c:errBars, incl. line width/dash)",
4552
+ inputSchema: FormatChartSeriesSchema.shape
4553
+ },
4554
+ async (params) => {
4555
+ const result = await runMcpTool(
4556
+ params.filePath,
4557
+ (ctx) => formatChartSeries(ctx, params)
4558
+ );
4559
+ return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
4560
+ }
4561
+ );
4562
+ server2.registerTool(
4563
+ "set_chart_helper_line",
4564
+ {
4565
+ description: "Set or remove a chart-level helper line on a line/stock/combo chart: c:dropLines or c:hiLowLines",
4566
+ inputSchema: SetChartHelperLineSchema.shape
4567
+ },
4568
+ async (params) => {
4569
+ const result = await runMcpTool(
4570
+ params.filePath,
4571
+ (ctx) => setChartHelperLineT(ctx, params)
4572
+ );
4573
+ return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
4574
+ }
4575
+ );
4576
+ server2.registerTool(
4577
+ "set_chart_color_map_override",
4578
+ {
4579
+ description: "Set or remove a chart's theme colour-map override (c:clrMapOvr), remapping theme colour roles for this chart only",
4580
+ inputSchema: SetChartColorMapOverrideSchema.shape
4581
+ },
4582
+ async (params) => {
4583
+ const result = await runMcpTool(
4584
+ params.filePath,
4585
+ (ctx) => setChartColorMapOverrideT(ctx, params)
4586
+ );
4587
+ return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
4588
+ }
4589
+ );
4590
+ server2.registerTool(
4591
+ "chart_user_shape_list",
4592
+ {
4593
+ description: "List a chart's drawing-overlay shapes (c:userShapes)",
4594
+ inputSchema: ListChartUserShapesSchema.shape
4595
+ },
4596
+ async (params) => {
4597
+ const result = await runMcpTool(
4598
+ params.filePath,
4599
+ (ctx) => listChartUserShapesT(ctx, params)
4600
+ );
4601
+ return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
4602
+ }
4603
+ );
4604
+ server2.registerTool(
4605
+ "chart_user_shape_add",
4606
+ {
4607
+ description: "Add a drawing-overlay shape (text box or connector) to a chart's c:userShapes",
4608
+ inputSchema: AddChartUserShapeSchema.shape
4609
+ },
4610
+ async (params) => {
4611
+ const result = await runMcpTool(
4612
+ params.filePath,
4613
+ (ctx) => addChartUserShapeT(ctx, params)
4614
+ );
4615
+ return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
4616
+ }
4617
+ );
4618
+ server2.registerTool(
4619
+ "chart_user_shape_update",
4620
+ {
4621
+ description: "Move, resize, or restyle one of a chart's drawing-overlay shapes by index",
4622
+ inputSchema: UpdateChartUserShapeSchema.shape
4623
+ },
4624
+ async (params) => {
4625
+ const result = await runMcpTool(
4626
+ params.filePath,
4627
+ (ctx) => updateChartUserShapeT(ctx, params)
4628
+ );
4629
+ return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
4630
+ }
4631
+ );
4632
+ server2.registerTool(
4633
+ "chart_user_shape_remove",
4634
+ {
4635
+ description: "Remove one of a chart's drawing-overlay shapes by index",
4636
+ inputSchema: RemoveChartUserShapeSchema.shape
4637
+ },
4638
+ async (params) => {
4639
+ const result = await runMcpTool(
4640
+ params.filePath,
4641
+ (ctx) => removeChartUserShapeT(ctx, params)
4642
+ );
4643
+ return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
4644
+ }
4645
+ );
3771
4646
  server2.registerTool(
3772
4647
  "manage_smart_art",
3773
4648
  {