indesign-cli 0.2.0__py3-none-any.whl

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.
Files changed (72) hide show
  1. cli_anything/indesign/README.md +32 -0
  2. cli_anything/indesign/__init__.py +1 -0
  3. cli_anything/indesign/__main__.py +5 -0
  4. cli_anything/indesign/core/artifacts.py +57 -0
  5. cli_anything/indesign/core/catalog.py +405 -0
  6. cli_anything/indesign/core/domains.py +178 -0
  7. cli_anything/indesign/core/envelope.py +65 -0
  8. cli_anything/indesign/core/errors.py +30 -0
  9. cli_anything/indesign/core/health.py +46 -0
  10. cli_anything/indesign/core/hidden_backend.py +116 -0
  11. cli_anything/indesign/core/hidden_handler_schemas.py +223 -0
  12. cli_anything/indesign/core/mcp_backend.py +152 -0
  13. cli_anything/indesign/core/node_setup.py +35 -0
  14. cli_anything/indesign/core/paths.py +41 -0
  15. cli_anything/indesign/core/plugins/__init__.py +2 -0
  16. cli_anything/indesign/core/plugins/backend.py +90 -0
  17. cli_anything/indesign/core/plugins/discovery.py +69 -0
  18. cli_anything/indesign/core/plugins/host_actions.py +76 -0
  19. cli_anything/indesign/core/plugins/install.py +38 -0
  20. cli_anything/indesign/core/plugins/manifest.py +279 -0
  21. cli_anything/indesign/core/plugins/validate.py +181 -0
  22. cli_anything/indesign/core/router.py +217 -0
  23. cli_anything/indesign/core/runtime.py +59 -0
  24. cli_anything/indesign/core/scripts.py +44 -0
  25. cli_anything/indesign/core/session.py +68 -0
  26. cli_anything/indesign/indesign_cli.py +320 -0
  27. cli_anything/indesign/node/hidden_handler_bridge.mjs +111 -0
  28. cli_anything/indesign/server/package-lock.json +168 -0
  29. cli_anything/indesign/server/package.json +45 -0
  30. cli_anything/indesign/server/src/advanced/index.js +76 -0
  31. cli_anything/indesign/server/src/core/InDesignMCPServer.js +273 -0
  32. cli_anything/indesign/server/src/core/scriptExecutor.js +271 -0
  33. cli_anything/indesign/server/src/core/sessionManager.js +545 -0
  34. cli_anything/indesign/server/src/handlers/advancedTemplateHandlers.js +1072 -0
  35. cli_anything/indesign/server/src/handlers/bookHandlers.js +490 -0
  36. cli_anything/indesign/server/src/handlers/documentHandlers.js +1472 -0
  37. cli_anything/indesign/server/src/handlers/exportHandlers.js +208 -0
  38. cli_anything/indesign/server/src/handlers/graphicsHandlers.js +605 -0
  39. cli_anything/indesign/server/src/handlers/groupHandlers.js +358 -0
  40. cli_anything/indesign/server/src/handlers/helpHandlers.js +347 -0
  41. cli_anything/indesign/server/src/handlers/index.js +77 -0
  42. cli_anything/indesign/server/src/handlers/layerHandlers.js +75 -0
  43. cli_anything/indesign/server/src/handlers/masterSpreadHandlers.js +451 -0
  44. cli_anything/indesign/server/src/handlers/pageHandlers.js +698 -0
  45. cli_anything/indesign/server/src/handlers/pageItemHandlers.js +704 -0
  46. cli_anything/indesign/server/src/handlers/presentationHandlers.js +220 -0
  47. cli_anything/indesign/server/src/handlers/spreadHandlers.js +348 -0
  48. cli_anything/indesign/server/src/handlers/styleHandlers.js +458 -0
  49. cli_anything/indesign/server/src/handlers/textHandlers.js +431 -0
  50. cli_anything/indesign/server/src/handlers/utilityHandlers.js +83 -0
  51. cli_anything/indesign/server/src/index.js +17 -0
  52. cli_anything/indesign/server/src/types/index.js +106 -0
  53. cli_anything/indesign/server/src/types/toolDefinitionsAdvancedTemplates.js +144 -0
  54. cli_anything/indesign/server/src/types/toolDefinitionsBook.js +224 -0
  55. cli_anything/indesign/server/src/types/toolDefinitionsContent.js +353 -0
  56. cli_anything/indesign/server/src/types/toolDefinitionsDocument.js +409 -0
  57. cli_anything/indesign/server/src/types/toolDefinitionsExport.js +65 -0
  58. cli_anything/indesign/server/src/types/toolDefinitionsLayer.js +40 -0
  59. cli_anything/indesign/server/src/types/toolDefinitionsMasterSpread.js +160 -0
  60. cli_anything/indesign/server/src/types/toolDefinitionsPage.js +271 -0
  61. cli_anything/indesign/server/src/types/toolDefinitionsPageItemGroup.js +437 -0
  62. cli_anything/indesign/server/src/types/toolDefinitionsPresentation.js +83 -0
  63. cli_anything/indesign/server/src/types/toolDefinitionsSpread.js +158 -0
  64. cli_anything/indesign/server/src/types/toolDefinitionsUtility.js +40 -0
  65. cli_anything/indesign/server/src/utils/stringUtils.js +107 -0
  66. cli_anything/indesign/skills/SKILL.md +198 -0
  67. indesign_cli-0.2.0.dist-info/METADATA +267 -0
  68. indesign_cli-0.2.0.dist-info/RECORD +72 -0
  69. indesign_cli-0.2.0.dist-info/WHEEL +5 -0
  70. indesign_cli-0.2.0.dist-info/entry_points.txt +3 -0
  71. indesign_cli-0.2.0.dist-info/licenses/LICENSE +21 -0
  72. indesign_cli-0.2.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,76 @@
