keyshot-mcp 0.0.0 → 0.2.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.
@@ -0,0 +1,45 @@
1
+ # Contributing / 贡献指南
2
+
3
+ ## English
4
+
5
+ Contributions are welcome.
6
+
7
+ Useful areas:
8
+
9
+ - Test with more KeyShot versions.
10
+ - Improve compatibility with macOS and Linux paths.
11
+ - Add examples for Claude Desktop, Codex, and other MCP clients.
12
+ - Add more precise wrappers for KeyShot `lux` APIs.
13
+
14
+ Before opening a pull request:
15
+
16
+ ```bash
17
+ npm install
18
+ npm run build
19
+ npm run status
20
+ ```
21
+
22
+ Do not include proprietary KeyShot scenes, license data, customer assets, or private render outputs in issues or pull requests.
23
+
24
+ ---
25
+
26
+ ## 中文
27
+
28
+ 欢迎参与贡献。
29
+
30
+ 比较有价值的方向:
31
+
32
+ - 测试更多 KeyShot 版本。
33
+ - 改进 macOS 和 Linux 路径兼容。
34
+ - 增加 Claude Desktop、Codex 和其他 MCP 客户端示例。
35
+ - 为 KeyShot `lux` API 增加更精确的封装。
36
+
37
+ 提交修改前建议先运行:
38
+
39
+ ```bash
40
+ npm install
41
+ npm run build
42
+ npm run status
43
+ ```
44
+
45
+ 请不要在 issue 或 pull request 里上传专有 KeyShot 场景、许可证数据、客户资产或私人渲染结果。
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 KeyShot MCP contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,4 +1,443 @@
1
- # keyshot-mcp placeholder
1
+ # KeyShot MCP
2
2
 
