@erliban/office-mcp-server 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js ADDED
@@ -0,0 +1,2209 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/index.ts
4
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
5
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
6
+ import {
7
+ CallToolRequestSchema,
8
+ ListToolsRequestSchema
9
+ } from "@modelcontextprotocol/sdk/types.js";
10
+
11
+ // src/tools/word/index.ts
12
+ import {
13
+ Document,
14
+ Paragraph,
15
+ TextRun,
16
+ HeadingLevel,
17
+ Table,
18
+ TableRow,
19
+ TableCell,
20
+ WidthType,
21
+ BorderStyle,
22
+ AlignmentType,
23
+ Packer,
24
+ ShadingType,
25
+ Header,
26
+ Footer,
27
+ PageNumber,
28
+ LineRuleType,
29
+ ImageRun
30
+ } from "docx";
31
+ import * as fs from "fs";
32
+ import * as path from "path";
33
+ import * as https from "https";
34
+
35
+ // src/styles/themes/index.ts
36
+ var cmToTwips = (cm) => Math.round(cm * 567);
37
+ var governmentTheme = {
38
+ name: "government",
39
+ displayName: "\u515A\u653F\u516C\u6587",
40
+ description: "\u7B26\u5408GB/T 9704-2012\u6807\u51C6\u7684\u515A\u653F\u673A\u5173\u516C\u6587\u683C\u5F0F",
41
+ colors: {
42
+ primary: "cc0000",
43
+ // 公文红
44
+ secondary: "000000",
45
+ accent: "cc0000",
46
+ background: "ffffff",
47
+ headerBg: "f0f0f0",
48
+ border: "000000",
49
+ text: "000000",
50
+ textSecondary: "333333"
51
+ },
52
+ // 页边距:上3.7cm 下3.5cm 左2.8cm 右2.6cm
53
+ pageLayout: {
54
+ marginTop: cmToTwips(3.7),
55
+ marginBottom: cmToTwips(3.5),
56
+ marginLeft: cmToTwips(2.8),
57
+ marginRight: cmToTwips(2.6)
58
+ },
59
+ word: {
60
+ fonts: {
61
+ title: "\u65B9\u6B63\u5C0F\u6807\u5B8B\u7B80\u4F53",
62
+ // 标题用小标宋
63
+ heading: "\u9ED1\u4F53",
64
+ // 一级标题用黑体
65
+ body: "\u4EFF\u5B8B",
66
+ // 正文用仿宋
67
+ code: "Consolas"
68
+ },
69
+ // 文件标题:二号小标宋,居中
70
+ heading1: {
71
+ font: "\u65B9\u6B63\u5C0F\u6807\u5B8B\u7B80\u4F53",
72
+ color: "000000",
73
+ fontSize: 44,
74
+ // 二号 22pt
75
+ bold: false,
76
+ // 小标宋本身就是粗体效果
77
+ alignment: "center",
78
+ spaceBefore: 0,
79
+ spaceAfter: 28
80
+ // 段后一行
81
+ },
82
+ // 一级标题:三号黑体
83
+ heading2: {
84
+ font: "\u9ED1\u4F53",
85
+ color: "000000",
86
+ fontSize: 32,
87
+ // 三号 16pt
88
+ bold: false,
89
+ alignment: "left",
90
+ spaceBefore: 0,
91
+ spaceAfter: 0
92
+ },
93
+ // 二级标题:三号楷体加粗
94
+ heading3: {
95
+ font: "\u6977\u4F53",
96
+ color: "000000",
97
+ fontSize: 32,
98
+ // 三号 16pt
99
+ bold: true,
100
+ alignment: "left",
101
+ spaceBefore: 0,
102
+ spaceAfter: 0
103
+ },
104
+ // 正文:三号仿宋,固定行距28磅,首行缩进2字符
105
+ paragraph: {
106
+ font: "\u4EFF\u5B8B",
107
+ color: "000000",
108
+ fontSize: 32,
109
+ // 三号 16pt
110
+ format: {
111
+ lineSpacing: 28,
112
+ lineSpacingType: "exact",
113
+ firstLineIndent: 2,
114
+ spaceBefore: 0,
115
+ spaceAfter: 0
116
+ }
117
+ },
118
+ table: {
119
+ headerBg: "f0f0f0",
120
+ headerColor: "000000",
121
+ headerFont: "\u9ED1\u4F53",
122
+ headerFontSize: 24,
123
+ // 小四
124
+ headerBold: true,
125
+ bodyFont: "\u4EFF\u5B8B",
126
+ bodyFontSize: 24,
127
+ stripedBg: "fafafa",
128
+ borderColor: "000000",
129
+ borderWidth: 1
130
+ },
131
+ quote: {
132
+ borderLeft: "cc0000",
133
+ borderWidth: 3,
134
+ background: "fff5f5",
135
+ font: "\u6977\u4F53",
136
+ fontSize: 32,
137
+ italic: false
138
+ },
139
+ code: {
140
+ background: "f5f5f5",
141
+ font: "Consolas",
142
+ fontSize: 24,
143
+ borderColor: "cccccc"
144
+ },
145
+ list: {
146
+ font: "\u4EFF\u5B8B",
147
+ fontSize: 32,
148
+ indent: 640,
149
+ // 约2字符
150
+ spacing: 0
151
+ }
152
+ },
153
+ excel: {
154
+ fonts: {
155
+ title: "\u9ED1\u4F53",
156
+ heading: "\u9ED1\u4F53",
157
+ body: "\u5B8B\u4F53",
158
+ code: "Consolas"
159
+ },
160
+ headerRow: {
161
+ fill: "f0f0f0",
162
+ fontColor: "000000",
163
+ font: "\u9ED1\u4F53",
164
+ fontSize: 11,
165
+ bold: true,
166
+ alignment: "center"
167
+ },
168
+ dataRow: {
169
+ fill: "ffffff",
170
+ font: "\u5B8B\u4F53",
171
+ fontSize: 10
172
+ },
173
+ alternateRow: { fill: "fafafa" },
174
+ border: { color: "000000", style: "thin" },
175
+ chartColors: ["cc0000", "1a1a1a", "666666", "999999", "cccccc"]
176
+ }
177
+ };
178
+ var academicTheme = {
179
+ name: "academic",
180
+ displayName: "\u5B66\u672F\u8BBA\u6587",
181
+ description: "\u7B26\u5408\u5B66\u672F\u8BBA\u6587\u89C4\u8303\uFF0C\u9002\u7528\u4E8E\u7814\u7A76\u62A5\u544A\u3001\u6BD5\u4E1A\u8BBA\u6587",
182
+ colors: {
183
+ primary: "000000",
184
+ secondary: "333333",
185
+ accent: "1a73e8",
186
+ background: "ffffff",
187
+ headerBg: "f8f9fa",
188
+ border: "dadce0",
189
+ text: "000000",
190
+ textSecondary: "5f6368"
191
+ },
192
+ // 页边距:上下2.5cm 左3cm 右2.5cm
193
+ pageLayout: {
194
+ marginTop: cmToTwips(2.5),
195
+ marginBottom: cmToTwips(2.5),
196
+ marginLeft: cmToTwips(3),
197
+ marginRight: cmToTwips(2.5)
198
+ },
199
+ word: {
200
+ fonts: {
201
+ title: "\u9ED1\u4F53",
202
+ heading: "\u9ED1\u4F53",
203
+ body: "\u5B8B\u4F53",
204
+ code: "Consolas"
205
+ },
206
+ // 论文标题:小三黑体,居中
207
+ heading1: {
208
+ font: "\u9ED1\u4F53",
209
+ color: "000000",
210
+ fontSize: 30,
211
+ // 小三 15pt
212
+ bold: true,
213
+ alignment: "center",
214
+ spaceBefore: 24,
215
+ spaceAfter: 18
216
+ },
217
+ // 一级标题:四号黑体
218
+ heading2: {
219
+ font: "\u9ED1\u4F53",
220
+ color: "000000",
221
+ fontSize: 28,
222
+ // 四号 14pt
223
+ bold: false,
224
+ alignment: "left",
225
+ spaceBefore: 12,
226
+ spaceAfter: 6
227
+ },
228
+ // 二级标题:小四黑体
229
+ heading3: {
230
+ font: "\u9ED1\u4F53",
231
+ color: "000000",
232
+ fontSize: 24,
233
+ // 小四 12pt
234
+ bold: false,
235
+ alignment: "left",
236
+ spaceBefore: 6,
237
+ spaceAfter: 6
238
+ },
239
+ // 正文:小四宋体,1.5倍行距,首行缩进2字符
240
+ paragraph: {
241
+ font: "\u5B8B\u4F53",
242
+ color: "000000",
243
+ fontSize: 24,
244
+ // 小四 12pt
245
+ format: {
246
+ lineSpacing: 1.5,
247
+ lineSpacingType: "multiple",
248
+ firstLineIndent: 2,
249
+ spaceBefore: 0,
250
+ spaceAfter: 0
251
+ }
252
+ },
253
+ table: {
254
+ headerBg: "f8f9fa",
255
+ headerColor: "000000",
256
+ headerFont: "\u9ED1\u4F53",
257
+ headerFontSize: 21,
258
+ // 五号
259
+ headerBold: true,
260
+ bodyFont: "\u5B8B\u4F53",
261
+ bodyFontSize: 21,
262
+ stripedBg: "f8f9fa",
263
+ borderColor: "000000",
264
+ borderWidth: 1
265
+ },
266
+ quote: {
267
+ borderLeft: "1a73e8",
268
+ borderWidth: 3,
269
+ background: "e8f0fe",
270
+ font: "\u6977\u4F53",
271
+ fontSize: 24,
272
+ italic: true
273
+ },
274
+ code: {
275
+ background: "f8f9fa",
276
+ font: "Consolas",
277
+ fontSize: 20,
278
+ borderColor: "dadce0"
279
+ },
280
+ list: {
281
+ font: "\u5B8B\u4F53",
282
+ fontSize: 24,
283
+ indent: 480,
284
+ spacing: 6
285
+ }
286
+ },
287
+ excel: {
288
+ fonts: {
289
+ title: "\u9ED1\u4F53",
290
+ heading: "\u9ED1\u4F53",
291
+ body: "\u5B8B\u4F53",
292
+ code: "Consolas"
293
+ },
294
+ headerRow: {
295
+ fill: "f8f9fa",
296
+ fontColor: "000000",
297
+ font: "\u9ED1\u4F53",
298
+ fontSize: 10,
299
+ bold: true,
300
+ alignment: "center"
301
+ },
302
+ dataRow: {
303
+ fill: "ffffff",
304
+ font: "\u5B8B\u4F53",
305
+ fontSize: 10
306
+ },
307
+ alternateRow: { fill: "f8f9fa" },
308
+ border: { color: "000000", style: "thin" },
309
+ chartColors: ["1a73e8", "34a853", "fbbc04", "ea4335", "673ab7"]
310
+ }
311
+ };
312
+ var softwareDocTheme = {
313
+ name: "software",
314
+ displayName: "\u8F6F\u4EF6\u6587\u6863",
315
+ description: "\u7B26\u5408GB/T 8567-2006\u89C4\u8303\uFF0C\u9002\u7528\u4E8E\u9700\u6C42\u89C4\u683C\u8BF4\u660E\u4E66\u3001\u8BBE\u8BA1\u6587\u6863\u3001\u6280\u672F\u65B9\u6848",
316
+ colors: {
317
+ primary: "000000",
318
+ // 正式文档使用黑色
319
+ secondary: "333333",
320
+ accent: "1a73e8",
321
+ // 蓝色用于链接/强调
322
+ background: "ffffff",
323
+ headerBg: "f5f5f5",
324
+ border: "000000",
325
+ text: "000000",
326
+ textSecondary: "666666"
327
+ },
328
+ // 页边距:上下2.54cm 左右3.17cm (国标要求)
329
+ pageLayout: {
330
+ marginTop: cmToTwips(2.54),
331
+ marginBottom: cmToTwips(2.54),
332
+ marginLeft: cmToTwips(3.17),
333
+ marginRight: cmToTwips(3.17)
334
+ },
335
+ word: {
336
+ fonts: {
337
+ title: "\u9ED1\u4F53",
338
+ // 标题用黑体 (国标)
339
+ heading: "\u9ED1\u4F53",
340
+ // 章节标题用黑体
341
+ body: "\u5B8B\u4F53",
342
+ // 正文用宋体
343
+ code: "Consolas"
344
+ },
345
+ // 文档标题:二号黑体,居中
346
+ heading1: {
347
+ font: "\u9ED1\u4F53",
348
+ color: "000000",
349
+ fontSize: 44,
350
+ // 二号 22pt
351
+ bold: true,
352
+ alignment: "center",
353
+ spaceBefore: 24,
354
+ spaceAfter: 24
355
+ },
356
+ // 一级标题:三号黑体
357
+ heading2: {
358
+ font: "\u9ED1\u4F53",
359
+ color: "000000",
360
+ fontSize: 32,
361
+ // 三号 16pt
362
+ bold: false,
363
+ alignment: "left",
364
+ spaceBefore: 12,
365
+ spaceAfter: 6
366
+ },
367
+ // 二级标题:四号黑体
368
+ heading3: {
369
+ font: "\u9ED1\u4F53",
370
+ color: "000000",
371
+ fontSize: 28,
372
+ // 四号 14pt
373
+ bold: false,
374
+ alignment: "left",
375
+ spaceBefore: 6,
376
+ spaceAfter: 6
377
+ },
378
+ // 正文:小四宋体,1.5倍行距,首行缩进2字符
379
+ paragraph: {
380
+ font: "\u5B8B\u4F53",
381
+ color: "000000",
382
+ fontSize: 24,
383
+ // 小四 12pt
384
+ format: {
385
+ lineSpacing: 1.5,
386
+ lineSpacingType: "multiple",
387
+ firstLineIndent: 2,
388
+ spaceBefore: 0,
389
+ spaceAfter: 0
390
+ }
391
+ },
392
+ table: {
393
+ headerBg: "f5f5f5",
394
+ headerColor: "000000",
395
+ headerFont: "\u9ED1\u4F53",
396
+ headerFontSize: 21,
397
+ // 五号
398
+ headerBold: true,
399
+ bodyFont: "\u5B8B\u4F53",
400
+ bodyFontSize: 21,
401
+ stripedBg: "fafafa",
402
+ borderColor: "000000",
403
+ borderWidth: 1
404
+ },
405
+ quote: {
406
+ borderLeft: "1a73e8",
407
+ borderWidth: 3,
408
+ background: "f5f5f5",
409
+ font: "\u6977\u4F53",
410
+ fontSize: 24,
411
+ italic: false
412
+ },
413
+ code: {
414
+ background: "f5f5f5",
415
+ font: "Consolas",
416
+ fontSize: 20,
417
+ borderColor: "cccccc"
418
+ },
419
+ list: {
420
+ font: "\u5B8B\u4F53",
421
+ fontSize: 24,
422
+ indent: 480,
423
+ spacing: 0
424
+ }
425
+ },
426
+ excel: {
427
+ fonts: {
428
+ title: "\u9ED1\u4F53",
429
+ heading: "\u9ED1\u4F53",
430
+ body: "\u5B8B\u4F53",
431
+ code: "Consolas"
432
+ },
433
+ headerRow: {
434
+ fill: "f5f5f5",
435
+ fontColor: "000000",
436
+ font: "\u9ED1\u4F53",
437
+ fontSize: 10,
438
+ bold: true,
439
+ alignment: "center"
440
+ },
441
+ dataRow: {
442
+ fill: "ffffff",
443
+ font: "\u5B8B\u4F53",
444
+ fontSize: 10
445
+ },
446
+ alternateRow: { fill: "fafafa" },
447
+ border: { color: "000000", style: "thin" },
448
+ chartColors: ["1a73e8", "34a853", "fbbc04", "ea4335", "673ab7"]
449
+ }
450
+ };
451
+ var businessTheme = {
452
+ name: "business",
453
+ displayName: "\u5546\u52A1\u62A5\u544A",
454
+ description: "\u9002\u7528\u4E8E\u5E02\u573A\u8C03\u7814\u62A5\u544A\u3001\u5546\u4E1A\u8BA1\u5212\u4E66\u3001\u5DE5\u4F5C\u6C47\u62A5",
455
+ colors: {
456
+ primary: "1890ff",
457
+ secondary: "13c2c2",
458
+ accent: "722ed1",
459
+ background: "f5f5f5",
460
+ headerBg: "e6f7ff",
461
+ border: "91d5ff",
462
+ text: "262626",
463
+ textSecondary: "8c8c8c"
464
+ },
465
+ pageLayout: {
466
+ marginTop: cmToTwips(2.54),
467
+ marginBottom: cmToTwips(2.54),
468
+ marginLeft: cmToTwips(3.17),
469
+ marginRight: cmToTwips(3.17)
470
+ },
471
+ word: {
472
+ fonts: {
473
+ title: "\u5FAE\u8F6F\u96C5\u9ED1",
474
+ heading: "\u5FAE\u8F6F\u96C5\u9ED1",
475
+ body: "\u5FAE\u8F6F\u96C5\u9ED1",
476
+ code: "Consolas"
477
+ },
478
+ heading1: {
479
+ font: "\u5FAE\u8F6F\u96C5\u9ED1",
480
+ color: "1890ff",
481
+ fontSize: 36,
482
+ // 小二
483
+ bold: true,
484
+ alignment: "center",
485
+ spaceBefore: 24,
486
+ spaceAfter: 24
487
+ },
488
+ heading2: {
489
+ font: "\u5FAE\u8F6F\u96C5\u9ED1",
490
+ color: "262626",
491
+ fontSize: 32,
492
+ // 三号
493
+ bold: true,
494
+ alignment: "left",
495
+ spaceBefore: 18,
496
+ spaceAfter: 12
497
+ },
498
+ heading3: {
499
+ font: "\u5FAE\u8F6F\u96C5\u9ED1",
500
+ color: "262626",
501
+ fontSize: 28,
502
+ // 四号
503
+ bold: true,
504
+ alignment: "left",
505
+ spaceBefore: 12,
506
+ spaceAfter: 6
507
+ },
508
+ paragraph: {
509
+ font: "\u5FAE\u8F6F\u96C5\u9ED1",
510
+ color: "262626",
511
+ fontSize: 24,
512
+ format: {
513
+ lineSpacing: 1.5,
514
+ lineSpacingType: "multiple",
515
+ firstLineIndent: 0,
516
+ // 商务文档通常不缩进
517
+ spaceBefore: 0,
518
+ spaceAfter: 8
519
+ }
520
+ },
521
+ table: {
522
+ headerBg: "e6f7ff",
523
+ headerColor: "1890ff",
524
+ headerFont: "\u5FAE\u8F6F\u96C5\u9ED1",
525
+ headerFontSize: 22,
526
+ headerBold: true,
527
+ bodyFont: "\u5FAE\u8F6F\u96C5\u9ED1",
528
+ bodyFontSize: 21,
529
+ stripedBg: "fafafa",
530
+ borderColor: "91d5ff",
531
+ borderWidth: 1
532
+ },
533
+ quote: {
534
+ borderLeft: "1890ff",
535
+ borderWidth: 4,
536
+ background: "e6f7ff",
537
+ font: "\u5FAE\u8F6F\u96C5\u9ED1",
538
+ fontSize: 24,
539
+ italic: false
540
+ },
541
+ code: {
542
+ background: "f5f5f5",
543
+ font: "Consolas",
544
+ fontSize: 20,
545
+ borderColor: "d9d9d9"
546
+ },
547
+ list: {
548
+ font: "\u5FAE\u8F6F\u96C5\u9ED1",
549
+ fontSize: 24,
550
+ indent: 480,
551
+ spacing: 6
552
+ }
553
+ },
554
+ excel: {
555
+ fonts: {
556
+ title: "\u5FAE\u8F6F\u96C5\u9ED1",
557
+ heading: "\u5FAE\u8F6F\u96C5\u9ED1",
558
+ body: "\u5FAE\u8F6F\u96C5\u9ED1",
559
+ code: "Consolas"
560
+ },
561
+ headerRow: {
562
+ fill: "e6f7ff",
563
+ fontColor: "1890ff",
564
+ font: "\u5FAE\u8F6F\u96C5\u9ED1",
565
+ fontSize: 11,
566
+ bold: true,
567
+ alignment: "center"
568
+ },
569
+ dataRow: {
570
+ fill: "ffffff",
571
+ font: "\u5FAE\u8F6F\u96C5\u9ED1",
572
+ fontSize: 10
573
+ },
574
+ alternateRow: { fill: "fafafa" },
575
+ border: { color: "91d5ff", style: "thin" },
576
+ chartColors: ["1890ff", "52c41a", "faad14", "f5222d", "722ed1"]
577
+ }
578
+ };
579
+ var alibabaTheme = {
580
+ name: "alibaba",
581
+ displayName: "\u963F\u91CC\u98CE\u683C",
582
+ description: "\u963F\u91CC\u6A59\u8272\u7CFB\uFF0C\u9002\u7528\u4E8E\u7535\u5546\u3001\u96F6\u552E\u884C\u4E1A",
583
+ colors: {
584
+ primary: "ff6a00",
585
+ secondary: "1677ff",
586
+ accent: "fa8c16",
587
+ background: "f5f5f5",
588
+ headerBg: "fff7e6",
589
+ border: "ffe7ba",
590
+ text: "333333",
591
+ textSecondary: "666666"
592
+ },
593
+ pageLayout: {
594
+ marginTop: cmToTwips(2.54),
595
+ marginBottom: cmToTwips(2.54),
596
+ marginLeft: cmToTwips(3.17),
597
+ marginRight: cmToTwips(3.17)
598
+ },
599
+ word: {
600
+ fonts: {
601
+ title: "\u963F\u91CC\u5DF4\u5DF4\u666E\u60E0\u4F53",
602
+ heading: "\u963F\u91CC\u5DF4\u5DF4\u666E\u60E0\u4F53",
603
+ body: "\u963F\u91CC\u5DF4\u5DF4\u666E\u60E0\u4F53",
604
+ code: "Consolas"
605
+ },
606
+ heading1: {
607
+ font: "\u963F\u91CC\u5DF4\u5DF4\u666E\u60E0\u4F53",
608
+ color: "ff6a00",
609
+ fontSize: 36,
610
+ bold: true,
611
+ alignment: "left",
612
+ spaceBefore: 24,
613
+ spaceAfter: 18
614
+ },
615
+ heading2: {
616
+ font: "\u963F\u91CC\u5DF4\u5DF4\u666E\u60E0\u4F53",
617
+ color: "1677ff",
618
+ fontSize: 32,
619
+ bold: true,
620
+ alignment: "left",
621
+ spaceBefore: 18,
622
+ spaceAfter: 12
623
+ },
624
+ heading3: {
625
+ font: "\u963F\u91CC\u5DF4\u5DF4\u666E\u60E0\u4F53",
626
+ color: "333333",
627
+ fontSize: 28,
628
+ bold: true,
629
+ alignment: "left",
630
+ spaceBefore: 12,
631
+ spaceAfter: 6
632
+ },
633
+ paragraph: {
634
+ font: "\u963F\u91CC\u5DF4\u5DF4\u666E\u60E0\u4F53",
635
+ color: "333333",
636
+ fontSize: 24,
637
+ format: {
638
+ lineSpacing: 1.6,
639
+ lineSpacingType: "multiple",
640
+ firstLineIndent: 0,
641
+ spaceBefore: 0,
642
+ spaceAfter: 8
643
+ }
644
+ },
645
+ table: {
646
+ headerBg: "fff7e6",
647
+ headerColor: "d46b08",
648
+ headerFont: "\u963F\u91CC\u5DF4\u5DF4\u666E\u60E0\u4F53",
649
+ headerFontSize: 22,
650
+ headerBold: true,
651
+ bodyFont: "\u963F\u91CC\u5DF4\u5DF4\u666E\u60E0\u4F53",
652
+ bodyFontSize: 21,
653
+ stripedBg: "fafafa",
654
+ borderColor: "ffe7ba",
655
+ borderWidth: 1
656
+ },
657
+ quote: {
658
+ borderLeft: "ff6a00",
659
+ borderWidth: 4,
660
+ background: "fff7e6",
661
+ font: "\u963F\u91CC\u5DF4\u5DF4\u666E\u60E0\u4F53",
662
+ fontSize: 24,
663
+ italic: false
664
+ },
665
+ code: {
666
+ background: "f5f5f5",
667
+ font: "Consolas",
668
+ fontSize: 20,
669
+ borderColor: "e8e8e8"
670
+ },
671
+ list: {
672
+ font: "\u963F\u91CC\u5DF4\u5DF4\u666E\u60E0\u4F53",
673
+ fontSize: 24,
674
+ indent: 480,
675
+ spacing: 6
676
+ }
677
+ },
678
+ excel: {
679
+ fonts: {
680
+ title: "\u5FAE\u8F6F\u96C5\u9ED1",
681
+ heading: "\u5FAE\u8F6F\u96C5\u9ED1",
682
+ body: "\u5FAE\u8F6F\u96C5\u9ED1",
683
+ code: "Consolas"
684
+ },
685
+ headerRow: {
686
+ fill: "fff7e6",
687
+ fontColor: "d46b08",
688
+ font: "\u5FAE\u8F6F\u96C5\u9ED1",
689
+ fontSize: 11,
690
+ bold: true,
691
+ alignment: "center"
692
+ },
693
+ dataRow: {
694
+ fill: "ffffff",
695
+ font: "\u5FAE\u8F6F\u96C5\u9ED1",
696
+ fontSize: 10
697
+ },
698
+ alternateRow: { fill: "fafafa" },
699
+ border: { color: "ffe7ba", style: "thin" },
700
+ chartColors: ["ff6a00", "1677ff", "52c41a", "faad14", "722ed1"]
701
+ }
702
+ };
703
+ var tencentTheme = {
704
+ name: "tencent",
705
+ displayName: "\u817E\u8BAF\u98CE\u683C",
706
+ description: "\u817E\u8BAF\u7EFF\u8272\u7CFB\uFF0C\u9002\u7528\u4E8E\u793E\u4EA4\u3001\u91D1\u878D\u884C\u4E1A",
707
+ colors: {
708
+ primary: "07c160",
709
+ secondary: "576b95",
710
+ accent: "10aeff",
711
+ background: "f7f7f7",
712
+ headerBg: "f0f9eb",
713
+ border: "e5e5e5",
714
+ text: "191919",
715
+ textSecondary: "999999"
716
+ },
717
+ pageLayout: {
718
+ marginTop: cmToTwips(2.54),
719
+ marginBottom: cmToTwips(2.54),
720
+ marginLeft: cmToTwips(3.17),
721
+ marginRight: cmToTwips(3.17)
722
+ },
723
+ word: {
724
+ fonts: {
725
+ title: "\u5FAE\u8F6F\u96C5\u9ED1",
726
+ heading: "\u5FAE\u8F6F\u96C5\u9ED1",
727
+ body: "\u5FAE\u8F6F\u96C5\u9ED1",
728
+ code: "Consolas"
729
+ },
730
+ heading1: {
731
+ font: "\u5FAE\u8F6F\u96C5\u9ED1",
732
+ color: "07c160",
733
+ fontSize: 36,
734
+ bold: true,
735
+ alignment: "left",
736
+ spaceBefore: 24,
737
+ spaceAfter: 18
738
+ },
739
+ heading2: {
740
+ font: "\u5FAE\u8F6F\u96C5\u9ED1",
741
+ color: "191919",
742
+ fontSize: 32,
743
+ bold: true,
744
+ alignment: "left",
745
+ spaceBefore: 18,
746
+ spaceAfter: 12
747
+ },
748
+ heading3: {
749
+ font: "\u5FAE\u8F6F\u96C5\u9ED1",
750
+ color: "191919",
751
+ fontSize: 28,
752
+ bold: true,
753
+ alignment: "left",
754
+ spaceBefore: 12,
755
+ spaceAfter: 6
756
+ },
757
+ paragraph: {
758
+ font: "\u5FAE\u8F6F\u96C5\u9ED1",
759
+ color: "191919",
760
+ fontSize: 24,
761
+ format: {
762
+ lineSpacing: 1.5,
763
+ lineSpacingType: "multiple",
764
+ firstLineIndent: 0,
765
+ spaceBefore: 0,
766
+ spaceAfter: 8
767
+ }
768
+ },
769
+ table: {
770
+ headerBg: "f0f9eb",
771
+ headerColor: "07c160",
772
+ headerFont: "\u5FAE\u8F6F\u96C5\u9ED1",
773
+ headerFontSize: 22,
774
+ headerBold: true,
775
+ bodyFont: "\u5FAE\u8F6F\u96C5\u9ED1",
776
+ bodyFontSize: 21,
777
+ stripedBg: "f7f7f7",
778
+ borderColor: "e5e5e5",
779
+ borderWidth: 1
780
+ },
781
+ quote: {
782
+ borderLeft: "07c160",
783
+ borderWidth: 4,
784
+ background: "f0f9eb",
785
+ font: "\u5FAE\u8F6F\u96C5\u9ED1",
786
+ fontSize: 24,
787
+ italic: false
788
+ },
789
+ code: {
790
+ background: "f7f7f7",
791
+ font: "Consolas",
792
+ fontSize: 20,
793
+ borderColor: "e5e5e5"
794
+ },
795
+ list: {
796
+ font: "\u5FAE\u8F6F\u96C5\u9ED1",
797
+ fontSize: 24,
798
+ indent: 480,
799
+ spacing: 6
800
+ }
801
+ },
802
+ excel: {
803
+ fonts: {
804
+ title: "\u5FAE\u8F6F\u96C5\u9ED1",
805
+ heading: "\u5FAE\u8F6F\u96C5\u9ED1",
806
+ body: "\u5FAE\u8F6F\u96C5\u9ED1",
807
+ code: "Consolas"
808
+ },
809
+ headerRow: {
810
+ fill: "f0f9eb",
811
+ fontColor: "07c160",
812
+ font: "\u5FAE\u8F6F\u96C5\u9ED1",
813
+ fontSize: 11,
814
+ bold: true,
815
+ alignment: "center"
816
+ },
817
+ dataRow: {
818
+ fill: "ffffff",
819
+ font: "\u5FAE\u8F6F\u96C5\u9ED1",
820
+ fontSize: 10
821
+ },
822
+ alternateRow: { fill: "f7f7f7" },
823
+ border: { color: "e5e5e5", style: "thin" },
824
+ chartColors: ["07c160", "576b95", "fa5151", "ffc300", "1485ee"]
825
+ }
826
+ };
827
+ var bytedanceTheme = {
828
+ name: "bytedance",
829
+ displayName: "\u5B57\u8282\u98CE\u683C",
830
+ description: "\u5B57\u8282\u9ED1\u8272\u7CFB\uFF0C\u9002\u7528\u4E8E\u79D1\u6280\u3001\u5A92\u4F53\u884C\u4E1A",
831
+ colors: {
832
+ primary: "fe2c55",
833
+ secondary: "161823",
834
+ accent: "25f4ee",
835
+ background: "f8f8f8",
836
+ headerBg: "161823",
837
+ border: "e1e1e1",
838
+ text: "161823",
839
+ textSecondary: "86868b"
840
+ },
841
+ pageLayout: {
842
+ marginTop: cmToTwips(2.54),
843
+ marginBottom: cmToTwips(2.54),
844
+ marginLeft: cmToTwips(3.17),
845
+ marginRight: cmToTwips(3.17)
846
+ },
847
+ word: {
848
+ fonts: {
849
+ title: "\u6296\u97F3\u7F8E\u597D\u4F53",
850
+ heading: "\u6296\u97F3\u7F8E\u597D\u4F53",
851
+ body: "\u5FAE\u8F6F\u96C5\u9ED1",
852
+ code: "Consolas"
853
+ },
854
+ heading1: {
855
+ font: "\u6296\u97F3\u7F8E\u597D\u4F53",
856
+ color: "161823",
857
+ fontSize: 40,
858
+ bold: true,
859
+ alignment: "left",
860
+ spaceBefore: 24,
861
+ spaceAfter: 18
862
+ },
863
+ heading2: {
864
+ font: "\u6296\u97F3\u7F8E\u597D\u4F53",
865
+ color: "161823",
866
+ fontSize: 32,
867
+ bold: true,
868
+ alignment: "left",
869
+ spaceBefore: 18,
870
+ spaceAfter: 12
871
+ },
872
+ heading3: {
873
+ font: "\u5FAE\u8F6F\u96C5\u9ED1",
874
+ color: "161823",
875
+ fontSize: 28,
876
+ bold: true,
877
+ alignment: "left",
878
+ spaceBefore: 12,
879
+ spaceAfter: 6
880
+ },
881
+ paragraph: {
882
+ font: "\u5FAE\u8F6F\u96C5\u9ED1",
883
+ color: "161823",
884
+ fontSize: 24,
885
+ format: {
886
+ lineSpacing: 1.8,
887
+ lineSpacingType: "multiple",
888
+ firstLineIndent: 0,
889
+ spaceBefore: 0,
890
+ spaceAfter: 10
891
+ }
892
+ },
893
+ table: {
894
+ headerBg: "161823",
895
+ headerColor: "ffffff",
896
+ headerFont: "\u5FAE\u8F6F\u96C5\u9ED1",
897
+ headerFontSize: 22,
898
+ headerBold: true,
899
+ bodyFont: "\u5FAE\u8F6F\u96C5\u9ED1",
900
+ bodyFontSize: 21,
901
+ stripedBg: "f8f8f8",
902
+ borderColor: "e1e1e1",
903
+ borderWidth: 1
904
+ },
905
+ quote: {
906
+ borderLeft: "fe2c55",
907
+ borderWidth: 4,
908
+ background: "fff0f3",
909
+ font: "\u5FAE\u8F6F\u96C5\u9ED1",
910
+ fontSize: 24,
911
+ italic: false
912
+ },
913
+ code: {
914
+ background: "f8f8f8",
915
+ font: "Consolas",
916
+ fontSize: 20,
917
+ borderColor: "e1e1e1"
918
+ },
919
+ list: {
920
+ font: "\u5FAE\u8F6F\u96C5\u9ED1",
921
+ fontSize: 24,
922
+ indent: 480,
923
+ spacing: 8
924
+ }
925
+ },
926
+ excel: {
927
+ fonts: {
928
+ title: "\u5FAE\u8F6F\u96C5\u9ED1",
929
+ heading: "\u5FAE\u8F6F\u96C5\u9ED1",
930
+ body: "\u5FAE\u8F6F\u96C5\u9ED1",
931
+ code: "Consolas"
932
+ },
933
+ headerRow: {
934
+ fill: "161823",
935
+ fontColor: "ffffff",
936
+ font: "\u5FAE\u8F6F\u96C5\u9ED1",
937
+ fontSize: 11,
938
+ bold: true,
939
+ alignment: "center"
940
+ },
941
+ dataRow: {
942
+ fill: "ffffff",
943
+ font: "\u5FAE\u8F6F\u96C5\u9ED1",
944
+ fontSize: 10
945
+ },
946
+ alternateRow: { fill: "f8f8f8" },
947
+ border: { color: "e1e1e1", style: "thin" },
948
+ chartColors: ["fe2c55", "25f4ee", "161823", "ee1d52", "69c9d0"]
949
+ }
950
+ };
951
+ var minimalTheme = {
952
+ name: "minimal",
953
+ displayName: "\u7B80\u7EA6\u9ED1\u767D",
954
+ description: "\u7B80\u6D01\u7684\u9ED1\u767D\u914D\u8272\uFF0C\u901A\u7528\u4E8E\u5404\u7C7B\u6B63\u5F0F\u6587\u6863",
955
+ colors: {
956
+ primary: "000000",
957
+ secondary: "666666",
958
+ accent: "000000",
959
+ background: "ffffff",
960
+ headerBg: "f5f5f5",
961
+ border: "cccccc",
962
+ text: "000000",
963
+ textSecondary: "666666"
964
+ },
965
+ pageLayout: {
966
+ marginTop: cmToTwips(2.54),
967
+ marginBottom: cmToTwips(2.54),
968
+ marginLeft: cmToTwips(3.17),
969
+ marginRight: cmToTwips(3.17)
970
+ },
971
+ word: {
972
+ fonts: {
973
+ title: "\u9ED1\u4F53",
974
+ heading: "\u9ED1\u4F53",
975
+ body: "\u5B8B\u4F53",
976
+ code: "Consolas"
977
+ },
978
+ heading1: {
979
+ font: "\u9ED1\u4F53",
980
+ color: "000000",
981
+ fontSize: 36,
982
+ bold: true,
983
+ alignment: "center",
984
+ spaceBefore: 24,
985
+ spaceAfter: 18
986
+ },
987
+ heading2: {
988
+ font: "\u9ED1\u4F53",
989
+ color: "000000",
990
+ fontSize: 30,
991
+ bold: false,
992
+ alignment: "left",
993
+ spaceBefore: 12,
994
+ spaceAfter: 6
995
+ },
996
+ heading3: {
997
+ font: "\u9ED1\u4F53",
998
+ color: "000000",
999
+ fontSize: 26,
1000
+ bold: false,
1001
+ alignment: "left",
1002
+ spaceBefore: 6,
1003
+ spaceAfter: 6
1004
+ },
1005
+ paragraph: {
1006
+ font: "\u5B8B\u4F53",
1007
+ color: "000000",
1008
+ fontSize: 24,
1009
+ format: {
1010
+ lineSpacing: 1.5,
1011
+ lineSpacingType: "multiple",
1012
+ firstLineIndent: 2,
1013
+ spaceBefore: 0,
1014
+ spaceAfter: 0
1015
+ }
1016
+ },
1017
+ table: {
1018
+ headerBg: "f5f5f5",
1019
+ headerColor: "000000",
1020
+ headerFont: "\u9ED1\u4F53",
1021
+ headerFontSize: 22,
1022
+ headerBold: true,
1023
+ bodyFont: "\u5B8B\u4F53",
1024
+ bodyFontSize: 21,
1025
+ stripedBg: "fafafa",
1026
+ borderColor: "000000",
1027
+ borderWidth: 1
1028
+ },
1029
+ quote: {
1030
+ borderLeft: "000000",
1031
+ borderWidth: 3,
1032
+ background: "f5f5f5",
1033
+ font: "\u6977\u4F53",
1034
+ fontSize: 24,
1035
+ italic: true
1036
+ },
1037
+ code: {
1038
+ background: "f5f5f5",
1039
+ font: "Consolas",
1040
+ fontSize: 20,
1041
+ borderColor: "cccccc"
1042
+ },
1043
+ list: {
1044
+ font: "\u5B8B\u4F53",
1045
+ fontSize: 24,
1046
+ indent: 480,
1047
+ spacing: 6
1048
+ }
1049
+ },
1050
+ excel: {
1051
+ fonts: {
1052
+ title: "\u9ED1\u4F53",
1053
+ heading: "\u9ED1\u4F53",
1054
+ body: "\u5B8B\u4F53",
1055
+ code: "Consolas"
1056
+ },
1057
+ headerRow: {
1058
+ fill: "f5f5f5",
1059
+ fontColor: "000000",
1060
+ font: "\u9ED1\u4F53",
1061
+ fontSize: 11,
1062
+ bold: true,
1063
+ alignment: "center"
1064
+ },
1065
+ dataRow: {
1066
+ fill: "ffffff",
1067
+ font: "\u5B8B\u4F53",
1068
+ fontSize: 10
1069
+ },
1070
+ alternateRow: { fill: "fafafa" },
1071
+ border: { color: "000000", style: "thin" },
1072
+ chartColors: ["000000", "333333", "666666", "999999", "cccccc"]
1073
+ }
1074
+ };
1075
+ var defaultTheme = businessTheme;
1076
+ var themes = {
1077
+ government: governmentTheme,
1078
+ academic: academicTheme,
1079
+ software: softwareDocTheme,
1080
+ business: businessTheme,
1081
+ alibaba: alibabaTheme,
1082
+ tencent: tencentTheme,
1083
+ bytedance: bytedanceTheme,
1084
+ minimal: minimalTheme,
1085
+ default: defaultTheme
1086
+ };
1087
+ function getTheme(name) {
1088
+ return themes[name] || defaultTheme;
1089
+ }
1090
+
1091
+ // src/tools/word/index.ts
1092
+ var documents = /* @__PURE__ */ new Map();
1093
+ function generateId() {
1094
+ return `word_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
1095
+ }
1096
+ var wordTools = [
1097
+ {
1098
+ name: "word_create",
1099
+ description: "\u521B\u5EFA\u4E00\u4E2A\u65B0\u7684 Word \u6587\u6863",
1100
+ inputSchema: {
1101
+ type: "object",
1102
+ properties: {
1103
+ title: { type: "string", description: "\u6587\u6863\u6807\u9898" },
1104
+ template: {
1105
+ type: "string",
1106
+ enum: ["tech-doc", "weekly-report", "monthly-report", "prd", "meeting-notes", "blank"],
1107
+ description: "\u4F7F\u7528\u7684\u6A21\u677F\u7C7B\u578B"
1108
+ },
1109
+ theme: {
1110
+ type: "string",
1111
+ enum: ["government", "academic", "business", "alibaba", "tencent", "bytedance", "minimal", "default"],
1112
+ description: "\u4E3B\u9898\u98CE\u683C\uFF1Agovernment(\u515A\u653F\u516C\u6587)\u3001academic(\u5B66\u672F\u8BBA\u6587)\u3001business(\u5546\u52A1\u62A5\u544A)\u3001alibaba/tencent/bytedance(\u4F01\u4E1A\u98CE\u683C)\u3001minimal(\u7B80\u7EA6\u9ED1\u767D)"
1113
+ },
1114
+ author: { type: "string", description: "\u4F5C\u8005" },
1115
+ outputPath: { type: "string", description: "\u8F93\u51FA\u8DEF\u5F84" }
1116
+ },
1117
+ required: ["title", "outputPath"]
1118
+ }
1119
+ },
1120
+ {
1121
+ name: "word_add_heading",
1122
+ description: "\u6DFB\u52A0\u6807\u9898\uFF08\u652F\u63011-6\u7EA7\uFF09",
1123
+ inputSchema: {
1124
+ type: "object",
1125
+ properties: {
1126
+ docId: { type: "string", description: "\u6587\u6863ID" },
1127
+ text: { type: "string", description: "\u6807\u9898\u6587\u672C" },
1128
+ level: { type: "number", enum: [1, 2, 3, 4, 5, 6], description: "\u6807\u9898\u7EA7\u522B" },
1129
+ numbering: { type: "boolean", description: "\u662F\u5426\u81EA\u52A8\u7F16\u53F7" }
1130
+ },
1131
+ required: ["docId", "text", "level"]
1132
+ }
1133
+ },
1134
+ {
1135
+ name: "word_add_paragraph",
1136
+ description: "\u6DFB\u52A0\u6B63\u6587\u6BB5\u843D",
1137
+ inputSchema: {
1138
+ type: "object",
1139
+ properties: {
1140
+ docId: { type: "string", description: "\u6587\u6863ID" },
1141
+ text: { type: "string", description: "\u6BB5\u843D\u6587\u672C" },
1142
+ style: {
1143
+ type: "string",
1144
+ enum: ["normal", "quote", "note", "warning", "tip"],
1145
+ description: "\u6BB5\u843D\u6837\u5F0F"
1146
+ },
1147
+ bold: { type: "boolean", description: "\u662F\u5426\u52A0\u7C97" },
1148
+ italic: { type: "boolean", description: "\u662F\u5426\u659C\u4F53" }
1149
+ },
1150
+ required: ["docId", "text"]
1151
+ }
1152
+ },
1153
+ {
1154
+ name: "word_add_table",
1155
+ description: "\u6DFB\u52A0\u8868\u683C",
1156
+ inputSchema: {
1157
+ type: "object",
1158
+ properties: {
1159
+ docId: { type: "string", description: "\u6587\u6863ID" },
1160
+ headers: { type: "array", items: { type: "string" }, description: "\u8868\u5934" },
1161
+ rows: { type: "array", items: { type: "array" }, description: "\u6570\u636E\u884C" },
1162
+ style: {
1163
+ type: "string",
1164
+ enum: ["striped", "bordered", "minimal", "professional"],
1165
+ description: "\u8868\u683C\u6837\u5F0F"
1166
+ }
1167
+ },
1168
+ required: ["docId", "headers", "rows"]
1169
+ }
1170
+ },
1171
+ {
1172
+ name: "word_add_list",
1173
+ description: "\u6DFB\u52A0\u6709\u5E8F/\u65E0\u5E8F\u5217\u8868",
1174
+ inputSchema: {
1175
+ type: "object",
1176
+ properties: {
1177
+ docId: { type: "string", description: "\u6587\u6863ID" },
1178
+ items: { type: "array", items: { type: "string" }, description: "\u5217\u8868\u9879" },
1179
+ ordered: { type: "boolean", description: "\u662F\u5426\u6709\u5E8F\u5217\u8868" }
1180
+ },
1181
+ required: ["docId", "items"]
1182
+ }
1183
+ },
1184
+ {
1185
+ name: "word_add_code",
1186
+ description: "\u6DFB\u52A0\u4EE3\u7801\u5757",
1187
+ inputSchema: {
1188
+ type: "object",
1189
+ properties: {
1190
+ docId: { type: "string", description: "\u6587\u6863ID" },
1191
+ code: { type: "string", description: "\u4EE3\u7801\u5185\u5BB9" },
1192
+ language: { type: "string", description: "\u7F16\u7A0B\u8BED\u8A00" }
1193
+ },
1194
+ required: ["docId", "code"]
1195
+ }
1196
+ },
1197
+ {
1198
+ name: "word_add_diagram",
1199
+ description: "\u6DFB\u52A0 Mermaid \u6D41\u7A0B\u56FE/\u67B6\u6784\u56FE\uFF08\u81EA\u52A8\u8F6C\u6362\u4E3A\u56FE\u7247\u63D2\u5165\uFF09",
1200
+ inputSchema: {
1201
+ type: "object",
1202
+ properties: {
1203
+ docId: { type: "string", description: "\u6587\u6863ID" },
1204
+ mermaid: { type: "string", description: "Mermaid \u56FE\u8868\u4EE3\u7801" },
1205
+ caption: { type: "string", description: "\u56FE\u8868\u6807\u9898\uFF08\u53EF\u9009\uFF09" },
1206
+ width: { type: "number", description: "\u56FE\u7247\u5BBD\u5EA6\uFF08\u5398\u7C73\uFF09\uFF0C\u9ED8\u8BA415" },
1207
+ theme: {
1208
+ type: "string",
1209
+ enum: ["professional", "fresh", "business", "tech", "warm", "default"],
1210
+ description: "\u56FE\u8868\u98CE\u683C\uFF1Aprofessional(\u4E13\u4E1A\u84DD)\u3001fresh(\u6E05\u65B0\u7EFF)\u3001business(\u5546\u52A1\u7070)\u3001tech(\u79D1\u6280\u7D2B)\u3001warm(\u6696\u6A59\u8272)\u3001default(\u539F\u751F)"
1211
+ }
1212
+ },
1213
+ required: ["docId", "mermaid"]
1214
+ }
1215
+ },
1216
+ {
1217
+ name: "word_save",
1218
+ description: "\u4FDD\u5B58\u6587\u6863",
1219
+ inputSchema: {
1220
+ type: "object",
1221
+ properties: {
1222
+ docId: { type: "string", description: "\u6587\u6863ID" },
1223
+ addPageNumbers: { type: "boolean", description: "\u6DFB\u52A0\u9875\u7801" },
1224
+ addHeader: { type: "string", description: "\u9875\u7709\u6587\u5B57" },
1225
+ addFooter: { type: "string", description: "\u9875\u811A\u6587\u5B57" }
1226
+ },
1227
+ required: ["docId"]
1228
+ }
1229
+ }
1230
+ ];
1231
+ function wordCreate(args) {
1232
+ const { title, theme = "default", author, outputPath } = args;
1233
+ const id = generateId();
1234
+ const themeConfig = getTheme(theme);
1235
+ documents.set(id, {
1236
+ children: [],
1237
+ outputPath,
1238
+ theme: themeConfig,
1239
+ title,
1240
+ author
1241
+ });
1242
+ return {
1243
+ success: true,
1244
+ docId: id,
1245
+ message: `\u6587\u6863 "${title}" \u521B\u5EFA\u6210\u529F\uFF0C\u4E3B\u9898: ${themeConfig.displayName}`
1246
+ };
1247
+ }
1248
+ function wordAddHeading(args) {
1249
+ const { docId, text, level } = args;
1250
+ const doc = documents.get(docId);
1251
+ if (!doc) {
1252
+ return { success: false, message: `\u6587\u6863 ${docId} \u4E0D\u5B58\u5728` };
1253
+ }
1254
+ const headingLevelMap = {
1255
+ 1: HeadingLevel.HEADING_1,
1256
+ 2: HeadingLevel.HEADING_2,
1257
+ 3: HeadingLevel.HEADING_3,
1258
+ 4: HeadingLevel.HEADING_4,
1259
+ 5: HeadingLevel.HEADING_5,
1260
+ 6: HeadingLevel.HEADING_6
1261
+ };
1262
+ const styleKey = `heading${Math.min(level, 3)}`;
1263
+ const style = doc.theme.word[styleKey];
1264
+ const alignmentMap = {
1265
+ left: AlignmentType.LEFT,
1266
+ center: AlignmentType.CENTER,
1267
+ right: AlignmentType.RIGHT
1268
+ };
1269
+ const alignment = alignmentMap[style.alignment] || AlignmentType.LEFT;
1270
+ const spaceBefore = style.spaceBefore * 20;
1271
+ const spaceAfter = style.spaceAfter * 20;
1272
+ const paragraph = new Paragraph({
1273
+ heading: headingLevelMap[level],
1274
+ alignment,
1275
+ children: [
1276
+ new TextRun({
1277
+ text,
1278
+ bold: style.bold,
1279
+ color: style.color,
1280
+ size: style.fontSize,
1281
+ font: style.font
1282
+ })
1283
+ ],
1284
+ spacing: { after: spaceAfter, before: spaceBefore }
1285
+ });
1286
+ doc.children.push(paragraph);
1287
+ return { success: true, message: `\u5DF2\u6DFB\u52A0 ${level} \u7EA7\u6807\u9898: ${text}` };
1288
+ }
1289
+ function wordAddParagraph(args) {
1290
+ const { docId, text, style = "normal", bold = false, italic = false } = args;
1291
+ const doc = documents.get(docId);
1292
+ if (!doc) {
1293
+ return { success: false, message: `\u6587\u6863 ${docId} \u4E0D\u5B58\u5728` };
1294
+ }
1295
+ const themeStyle = doc.theme.word.paragraph;
1296
+ const format = themeStyle.format;
1297
+ let shading;
1298
+ let border;
1299
+ let fontToUse = themeStyle.font;
1300
+ let fontSizeToUse = themeStyle.fontSize;
1301
+ let isItalic = italic;
1302
+ if (style === "quote") {
1303
+ const quoteStyle = doc.theme.word.quote;
1304
+ shading = { type: ShadingType.SOLID, color: quoteStyle.background };
1305
+ border = { left: { style: BorderStyle.SINGLE, size: quoteStyle.borderWidth * 8, color: quoteStyle.borderLeft } };
1306
+ fontToUse = quoteStyle.font;
1307
+ fontSizeToUse = quoteStyle.fontSize;
1308
+ isItalic = quoteStyle.italic || italic;
1309
+ } else if (style === "note" || style === "tip") {
1310
+ shading = { type: ShadingType.SOLID, color: "e6f7ff" };
1311
+ } else if (style === "warning") {
1312
+ shading = { type: ShadingType.SOLID, color: "fff7e6" };
1313
+ }
1314
+ const lineSpacing = format.lineSpacingType === "multiple" ? { line: Math.round(format.lineSpacing * 240), lineRule: LineRuleType.AUTO } : { line: Math.round(format.lineSpacing * 20), lineRule: LineRuleType.EXACT };
1315
+ const firstLineIndent = format.firstLineIndent > 0 ? Math.round(format.firstLineIndent * themeStyle.fontSize * 10) : 0;
1316
+ const paragraph = new Paragraph({
1317
+ children: [
1318
+ new TextRun({
1319
+ text,
1320
+ color: themeStyle.color,
1321
+ size: fontSizeToUse,
1322
+ font: fontToUse,
1323
+ bold,
1324
+ italics: isItalic
1325
+ })
1326
+ ],
1327
+ spacing: {
1328
+ ...lineSpacing,
1329
+ before: format.spaceBefore * 20,
1330
+ after: format.spaceAfter * 20
1331
+ },
1332
+ indent: {
1333
+ firstLine: firstLineIndent,
1334
+ ...style === "quote" ? { left: 720 } : {}
1335
+ },
1336
+ shading,
1337
+ border
1338
+ });
1339
+ doc.children.push(paragraph);
1340
+ return { success: true, message: "\u5DF2\u6DFB\u52A0\u6BB5\u843D" };
1341
+ }
1342
+ function wordAddTable(args) {
1343
+ const { docId, headers, rows, style = "professional" } = args;
1344
+ const doc = documents.get(docId);
1345
+ if (!doc) {
1346
+ return { success: false, message: `\u6587\u6863 ${docId} \u4E0D\u5B58\u5728` };
1347
+ }
1348
+ const tableStyle = doc.theme.word.table;
1349
+ const colCount = headers.length;
1350
+ const headerRow = new TableRow({
1351
+ children: headers.map(
1352
+ (header) => new TableCell({
1353
+ children: [
1354
+ new Paragraph({
1355
+ children: [
1356
+ new TextRun({
1357
+ text: header,
1358
+ bold: tableStyle.headerBold,
1359
+ color: tableStyle.headerColor,
1360
+ size: tableStyle.headerFontSize,
1361
+ font: tableStyle.headerFont
1362
+ })
1363
+ ],
1364
+ alignment: AlignmentType.CENTER
1365
+ })
1366
+ ],
1367
+ shading: { type: ShadingType.SOLID, color: tableStyle.headerBg },
1368
+ width: { size: 100 / colCount, type: WidthType.PERCENTAGE }
1369
+ })
1370
+ )
1371
+ });
1372
+ const dataRows = rows.map(
1373
+ (row, rowIndex) => new TableRow({
1374
+ children: row.map(
1375
+ (cell) => new TableCell({
1376
+ children: [
1377
+ new Paragraph({
1378
+ children: [
1379
+ new TextRun({
1380
+ text: String(cell),
1381
+ size: tableStyle.bodyFontSize,
1382
+ font: tableStyle.bodyFont
1383
+ })
1384
+ ]
1385
+ })
1386
+ ],
1387
+ shading: style === "striped" && rowIndex % 2 === 1 ? { type: ShadingType.SOLID, color: tableStyle.stripedBg } : void 0,
1388
+ width: { size: 100 / colCount, type: WidthType.PERCENTAGE }
1389
+ })
1390
+ )
1391
+ })
1392
+ );
1393
+ const borderConfig = style === "minimal" ? void 0 : {
1394
+ top: { style: BorderStyle.SINGLE, size: tableStyle.borderWidth, color: tableStyle.borderColor },
1395
+ bottom: { style: BorderStyle.SINGLE, size: tableStyle.borderWidth, color: tableStyle.borderColor },
1396
+ left: { style: BorderStyle.SINGLE, size: tableStyle.borderWidth, color: tableStyle.borderColor },
1397
+ right: { style: BorderStyle.SINGLE, size: tableStyle.borderWidth, color: tableStyle.borderColor },
1398
+ insideHorizontal: { style: BorderStyle.SINGLE, size: tableStyle.borderWidth, color: tableStyle.borderColor },
1399
+ insideVertical: { style: BorderStyle.SINGLE, size: tableStyle.borderWidth, color: tableStyle.borderColor }
1400
+ };
1401
+ const table = new Table({
1402
+ rows: [headerRow, ...dataRows],
1403
+ width: { size: 100, type: WidthType.PERCENTAGE },
1404
+ borders: borderConfig
1405
+ });
1406
+ doc.children.push(table);
1407
+ doc.children.push(new Paragraph({ children: [] }));
1408
+ return { success: true, message: `\u5DF2\u6DFB\u52A0 ${headers.length} \u5217 ${rows.length} \u884C\u7684\u8868\u683C` };
1409
+ }
1410
+ function wordAddList(args) {
1411
+ const { docId, items, ordered = false } = args;
1412
+ const doc = documents.get(docId);
1413
+ if (!doc) {
1414
+ return { success: false, message: `\u6587\u6863 ${docId} \u4E0D\u5B58\u5728` };
1415
+ }
1416
+ const listStyle = doc.theme.word.list;
1417
+ const format = doc.theme.word.paragraph.format;
1418
+ const lineSpacing = format.lineSpacingType === "multiple" ? { line: Math.round(format.lineSpacing * 240), lineRule: LineRuleType.AUTO } : { line: Math.round(format.lineSpacing * 20), lineRule: LineRuleType.EXACT };
1419
+ items.forEach((item, index) => {
1420
+ const bullet = ordered ? `${index + 1}. ` : "\u2022 ";
1421
+ const paragraph = new Paragraph({
1422
+ children: [
1423
+ new TextRun({
1424
+ text: bullet + item,
1425
+ size: listStyle.fontSize,
1426
+ font: listStyle.font
1427
+ })
1428
+ ],
1429
+ indent: { left: listStyle.indent },
1430
+ spacing: {
1431
+ ...lineSpacing,
1432
+ after: listStyle.spacing * 20
1433
+ // 磅转 twips
1434
+ }
1435
+ });
1436
+ doc.children.push(paragraph);
1437
+ });
1438
+ return { success: true, message: `\u5DF2\u6DFB\u52A0 ${items.length} \u9879${ordered ? "\u6709\u5E8F" : "\u65E0\u5E8F"}\u5217\u8868` };
1439
+ }
1440
+ function wordAddCode(args) {
1441
+ const { docId, code, language = "" } = args;
1442
+ const doc = documents.get(docId);
1443
+ if (!doc) {
1444
+ return { success: false, message: `\u6587\u6863 ${docId} \u4E0D\u5B58\u5728` };
1445
+ }
1446
+ const codeStyle = doc.theme.word.code;
1447
+ if (language) {
1448
+ doc.children.push(
1449
+ new Paragraph({
1450
+ children: [
1451
+ new TextRun({
1452
+ text: language,
1453
+ size: 18,
1454
+ color: "888888",
1455
+ font: codeStyle.font
1456
+ })
1457
+ ],
1458
+ spacing: { after: 0 }
1459
+ })
1460
+ );
1461
+ }
1462
+ const lines = code.split("\n");
1463
+ lines.forEach((line) => {
1464
+ doc.children.push(
1465
+ new Paragraph({
1466
+ children: [
1467
+ new TextRun({
1468
+ text: line || " ",
1469
+ font: codeStyle.font,
1470
+ size: codeStyle.fontSize
1471
+ })
1472
+ ],
1473
+ shading: { type: ShadingType.SOLID, color: codeStyle.background },
1474
+ spacing: { after: 0, line: 280, lineRule: LineRuleType.AUTO },
1475
+ indent: { left: 360 },
1476
+ border: {
1477
+ left: { style: BorderStyle.SINGLE, size: 1, color: codeStyle.borderColor }
1478
+ }
1479
+ })
1480
+ );
1481
+ });
1482
+ doc.children.push(new Paragraph({ children: [], spacing: { after: 200 } }));
1483
+ return { success: true, message: `\u5DF2\u6DFB\u52A0\u4EE3\u7801\u5757 (${language || "\u65E0\u8BED\u8A00\u6807\u8BB0"})` };
1484
+ }
1485
+ var mermaidThemes = {
1486
+ // 专业蓝 - 适合技术文档
1487
+ professional: `%%{init: {
1488
+ 'theme': 'base',
1489
+ 'themeVariables': {
1490
+ 'primaryColor': '#4a90d9',
1491
+ 'primaryTextColor': '#ffffff',
1492
+ 'primaryBorderColor': '#2d6cb5',
1493
+ 'secondaryColor': '#e8f4fc',
1494
+ 'tertiaryColor': '#f5f9fc',
1495
+ 'lineColor': '#5c6bc0',
1496
+ 'textColor': '#333333',
1497
+ 'fontSize': '14px',
1498
+ 'fontFamily': 'Microsoft YaHei, Arial, sans-serif'
1499
+ }
1500
+ }}%%`,
1501
+ // 清新绿 - 适合流程图
1502
+ fresh: `%%{init: {
1503
+ 'theme': 'base',
1504
+ 'themeVariables': {
1505
+ 'primaryColor': '#52c41a',
1506
+ 'primaryTextColor': '#ffffff',
1507
+ 'primaryBorderColor': '#389e0d',
1508
+ 'secondaryColor': '#f6ffed',
1509
+ 'tertiaryColor': '#d9f7be',
1510
+ 'lineColor': '#73d13d',
1511
+ 'textColor': '#333333',
1512
+ 'fontSize': '14px',
1513
+ 'fontFamily': 'Microsoft YaHei, Arial, sans-serif'
1514
+ }
1515
+ }}%%`,
1516
+ // 商务灰 - 适合正式报告
1517
+ business: `%%{init: {
1518
+ 'theme': 'base',
1519
+ 'themeVariables': {
1520
+ 'primaryColor': '#595959',
1521
+ 'primaryTextColor': '#ffffff',
1522
+ 'primaryBorderColor': '#434343',
1523
+ 'secondaryColor': '#fafafa',
1524
+ 'tertiaryColor': '#f0f0f0',
1525
+ 'lineColor': '#8c8c8c',
1526
+ 'textColor': '#262626',
1527
+ 'fontSize': '14px',
1528
+ 'fontFamily': 'Microsoft YaHei, Arial, sans-serif'
1529
+ }
1530
+ }}%%`,
1531
+ // 科技紫 - 适合产品文档
1532
+ tech: `%%{init: {
1533
+ 'theme': 'base',
1534
+ 'themeVariables': {
1535
+ 'primaryColor': '#722ed1',
1536
+ 'primaryTextColor': '#ffffff',
1537
+ 'primaryBorderColor': '#531dab',
1538
+ 'secondaryColor': '#f9f0ff',
1539
+ 'tertiaryColor': '#efdbff',
1540
+ 'lineColor': '#9254de',
1541
+ 'textColor': '#333333',
1542
+ 'fontSize': '14px',
1543
+ 'fontFamily': 'Microsoft YaHei, Arial, sans-serif'
1544
+ }
1545
+ }}%%`,
1546
+ // 暖橙色 - 适合产品方案
1547
+ warm: `%%{init: {
1548
+ 'theme': 'base',
1549
+ 'themeVariables': {
1550
+ 'primaryColor': '#fa8c16',
1551
+ 'primaryTextColor': '#ffffff',
1552
+ 'primaryBorderColor': '#d46b08',
1553
+ 'secondaryColor': '#fff7e6',
1554
+ 'tertiaryColor': '#ffe7ba',
1555
+ 'lineColor': '#ffa940',
1556
+ 'textColor': '#333333',
1557
+ 'fontSize': '14px',
1558
+ 'fontFamily': 'Microsoft YaHei, Arial, sans-serif'
1559
+ }
1560
+ }}%%`,
1561
+ // 默认 - Mermaid 原生
1562
+ default: ""
1563
+ };
1564
+ async function mermaidToImage(mermaidCode, theme = "professional") {
1565
+ const themeConfig = mermaidThemes[theme] || mermaidThemes.professional;
1566
+ const cleanCode = mermaidCode.trim();
1567
+ const fullCode = themeConfig ? `${themeConfig}
1568
+ ${cleanCode}` : cleanCode;
1569
+ return new Promise((resolve, reject) => {
1570
+ const postData = fullCode;
1571
+ const options = {
1572
+ hostname: "kroki.io",
1573
+ port: 443,
1574
+ path: "/mermaid/png",
1575
+ method: "POST",
1576
+ headers: {
1577
+ "Content-Type": "text/plain",
1578
+ "Content-Length": Buffer.byteLength(postData, "utf-8")
1579
+ }
1580
+ };
1581
+ const req = https.request(options, (res) => {
1582
+ if (res.statusCode !== 200) {
1583
+ let errorBody = "";
1584
+ res.on("data", (chunk) => errorBody += chunk);
1585
+ res.on("end", () => {
1586
+ reject(new Error(`Mermaid \u6E32\u67D3\u5931\u8D25: HTTP ${res.statusCode}, ${errorBody.slice(0, 100)}`));
1587
+ });
1588
+ return;
1589
+ }
1590
+ const chunks = [];
1591
+ res.on("data", (chunk) => chunks.push(chunk));
1592
+ res.on("end", () => resolve(Buffer.concat(chunks)));
1593
+ res.on("error", reject);
1594
+ });
1595
+ req.on("error", reject);
1596
+ req.write(postData);
1597
+ req.end();
1598
+ });
1599
+ }
1600
+ function getPngDimensions(buffer) {
1601
+ if (buffer.length < 24 || buffer[0] !== 137 || buffer[1] !== 80) {
1602
+ return { width: 800, height: 400 };
1603
+ }
1604
+ const width = buffer.readUInt32BE(16);
1605
+ const height = buffer.readUInt32BE(20);
1606
+ return { width, height };
1607
+ }
1608
+ async function wordAddDiagram(args) {
1609
+ const {
1610
+ docId,
1611
+ mermaid: mermaidCode,
1612
+ caption,
1613
+ width: targetWidthCm = 15,
1614
+ theme = "default"
1615
+ } = args;
1616
+ const doc = documents.get(docId);
1617
+ if (!doc) {
1618
+ return { success: false, message: `\u6587\u6863 ${docId} \u4E0D\u5B58\u5728` };
1619
+ }
1620
+ try {
1621
+ const imageBuffer = await mermaidToImage(mermaidCode, theme);
1622
+ const { width: origWidth, height: origHeight } = getPngDimensions(imageBuffer);
1623
+ const targetWidthPx = Math.round(targetWidthCm * 37.8);
1624
+ const scale = targetWidthPx / origWidth;
1625
+ const targetHeightPx = Math.round(origHeight * scale);
1626
+ const imageParagraph = new Paragraph({
1627
+ children: [
1628
+ new ImageRun({
1629
+ data: imageBuffer,
1630
+ transformation: {
1631
+ width: targetWidthPx,
1632
+ height: targetHeightPx
1633
+ },
1634
+ type: "png"
1635
+ })
1636
+ ],
1637
+ alignment: AlignmentType.CENTER,
1638
+ spacing: { before: 200, after: 100 }
1639
+ });
1640
+ doc.children.push(imageParagraph);
1641
+ if (caption) {
1642
+ const captionParagraph = new Paragraph({
1643
+ children: [
1644
+ new TextRun({
1645
+ text: caption,
1646
+ size: 21,
1647
+ // 五号字
1648
+ color: "666666",
1649
+ font: doc.theme.word.fonts.body
1650
+ })
1651
+ ],
1652
+ alignment: AlignmentType.CENTER,
1653
+ spacing: { after: 200 }
1654
+ });
1655
+ doc.children.push(captionParagraph);
1656
+ }
1657
+ return { success: true, message: `\u5DF2\u6DFB\u52A0 Mermaid \u56FE\u8868${caption ? `: ${caption}` : ""}` };
1658
+ } catch (error) {
1659
+ const errMsg = error instanceof Error ? error.message : String(error);
1660
+ return { success: false, message: `Mermaid \u56FE\u8868\u6E32\u67D3\u5931\u8D25: ${errMsg}` };
1661
+ }
1662
+ }
1663
+ async function wordSave(args) {
1664
+ const { docId, addPageNumbers = false, addHeader, addFooter } = args;
1665
+ const doc = documents.get(docId);
1666
+ if (!doc) {
1667
+ return { success: false, message: `\u6587\u6863 ${docId} \u4E0D\u5B58\u5728` };
1668
+ }
1669
+ const pageLayout = doc.theme.pageLayout;
1670
+ const headers = addHeader ? {
1671
+ default: new Header({
1672
+ children: [
1673
+ new Paragraph({
1674
+ children: [new TextRun({ text: addHeader, color: "888888", size: 18 })],
1675
+ alignment: AlignmentType.RIGHT
1676
+ })
1677
+ ]
1678
+ })
1679
+ } : void 0;
1680
+ const footers = addFooter || addPageNumbers ? {
1681
+ default: new Footer({
1682
+ children: [
1683
+ new Paragraph({
1684
+ children: [
1685
+ ...addFooter ? [new TextRun({ text: addFooter, color: "888888", size: 18 })] : [],
1686
+ ...addPageNumbers ? [
1687
+ new TextRun({ text: addFooter ? " | \u7B2C " : "\u7B2C ", color: "888888", size: 18 }),
1688
+ new TextRun({
1689
+ children: [PageNumber.CURRENT],
1690
+ color: "888888",
1691
+ size: 18
1692
+ }),
1693
+ new TextRun({ text: " \u9875", color: "888888", size: 18 })
1694
+ ] : []
1695
+ ],
1696
+ alignment: AlignmentType.CENTER
1697
+ })
1698
+ ]
1699
+ })
1700
+ } : void 0;
1701
+ const document = new Document({
1702
+ creator: doc.author || "Office MCP Server",
1703
+ title: doc.title,
1704
+ sections: [
1705
+ {
1706
+ properties: {
1707
+ page: {
1708
+ margin: {
1709
+ top: pageLayout.marginTop,
1710
+ bottom: pageLayout.marginBottom,
1711
+ left: pageLayout.marginLeft,
1712
+ right: pageLayout.marginRight
1713
+ }
1714
+ }
1715
+ },
1716
+ headers,
1717
+ footers,
1718
+ children: doc.children
1719
+ }
1720
+ ]
1721
+ });
1722
+ const dir = path.dirname(doc.outputPath);
1723
+ if (!fs.existsSync(dir)) {
1724
+ fs.mkdirSync(dir, { recursive: true });
1725
+ }
1726
+ const buffer = await Packer.toBuffer(document);
1727
+ fs.writeFileSync(doc.outputPath, buffer);
1728
+ documents.delete(docId);
1729
+ return {
1730
+ success: true,
1731
+ message: `\u6587\u6863\u5DF2\u4FDD\u5B58\u81F3: ${doc.outputPath}`,
1732
+ path: doc.outputPath
1733
+ };
1734
+ }
1735
+ async function handleWordTool(name, args) {
1736
+ let result;
1737
+ switch (name) {
1738
+ case "word_create":
1739
+ result = wordCreate(args);
1740
+ break;
1741
+ case "word_add_heading":
1742
+ result = wordAddHeading(args);
1743
+ break;
1744
+ case "word_add_paragraph":
1745
+ result = wordAddParagraph(args);
1746
+ break;
1747
+ case "word_add_table":
1748
+ result = wordAddTable(args);
1749
+ break;
1750
+ case "word_add_list":
1751
+ result = wordAddList(args);
1752
+ break;
1753
+ case "word_add_code":
1754
+ result = wordAddCode(args);
1755
+ break;
1756
+ case "word_add_diagram":
1757
+ result = await wordAddDiagram(args);
1758
+ break;
1759
+ case "word_save":
1760
+ result = await wordSave(args);
1761
+ break;
1762
+ default:
1763
+ result = { success: false, message: `\u672A\u77E5\u7684 Word \u5DE5\u5177: ${name}` };
1764
+ }
1765
+ return {
1766
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
1767
+ };
1768
+ }
1769
+
1770
+ // src/tools/excel/index.ts
1771
+ import ExcelJS from "exceljs";
1772
+ import * as fs2 from "fs";
1773
+ import * as path2 from "path";
1774
+ var workbooks = /* @__PURE__ */ new Map();
1775
+ function generateId2() {
1776
+ return `excel_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
1777
+ }
1778
+ var excelTools = [
1779
+ {
1780
+ name: "excel_create",
1781
+ description: "\u521B\u5EFA Excel \u5DE5\u4F5C\u7C3F",
1782
+ inputSchema: {
1783
+ type: "object",
1784
+ properties: {
1785
+ title: { type: "string", description: "\u5DE5\u4F5C\u7C3F\u6807\u9898" },
1786
+ template: {
1787
+ type: "string",
1788
+ enum: ["data-report", "project-tracker", "budget", "blank"],
1789
+ description: "\u4F7F\u7528\u7684\u6A21\u677F"
1790
+ },
1791
+ theme: {
1792
+ type: "string",
1793
+ enum: ["alibaba", "tencent", "bytedance", "default"],
1794
+ description: "\u4E3B\u9898\u98CE\u683C"
1795
+ },
1796
+ outputPath: { type: "string", description: "\u8F93\u51FA\u8DEF\u5F84" }
1797
+ },
1798
+ required: ["title", "outputPath"]
1799
+ }
1800
+ },
1801
+ {
1802
+ name: "excel_add_sheet",
1803
+ description: "\u6DFB\u52A0\u5DE5\u4F5C\u8868",
1804
+ inputSchema: {
1805
+ type: "object",
1806
+ properties: {
1807
+ workbookId: { type: "string", description: "\u5DE5\u4F5C\u7C3FID" },
1808
+ sheetName: { type: "string", description: "\u5DE5\u4F5C\u8868\u540D\u79F0" },
1809
+ tabColor: { type: "string", description: "\u6807\u7B7E\u989C\u8272\uFF08\u5982 FF0000\uFF09" }
1810
+ },
1811
+ required: ["workbookId", "sheetName"]
1812
+ }
1813
+ },
1814
+ {
1815
+ name: "excel_write_data",
1816
+ description: "\u5199\u5165\u8868\u683C\u6570\u636E",
1817
+ inputSchema: {
1818
+ type: "object",
1819
+ properties: {
1820
+ workbookId: { type: "string", description: "\u5DE5\u4F5C\u7C3FID" },
1821
+ sheetName: { type: "string", description: "\u5DE5\u4F5C\u8868\u540D\u79F0" },
1822
+ headers: { type: "array", items: { type: "string" }, description: "\u8868\u5934" },
1823
+ rows: { type: "array", items: { type: "array" }, description: "\u6570\u636E\u884C" },
1824
+ startCell: { type: "string", description: "\u8D77\u59CB\u5355\u5143\u683C\uFF0C\u9ED8\u8BA4A1" },
1825
+ autoFilter: { type: "boolean", description: "\u662F\u5426\u6DFB\u52A0\u7B5B\u9009" },
1826
+ freezeHeader: { type: "boolean", description: "\u662F\u5426\u51BB\u7ED3\u9996\u884C" },
1827
+ style: {
1828
+ type: "string",
1829
+ enum: ["striped", "bordered", "professional", "minimal"],
1830
+ description: "\u8868\u683C\u6837\u5F0F"
1831
+ }
1832
+ },
1833
+ required: ["workbookId", "sheetName", "headers", "rows"]
1834
+ }
1835
+ },
1836
+ {
1837
+ name: "excel_add_chart",
1838
+ description: "\u6DFB\u52A0\u56FE\u8868",
1839
+ inputSchema: {
1840
+ type: "object",
1841
+ properties: {
1842
+ workbookId: { type: "string", description: "\u5DE5\u4F5C\u7C3FID" },
1843
+ sheetName: { type: "string", description: "\u5DE5\u4F5C\u8868\u540D\u79F0" },
1844
+ chartType: {
1845
+ type: "string",
1846
+ enum: ["bar", "column", "line", "pie", "doughnut", "area"],
1847
+ description: "\u56FE\u8868\u7C7B\u578B"
1848
+ },
1849
+ title: { type: "string", description: "\u56FE\u8868\u6807\u9898" },
1850
+ categories: { type: "array", items: { type: "string" }, description: "\u5206\u7C7B\u6807\u7B7E" },
1851
+ series: {
1852
+ type: "array",
1853
+ items: {
1854
+ type: "object",
1855
+ properties: {
1856
+ name: { type: "string" },
1857
+ values: { type: "array", items: { type: "number" } }
1858
+ }
1859
+ },
1860
+ description: "\u6570\u636E\u7CFB\u5217"
1861
+ },
1862
+ position: { type: "string", description: "\u56FE\u8868\u4F4D\u7F6E\uFF0C\u5982 F2" }
1863
+ },
1864
+ required: ["workbookId", "sheetName", "chartType", "categories", "series"]
1865
+ }
1866
+ },
1867
+ {
1868
+ name: "excel_add_formula",
1869
+ description: "\u6DFB\u52A0\u516C\u5F0F",
1870
+ inputSchema: {
1871
+ type: "object",
1872
+ properties: {
1873
+ workbookId: { type: "string", description: "\u5DE5\u4F5C\u7C3FID" },
1874
+ sheetName: { type: "string", description: "\u5DE5\u4F5C\u8868\u540D\u79F0" },
1875
+ cell: { type: "string", description: "\u5355\u5143\u683C\u4F4D\u7F6E" },
1876
+ formula: { type: "string", description: "\u516C\u5F0F\uFF0C\u5982 SUM(A1:A10)" }
1877
+ },
1878
+ required: ["workbookId", "sheetName", "cell", "formula"]
1879
+ }
1880
+ },
1881
+ {
1882
+ name: "excel_set_column_width",
1883
+ description: "\u8BBE\u7F6E\u5217\u5BBD",
1884
+ inputSchema: {
1885
+ type: "object",
1886
+ properties: {
1887
+ workbookId: { type: "string", description: "\u5DE5\u4F5C\u7C3FID" },
1888
+ sheetName: { type: "string", description: "\u5DE5\u4F5C\u8868\u540D\u79F0" },
1889
+ columns: {
1890
+ type: "object",
1891
+ description: '\u5217\u5BBD\u6620\u5C04\uFF0C\u5982 { "A": 20, "B": 30 }'
1892
+ }
1893
+ },
1894
+ required: ["workbookId", "sheetName", "columns"]
1895
+ }
1896
+ },
1897
+ {
1898
+ name: "excel_merge_cells",
1899
+ description: "\u5408\u5E76\u5355\u5143\u683C",
1900
+ inputSchema: {
1901
+ type: "object",
1902
+ properties: {
1903
+ workbookId: { type: "string", description: "\u5DE5\u4F5C\u7C3FID" },
1904
+ sheetName: { type: "string", description: "\u5DE5\u4F5C\u8868\u540D\u79F0" },
1905
+ range: { type: "string", description: "\u5355\u5143\u683C\u8303\u56F4\uFF0C\u5982 A1:C1" }
1906
+ },
1907
+ required: ["workbookId", "sheetName", "range"]
1908
+ }
1909
+ },
1910
+ {
1911
+ name: "excel_save",
1912
+ description: "\u4FDD\u5B58\u5DE5\u4F5C\u7C3F",
1913
+ inputSchema: {
1914
+ type: "object",
1915
+ properties: {
1916
+ workbookId: { type: "string", description: "\u5DE5\u4F5C\u7C3FID" }
1917
+ },
1918
+ required: ["workbookId"]
1919
+ }
1920
+ }
1921
+ ];
1922
+ function excelCreate(args) {
1923
+ const { title, theme = "default", outputPath } = args;
1924
+ const id = generateId2();
1925
+ const themeConfig = getTheme(theme);
1926
+ const workbook = new ExcelJS.Workbook();
1927
+ workbook.creator = "Office MCP Server";
1928
+ workbook.created = /* @__PURE__ */ new Date();
1929
+ workbook.title = title;
1930
+ workbooks.set(id, {
1931
+ workbook,
1932
+ outputPath,
1933
+ theme: themeConfig,
1934
+ title
1935
+ });
1936
+ return {
1937
+ success: true,
1938
+ workbookId: id,
1939
+ message: `\u5DE5\u4F5C\u7C3F "${title}" \u521B\u5EFA\u6210\u529F\uFF0C\u4E3B\u9898: ${themeConfig.displayName}`
1940
+ };
1941
+ }
1942
+ function excelAddSheet(args) {
1943
+ const { workbookId, sheetName, tabColor } = args;
1944
+ const entry = workbooks.get(workbookId);
1945
+ if (!entry) {
1946
+ return { success: false, message: `\u5DE5\u4F5C\u7C3F ${workbookId} \u4E0D\u5B58\u5728` };
1947
+ }
1948
+ const sheet = entry.workbook.addWorksheet(sheetName);
1949
+ if (tabColor) {
1950
+ sheet.properties.tabColor = { argb: `FF${tabColor}` };
1951
+ }
1952
+ return { success: true, message: `\u5DF2\u6DFB\u52A0\u5DE5\u4F5C\u8868: ${sheetName}` };
1953
+ }
1954
+ function excelWriteData(args) {
1955
+ const {
1956
+ workbookId,
1957
+ sheetName,
1958
+ headers,
1959
+ rows,
1960
+ startCell = "A1",
1961
+ autoFilter = false,
1962
+ freezeHeader = false,
1963
+ style = "professional"
1964
+ } = args;
1965
+ const entry = workbooks.get(workbookId);
1966
+ if (!entry) {
1967
+ return { success: false, message: `\u5DE5\u4F5C\u7C3F ${workbookId} \u4E0D\u5B58\u5728` };
1968
+ }
1969
+ let sheet = entry.workbook.getWorksheet(sheetName);
1970
+ if (!sheet) {
1971
+ sheet = entry.workbook.addWorksheet(sheetName);
1972
+ }
1973
+ const themeStyle = entry.theme.excel;
1974
+ const startMatch = startCell.match(/^([A-Z]+)(\d+)$/);
1975
+ const startCol = startMatch ? startMatch[1].charCodeAt(0) - 64 : 1;
1976
+ const startRow = startMatch ? parseInt(startMatch[2]) : 1;
1977
+ const headerRow = sheet.getRow(startRow);
1978
+ headers.forEach((header, index) => {
1979
+ const cell = headerRow.getCell(startCol + index);
1980
+ cell.value = header;
1981
+ cell.font = {
1982
+ bold: themeStyle.headerRow.bold,
1983
+ color: { argb: `FF${themeStyle.headerRow.fontColor}` }
1984
+ };
1985
+ cell.fill = {
1986
+ type: "pattern",
1987
+ pattern: "solid",
1988
+ fgColor: { argb: `FF${themeStyle.headerRow.fill}` }
1989
+ };
1990
+ cell.alignment = { horizontal: "center", vertical: "middle" };
1991
+ if (style !== "minimal") {
1992
+ cell.border = {
1993
+ top: { style: "thin", color: { argb: `FF${themeStyle.border.color}` } },
1994
+ bottom: { style: "thin", color: { argb: `FF${themeStyle.border.color}` } },
1995
+ left: { style: "thin", color: { argb: `FF${themeStyle.border.color}` } },
1996
+ right: { style: "thin", color: { argb: `FF${themeStyle.border.color}` } }
1997
+ };
1998
+ }
1999
+ });
2000
+ headerRow.height = 25;
2001
+ rows.forEach((row, rowIndex) => {
2002
+ const dataRow = sheet.getRow(startRow + 1 + rowIndex);
2003
+ row.forEach((value, colIndex) => {
2004
+ const cell = dataRow.getCell(startCol + colIndex);
2005
+ cell.value = value;
2006
+ if (style === "striped" && rowIndex % 2 === 1) {
2007
+ cell.fill = {
2008
+ type: "pattern",
2009
+ pattern: "solid",
2010
+ fgColor: { argb: `FF${themeStyle.alternateRow.fill}` }
2011
+ };
2012
+ }
2013
+ if (style !== "minimal") {
2014
+ cell.border = {
2015
+ top: { style: "thin", color: { argb: `FF${themeStyle.border.color}` } },
2016
+ bottom: { style: "thin", color: { argb: `FF${themeStyle.border.color}` } },
2017
+ left: { style: "thin", color: { argb: `FF${themeStyle.border.color}` } },
2018
+ right: { style: "thin", color: { argb: `FF${themeStyle.border.color}` } }
2019
+ };
2020
+ }
2021
+ });
2022
+ });
2023
+ headers.forEach((_, index) => {
2024
+ const column = sheet.getColumn(startCol + index);
2025
+ column.width = 15;
2026
+ });
2027
+ if (freezeHeader) {
2028
+ sheet.views = [{ state: "frozen", ySplit: startRow }];
2029
+ }
2030
+ if (autoFilter) {
2031
+ const endCol = String.fromCharCode(64 + startCol + headers.length - 1);
2032
+ const endRow = startRow + rows.length;
2033
+ sheet.autoFilter = `${startCell}:${endCol}${endRow}`;
2034
+ }
2035
+ return {
2036
+ success: true,
2037
+ message: `\u5DF2\u5199\u5165 ${headers.length} \u5217 ${rows.length} \u884C\u6570\u636E`
2038
+ };
2039
+ }
2040
+ function excelAddChart(args) {
2041
+ const { workbookId, sheetName, chartType, title, categories, series, position = "F2" } = args;
2042
+ const entry = workbooks.get(workbookId);
2043
+ if (!entry) {
2044
+ return { success: false, message: `\u5DE5\u4F5C\u7C3F ${workbookId} \u4E0D\u5B58\u5728` };
2045
+ }
2046
+ const sheet = entry.workbook.getWorksheet(sheetName);
2047
+ if (!sheet) {
2048
+ return { success: false, message: `\u5DE5\u4F5C\u8868 ${sheetName} \u4E0D\u5B58\u5728` };
2049
+ }
2050
+ const posMatch = position.match(/^([A-Z]+)(\d+)$/);
2051
+ const posCol = posMatch ? posMatch[1].charCodeAt(0) - 64 : 6;
2052
+ const posRow = posMatch ? parseInt(posMatch[2]) : 2;
2053
+ if (title) {
2054
+ const titleCell = sheet.getCell(posRow, posCol);
2055
+ titleCell.value = `\u{1F4CA} ${title}`;
2056
+ titleCell.font = { bold: true, size: 14 };
2057
+ }
2058
+ const dataStartRow = posRow + (title ? 2 : 1);
2059
+ const headerRow = sheet.getRow(dataStartRow);
2060
+ headerRow.getCell(posCol).value = "\u5206\u7C7B";
2061
+ series.forEach((s, i) => {
2062
+ headerRow.getCell(posCol + 1 + i).value = s.name;
2063
+ });
2064
+ categories.forEach((cat, catIndex) => {
2065
+ const row = sheet.getRow(dataStartRow + 1 + catIndex);
2066
+ row.getCell(posCol).value = cat;
2067
+ series.forEach((s, seriesIndex) => {
2068
+ row.getCell(posCol + 1 + seriesIndex).value = s.values[catIndex];
2069
+ });
2070
+ });
2071
+ return {
2072
+ success: true,
2073
+ message: `\u56FE\u8868\u6570\u636E\u5DF2\u5199\u5165\uFF08${chartType} \u7C7B\u578B\uFF09\uFF0C\u8BF7\u5728 Excel \u4E2D\u9009\u62E9\u6570\u636E\u521B\u5EFA\u56FE\u8868`,
2074
+ note: "exceljs \u4E0D\u652F\u6301\u76F4\u63A5\u521B\u5EFA\u56FE\u8868\uFF0C\u6570\u636E\u5DF2\u51C6\u5907\u597D\u4F9B\u624B\u52A8\u521B\u5EFA\u56FE\u8868\u4F7F\u7528"
2075
+ };
2076
+ }
2077
+ function excelAddFormula(args) {
2078
+ const { workbookId, sheetName, cell, formula } = args;
2079
+ const entry = workbooks.get(workbookId);
2080
+ if (!entry) {
2081
+ return { success: false, message: `\u5DE5\u4F5C\u7C3F ${workbookId} \u4E0D\u5B58\u5728` };
2082
+ }
2083
+ const sheet = entry.workbook.getWorksheet(sheetName);
2084
+ if (!sheet) {
2085
+ return { success: false, message: `\u5DE5\u4F5C\u8868 ${sheetName} \u4E0D\u5B58\u5728` };
2086
+ }
2087
+ const cleanFormula = formula.startsWith("=") ? formula.slice(1) : formula;
2088
+ const targetCell = sheet.getCell(cell);
2089
+ targetCell.value = { formula: cleanFormula };
2090
+ return { success: true, message: `\u5DF2\u5728 ${cell} \u6DFB\u52A0\u516C\u5F0F: =${cleanFormula}` };
2091
+ }
2092
+ function excelSetColumnWidth(args) {
2093
+ const { workbookId, sheetName, columns } = args;
2094
+ const entry = workbooks.get(workbookId);
2095
+ if (!entry) {
2096
+ return { success: false, message: `\u5DE5\u4F5C\u7C3F ${workbookId} \u4E0D\u5B58\u5728` };
2097
+ }
2098
+ const sheet = entry.workbook.getWorksheet(sheetName);
2099
+ if (!sheet) {
2100
+ return { success: false, message: `\u5DE5\u4F5C\u8868 ${sheetName} \u4E0D\u5B58\u5728` };
2101
+ }
2102
+ Object.entries(columns).forEach(([col, width]) => {
2103
+ const column = sheet.getColumn(col);
2104
+ column.width = width;
2105
+ });
2106
+ return { success: true, message: `\u5DF2\u8BBE\u7F6E ${Object.keys(columns).length} \u5217\u7684\u5BBD\u5EA6` };
2107
+ }
2108
+ function excelMergeCells(args) {
2109
+ const { workbookId, sheetName, range } = args;
2110
+ const entry = workbooks.get(workbookId);
2111
+ if (!entry) {
2112
+ return { success: false, message: `\u5DE5\u4F5C\u7C3F ${workbookId} \u4E0D\u5B58\u5728` };
2113
+ }
2114
+ const sheet = entry.workbook.getWorksheet(sheetName);
2115
+ if (!sheet) {
2116
+ return { success: false, message: `\u5DE5\u4F5C\u8868 ${sheetName} \u4E0D\u5B58\u5728` };
2117
+ }
2118
+ sheet.mergeCells(range);
2119
+ return { success: true, message: `\u5DF2\u5408\u5E76\u5355\u5143\u683C: ${range}` };
2120
+ }
2121
+ async function excelSave(args) {
2122
+ const { workbookId } = args;
2123
+ const entry = workbooks.get(workbookId);
2124
+ if (!entry) {
2125
+ return { success: false, message: `\u5DE5\u4F5C\u7C3F ${workbookId} \u4E0D\u5B58\u5728` };
2126
+ }
2127
+ const dir = path2.dirname(entry.outputPath);
2128
+ if (!fs2.existsSync(dir)) {
2129
+ fs2.mkdirSync(dir, { recursive: true });
2130
+ }
2131
+ await entry.workbook.xlsx.writeFile(entry.outputPath);
2132
+ workbooks.delete(workbookId);
2133
+ return {
2134
+ success: true,
2135
+ message: `\u5DE5\u4F5C\u7C3F\u5DF2\u4FDD\u5B58\u81F3: ${entry.outputPath}`,
2136
+ path: entry.outputPath
2137
+ };
2138
+ }
2139
+ async function handleExcelTool(name, args) {
2140
+ let result;
2141
+ switch (name) {
2142
+ case "excel_create":
2143
+ result = excelCreate(args);
2144
+ break;
2145
+ case "excel_add_sheet":
2146
+ result = excelAddSheet(args);
2147
+ break;
2148
+ case "excel_write_data":
2149
+ result = excelWriteData(args);
2150
+ break;
2151
+ case "excel_add_chart":
2152
+ result = excelAddChart(args);
2153
+ break;
2154
+ case "excel_add_formula":
2155
+ result = excelAddFormula(args);
2156
+ break;
2157
+ case "excel_set_column_width":
2158
+ result = excelSetColumnWidth(args);
2159
+ break;
2160
+ case "excel_merge_cells":
2161
+ result = excelMergeCells(args);
2162
+ break;
2163
+ case "excel_save":
2164
+ result = await excelSave(args);
2165
+ break;
2166
+ default:
2167
+ result = { success: false, message: `\u672A\u77E5\u7684 Excel \u5DE5\u5177: ${name}` };
2168
+ }
2169
+ return {
2170
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
2171
+ };
2172
+ }
2173
+
2174
+ // src/index.ts
2175
+ var server = new Server(
2176
+ {
2177
+ name: "office-mcp-server",
2178
+ version: "0.1.0"
2179
+ },
2180
+ {
2181
+ capabilities: {
2182
+ tools: {}
2183
+ }
2184
+ }
2185
+ );
2186
+ server.setRequestHandler(ListToolsRequestSchema, async () => {
2187
+ return {
2188
+ tools: [...wordTools, ...excelTools]
2189
+ };
2190
+ });
2191
+ server.setRequestHandler(CallToolRequestSchema, async (request2) => {
2192
+ const { name, arguments: args = {} } = request2.params;
2193
+ if (name.startsWith("word_")) {
2194
+ return handleWordTool(name, args);
2195
+ }
2196
+ if (name.startsWith("excel_")) {
2197
+ return handleExcelTool(name, args);
2198
+ }
2199
+ throw new Error(`Unknown tool: ${name}`);
2200
+ });
2201
+ async function main() {
2202
+ const transport = new StdioServerTransport();
2203
+ await server.connect(transport);
2204
+ console.error("Office MCP Server started");
2205
+ }
2206
+ main().catch((err) => {
2207
+ console.error("Failed to start server:", err);
2208
+ process.exit(1);
2209
+ });