1
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
2
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
3
+ import { ListToolsRequestSchema, CallToolRequestSchema } from '@modelcontextprotocol/sdk/types.js';
4
+ import { advancedTemplateToolDefinitions } from '../types/toolDefinitionsAdvancedTemplates.js';
5
+ import { AdvancedTemplateHandlers } from '../handlers/advancedTemplateHandlers.js';
6
+ import { formatErrorResponse } from '../utils/stringUtils.js';
7
+
8
+ const TOOL_MAP = {
9
+ list_template_blueprints: AdvancedTemplateHandlers.listTemplateBlueprints,
10
+ inspect_template_blueprint: AdvancedTemplateHandlers.inspectTemplate,
11
+ create_page_with_template: AdvancedTemplateHandlers.createPageWithTemplate,
12
+ get_page_information: AdvancedTemplateHandlers.getPageInformation,
13
+ populate_template_slots: AdvancedTemplateHandlers.fillTemplateFromSlots,
14
+ run_jsx_file: AdvancedTemplateHandlers.runJsxFile,
15
+ };
16
+
17
+ class AdvancedTemplateServer {
18
+ constructor() {
19
+ this.server = new Server(
20
+ {
21
+ name: 'indesign-template-orchestrator',
22
+ version: '0.1.0'
23
+ },
24
+ {
25
+ capabilities: {
26
+ tools: {}
27
+ }
28
+ }
29
+ );
30
+
31
+ this.server.setRequestHandler(ListToolsRequestSchema, async () => ({
32
+ tools: advancedTemplateToolDefinitions.map((tool) => ({
33
+ name: tool.name,
34
+ description: tool.description,
35
+ inputSchema: tool.inputSchema
36
+ }))
37
+ }));
38
+
39
+ this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
40
+ const { name, arguments: args } = request.params;
41
+ const handler = TOOL_MAP[name];
42
+ if (!handler) {
43
+ const payload = formatErrorResponse(`Tool not found: ${name}`, 'Advanced Template Tool Call');
44
+ return {
45
+ content: [{ type: 'text', text: JSON.stringify(payload, null, 2) }]
46
+ };
47
+ }
48
+ try {
49
+ const result = await handler(args || {});
50
+ return {
51
+ content: [{ type: 'text', text: JSON.stringify(result, null, 2) }]
52
+ };
53
+ } catch (error) {
54
+ const payload = formatErrorResponse(error.message, `Advanced Template Tool '${name}'`);
55
+ return {
56
+ content: [{ type: 'text', text: JSON.stringify(payload, null, 2) }]
57
+ };
58
+ }
59
+ });
60
+ }
61
+
62
+ async run() {
63
+ const transport = new StdioServerTransport();
64
+ await this.server.connect(transport);
65
+ }
66
+ }
67
+
68
+ async function main() {
69
+ const server = new AdvancedTemplateServer();
70
+ await server.run();
71
+ }
72
+
73
+ main().catch((error) => {
74
+ console.error('Failed to start advanced template server:', error);
75
+ process.exit(1);
76
+ });
@@ -0,0 +1,273 @@
1
+ /**
2
+ * Main InDesign MCP Server class
3
+ */
4
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
5
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
6
+ import { ListToolsRequestSchema, CallToolRequestSchema } from '@modelcontextprotocol/sdk/types.js';
7
+ import { allToolDefinitions } from '../types/index.js';
8
+ import {
9
+ BookHandlers,
10
+ DocumentHandlers,
11
+ ExportHandlers,
12
+ GraphicsHandlers,
13
+ GroupHandlers,
14
+ HelpHandlers,
15
+ MasterSpreadHandlers,
16
+ SpreadHandlers,
17
+ LayerHandlers,
18
+ PageHandlers,
19
+ PageItemHandlers,
20
+ StyleHandlers,
21
+ TextHandlers,
22
+ UtilityHandlers,
23
+ PresentationHandlers
24
+ } from '../handlers/index.js';
25
+ import { formatErrorResponse } from '../utils/stringUtils.js';
26
+
27
+ export class InDesignMCPServer {
28
+ constructor() {
29
+ this.server = new Server(
30
+ {
31
+ name: 'indesign-server-complete',
32
+ version: '1.0.0',
33
+ },
34
+ {
35
+ capabilities: {
36
+ tools: {},
37
+ },
38
+ }
39
+ );
40
+
41
+ this.setupToolHandlers();
42
+ }
43
+
44
+ setupToolHandlers() {
45
+ this.server.setRequestHandler(ListToolsRequestSchema, async () => ({
46
+ tools: allToolDefinitions,
47
+ }));
48
+
49
+ this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
50
+ const { name, arguments: args } = request.params;
51
+
52
+ try {
53
+ const result = await this.handleToolCall(name, args);
54
+ return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
55
+ } catch (error) {
56
+ return { content: [{ type: 'text', text: `Error: ${error.message}` }] };
57
+ }
58
+ });
59
+ }
60
+
61
+ async handleToolCall(name, args) {
62
+ // Document Management
63
+ switch (name) {
64
+ case 'get_document_info': return await DocumentHandlers.getDocumentInfo();
65
+ case 'create_document': return await DocumentHandlers.createDocument(args);
66
+ case 'open_document': return await DocumentHandlers.openDocument(args);
67
+ case 'save_document': return await DocumentHandlers.saveDocument(args);
68
+ case 'close_document': return await DocumentHandlers.closeDocument();
69
+
70
+ // Document Advanced Tools
71
+ case 'preflight_document': return await DocumentHandlers.preflightDocument(args);
72
+ case 'zoom_to_page': return await DocumentHandlers.zoomToPage(args);
73
+ case 'data_merge': return await DocumentHandlers.dataMerge(args);
74
+
75
+ // Document Elements & Styles
76
+ case 'get_document_elements': return await DocumentHandlers.getDocumentElements(args);
77
+ case 'get_document_styles': return await DocumentHandlers.getDocumentStyles(args);
78
+ case 'get_document_colors': return await DocumentHandlers.getDocumentColors(args);
79
+
80
+ // Document Preferences
81
+ case 'get_document_preferences': return await DocumentHandlers.getDocumentPreferences(args);
82
+ case 'set_document_preferences': return await DocumentHandlers.setDocumentPreferences(args);
83
+
84
+ // Document Stories & Text
85
+ case 'get_document_stories': return await DocumentHandlers.getDocumentStories(args);
86
+ case 'find_text_in_document': return await DocumentHandlers.findTextInDocument(args);
87
+
88
+ // Document Layers & Organization
89
+ case 'get_document_layers': return await DocumentHandlers.getDocumentLayers(args);
90
+ case 'organize_document_layers': return await DocumentHandlers.organizeDocumentLayers(args);
91
+
92
+ // Document Hyperlinks & Interactivity
93
+ case 'get_document_hyperlinks': return await DocumentHandlers.getDocumentHyperlinks(args);
94
+ case 'create_document_hyperlink': return await DocumentHandlers.createDocumentHyperlink(args);
95
+
96
+ // Document Sections & Numbering
97
+ case 'get_document_sections': return await DocumentHandlers.getDocumentSections();
98
+ case 'create_document_section': return await DocumentHandlers.createDocumentSection(args);
99
+
100
+ // Document XML & Structure
101
+ case 'get_document_xml_structure': return await DocumentHandlers.getDocumentXmlStructure(args);
102
+ case 'export_document_xml': return await DocumentHandlers.exportDocumentXml(args);
103
+
104
+ // Document Cloud & Collaboration
105
+ case 'save_document_to_cloud': return await DocumentHandlers.saveDocumentToCloud(args);
106
+ case 'open_cloud_document': return await DocumentHandlers.openCloudDocument(args);
107
+
108
+ // Document Grid & Layout
109
+ case 'get_document_grid_settings': return await DocumentHandlers.getDocumentGridSettings();
110
+ case 'set_document_grid_settings': return await DocumentHandlers.setDocumentGridSettings(args);
111
+ case 'get_document_layout_preferences': return await DocumentHandlers.getDocumentLayoutPreferences();
112
+ case 'set_document_layout_preferences': return await DocumentHandlers.setDocumentLayoutPreferences(args);
113
+
114
+ // Document Validation & Cleanup
115
+ case 'validate_document': return await DocumentHandlers.validateDocument(args);
116
+ case 'cleanup_document': return await DocumentHandlers.cleanupDocument(args);
117
+
118
+ // Page Management
119
+ case 'add_page': return await PageHandlers.addPage(args);
120
+ case 'get_page_info': return await PageHandlers.getPageInfo(args);
121
+ case 'navigate_to_page': return await PageHandlers.navigateToPage(args);
122
+
123
+ // Advanced Page Management
124
+ case 'duplicate_page': return await PageHandlers.duplicatePage(args);
125
+ case 'move_page': return await PageHandlers.movePage(args);
126
+ case 'delete_page': return await PageHandlers.deletePage(args);
127
+ case 'set_page_properties': return await PageHandlers.setPageProperties(args);
128
+ case 'set_page_background': return await PageHandlers.setPageBackground(args);
129
+ case 'adjust_page_layout': return await PageHandlers.adjustPageLayout(args);
130
+ case 'resize_page': return await PageHandlers.resizePage(args);
131
+ case 'create_page_guides': return await PageHandlers.createPageGuides(args);
132
+ case 'place_file_on_page': return await PageHandlers.placeFileOnPage(args);
133
+ case 'place_xml_on_page': return await PageHandlers.placeXmlOnPage(args);
134
+ case 'snapshot_page_layout': return await PageHandlers.snapshotPageLayout(args);
135
+ case 'delete_page_layout_snapshot': return await PageHandlers.deletePageLayoutSnapshot(args);
136
+ case 'delete_all_page_layout_snapshots': return await PageHandlers.deleteAllPageLayoutSnapshots(args);
137
+ case 'reframe_page': return await PageHandlers.reframePage(args);
138
+ case 'select_page': return await PageHandlers.selectPage(args);
139
+ case 'get_page_content_summary': return await PageHandlers.getPageContentSummary(args);
140
+
141
+ // Text Management
142
+ case 'create_text_frame': return await TextHandlers.createTextFrame(args);
143
+ case 'edit_text_frame': return await TextHandlers.editTextFrame(args);
144
+ case 'create_table': return await TextHandlers.createTable(args);
145
+ case 'populate_table': return await TextHandlers.populateTable(args);
146
+ case 'find_replace_text': return await TextHandlers.findReplaceText(args);
147
+
148
+ // Graphics Management
149
+ case 'create_rectangle': return await GraphicsHandlers.createRectangle(args);
150
+ case 'create_ellipse': return await GraphicsHandlers.createEllipse(args);
151
+ case 'create_polygon': return await GraphicsHandlers.createPolygon(args);
152
+ case 'place_image': return await GraphicsHandlers.placeImage(args);
153
+ case 'create_object_style': return await GraphicsHandlers.createObjectStyle(args);
154
+ case 'list_object_styles': return await GraphicsHandlers.listObjectStyles();
155
+ case 'apply_object_style': return await GraphicsHandlers.applyObjectStyle(args);
156
+ case 'get_image_info': return await GraphicsHandlers.getImageInfo(args);
157
+
158
+ // Style Management
159
+ case 'create_paragraph_style': return await StyleHandlers.createParagraphStyle(args);
160
+ case 'create_character_style': return await StyleHandlers.createCharacterStyle(args);
161
+ case 'apply_paragraph_style': return await StyleHandlers.applyParagraphStyle(args);
162
+ case 'apply_character_style': return await StyleHandlers.applyCharacterStyle(args);
163
+ case 'apply_color': return await StyleHandlers.applyColor(args);
164
+ case 'create_color_swatch': return await StyleHandlers.createColorSwatch(args);
165
+ case 'list_styles': return await StyleHandlers.listStyles(args);
166
+ case 'list_color_swatches': return await StyleHandlers.listColorSwatches();
167
+
168
+ // Export Functions
169
+ case 'export_pdf': return await ExportHandlers.exportPDF(args);
170
+ case 'export_images': return await ExportHandlers.exportImages(args);
171
+ case 'package_document': return await ExportHandlers.packageDocument(args);
172
+ case 'export_epub': return await ExportHandlers.exportEPUB(args);
173
+
174
+ // Master Spread Management
175
+ case 'create_master_spread': return await MasterSpreadHandlers.createMasterSpread(args);
176
+ case 'list_master_spreads': return await MasterSpreadHandlers.listMasterSpreads(args);
177
+ case 'delete_master_spread': return await MasterSpreadHandlers.deleteMasterSpread(args);
178
+ case 'duplicate_master_spread': return await MasterSpreadHandlers.duplicateMasterSpread(args);
179
+ case 'apply_master_spread': return await MasterSpreadHandlers.applyMasterSpread(args);
180
+ case 'create_master_text_frame': return await MasterSpreadHandlers.createMasterTextFrame(args);
181
+ case 'create_master_rectangle': return await MasterSpreadHandlers.createMasterRectangle(args);
182
+ case 'create_master_guides': return await MasterSpreadHandlers.createMasterGuides(args);
183
+ case 'get_master_spread_info': return await MasterSpreadHandlers.getMasterSpreadInfo(args);
184
+ case 'detach_master_items': return await MasterSpreadHandlers.detachMasterItems(args);
185
+ case 'remove_master_override': return await MasterSpreadHandlers.removeMasterOverride(args);
186
+
187
+ // Spread Management
188
+ case 'list_spreads': return await SpreadHandlers.listSpreads(args);
189
+ case 'get_spread_info': return await SpreadHandlers.getSpreadInfo(args);
190
+ case 'duplicate_spread': return await SpreadHandlers.duplicateSpread(args);
191
+ case 'move_spread': return await SpreadHandlers.moveSpread(args);
192
+ case 'delete_spread': return await SpreadHandlers.deleteSpread(args);
193
+ case 'set_spread_properties': return await SpreadHandlers.setSpreadProperties(args);
194
+ case 'create_spread_guides': return await SpreadHandlers.createSpreadGuides(args);
195
+ case 'place_file_on_spread': return await SpreadHandlers.placeFileOnSpread(args);
196
+ case 'place_xml_on_spread': return await SpreadHandlers.placeXmlOnSpread(args);
197
+ case 'select_spread': return await SpreadHandlers.selectSpread(args);
198
+ case 'get_spread_content_summary': return await SpreadHandlers.getSpreadContentSummary(args);
199
+
200
+ // Layer Management
201
+ case 'create_layer': return await LayerHandlers.createLayer(args);
202
+ case 'set_active_layer': return await LayerHandlers.setActiveLayer(args);
203
+ case 'list_layers': return await LayerHandlers.listLayers(args);
204
+
205
+ // Book Management
206
+ case 'create_book': return await BookHandlers.createBook(args);
207
+ case 'open_book': return await BookHandlers.openBook(args);
208
+ case 'list_books': return await BookHandlers.listBooks(args);
209
+ case 'add_document_to_book': return await BookHandlers.addDocumentToBook(args);
210
+ case 'synchronize_book': return await BookHandlers.synchronizeBook(args);
211
+ case 'repaginate_book': return await BookHandlers.repaginateBook(args);
212
+ case 'update_all_cross_references': return await BookHandlers.updateAllCrossReferences(args);
213
+ case 'update_all_numbers': return await BookHandlers.updateAllNumbers(args);
214
+ case 'update_chapter_and_paragraph_numbers': return await BookHandlers.updateChapterAndParagraphNumbers(args);
215
+ case 'export_book': return await BookHandlers.exportBook(args);
216
+ case 'package_book': return await BookHandlers.packageBook(args);
217
+ case 'preflight_book': return await BookHandlers.preflightBook(args);
218
+ case 'print_book': return await BookHandlers.printBook(args);
219
+ case 'get_book_info': return await BookHandlers.getBookInfo(args);
220
+ case 'set_book_properties': return await BookHandlers.setBookProperties(args);
221
+
222
+ // PageItem Management
223
+ case 'get_page_item_info': return await PageItemHandlers.getPageItemInfo(args);
224
+ case 'select_page_item': return await PageItemHandlers.selectPageItem(args);
225
+ case 'move_page_item': return await PageItemHandlers.movePageItem(args);
226
+ case 'resize_page_item': return await PageItemHandlers.resizePageItem(args);
227
+ case 'set_page_item_properties': return await PageItemHandlers.setPageItemProperties(args);
228
+ case 'duplicate_page_item': return await PageItemHandlers.duplicatePageItem(args);
229
+ case 'delete_page_item': return await PageItemHandlers.deletePageItem(args);
230
+ case 'get_page_item_script_labels': return await PageItemHandlers.getPageItemScriptLabels(args);
231
+ case 'set_page_item_script_label': return await PageItemHandlers.setPageItemScriptLabel(args);
232
+ case 'list_page_items': return await PageItemHandlers.listPageItems(args);
233
+
234
+ // Group Management
235
+ case 'create_group': return await GroupHandlers.createGroup(args);
236
+ case 'create_group_from_items': return await GroupHandlers.createGroupFromItems(args);
237
+ case 'ungroup': return await GroupHandlers.ungroup(args);
238
+ case 'get_group_info': return await GroupHandlers.getGroupInfo(args);
239
+ case 'add_item_to_group': return await GroupHandlers.addItemToGroup(args);
240
+ case 'remove_item_from_group': return await GroupHandlers.removeItemFromGroup(args);
241
+ case 'list_groups': return await GroupHandlers.listGroups(args);
242
+ case 'set_group_properties': return await GroupHandlers.setGroupProperties(args);
243
+
244
+ // Utility Functions
245
+ case 'execute_indesign_code': return await UtilityHandlers.executeInDesignCode(args);
246
+ case 'view_document': return await UtilityHandlers.viewDocument();
247
+ case 'get_session_info': return await UtilityHandlers.getSessionInfo();
248
+ case 'clear_session': return await UtilityHandlers.clearSession();
249
+
250
+ // Presentation (Architecture report deck)
251
+ case 'create_presentation_document': return await PresentationHandlers.createPresentationDocument(args);
252
+ case 'add_cover_page': return await PresentationHandlers.addCoverPage(args);
253
+ case 'add_section_page': return await PresentationHandlers.addSectionPage(args);
254
+ case 'add_full_bleed_image': return await PresentationHandlers.addFullBleedImage(args);
255
+ case 'add_image_grid': return await PresentationHandlers.addImageGrid(args);
256
+ case 'export_presentation_pdf': return await PresentationHandlers.exportPresentationPDF(args);
257
+
258
+ // Help System
259
+ case 'help': return await HelpHandlers.getHelp(args);
260
+
261
+ // Add more handlers as we create them
262
+ default:
263
+ return formatErrorResponse(`Tool '${name}' not found or not implemented. Use 'help' to see available tools.`, "Tool Call");
264
+ }
265
+ }
266
+
267
+ async run() {
268
+ const transport = new StdioServerTransport();
269
+ await this.server.connect(transport);
270
+ // Don't log to stdout as it interferes with MCP protocol
271
+ // console.log('InDesign MCP Server started');
272
+ }
273
+ }
@@ -0,0 +1,271 @@
1
+ /**
2
+ * Core script execution functionality (macOS AppleScript + Windows COM)
3
+ */
4
+ import { execFileSync } from 'child_process';
5
+ import fs from 'fs';
6
+ import path from 'path';
7
+ import os from 'os';
8
+ import { fileURLToPath } from 'url';
9
+ import { createRequire } from 'module';
10
+
11
+ const __filename = fileURLToPath(import.meta.url);
12
+ const __dirname = path.dirname(__filename);
13
+
14
+ const EXTENDSCRIPT_RUNTIME_SNIPPET = `
15
+ if (typeof JSON === "undefined") { JSON = {}; }
16
+ function __mcpJsonSeenContains(arr, value) {
17
+ for (var i = 0; i < arr.length; i++) {
18
+ if (arr[i] === value) return true;
19
+ }
20
+ return false;
21
+ }
22
+ function __mcpJsonEscapeString(str) {
23
+ if (str === null || str === undefined) return "";
24
+ var result = "";
25
+ var backslash = String.fromCharCode(92);
26
+ for (var i = 0; i < str.length; i++) {
27
+ var ch = str.charAt(i);
28
+ var code = str.charCodeAt(i);
29
+ if (code === 34) {
30
+ result += backslash + '"';
31
+ } else if (code === 92) {
32
+ result += backslash + backslash;
33
+ } else if (code === 8) {
34
+ result += backslash + "b";
35
+ } else if (code === 9) {
36
+ result += backslash + "t";
37
+ } else if (code === 10) {
38
+ result += backslash + "n";
39
+ } else if (code === 12) {
40
+ result += backslash + "f";
41
+ } else if (code === 13) {
42
+ result += backslash + "r";
43
+ } else if (code === 0x2028 || code === 0x2029) {
44
+ result += backslash + "u" + code.toString(16);
45
+ } else if (code < 32) {
46
+ var hex = code.toString(16);
47
+ result += backslash + "u" + ("0000" + hex).slice(-4);
48
+ } else {
49
+ result += ch;
50
+ }
51
+ }
52
+ return result;
53
+ }
54
+ function __mcpJsonSerialize(value) {
55
+ var seen = [];
56
+ function serialize(v) {
57
+ if (v === null) return "null";
58
+ var t = typeof v;
59
+ if (t === "number" || t === "boolean") return String(v);
60
+ if (t === "string") return '"' + __mcpJsonEscapeString(v) + '"';
61
+ if (v instanceof Array) {
62
+ var arr = [];
63
+ for (var i = 0; i < v.length; i++) arr.push(serialize(v[i]));
64
+ return "[" + arr.join(",") + "]";
65
+ }
66
+ if (t === "object") {
67
+ if (__mcpJsonSeenContains(seen, v)) return '"[Circular]"';
68
+ seen.push(v);
69
+ var props = [];
70
+ for (var key in v) {
71
+ if (!v.hasOwnProperty(key)) continue;
72
+ props.push('"' + __mcpJsonEscapeString(key) + '":' + serialize(v[key]));
73
+ }
74
+ seen.pop();
75
+ return "{" + props.join(",") + "}";
76
+ }
77
+ return "null";
78
+ }
79
+ return serialize(value);
80
+ }
81
+ if (typeof JSON.stringify !== "function") {
82
+ JSON.stringify = function(value) { return __mcpJsonSerialize(value); };
83
+ }
84
+ if (typeof JSON.parse !== "function") {
85
+ JSON.parse = function(text) { return eval("(" + text + ")"); };
86
+ }
87
+ `;
88
+
89
+ export class ScriptExecutor {
90
+ // Cache a COM Application instance for Windows to avoid repeated activation
91
+ static _winApp = null;
92
+
93
+ static isWindows() {
94
+ return process.platform === 'win32';
95
+ }
96
+
97
+ /**
98
+ * Execute AppleScript command (macOS only)
99
+ * @param {string} script - The AppleScript to execute
100
+ * @returns {string} The result of the AppleScript execution
101
+ */
102
+ static async executeAppleScript(script) {
103
+ try {
104
+ const result = execFileSync('osascript', ['-e', script], { encoding: 'utf8' });
105
+ return result.trim();
106
+ } catch (error) {
107
+ throw new Error(`AppleScript execution failed: ${error.message}`);
108
+ }
109
+ }
110
+
111
+ /**
112
+ * Resolve a Windows COM InDesign.Application object via winax
113
+ * Tries multiple ProgIDs to maximize compatibility across versions.
114
+ */
115
+ static _getWindowsInDesignApp() {
116
+ if (!this.isWindows()) {
117
+ throw new Error('Windows COM is only available on Windows');
118
+ }
119
+ if (this._winApp) return this._winApp;
120
+
121
+ // Lazy-require winax to avoid issues on non-Windows platforms
122
+ const requireCjs = createRequire(import.meta.url);
123
+ let WinaxObject;
124
+ try {
125
+ const winax = requireCjs('winax');
126
+ // winax provides constructor as winax.Object and also sets global.ActiveXObject in CJS
127
+ WinaxObject = winax.Object || global.ActiveXObject;
128
+ } catch (e) {
129
+ throw new Error("Missing dependency 'winax'. Please run: npm install winax");
130
+ }
131
+
132
+ // Prefer explicit recent desktop ProgIDs, then generic, then older versions
133
+ const progIDs = [
134
+ // Newer/future first
135
+ 'InDesign.Application.2026',
136
+ 'InDesign.Application.CC.2026',
137
+ // Current
138
+ 'InDesign.Application.2025',
139
+ 'InDesign.Application.CC.2025',
140
+ // Generic
141
+ 'InDesign.Application',
142
+ // Recent past
143
+ 'InDesign.Application.2024',
144
+ 'InDesign.Application.CC.2024',
145
+ 'InDesign.Application.2023',
146
+ 'InDesign.Application.CC.2023',
147
+ 'InDesign.Application.2022',
148
+ 'InDesign.Application.CC.2022',
149
+ // InDesign Server fallbacks (least preferred)
150
+ 'InDesignServer.Application.2025',
151
+ 'InDesignServer.Application.2024',
152
+ 'InDesignServer.Application',
153
+ ];
154
+
155
+ let lastError;
156
+ for (const id of progIDs) {
157
+ try {
158
+ const app = new WinaxObject(id);
159
+ this._winApp = app;
160
+ return app;
161
+ } catch (err) {
162
+ lastError = err;
163
+ }
164
+ }
165
+ throw new Error(
166
+ `Could not create InDesign COM object. Tried: ${progIDs.join(', ')}. ` +
167
+ `Last error: ${lastError?.message || lastError}. ` +
168
+ `Tips: Ensure Adobe InDesign desktop is installed and has been launched at least once, ` +
169
+ `and that COM registration is available. If installation is fresh, try restarting or running once as administrator.`
170
+ );
171
+ }
172
+
173
+ /**
174
+ * Execute InDesign ExtendScript/JavaScript code
175
+ * - On Windows: Use COM DoScript via winax
176
+ * - On macOS: Use AppleScript to run the temp JSX file
177
+ * @param {string} script - The ExtendScript to execute
178
+ * @returns {string} The result of the script execution
179
+ */
180
+ static async executeInDesignScript(script) {
181
+ if (this.isWindows()) {
182
+ return await this._executeInDesignScriptWindows(script);
183
+ }
184
+ // macOS path (AppleScript + temp JSX file)
185
+ let tempDir;
186
+ let tempScriptPath;
187
+ try {
188
+ tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'indesign-mcp-'));
189
+ tempScriptPath = path.join(tempDir, 'script.jsx');
190
+
191
+ // Force non-interactive (headless) execution where possible
192
+ const wrapped = [
193
+ 'try {',
194
+ ' app.scriptPreferences.userInteractionLevel = UserInteractionLevels.NEVER_INTERACT;',
195
+ EXTENDSCRIPT_RUNTIME_SNIPPET,
196
+ script,
197
+ '} catch (e) {',
198
+ ' "Error: " + e.message;',
199
+ '}'
200
+ ].join('\n');
201
+ fs.writeFileSync(tempScriptPath, wrapped, { encoding: 'utf8' });
202
+
203
+ const escapedScriptPath = tempScriptPath.replace(/"/g, '\\"');
204
+ const appleScript = `
205
+ tell application "Adobe InDesign 2025"
206
+ do script POSIX file "${escapedScriptPath}" language javascript
207
+ end tell
208
+ `;
209
+
210
+ const result = await this.executeAppleScript(appleScript);
211
+
212
+ return result;
213
+ } catch (error) {
214
+ throw new Error(`Error executing tool (macOS): ${error.message}`);
215
+ } finally {
216
+ if (tempDir) {
217
+ try { fs.rmSync(tempDir, { recursive: true, force: true }); } catch {}
218
+ }
219
+ }
220
+ }
221
+
222
+ /**
223
+ * Execute a JSX file directly so $.fileName, relative #include, etc. behave correctly.
224
+ * @param {string} filePath - Absolute or relative path to the JSX file.
225
+ * @returns {string} The result of the script execution.
226
+ */
227
+ static async executeInDesignScriptFile(filePath) {
228
+ if (!filePath || typeof filePath !== 'string') {
229
+ throw new Error('filePath must be a string');
230
+ }
231
+ const resolved = path.resolve(filePath);
232
+ const escaped = resolved.replace(/\\/g, '\\\\').replace(/"/g, '\\"');
233
+ const wrapper = [
234
+ 'var __mcpResult = "";',
235
+ 'try {',
236
+ ` var __mcpFile = File("${escaped}");`,
237
+ ' if (!__mcpFile.exists) { throw new Error("JSX 文件不存在: " + __mcpFile.fsName); }',
238
+ ' __mcpResult = app.doScript(__mcpFile, ScriptLanguage.JAVASCRIPT);',
239
+ '} catch (e) {',
240
+ ' __mcpResult = "Error: " + (e && e.message ? e.message : e);',
241
+ '}',
242
+ '__mcpResult;'
243
+ ].join('\n');
244
+ return await this.executeInDesignScript(wrapper);
245
+ }
246
+
247
+ /**
248
+ * Windows: Execute via COM DoScript
249
+ */
250
+ static async _executeInDesignScriptWindows(script) {
251
+ try {
252
+ const app = this._getWindowsInDesignApp();
253
+ // Wrap to enforce non-interactive mode and basic error capture
254
+ const wrapped = [
255
+ 'try {',
256
+ ' app.scriptPreferences.userInteractionLevel = UserInteractionLevels.NEVER_INTERACT;',
257
+ EXTENDSCRIPT_RUNTIME_SNIPPET,
258
+ script,
259
+ '} catch (e) {',
260
+ ' "Error: " + e.message;',
261
+ '}'
262
+ ].join('\n');
263
+ // ScriptLanguage.JAVASCRIPT (numeric enum for COM environments)
264
+ const ScriptLanguage_JAVASCRIPT = 1246973031;
265
+ const result = app.DoScript(wrapped, ScriptLanguage_JAVASCRIPT);
266
+ return (result === undefined || result === null) ? '' : String(result);
267
+ } catch (error) {
268
+ throw new Error(`Windows COM execution failed: ${error.message}`);
269
+ }
270
+ }
271
+ }