3
- This is a temporary placeholder package used to configure npm Trusted Publishing.
4
- The real package is maintained at https://github.com/truman-t3/keyshot-mcp.
3
+ [![MCP Badge](https://lobehub.com/badge/mcp/truman-t3-keyshot-mcp)](https://lobehub.com/mcp/truman-t3-keyshot-mcp)
4
+ [![GitHub Release](https://img.shields.io/github/v/release/truman-t3/keyshot-mcp)](https://github.com/truman-t3/keyshot-mcp/releases)
5
+ [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE)
6
+
7
+ English | [中文](#中文说明)
8
+
9
+ A local MCP server for controlling KeyShot Studio through KeyShot headless scripting.
10
+
11
+ It lets an AI app that supports MCP ask KeyShot to inspect scenes, render images, import models, change materials, adjust cameras, set environments, and save scenes.
12
+
13
+ Optimized for Windows-based KeyShot Studio product visualization workflows.
14
+
15
+ Unlike GUI-only automation scripts, this project targets KeyShot headless workflows and keeps a stable MCP interface for AI agents.
16
+
17
+ ## Who This Is For
18
+
19
+ - Designers who want AI-assisted KeyShot rendering.
20
+ - Developers who want a simple stdio MCP bridge for KeyShot.
21
+ - Teams that already have KeyShot licenses configured on their machines.
22
+
23
+ This project does not include KeyShot, does not bypass licensing, and does not store license keys.
24
+
25
+ ## What It Can Do
26
+
27
+ - Check whether KeyShot headless can start.
28
+ - Inspect a `.bip` or supported KeyShot scene file.
29
+ - Render a scene to an image.
30
+ - Batch render multiple named cameras from one scene.
31
+ - Import a model into a scene.
32
+ - Apply a material to an object.
33
+ - Create or update a camera.
34
+ - Set an environment when the installed KeyShot version exposes that function.
35
+ - Save a scene to a new file.
36
+
37
+ ## Example Workflows
38
+
39
+ - Batch render multiple camera views from one KeyShot scene.
40
+ - Test several material options on the same product model.
41
+ - Generate product hero images with consistent resolution and output naming.
42
+ - Import a model, apply a material preset, set a camera, and render in one AI instruction.
43
+
44
+ ## Workflow
45
+
46
+ ![KeyShot MCP Workflow](assets/workflow.svg)
47
+
48
+ ## Requirements
49
+
50
+ - KeyShot Studio with `keyshot_headless` support.
51
+ - Node.js 20 or newer.
52
+ - A valid KeyShot license already configured on the computer.
53
+
54
+ ## Compatibility
55
+
56
+ | Platform | KeyShot Version | Node Version | Status |
57
+ | --- | --- | --- | --- |
58
+ | Windows 11 | KeyShot Studio 2025 / 14.1 | Node 22 | Tested |
59
+ | macOS | Not tested | - | Need contributors |
60
+ | Linux | Not tested | - | Need contributors |
61
+
62
+ ## Install
63
+
64
+ ```bash
65
+ npm install
66
+ npm run build
67
+ ```
68
+
69
+ ## Copy-Paste Setup Prompt for an Agent
70
+
71
+ If you use Codex or another coding agent, you can copy this prompt and let the agent install the MCP server for you:
72
+
73
+ ```text
74
+ Install the KeyShot MCP server from https://github.com/truman-t3/keyshot-mcp.
75
+
76
+ Please:
77
+ 1. Clone the repository or use my local copy if it already exists.
78
+ 2. Run npm install and npm run build.
79
+ 3. Find my KeyShot headless executable path.
80
+ 4. Add a keyshot MCP server entry to my MCP client configuration.
81
+ 5. Set KEYSHOT_HEADLESS_EXE to the detected keyshot_headless path.
82
+ 6. Test the setup by running the keyshot_status tool.
83
+ 7. Tell me the exact config that was added and whether the status check passed.
84
+
85
+ Do not store license keys or account passwords. Use my existing local KeyShot license configuration.
86
+ ```
87
+
88
+ ## Configure
89
+
90
+ Set the path to your KeyShot headless executable.
91
+
92
+ Windows PowerShell example:
93
+
94
+ ```powershell
95
+ $env:KEYSHOT_HEADLESS_EXE="C:\Program Files\KeyShot Studio\bin\keyshot_headless.exe"
96
+ ```
97
+
98
+ macOS/Linux shell example:
99
+
100
+ ```bash
101
+ export KEYSHOT_HEADLESS_EXE="/Applications/KeyShot Studio.app/Contents/MacOS/keyshot_headless"
102
+ ```
103
+
104
+ Then test startup:
105
+
106
+ ```bash
107
+ npm run status
108
+ ```
109
+
110
+ ## MCP Client Example
111
+
112
+ Add a server like this to your MCP client config:
113
+
114
+ ```json
115
+ {
116
+ "mcpServers": {
117
+ "keyshot": {
118
+ "command": "node",
119
+ "args": ["/absolute/path/to/keyshot-mcp/dist/index.js"],
120
+ "env": {
121
+ "KEYSHOT_HEADLESS_EXE": "/absolute/path/to/keyshot_headless"
122
+ }
123
+ }
124
+ }
125
+ }
126
+ ```
127
+
128
+ A generic Codex configuration template is in:
129
+
130
+ ```text
131
+ examples/codex.example.json
132
+ ```
133
+
134
+ ## Codex Configuration
135
+
136
+ For Codex, add a `keyshot` MCP server entry to your Codex MCP configuration and point it to the built server file:
137
+
138
+ ```json
139
+ {
140
+ "mcpServers": {
141
+ "keyshot": {
142
+ "command": "node",
143
+ "args": ["/absolute/path/to/keyshot-mcp/dist/index.js"],
144
+ "env": {
145
+ "KEYSHOT_HEADLESS_EXE": "/absolute/path/to/keyshot_headless"
146
+ }
147
+ }
148
+ }
149
+ }
150
+ ```
151
+
152
+ Use `examples/codex.example.json` as a starting point and replace all paths with paths on your own computer.
153
+
154
+ ## Prompt Examples
155
+
156
+ ```text
157
+ Render the current KeyShot scene into three views: front, 45-degree perspective, and top-down. Use 1920x1080 resolution and save the outputs to the configured output folder.
158
+ ```
159
+
160
+ ```text
161
+ Import the model file at /path/to/model.step, apply a brushed metal material to the main housing, set a 45-degree camera, and render a product hero image.
162
+ ```
163
+
164
+ ```text
165
+ Inspect this KeyShot scene and summarize the available objects, cameras, materials, and renderable outputs.
166
+ ```
167
+
168
+ ## Environment Variables
169
+
170
+ - `KEYSHOT_HEADLESS_EXE`: path to `keyshot_headless` or `keyshot_headless.exe`.
171
+ - `KEYSHOT_OUTPUT_DIR`: default output folder for renders.
172
+ - `KEYSHOT_LICENSE_ARGS`: optional KeyShot headless license arguments. Empty by default.
173
+ - `KEYSHOT_TIMEOUT_MS`: operation timeout in milliseconds. Default: `600000`.
174
+
175
+ ## MCP Tools
176
+
177
+ - `keyshot_status`
178
+ - `keyshot_inspect_scene`
179
+ - `keyshot_render`: render a single image
180
+ - `keyshot_batch_render`
181
+ - `keyshot_import_model`
182
+ - `keyshot_apply_material`
183
+ - `keyshot_set_camera`
184
+ - `keyshot_set_environment`
185
+ - `keyshot_save_scene`
186
+
187
+ ## MCP Prompts and Resources
188
+
189
+ - Prompt: `keyshot_product_render`
190
+ - Resource: `keyshot://workflow`
191
+
192
+ Each tool returns JSON with:
193
+
194
+ - `ok`
195
+ - `data`
196
+ - `outputFiles`
197
+ - `warnings`
198
+ - `keyshotStdoutTail`
199
+ - `error`
200
+
201
+ ## Notes
202
+
203
+ KeyShot's Python `lux` API changes across versions. This server keeps the MCP interface stable and returns a clear error when an installed KeyShot version does not expose a requested headless function.
204
+
205
+ ## Roadmap
206
+
207
+ - [ ] Auto-discover and batch render all cameras in a scene
208
+ - [ ] Material preset library
209
+ - [ ] Camera preset templates
210
+ - [ ] Render queue status
211
+ - [ ] Safer output directory restrictions
212
+ - [ ] More tested KeyShot versions
213
+ - [ ] macOS compatibility verification
214
+ - [ ] Claude Desktop / Cursor / Codex config examples
215
+
216
+ ## License
217
+
218
+ MIT
219
+
220
+ ---
221
+
222
+ # 中文说明
223
+
224
+ [English](#keyshot-mcp) | 中文
225
+
226
+ 这是一个本地 KeyShot MCP 服务,可以让支持 MCP 的 AI 工具通过 KeyShot 的无界面脚本能力控制 KeyShot Studio。
227
+
228
+ 简单说:你可以让 AI 帮你检查 KeyShot 场景、渲染图片、导入模型、替换材质、调整相机、设置环境并保存场景。
229
+
230
+ 本项目优先面向 Windows 环境下的 KeyShot Studio 产品渲染自动化流程。
231
+
232
+ 与仅面向界面操作的自动化脚本不同,本项目优先面向 KeyShot 无界面工作流,并为 AI Agent 提供稳定的 MCP 工具接口。
233
+
234
+ ## 适合谁使用
235
+
236
+ - 希望用 AI 辅助 KeyShot 渲染的设计师。
237
+ - 想要 KeyShot MCP 桥接工具的开发者。
238
+ - 已经在电脑上配置好 KeyShot 授权的团队。
239
+
240
+ 这个项目不包含 KeyShot,不绕过 KeyShot 授权,也不会保存许可证密钥。
241
+
242
+ ## 能做什么
243
+
244
+ - 检查 KeyShot 无界面程序是否能启动。
245
+ - 检查 `.bip` 或 KeyShot 支持的场景文件。
246
+ - 把场景渲染成图片。
247
+ - 从同一个场景批量渲染多个指定相机。
248
+ - 把模型导入场景。
249
+ - 给对象替换材质。
250
+ - 创建或更新相机。
251
+ - 在当前 KeyShot 版本支持时设置环境。
252
+ - 把场景保存为新文件。
253
+
254
+ ## 典型使用场景
255
+
256
+ - 批量渲染同一个 KeyShot 场景的多个相机视角。
257
+ - 对同一个产品模型快速测试多组材质方案。
258
+ - 统一输出产品首图、封面图、详情页渲染图。
259
+ - 用一句自然语言完成导入模型、替换材质、设置相机、渲染出图。
260
+
261
+ ## 工作流程
262
+
263
+ ![KeyShot MCP Workflow](assets/workflow.svg)
264
+
265
+ ## 使用要求
266
+
267
+ - 已安装支持 `keyshot_headless` 的 KeyShot Studio。
268
+ - Node.js 20 或更新版本。
269
+ - 电脑上已经配置好有效的 KeyShot 授权。
270
+
271
+ ## 版本兼容表
272
+
273
+ | 平台 | KeyShot 版本 | Node 版本 | 状态 |
274
+ | --- | --- | --- | --- |
275
+ | Windows 11 | KeyShot Studio 2025 / 14.1 | Node 22 | 已测试 |
276
+ | macOS | 未测试 | - | 需要贡献者 |
277
+ | Linux | 未测试 | - | 需要贡献者 |
278
+
279
+ ## 安装
280
+
281
+ ```bash
282
+ npm install
283
+ npm run build
284
+ ```
285
+
286
+ ## 复制给 Agent 的安装提示词
287
+
288
+ 如果你使用 Codex 或其他编程 Agent,可以复制下面这段话,让 Agent 帮你安装和配置 MCP:
289
+
290
+ ```text
291
+ 请帮我安装 KeyShot MCP Server:https://github.com/truman-t3/keyshot-mcp。
292
+
293
+ 请你:
294
+ 1. 克隆这个仓库;如果本地已有,就使用本地版本。
295
+ 2. 运行 npm install 和 npm run build。
296
+ 3. 查找我电脑上的 KeyShot headless 可执行文件路径。
297
+ 4. 把 keyshot MCP server 添加到我的 MCP 客户端配置里。
298
+ 5. 把 KEYSHOT_HEADLESS_EXE 设置为检测到的 keyshot_headless 路径。
299
+ 6. 用 keyshot_status 工具测试是否配置成功。
300
+ 7. 最后告诉我实际添加的配置,以及状态检查是否通过。
301
+
302
+ 不要保存许可证密钥、账号密码或授权信息。直接使用我电脑上已有的 KeyShot 本地授权配置。
303
+ ```
304
+
305
+ ## 配置
306
+
307
+ 需要告诉 MCP 服务 KeyShot 无界面程序在哪里。
308
+
309
+ Windows PowerShell 示例:
310
+
311
+ ```powershell
312
+ $env:KEYSHOT_HEADLESS_EXE="C:\Program Files\KeyShot Studio\bin\keyshot_headless.exe"
313
+ ```
314
+
315
+ macOS/Linux 示例:
316
+
317
+ ```bash
318
+ export KEYSHOT_HEADLESS_EXE="/Applications/KeyShot Studio.app/Contents/MacOS/keyshot_headless"
319
+ ```
320
+
321
+ 然后测试能否启动:
322
+
323
+ ```bash
324
+ npm run status
325
+ ```
326
+
327
+ ## MCP 客户端配置示例
328
+
329
+ 把类似下面的配置加到你的 MCP 客户端里:
330
+
331
+ ```json
332
+ {
333
+ "mcpServers": {
334
+ "keyshot": {
335
+ "command": "node",
336
+ "args": ["/absolute/path/to/keyshot-mcp/dist/index.js"],
337
+ "env": {
338
+ "KEYSHOT_HEADLESS_EXE": "/absolute/path/to/keyshot_headless"
339
+ }
340
+ }
341
+ }
342
+ }
343
+ ```
344
+
345
+ 通用 Codex 配置模板在:
346
+
347
+ ```text
348
+ examples/codex.example.json
349
+ ```
350
+
351
+ ## Codex 配置
352
+
353
+ 如果你使用 Codex,请在 Codex 的 MCP 配置里添加一个 `keyshot` 服务,并指向构建后的服务文件:
354
+
355
+ ```json
356
+ {
357
+ "mcpServers": {
358
+ "keyshot": {
359
+ "command": "node",
360
+ "args": ["/absolute/path/to/keyshot-mcp/dist/index.js"],
361
+ "env": {
362
+ "KEYSHOT_HEADLESS_EXE": "/absolute/path/to/keyshot_headless"
363
+ }
364
+ }
365
+ }
366
+ }
367
+ ```
368
+
369
+ `examples/codex.example.json` 是通用配置模板。使用时请把里面的路径换成自己电脑上的路径。
370
+
371
+ ## 提示词示例
372
+
373
+ ```text
374
+ 把当前 KeyShot 场景渲染成三个视角:正视图、45 度透视图和俯视图。分辨率为 1920x1080,并保存到默认输出文件夹。
375
+ ```
376
+
377
+ ```text
378
+ 导入 /path/to/model.step,给主体外壳应用拉丝金属材质,设置 45 度相机,并渲染一张产品主视觉图。
379
+ ```
380
+
381
+ ```text
382
+ 检查当前 KeyShot 场景,并总结场景中的对象、相机、材质和可渲染输出。
383
+ ```
384
+
385
+ ## 环境变量
386
+
387
+ - `KEYSHOT_HEADLESS_EXE`:`keyshot_headless` 或 `keyshot_headless.exe` 的路径。
388
+ - `KEYSHOT_OUTPUT_DIR`:默认渲染输出文件夹。
389
+ - `KEYSHOT_LICENSE_ARGS`:可选的 KeyShot 无界面许可证参数,默认留空。
390
+ - `KEYSHOT_TIMEOUT_MS`:单次操作超时时间,单位毫秒,默认 `600000`。
391
+
392
+ ## MCP 工具
393
+
394
+ - `keyshot_status`:检查 KeyShot 是否能启动。
395
+ - `keyshot_inspect_scene`:检查场景内容。
396
+ - `keyshot_render`:渲染单张图片。
397
+ - `keyshot_batch_render`:批量渲染多个相机视角。
398
+ - `keyshot_import_model`:导入模型。
399
+ - `keyshot_apply_material`:替换材质。
400
+ - `keyshot_set_camera`:设置相机。
401
+ - `keyshot_set_environment`:设置环境。
402
+ - `keyshot_save_scene`:保存场景。
403
+
404
+ ## MCP 提示词和资源
405
+
406
+ - 提示词:`keyshot_product_render`
407
+ - 资源:`keyshot://workflow`
408
+
409
+ 每个工具都会返回 JSON,包含:
410
+
411
+ - `ok`:是否成功。
412
+ - `data`:主要结果。
413
+ - `outputFiles`:生成的文件。
414
+ - `warnings`:警告信息。
415
+ - `keyshotStdoutTail`:KeyShot 输出摘要。
416
+ - `error`:错误信息。
417
+
418
+ ## 说明
419
+
420
+ KeyShot 的 Python `lux` API 会随版本变化。这个 MCP 会尽量保持对外工具名称稳定;如果当前 KeyShot 版本不支持某个无界面功能,会返回明确错误,而不是假装成功。
421
+
422
+ ## 路线图
423
+
424
+ - [ ] 自动发现并批量渲染场景中的所有相机
425
+ - [ ] 材质预设库
426
+ - [ ] 相机预设模板
427
+ - [ ] 渲染队列状态
428
+ - [ ] 更安全的输出目录限制
429
+ - [ ] 测试更多 KeyShot 版本
430
+ - [ ] 验证 macOS 兼容性
431
+ - [ ] 补充 Claude Desktop / Cursor / Codex 配置示例
432
+
433
+ ## 开源协议
434
+
435
+ MIT
436
+
437
+ ## Star History / 星标趋势
438
+
439
+ ![Star History Chart](assets/star-history.svg)
440
+
441
+ This chart is generated from GitHub stargazer data and refreshed by GitHub Actions.
442
+
443
+ 这张图由 GitHub star 数据生成,并通过 GitHub Actions 定时刷新。
package/SECURITY.md ADDED
@@ -0,0 +1,33 @@
1
+ # Security / 安全说明
2
+
3
+ ## English
4
+
5
+ This MCP server runs KeyShot headless on the local machine. It can read scene/model files and write rendered images or saved scenes.
6
+
7
+ ### Safe Use
8
+
9
+ - Only connect this server to MCP clients you trust.
10
+ - Only open scene/model/material files from trusted sources.
11
+ - Do not put license keys, account passwords, or private tokens in prompts.
12
+ - Prefer using the local KeyShot license configuration instead of passing license details through environment variables.
13
+
14
+ ### Reporting Issues
15
+
16
+ If you find a security issue, open a private advisory or contact the project maintainer directly before posting details publicly.
17
+
18
+ ---
19
+
20
+ ## 中文
21
+
22
+ 这个 MCP 服务会在本机运行 KeyShot 无界面程序。它可以读取场景、模型、材质文件,也可以写入渲染图片或保存后的场景文件。
23
+
24
+ ### 安全使用建议
25
+
26
+ - 只把这个服务连接到你信任的 MCP 客户端。
27
+ - 只打开来源可信的场景、模型和材质文件。
28
+ - 不要在提示词里输入许可证密钥、账号密码或私人 token。
29
+ - 优先使用本机已经配置好的 KeyShot 授权,不建议通过环境变量传递许可证细节。
30
+
31
+ ### 报告安全问题
32
+
33
+ 如果发现安全问题,请先通过私密方式联系维护者,不要直接公开细节。
@@ -0,0 +1,5 @@
1
+ import { getConfig } from "../config.js";
2
+ import { runKeyShotSerialized } from "../runner.js";
3
+ const result = await runKeyShotSerialized(getConfig(), { operation: "status" });
4
+ console.log(JSON.stringify(result, null, 2));
5
+ process.exit(result.ok ? 0 : 1);
package/dist/config.js ADDED
@@ -0,0 +1,50 @@
1
+ import path from "node:path";
2
+ import { fileURLToPath } from "node:url";
3
+ const DEFAULT_KEYSHOT_EXE = process.platform === "win32" ? "keyshot_headless.exe" : "keyshot_headless";
4
+ const DEFAULT_TIMEOUT_MS = 600_000;
5
+ export function getConfig() {
6
+ const projectRoot = path.resolve(fileURLToPath(new URL("..", import.meta.url)));
7
+ const keyshotOutputDir = path.resolve(process.env.KEYSHOT_OUTPUT_DIR ?? path.join(projectRoot, "outputs"));
8
+ return {
9
+ projectRoot,
10
+ keyshotHeadlessExe: process.env.KEYSHOT_HEADLESS_EXE ?? DEFAULT_KEYSHOT_EXE,
11
+ keyshotOutputDir,
12
+ keyshotLicenseArgs: splitWindowsArgs(process.env.KEYSHOT_LICENSE_ARGS ?? ""),
13
+ keyshotTimeoutMs: parsePositiveInt(process.env.KEYSHOT_TIMEOUT_MS, DEFAULT_TIMEOUT_MS),
14
+ tmpDir: path.join(projectRoot, "work", "tmp"),
15
+ bridgeScriptPath: path.join(projectRoot, "scripts", "keyshot_bridge.py"),
16
+ };
17
+ }
18
+ function parsePositiveInt(value, fallback) {
19
+ if (!value)
20
+ return fallback;
21
+ const parsed = Number.parseInt(value, 10);
22
+ return Number.isFinite(parsed) && parsed > 0 ? parsed : fallback;
23
+ }
24
+ function splitWindowsArgs(value) {
25
+ const args = [];
26
+ let current = "";
27
+ let quote = null;
28
+ for (let i = 0; i < value.length; i += 1) {
29
+ const ch = value[i];
30
+ if ((ch === '"' || ch === "'") && quote === null) {
31
+ quote = ch;
32
+ continue;
33
+ }
34
+ if (ch === quote) {
35
+ quote = null;
36
+ continue;
37
+ }
38
+ if (/\s/.test(ch) && quote === null) {
39
+ if (current) {
40
+ args.push(current);
41
+ current = "";
42
+ }
43
+ continue;
44
+ }
45
+ current += ch;
46
+ }
47
+ if (current)
48
+ args.push(current);
49
+ return args;
50
+ }
package/dist/index.js ADDED
@@ -0,0 +1,71 @@
1
+ #!/usr/bin/env node
2
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
3
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4
+ import { getConfig } from "./config.js";
5
+ import { toolResponse } from "./result.js";
6
+ import { runKeyShotSerialized } from "./runner.js";
7
+ import { applyMaterialSchema, applyMaterialInputSchema, batchRenderSchema, importModelSchema, renderSchema, saveSceneSchema, scenePathSchema, setCameraSchema, setEnvironmentSchema, } from "./schemas.js";
8
+ const config = getConfig();
9
+ const server = new McpServer({
10
+ name: "keyshot-mcp",
11
+ version: "0.2.1",
12
+ });
13
+ server.registerResource("keyshot-workflow", "keyshot://workflow", {
14
+ title: "KeyShot MCP Workflow",
15
+ description: "How this MCP server connects AI agents to KeyShot headless scripting.",
16
+ mimeType: "text/plain",
17
+ }, async (uri) => ({
18
+ contents: [
19
+ {
20
+ uri: uri.href,
21
+ text: [
22
+ "KeyShot MCP workflow:",
23
+ "1. The user asks an AI agent to inspect, edit, or render a KeyShot scene.",
24
+ "2. The MCP client sends a structured tool call to this server.",
25
+ "3. This server runs a temporary Python script through KeyShot headless.",
26
+ "4. KeyShot writes images or scene files and returns structured JSON results.",
27
+ ].join("\n"),
28
+ },
29
+ ],
30
+ }));
31
+ server.registerPrompt("keyshot_product_render", {
32
+ title: "Render a KeyShot product scene",
33
+ description: "Create a practical prompt for rendering or batch-rendering a KeyShot product scene.",
34
+ argsSchema: {
35
+ scenePath: scenePathSchema.shape.scenePath.optional(),
36
+ goal: scenePathSchema.shape.scenePath.optional(),
37
+ },
38
+ }, async (args) => ({
39
+ messages: [
40
+ {
41
+ role: "user",
42
+ content: {
43
+ type: "text",
44
+ text: [
45
+ "Use KeyShot MCP to prepare a product render.",
46
+ args.scenePath ? `Scene path: ${args.scenePath}` : "Ask me for the KeyShot scene path first.",
47
+ args.goal ? `Goal: ${args.goal}` : "Inspect the scene, choose a suitable camera, then render a PNG preview.",
48
+ "Start with keyshot_status, then keyshot_inspect_scene, then render or batch render as needed.",
49
+ ].join("\n"),
50
+ },
51
+ },
52
+ ],
53
+ }));
54
+ server.tool("keyshot_status", "Check KeyShot headless availability and script startup.", {}, async () => toolResponse(await runKeyShotSerialized(config, { operation: "status" })));
55
+ server.tool("keyshot_inspect_scene", "Open a KeyShot scene and return available objects, cameras, materials and scene metadata.", scenePathSchema.shape, async (args) => toolResponse(await runKeyShotSerialized(config, { operation: "inspect_scene", ...args })));
56
+ server.tool("keyshot_render", "Render a KeyShot scene to an image file.", renderSchema.shape, async (args) => toolResponse(await runKeyShotSerialized(config, { operation: "render", ...args })));
57
+ server.tool("keyshot_batch_render", "Render multiple named cameras from one KeyShot scene into an output directory.", batchRenderSchema.shape, async (args) => toolResponse(await runKeyShotSerialized(config, { operation: "batch_render", ...args })));
58
+ server.tool("keyshot_import_model", "Import a model into an optional base scene and save the resulting scene.", importModelSchema.shape, async (args) => toolResponse(await runKeyShotSerialized(config, {
59
+ operation: "import_model",
60
+ scenePath: args.baseScenePath,
61
+ ...args,
62
+ })));
63
+ server.tool("keyshot_apply_material", "Apply a material by name or material file to a scene object and save the resulting scene.", applyMaterialInputSchema.shape, async (args) => {
64
+ const parsed = applyMaterialSchema.parse(args);
65
+ return toolResponse(await runKeyShotSerialized(config, { operation: "apply_material", ...parsed }));
66
+ });
67
+ server.tool("keyshot_set_camera", "Create or update a camera from position/look-at vectors and save the resulting scene.", setCameraSchema.shape, async (args) => toolResponse(await runKeyShotSerialized(config, { operation: "set_camera", ...args })));
68
+ server.tool("keyshot_set_environment", "Set a scene environment by name or file when supported by KeyShot headless scripting.", setEnvironmentSchema.shape, async (args) => toolResponse(await runKeyShotSerialized(config, { operation: "set_environment", ...args })));
69
+ server.tool("keyshot_save_scene", "Save a KeyShot scene to a new path.", saveSceneSchema.shape, async (args) => toolResponse(await runKeyShotSerialized(config, { operation: "save_scene", ...args })));
70
+ const transport = new StdioServerTransport();
71
+ await server.connect(transport);
package/dist/result.js ADDED
@@ -0,0 +1,21 @@
1
+ export function toolResponse(result) {
2
+ return {
3
+ content: [
4
+ {
5
+ type: "text",
6
+ text: JSON.stringify(result, null, 2),
7
+ },
8
+ ],
9
+ isError: !result.ok,
10
+ };
11
+ }
12
+ export function localFailure(error, extra) {
13
+ return {
14
+ ok: false,
15
+ data: extra?.data ?? null,
16
+ outputFiles: extra?.outputFiles ?? [],
17
+ warnings: extra?.warnings ?? [],
18
+ keyshotStdoutTail: extra?.keyshotStdoutTail ?? "",
19
+ error,
20
+ };
21
+ }