@8btc/ppt-generator-mcp 0.0.30 → 0.0.31-beta.1
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/export-pptx.js +16 -20
- package/dist/index.d.ts +1 -1
- package/dist/index.js +93 -192
- package/dist/index1.d.ts +2 -0
- package/dist/index1.js +198 -0
- package/dist/server.d.ts +6 -0
- package/dist/server.js +90 -0
- package/dist/services/index.d.ts +3 -0
- package/dist/services/index.js +9 -0
- package/dist/services/sse.d.ts +2 -0
- package/dist/services/sse.js +44 -0
- package/dist/services/stdio.d.ts +2 -0
- package/dist/services/stdio.js +8 -0
- package/dist/services/streamable.d.ts +2 -0
- package/dist/services/streamable.js +55 -0
- package/dist/tools/export-pptx.d.ts +6 -0
- package/dist/tools/export-pptx.js +876 -0
- package/dist/tools/generate-ppt-slides.d.ts +10 -0
- package/dist/tools/generate-ppt-slides.js +583 -0
- package/dist/tools/generate-ppt.d.ts +230 -0
- package/dist/tools/generate-ppt.js +144 -0
- package/dist/tools/get-ppt-template-list.d.ts +25 -0
- package/dist/tools/get-ppt-template-list.js +73 -0
- package/dist/tools/getPptTemplateList.d.ts +25 -0
- package/dist/tools/getPptTemplateList.js +78 -0
- package/dist/tools/index.d.ts +3 -0
- package/dist/tools/index.js +9 -0
- package/dist/tools/ppt-generator.d.ts +29 -0
- package/dist/tools/ppt-generator.js +60 -0
- package/dist/tools/pptGenerator/export-pptx.d.ts +6 -0
- package/dist/tools/pptGenerator/export-pptx.js +880 -0
- package/dist/tools/pptGenerator/generate-ppt-slides.d.ts +10 -0
- package/dist/tools/pptGenerator/generate-ppt-slides.js +589 -0
- package/dist/tools/pptGenerator/ppt-generator.d.ts +29 -0
- package/dist/tools/pptGenerator/ppt-generator.js +60 -0
- package/dist/tools/update-ppt-image.d.ts +44 -0
- package/dist/tools/update-ppt-image.js +78 -0
- package/dist/tools/update-ppt-outline.d.ts +220 -0
- package/dist/tools/update-ppt-outline.js +113 -0
- package/dist/tools/update-ppt-theme.d.ts +38 -0
- package/dist/tools/update-ppt-theme.js +56 -0
- package/dist/tpls/temp.json +228 -0
- package/dist/tpls/test-img-temp.json +242 -0
- package/dist/utils/logger.js +6 -2
- package/dist/utils/schema.d.ts +7 -0
- package/dist/utils/schema.js +14 -0
- package/dist/utils/validator.d.ts +6 -0
- package/dist/utils/validator.js +13 -0
- package/package.json +16 -3
- package/dist/tpls/tpl-a.json +0 -1
package/dist/export-pptx.js
CHANGED
|
@@ -29,7 +29,7 @@ const exportPPTX = (_slides, ignoreMedia, options) => {
|
|
|
29
29
|
pptx.layout = "A3_V";
|
|
30
30
|
}
|
|
31
31
|
else
|
|
32
|
-
pptx.layout = "LAYOUT_16x9";
|
|
32
|
+
pptx.layout = "LAYOUT_16x9";
|
|
33
33
|
for (const slide of _slides) {
|
|
34
34
|
const pptxSlide = pptx.addSlide();
|
|
35
35
|
if (slide.background) {
|
|
@@ -160,25 +160,21 @@ const exportPPTX = (_slides, ignoreMedia, options) => {
|
|
|
160
160
|
const [start, end] = el.clip.range;
|
|
161
161
|
const [startX, startY] = start;
|
|
162
162
|
const [endX, endY] = end;
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
h: (((endY - startY) / ratioPx2Inch(viewportSize)) * originH) /
|
|
179
|
-
ratioPx2Inch(viewportSize),
|
|
180
|
-
};
|
|
181
|
-
}
|
|
163
|
+
const originW = el.width / ((endX - startX) / ratioPx2Inch(viewportSize));
|
|
164
|
+
const originH = el.height / ((endY - startY) / ratioPx2Inch(viewportSize));
|
|
165
|
+
options.w = originW / ratioPx2Inch(viewportSize);
|
|
166
|
+
options.h = originH / ratioPx2Inch(viewportSize);
|
|
167
|
+
options.sizing = {
|
|
168
|
+
type: "crop",
|
|
169
|
+
x: ((startX / ratioPx2Inch(viewportSize)) * originW) /
|
|
170
|
+
ratioPx2Inch(viewportSize),
|
|
171
|
+
y: ((startY / ratioPx2Inch(viewportSize)) * originH) /
|
|
172
|
+
ratioPx2Inch(viewportSize),
|
|
173
|
+
w: (((endX - startX) / ratioPx2Inch(viewportSize)) * originW) /
|
|
174
|
+
ratioPx2Inch(viewportSize),
|
|
175
|
+
h: (((endY - startY) / ratioPx2Inch(viewportSize)) * originH) /
|
|
176
|
+
ratioPx2Inch(viewportSize),
|
|
177
|
+
};
|
|
182
178
|
}
|
|
183
179
|
pptxSlide.addImage(options);
|
|
184
180
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
2
|
+
export {};
|
package/dist/index.js
CHANGED
|
@@ -1,198 +1,99 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
"use strict";
|
|
3
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
4
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
5
|
-
};
|
|
6
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
const
|
|
8
|
-
const
|
|
9
|
-
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
{
|
|
51
|
-
name: "简约风格模板-莫兰迪色系",
|
|
52
|
-
path: node_path_1.default.join(__dirname, "tpls", "tpl-2.json"),
|
|
53
|
-
},
|
|
54
|
-
{
|
|
55
|
-
name: "简单模板-蓝色调",
|
|
56
|
-
path: node_path_1.default.join(__dirname, "tpls", "tpl-1.json"),
|
|
57
|
-
},
|
|
58
|
-
{
|
|
59
|
-
name: "通用模板-商务风格",
|
|
60
|
-
path: node_path_1.default.join(__dirname, "tpls", "custom-1.json"),
|
|
61
|
-
},
|
|
62
|
-
{
|
|
63
|
-
name: "通用模板-报告风格",
|
|
64
|
-
path: node_path_1.default.join(__dirname, "tpls", "custom-2.json"),
|
|
65
|
-
},
|
|
66
|
-
]),
|
|
67
|
-
},
|
|
68
|
-
],
|
|
69
|
-
};
|
|
70
|
-
});
|
|
71
|
-
this.server.registerTool("generate_ppt", {
|
|
72
|
-
title: "ppt生成工具",
|
|
73
|
-
description: "根据大纲自动匹配模板生成PPT文件",
|
|
74
|
-
inputSchema: {
|
|
75
|
-
templateFilePath: zod_1.z.string().optional(),
|
|
76
|
-
outputPath: zod_1.z.string().optional(),
|
|
77
|
-
outline: zod_1.z.array(zod_1.z.discriminatedUnion("type", [
|
|
78
|
-
zod_1.z.object({
|
|
79
|
-
type: zod_1.z.literal("cover"),
|
|
80
|
-
data: zod_1.z.object({
|
|
81
|
-
title: zod_1.z.string(),
|
|
82
|
-
text: zod_1.z.string(),
|
|
83
|
-
}),
|
|
84
|
-
}),
|
|
85
|
-
zod_1.z.object({
|
|
86
|
-
type: zod_1.z.literal("contents"),
|
|
87
|
-
data: zod_1.z.object({
|
|
88
|
-
items: zod_1.z.array(zod_1.z.string()),
|
|
89
|
-
}),
|
|
90
|
-
offset: zod_1.z.number().optional(),
|
|
91
|
-
}),
|
|
92
|
-
zod_1.z.object({
|
|
93
|
-
type: zod_1.z.literal("transition"),
|
|
94
|
-
data: zod_1.z.object({
|
|
95
|
-
title: zod_1.z.string(),
|
|
96
|
-
text: zod_1.z.string(),
|
|
97
|
-
}),
|
|
98
|
-
}),
|
|
99
|
-
zod_1.z.object({
|
|
100
|
-
type: zod_1.z.literal("content"),
|
|
101
|
-
data: zod_1.z.object({
|
|
102
|
-
title: zod_1.z.string(),
|
|
103
|
-
items: zod_1.z.array(zod_1.z.object({
|
|
104
|
-
title: zod_1.z.string(),
|
|
105
|
-
text: zod_1.z.string(),
|
|
106
|
-
})),
|
|
107
|
-
}),
|
|
108
|
-
}),
|
|
109
|
-
zod_1.z.object({
|
|
110
|
-
type: zod_1.z.literal("end"),
|
|
111
|
-
}),
|
|
112
|
-
])),
|
|
113
|
-
},
|
|
114
|
-
}, async ({ outline, templateFilePath, outputPath }) => {
|
|
115
|
-
logger_js_1.default.info("generate_ppt", { outline, templateFilePath, outputPath });
|
|
116
|
-
if (!templateFilePath) {
|
|
117
|
-
templateFilePath = node_path_1.default.join(__dirname, "tpls", "tpl-2.json");
|
|
118
|
-
}
|
|
119
|
-
// 演示用,固定模版
|
|
120
|
-
templateFilePath = node_path_1.default.join(__dirname, "tpls", "custom-1.json");
|
|
121
|
-
if (!outputPath) {
|
|
122
|
-
outputPath = process.cwd();
|
|
123
|
-
}
|
|
124
|
-
outputPath = node_path_1.default.resolve(outputPath);
|
|
125
|
-
try {
|
|
126
|
-
fs_extra_1.default.ensureDirSync(outputPath);
|
|
127
|
-
// 保存result.json
|
|
128
|
-
await fs_extra_1.default.writeJson(node_path_1.default.join(outputPath, "outline.json"), outline, {
|
|
129
|
-
spaces: 2,
|
|
130
|
-
});
|
|
131
|
-
// 读取模板文件
|
|
132
|
-
const templateData = await fs_extra_1.default.readJson(templateFilePath);
|
|
133
|
-
const resultJSON = await this.pptGenerator.generateResultJson({
|
|
134
|
-
outline: outline,
|
|
135
|
-
templateData: templateData,
|
|
136
|
-
});
|
|
137
|
-
// 保存result.json
|
|
138
|
-
await fs_extra_1.default.writeJson(node_path_1.default.join(outputPath, "result.json"), resultJSON, {
|
|
139
|
-
spaces: 2,
|
|
140
|
-
});
|
|
141
|
-
if (!resultJSON) {
|
|
142
|
-
console.error("generate_result_json 生成 result.json 失败");
|
|
143
|
-
throw new types_js_1.McpError(types_js_1.ErrorCode.InternalError, "生成result.json失败");
|
|
144
|
-
}
|
|
145
|
-
const pptx = await this.pptGenerator.generatePPTFromResult({
|
|
146
|
-
result: resultJSON,
|
|
147
|
-
});
|
|
148
|
-
// 确定输出路径
|
|
149
|
-
const pptOutputPath = node_path_1.default.join(outputPath, "result.pptx");
|
|
150
|
-
// 确保输出目录存在
|
|
151
|
-
await fs_extra_1.default.ensureDir(node_path_1.default.dirname(pptOutputPath));
|
|
152
|
-
// 保存PPT文件
|
|
153
|
-
await pptx.writeFile({ fileName: pptOutputPath });
|
|
154
|
-
return {
|
|
155
|
-
content: [
|
|
156
|
-
{
|
|
157
|
-
type: "text",
|
|
158
|
-
text: JSON.stringify({
|
|
159
|
-
success: true,
|
|
160
|
-
outputPath: pptOutputPath,
|
|
161
|
-
message: `PPT文件生成成功: ${pptOutputPath}`,
|
|
162
|
-
}, null, 2),
|
|
163
|
-
},
|
|
164
|
-
{
|
|
165
|
-
type: "resource_link",
|
|
166
|
-
uri: `file:///${pptOutputPath}`,
|
|
167
|
-
name: "result.pptx",
|
|
168
|
-
description: "生成的PPT",
|
|
169
|
-
mimeType: "application/vnd.openxmlformats-officedocument.presentationml.presentation",
|
|
170
|
-
annotations: {
|
|
171
|
-
audience: ["assistant"],
|
|
172
|
-
priority: 0.9,
|
|
173
|
-
},
|
|
174
|
-
},
|
|
175
|
-
],
|
|
176
|
-
};
|
|
177
|
-
}
|
|
178
|
-
catch (err) {
|
|
179
|
-
console.error(err);
|
|
180
|
-
logger_js_1.default.error("generate_ppt error", err);
|
|
181
|
-
throw new types_js_1.McpError(types_js_1.ErrorCode.InternalError, "生成PPT失败");
|
|
182
|
-
}
|
|
183
|
-
});
|
|
4
|
+
const node_util_1 = require("node:util");
|
|
5
|
+
const server_1 = require("./server");
|
|
6
|
+
// Parse command line arguments
|
|
7
|
+
const parsed = (0, node_util_1.parseArgs)({
|
|
8
|
+
options: {
|
|
9
|
+
transport: {
|
|
10
|
+
type: "string",
|
|
11
|
+
short: "t",
|
|
12
|
+
default: "stdio",
|
|
13
|
+
},
|
|
14
|
+
host: {
|
|
15
|
+
type: "string",
|
|
16
|
+
short: "h",
|
|
17
|
+
default: "localhost",
|
|
18
|
+
},
|
|
19
|
+
port: {
|
|
20
|
+
type: "string",
|
|
21
|
+
short: "p",
|
|
22
|
+
default: "1122",
|
|
23
|
+
},
|
|
24
|
+
endpoint: {
|
|
25
|
+
type: "string",
|
|
26
|
+
short: "e",
|
|
27
|
+
default: "", // We'll handle defaults per transport type
|
|
28
|
+
},
|
|
29
|
+
help: {
|
|
30
|
+
type: "boolean",
|
|
31
|
+
short: "H",
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
allowPositionals: true,
|
|
35
|
+
tokens: true,
|
|
36
|
+
});
|
|
37
|
+
// Initialize default host value
|
|
38
|
+
let host = "localhost";
|
|
39
|
+
// Flag to track if we're expecting a host value in the next token
|
|
40
|
+
let isHostValue = false;
|
|
41
|
+
// Iterate through parsed command line tokens to extract host value
|
|
42
|
+
for (const item of parsed.tokens) {
|
|
43
|
+
// If current token is the host option flag
|
|
44
|
+
if (item.kind === "option" && item.name === "host") {
|
|
45
|
+
isHostValue = true;
|
|
46
|
+
continue;
|
|
184
47
|
}
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
48
|
+
// If we're expecting a host value (previous token was --host flag)
|
|
49
|
+
if (isHostValue) {
|
|
50
|
+
// Deep copy the token to avoid reference issues
|
|
51
|
+
const temp = JSON.parse(JSON.stringify(item));
|
|
52
|
+
// Extract host value or default to "0.0.0.0"
|
|
53
|
+
host = temp.value || "0.0.0.0";
|
|
54
|
+
isHostValue = false;
|
|
55
|
+
break;
|
|
192
56
|
}
|
|
193
57
|
}
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
58
|
+
// If --host flag was set but no value followed it, use "0.0.0.0" as default
|
|
59
|
+
if (isHostValue) {
|
|
60
|
+
host = "0.0.0.0";
|
|
61
|
+
}
|
|
62
|
+
// Create a deep copy of parsed values and assign the determined host
|
|
63
|
+
const values = JSON.parse(JSON.stringify(parsed.values));
|
|
64
|
+
values.host = host;
|
|
65
|
+
// Display help information if requested
|
|
66
|
+
if (values.help) {
|
|
67
|
+
console.log(`
|
|
68
|
+
MCP Server Chart CLI
|
|
69
|
+
|
|
70
|
+
Options:
|
|
71
|
+
--transport, -t Specify the transport protocol: "stdio", "sse", or "streamable" (default: "stdio")
|
|
72
|
+
--host, -h Specify the host for SSE or streamable transport (default: localhost)
|
|
73
|
+
--port, -p Specify the port for SSE or streamable transport (default: 1122)
|
|
74
|
+
--endpoint, -e Specify the endpoint for the transport:
|
|
75
|
+
- For SSE: default is "/sse"
|
|
76
|
+
- For streamable: default is "/mcp"
|
|
77
|
+
--help, -H Show this help message
|
|
78
|
+
`);
|
|
79
|
+
process.exit(0);
|
|
80
|
+
}
|
|
81
|
+
// Run in the specified transport mode
|
|
82
|
+
const transport = values.transport.toLowerCase();
|
|
83
|
+
if (transport === "sse") {
|
|
84
|
+
const port = Number.parseInt(values.port, 10);
|
|
85
|
+
// Use provided endpoint or default to "/sse" for SSE
|
|
86
|
+
const endpoint = values.endpoint || "/sse";
|
|
87
|
+
const host = values.host || "localhost";
|
|
88
|
+
(0, server_1.runSSEServer)(host, port, endpoint).catch(console.error);
|
|
89
|
+
}
|
|
90
|
+
else if (transport === "streamable") {
|
|
91
|
+
const port = Number.parseInt(values.port, 10);
|
|
92
|
+
// Use provided endpoint or default to "/mcp" for streamable
|
|
93
|
+
const endpoint = values.endpoint || "/mcp";
|
|
94
|
+
const host = values.host || "localhost";
|
|
95
|
+
(0, server_1.runHTTPStreamableServer)(host, port, endpoint).catch(console.error);
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
(0, server_1.runStdioServer)().catch(console.error);
|
|
99
|
+
}
|
package/dist/index1.d.ts
ADDED
package/dist/index1.js
ADDED
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
4
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
5
|
+
};
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
const mcp_js_1 = require("@modelcontextprotocol/sdk/server/mcp.js");
|
|
8
|
+
const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js");
|
|
9
|
+
const types_js_1 = require("@modelcontextprotocol/sdk/types.js");
|
|
10
|
+
const ppt_generator_js_1 = require("./ppt-generator.js");
|
|
11
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
12
|
+
const zod_1 = require("zod");
|
|
13
|
+
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
14
|
+
const package_json_1 = __importDefault(require("../package.json"));
|
|
15
|
+
require("./node-only.js");
|
|
16
|
+
const logger_js_1 = __importDefault(require("./utils/logger.js"));
|
|
17
|
+
class PPTGeneratorMCPServer {
|
|
18
|
+
constructor() {
|
|
19
|
+
this.server = new mcp_js_1.McpServer({
|
|
20
|
+
name: "ppt-generator",
|
|
21
|
+
version: "0.1.0",
|
|
22
|
+
}, {
|
|
23
|
+
capabilities: {
|
|
24
|
+
tools: {},
|
|
25
|
+
},
|
|
26
|
+
});
|
|
27
|
+
// @ts-ignore
|
|
28
|
+
this.server.server.onerror = (error) => console.error("[MCP Error]", error);
|
|
29
|
+
this.pptGenerator = new ppt_generator_js_1.PPTGenerator();
|
|
30
|
+
this.setupToolHandlers();
|
|
31
|
+
}
|
|
32
|
+
setupToolHandlers() {
|
|
33
|
+
this.server.registerTool("get_ppt_template_list", {
|
|
34
|
+
title: "ppt模板列表",
|
|
35
|
+
description: "获取可使用的ppt模板",
|
|
36
|
+
}, async () => {
|
|
37
|
+
return {
|
|
38
|
+
content: [
|
|
39
|
+
{
|
|
40
|
+
type: "text",
|
|
41
|
+
text: JSON.stringify([
|
|
42
|
+
{
|
|
43
|
+
name: "清新风格模板-图标比较多",
|
|
44
|
+
path: node_path_1.default.join(__dirname, "tpls", "tpl-3.json"),
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
name: "研究报告风格模板-紫色系",
|
|
48
|
+
path: node_path_1.default.join(__dirname, "tpls", "tpl-4.json"),
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
name: "简约风格模板-莫兰迪色系",
|
|
52
|
+
path: node_path_1.default.join(__dirname, "tpls", "tpl-2.json"),
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
name: "简单模板-蓝色调",
|
|
56
|
+
path: node_path_1.default.join(__dirname, "tpls", "tpl-1.json"),
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
name: "通用模板-商务风格",
|
|
60
|
+
path: node_path_1.default.join(__dirname, "tpls", "custom-1.json"),
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
name: "通用模板-报告风格",
|
|
64
|
+
path: node_path_1.default.join(__dirname, "tpls", "custom-2.json"),
|
|
65
|
+
},
|
|
66
|
+
]),
|
|
67
|
+
},
|
|
68
|
+
],
|
|
69
|
+
};
|
|
70
|
+
});
|
|
71
|
+
this.server.registerTool("generate_ppt", {
|
|
72
|
+
title: "ppt生成工具",
|
|
73
|
+
description: "根据大纲自动匹配模板生成PPT文件",
|
|
74
|
+
inputSchema: {
|
|
75
|
+
templateFilePath: zod_1.z.string().optional(),
|
|
76
|
+
outputPath: zod_1.z.string().optional(),
|
|
77
|
+
outline: zod_1.z.array(zod_1.z.discriminatedUnion("type", [
|
|
78
|
+
zod_1.z.object({
|
|
79
|
+
type: zod_1.z.literal("cover"),
|
|
80
|
+
data: zod_1.z.object({
|
|
81
|
+
title: zod_1.z.string(),
|
|
82
|
+
text: zod_1.z.string(),
|
|
83
|
+
}),
|
|
84
|
+
}),
|
|
85
|
+
zod_1.z.object({
|
|
86
|
+
type: zod_1.z.literal("contents"),
|
|
87
|
+
data: zod_1.z.object({
|
|
88
|
+
items: zod_1.z.array(zod_1.z.string()),
|
|
89
|
+
}),
|
|
90
|
+
offset: zod_1.z.number().optional(),
|
|
91
|
+
}),
|
|
92
|
+
zod_1.z.object({
|
|
93
|
+
type: zod_1.z.literal("transition"),
|
|
94
|
+
data: zod_1.z.object({
|
|
95
|
+
title: zod_1.z.string(),
|
|
96
|
+
text: zod_1.z.string(),
|
|
97
|
+
}),
|
|
98
|
+
}),
|
|
99
|
+
zod_1.z.object({
|
|
100
|
+
type: zod_1.z.literal("content"),
|
|
101
|
+
data: zod_1.z.object({
|
|
102
|
+
title: zod_1.z.string(),
|
|
103
|
+
items: zod_1.z.array(zod_1.z.object({
|
|
104
|
+
title: zod_1.z.string(),
|
|
105
|
+
text: zod_1.z.string(),
|
|
106
|
+
})),
|
|
107
|
+
}),
|
|
108
|
+
}),
|
|
109
|
+
zod_1.z.object({
|
|
110
|
+
type: zod_1.z.literal("end"),
|
|
111
|
+
}),
|
|
112
|
+
])),
|
|
113
|
+
},
|
|
114
|
+
}, async ({ outline, templateFilePath, outputPath }) => {
|
|
115
|
+
logger_js_1.default.info("generate_ppt", { outline, templateFilePath, outputPath });
|
|
116
|
+
if (!templateFilePath) {
|
|
117
|
+
templateFilePath = node_path_1.default.join(__dirname, "tpls", "tpl-2.json");
|
|
118
|
+
}
|
|
119
|
+
// 演示用,固定模版
|
|
120
|
+
templateFilePath = node_path_1.default.join(__dirname, "tpls", "custom-1.json");
|
|
121
|
+
if (!outputPath) {
|
|
122
|
+
outputPath = process.cwd();
|
|
123
|
+
}
|
|
124
|
+
outputPath = node_path_1.default.resolve(outputPath);
|
|
125
|
+
try {
|
|
126
|
+
fs_extra_1.default.ensureDirSync(outputPath);
|
|
127
|
+
// 保存result.json
|
|
128
|
+
await fs_extra_1.default.writeJson(node_path_1.default.join(outputPath, "outline.json"), outline, {
|
|
129
|
+
spaces: 2,
|
|
130
|
+
});
|
|
131
|
+
// 读取模板文件
|
|
132
|
+
const templateData = await fs_extra_1.default.readJson(templateFilePath);
|
|
133
|
+
const resultJSON = await this.pptGenerator.generateResultJson({
|
|
134
|
+
outline: outline,
|
|
135
|
+
templateData: templateData,
|
|
136
|
+
});
|
|
137
|
+
// 保存result.json
|
|
138
|
+
await fs_extra_1.default.writeJson(node_path_1.default.join(outputPath, "result.json"), resultJSON, {
|
|
139
|
+
spaces: 2,
|
|
140
|
+
});
|
|
141
|
+
if (!resultJSON) {
|
|
142
|
+
console.error("generate_result_json 生成 result.json 失败");
|
|
143
|
+
throw new types_js_1.McpError(types_js_1.ErrorCode.InternalError, "生成result.json失败");
|
|
144
|
+
}
|
|
145
|
+
const pptx = await this.pptGenerator.generatePPTFromResult({
|
|
146
|
+
result: resultJSON,
|
|
147
|
+
});
|
|
148
|
+
// 确定输出路径
|
|
149
|
+
const pptOutputPath = node_path_1.default.join(outputPath, "result.pptx");
|
|
150
|
+
// 确保输出目录存在
|
|
151
|
+
await fs_extra_1.default.ensureDir(node_path_1.default.dirname(pptOutputPath));
|
|
152
|
+
// 保存PPT文件
|
|
153
|
+
await pptx.writeFile({ fileName: pptOutputPath });
|
|
154
|
+
return {
|
|
155
|
+
content: [
|
|
156
|
+
{
|
|
157
|
+
type: "text",
|
|
158
|
+
text: JSON.stringify({
|
|
159
|
+
success: true,
|
|
160
|
+
outputPath: pptOutputPath,
|
|
161
|
+
message: `PPT文件生成成功: ${pptOutputPath}`,
|
|
162
|
+
}, null, 2),
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
type: "resource_link",
|
|
166
|
+
uri: `file:///${pptOutputPath}`,
|
|
167
|
+
name: "result.pptx",
|
|
168
|
+
description: "生成的PPT",
|
|
169
|
+
mimeType: "application/vnd.openxmlformats-officedocument.presentationml.presentation",
|
|
170
|
+
annotations: {
|
|
171
|
+
audience: ["assistant"],
|
|
172
|
+
priority: 0.9,
|
|
173
|
+
},
|
|
174
|
+
},
|
|
175
|
+
],
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
catch (err) {
|
|
179
|
+
console.error(err);
|
|
180
|
+
logger_js_1.default.error("generate_ppt error", err);
|
|
181
|
+
throw new types_js_1.McpError(types_js_1.ErrorCode.InternalError, "生成PPT失败");
|
|
182
|
+
}
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
async run() {
|
|
186
|
+
const transport = new stdio_js_1.StdioServerTransport();
|
|
187
|
+
await this.server.connect(transport);
|
|
188
|
+
console.error("PPT Generator MCP server running on stdio");
|
|
189
|
+
console.error(`VERSION ${package_json_1.default.version}`);
|
|
190
|
+
logger_js_1.default.info("PPT Generator MCP server running on stdio");
|
|
191
|
+
logger_js_1.default.info(`VERSION ${package_json_1.default.version}`);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
const server = new PPTGeneratorMCPServer();
|
|
195
|
+
server.run().catch((err) => {
|
|
196
|
+
console.error(err);
|
|
197
|
+
logger_js_1.default.error("PPTGeneratorMCPServer run error", err);
|
|
198
|
+
});
|
package/dist/server.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
2
|
+
import "./node-only.js";
|
|
3
|
+
export declare function createServer(): Server;
|
|
4
|
+
export declare function runStdioServer(): Promise<void>;
|
|
5
|
+
export declare function runSSEServer(host?: string, port?: number, endpoint?: string): Promise<void>;
|
|
6
|
+
export declare function runHTTPStreamableServer(host?: string, port?: number, endpoint?: string): Promise<void>;
|
package/dist/server.js
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.createServer = createServer;
|
|
37
|
+
exports.runStdioServer = runStdioServer;
|
|
38
|
+
exports.runSSEServer = runSSEServer;
|
|
39
|
+
exports.runHTTPStreamableServer = runHTTPStreamableServer;
|
|
40
|
+
const index_js_1 = require("@modelcontextprotocol/sdk/server/index.js");
|
|
41
|
+
const types_js_1 = require("@modelcontextprotocol/sdk/types.js");
|
|
42
|
+
const services_1 = require("./services");
|
|
43
|
+
const Tools = __importStar(require("./tools"));
|
|
44
|
+
require("./node-only.js");
|
|
45
|
+
function createServer() {
|
|
46
|
+
const server = new index_js_1.Server({
|
|
47
|
+
name: "@8btc/ppt-generator-mcp",
|
|
48
|
+
version: "0.0.x",
|
|
49
|
+
}, {
|
|
50
|
+
capabilities: {
|
|
51
|
+
tools: {},
|
|
52
|
+
},
|
|
53
|
+
});
|
|
54
|
+
setupToolHandlers(server);
|
|
55
|
+
server.onerror = (error) => console.error("[MCP Error]", error);
|
|
56
|
+
process.on("SIGINT", async () => {
|
|
57
|
+
await server.close();
|
|
58
|
+
process.exit(0);
|
|
59
|
+
});
|
|
60
|
+
return server;
|
|
61
|
+
}
|
|
62
|
+
function getEnabledTools() {
|
|
63
|
+
// todo: disabled tool names。
|
|
64
|
+
return Object.values(Tools);
|
|
65
|
+
}
|
|
66
|
+
function setupToolHandlers(server) {
|
|
67
|
+
server.setRequestHandler(types_js_1.ListToolsRequestSchema, async () => ({
|
|
68
|
+
tools: getEnabledTools().map((toolItem) => toolItem.tool),
|
|
69
|
+
}));
|
|
70
|
+
server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
|
|
71
|
+
// 如果方法没执行,看看 tool.name 和导出的变量名是否相同
|
|
72
|
+
const toolHandler = Tools[request.params.name]
|
|
73
|
+
?.toolHandler;
|
|
74
|
+
if (typeof toolHandler !== "function") {
|
|
75
|
+
return `failed! tool function not exist`;
|
|
76
|
+
}
|
|
77
|
+
return await toolHandler(request.params.arguments);
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
async function runStdioServer() {
|
|
81
|
+
const server = createServer();
|
|
82
|
+
await (0, services_1.startStdioMcpServer)(server);
|
|
83
|
+
}
|
|
84
|
+
async function runSSEServer(host = "localhost", port = 1122, endpoint = "/sse") {
|
|
85
|
+
const server = createServer();
|
|
86
|
+
await (0, services_1.startSSEMcpServer)(server, endpoint, port, host);
|
|
87
|
+
}
|
|
88
|
+
async function runHTTPStreamableServer(host = "localhost", port = 1122, endpoint = "/mcp") {
|
|
89
|
+
await (0, services_1.startHTTPStreamableServer)(createServer, endpoint, port, host);
|
|
90
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.startHTTPStreamableServer = exports.startSSEMcpServer = exports.startStdioMcpServer = void 0;
|
|
4
|
+
var stdio_1 = require("./stdio");
|
|
5
|
+
Object.defineProperty(exports, "startStdioMcpServer", { enumerable: true, get: function () { return stdio_1.startStdioMcpServer; } });
|
|
6
|
+
var sse_1 = require("./sse");
|
|
7
|
+
Object.defineProperty(exports, "startSSEMcpServer", { enumerable: true, get: function () { return sse_1.startSSEMcpServer; } });
|
|
8
|
+
var streamable_1 = require("./streamable");
|
|
9
|
+
Object.defineProperty(exports, "startHTTPStreamableServer", { enumerable: true, get: function () { return streamable_1.startHTTPStreamableServer; } });
|