iwork-mcp 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/tools/keynote.js +74 -0
- package/dist/tools/numbers.js +89 -6
- package/package.json +1 -1
package/dist/tools/keynote.js
CHANGED
|
@@ -104,6 +104,80 @@ export function registerKeynoteTools(server) {
|
|
|
104
104
|
return { index: i, slideNumber: i + 1, title: title, skipped: s.skipped() };
|
|
105
105
|
}));
|
|
106
106
|
`, { documentName })));
|
|
107
|
+
server.tool("keynote_get_slide_content", "Read all content from a slide: title, body, presenter notes, and list of items", {
|
|
108
|
+
documentName: z.string().describe("Name of the open presentation"),
|
|
109
|
+
slideNumber: z.number().describe("Slide number (1-based)"),
|
|
110
|
+
}, async ({ documentName, slideNumber }) => handleJXA(() => runJXA(`
|
|
111
|
+
const app = Application("Keynote");
|
|
112
|
+
const doc = app.documents.byName(params.documentName);
|
|
113
|
+
const slide = doc.slides[params.slideNumber - 1];
|
|
114
|
+
|
|
115
|
+
let title = "";
|
|
116
|
+
try { const t = slide.defaultTitleItem(); if (t) title = t.objectText(); } catch(e) {}
|
|
117
|
+
let body = "";
|
|
118
|
+
try { const b = slide.defaultBodyItem(); if (b) body = b.objectText(); } catch(e) {}
|
|
119
|
+
let notes = "";
|
|
120
|
+
try { notes = slide.presenterNotes(); } catch(e) {}
|
|
121
|
+
|
|
122
|
+
const textItems = [];
|
|
123
|
+
try {
|
|
124
|
+
const items = slide.textItems();
|
|
125
|
+
for (let i = 0; i < items.length; i++) {
|
|
126
|
+
textItems.push({ index: i, text: items[i].objectText(), width: items[i].width(), height: items[i].height() });
|
|
127
|
+
}
|
|
128
|
+
} catch(e) {}
|
|
129
|
+
|
|
130
|
+
const images = [];
|
|
131
|
+
try {
|
|
132
|
+
const imgs = slide.images();
|
|
133
|
+
for (let i = 0; i < imgs.length; i++) {
|
|
134
|
+
images.push({ index: i, width: imgs[i].width(), height: imgs[i].height() });
|
|
135
|
+
}
|
|
136
|
+
} catch(e) {}
|
|
137
|
+
|
|
138
|
+
const shapes = [];
|
|
139
|
+
try {
|
|
140
|
+
const shps = slide.shapes();
|
|
141
|
+
for (let i = 0; i < shps.length; i++) {
|
|
142
|
+
shapes.push({ index: i, text: shps[i].objectText(), width: shps[i].width(), height: shps[i].height() });
|
|
143
|
+
}
|
|
144
|
+
} catch(e) {}
|
|
145
|
+
|
|
146
|
+
return JSON.stringify({ slideNumber: params.slideNumber, title, body, presenterNotes: notes, textItems, images, shapes });
|
|
147
|
+
`, { documentName, slideNumber })));
|
|
148
|
+
server.tool("keynote_delete_slide", "Delete a slide from the presentation", {
|
|
149
|
+
documentName: z.string().describe("Name of the open presentation"),
|
|
150
|
+
slideNumber: z.number().describe("Slide number to delete (1-based)"),
|
|
151
|
+
}, async ({ documentName, slideNumber }) => handleJXA(() => runJXA(`
|
|
152
|
+
const app = Application("Keynote");
|
|
153
|
+
const doc = app.documents.byName(params.documentName);
|
|
154
|
+
app.delete(doc.slides[params.slideNumber - 1]);
|
|
155
|
+
return JSON.stringify({ deleted: true, slideNumber: params.slideNumber, remainingSlides: doc.slides.length });
|
|
156
|
+
`, { documentName, slideNumber })));
|
|
157
|
+
server.tool("keynote_duplicate_slide", "Duplicate an existing slide", {
|
|
158
|
+
documentName: z.string().describe("Name of the open presentation"),
|
|
159
|
+
slideNumber: z.number().describe("Slide number to duplicate (1-based)"),
|
|
160
|
+
}, async ({ documentName, slideNumber }) => handleJXA(() => runJXA(`
|
|
161
|
+
const app = Application("Keynote");
|
|
162
|
+
const doc = app.documents.byName(params.documentName);
|
|
163
|
+
app.duplicate(doc.slides[params.slideNumber - 1]);
|
|
164
|
+
return JSON.stringify({ duplicated: true, totalSlides: doc.slides.length });
|
|
165
|
+
`, { documentName, slideNumber })));
|
|
166
|
+
server.tool("keynote_list_master_slides", "List all available master slide layouts in the current theme", {
|
|
167
|
+
documentName: z.string().describe("Name of the open presentation"),
|
|
168
|
+
}, async ({ documentName }) => handleJXA(() => runJXA(`
|
|
169
|
+
const app = Application("Keynote");
|
|
170
|
+
const doc = app.documents.byName(params.documentName);
|
|
171
|
+
const masters = doc.masterSlides();
|
|
172
|
+
return JSON.stringify(masters.map((m, i) => ({ index: i, name: m.name() })));
|
|
173
|
+
`, { documentName })));
|
|
174
|
+
server.tool("keynote_stop_slideshow", "Stop a running slideshow", {
|
|
175
|
+
documentName: z.string().describe("Name of the open presentation"),
|
|
176
|
+
}, async ({ documentName }) => handleJXA(() => runJXA(`
|
|
177
|
+
const app = Application("Keynote");
|
|
178
|
+
app.stop(app.documents.byName(params.documentName));
|
|
179
|
+
return JSON.stringify({ stopped: true });
|
|
180
|
+
`, { documentName })));
|
|
107
181
|
server.tool("keynote_add_slide", "Add a new slide to the presentation", {
|
|
108
182
|
documentName: z.string().describe("Name of the open presentation"),
|
|
109
183
|
masterSlideName: z.string().optional().describe("Master slide / layout name (e.g. 'Title & Subtitle', 'Blank')"),
|
package/dist/tools/numbers.js
CHANGED
|
@@ -154,6 +154,92 @@ export function registerNumbersTools(server) {
|
|
|
154
154
|
columnCount: table.columnCount(),
|
|
155
155
|
});
|
|
156
156
|
`, { documentName, sheetName: sheetName ?? null, tableName: tableName ?? null, rows: rows ?? null, columns: columns ?? null })));
|
|
157
|
+
server.tool("numbers_rename_sheet", "Rename a sheet in a Numbers document", {
|
|
158
|
+
documentName: z.string().describe("Name of the open document"),
|
|
159
|
+
sheetName: z.string().describe("Current sheet name"),
|
|
160
|
+
newName: z.string().describe("New name for the sheet"),
|
|
161
|
+
}, async ({ documentName, sheetName, newName }) => handleJXA(() => runJXA(`
|
|
162
|
+
const app = Application("Numbers");
|
|
163
|
+
const doc = app.documents.byName(params.documentName);
|
|
164
|
+
const sheet = doc.sheets.byName(params.sheetName);
|
|
165
|
+
sheet.name = params.newName;
|
|
166
|
+
return JSON.stringify({ renamed: true, oldName: params.sheetName, newName: params.newName });
|
|
167
|
+
`, { documentName, sheetName, newName })));
|
|
168
|
+
server.tool("numbers_delete_sheet", "Delete a sheet from a Numbers document", {
|
|
169
|
+
documentName: z.string().describe("Name of the open document"),
|
|
170
|
+
sheetName: z.string().describe("Name of the sheet to delete"),
|
|
171
|
+
}, async ({ documentName, sheetName }) => handleJXA(() => runJXA(`
|
|
172
|
+
const app = Application("Numbers");
|
|
173
|
+
const doc = app.documents.byName(params.documentName);
|
|
174
|
+
const sheet = doc.sheets.byName(params.sheetName);
|
|
175
|
+
app.delete(sheet);
|
|
176
|
+
return JSON.stringify({ deleted: true, sheetName: params.sheetName });
|
|
177
|
+
`, { documentName, sheetName })));
|
|
178
|
+
server.tool("numbers_rename_table", "Rename a table in a Numbers document", {
|
|
179
|
+
documentName: z.string().describe("Name of the open document"),
|
|
180
|
+
tableName: z.string().describe("Current table name"),
|
|
181
|
+
newName: z.string().describe("New name for the table"),
|
|
182
|
+
sheetName: z.string().optional().describe("Sheet name (defaults to first sheet)"),
|
|
183
|
+
}, async ({ documentName, tableName, newName, sheetName }) => handleJXA(() => runJXA(`
|
|
184
|
+
const app = Application("Numbers");
|
|
185
|
+
const doc = app.documents.byName(params.documentName);
|
|
186
|
+
const sheet = params.sheetName ? doc.sheets.byName(params.sheetName) : doc.sheets[0];
|
|
187
|
+
const table = sheet.tables.byName(params.tableName);
|
|
188
|
+
table.name = params.newName;
|
|
189
|
+
return JSON.stringify({ renamed: true, oldName: params.tableName, newName: params.newName });
|
|
190
|
+
`, { documentName, tableName, newName, sheetName: sheetName ?? null })));
|
|
191
|
+
server.tool("numbers_delete_table", "Delete a table from a sheet", {
|
|
192
|
+
documentName: z.string().describe("Name of the open document"),
|
|
193
|
+
tableName: z.string().describe("Name of the table to delete"),
|
|
194
|
+
sheetName: z.string().optional().describe("Sheet name (defaults to first sheet)"),
|
|
195
|
+
}, async ({ documentName, tableName, sheetName }) => handleJXA(() => runJXA(`
|
|
196
|
+
const app = Application("Numbers");
|
|
197
|
+
const doc = app.documents.byName(params.documentName);
|
|
198
|
+
const sheet = params.sheetName ? doc.sheets.byName(params.sheetName) : doc.sheets[0];
|
|
199
|
+
const table = sheet.tables.byName(params.tableName);
|
|
200
|
+
app.delete(table);
|
|
201
|
+
return JSON.stringify({ deleted: true, tableName: params.tableName });
|
|
202
|
+
`, { documentName, tableName, sheetName: sheetName ?? null })));
|
|
203
|
+
server.tool("numbers_delete_row", "Delete one or more rows from a table", {
|
|
204
|
+
documentName: z.string().describe("Name of the open document"),
|
|
205
|
+
rowIndex: z.number().describe("Row number to delete (1-based)"),
|
|
206
|
+
count: z.number().optional().describe("Number of rows to delete (default: 1)"),
|
|
207
|
+
sheetName: z.string().optional().describe("Sheet name (defaults to first sheet)"),
|
|
208
|
+
tableName: z.string().optional().describe("Table name (defaults to first table)"),
|
|
209
|
+
}, async ({ documentName, rowIndex, count, sheetName, tableName }) => handleJXA(() => runJXA(`
|
|
210
|
+
const app = Application("Numbers");
|
|
211
|
+
const doc = app.documents.byName(params.documentName);
|
|
212
|
+
const sheet = params.sheetName ? doc.sheets.byName(params.sheetName) : doc.sheets[0];
|
|
213
|
+
const table = params.tableName ? sheet.tables.byName(params.tableName) : sheet.tables[0];
|
|
214
|
+
const n = params.count || 1;
|
|
215
|
+
for (let i = 0; i < n; i++) {
|
|
216
|
+
app.delete(table.rows[params.rowIndex - 1]);
|
|
217
|
+
}
|
|
218
|
+
return JSON.stringify({ deleted: n, newRowCount: table.rowCount() });
|
|
219
|
+
`, { documentName, rowIndex, count: count ?? null, sheetName: sheetName ?? null, tableName: tableName ?? null })));
|
|
220
|
+
server.tool("numbers_delete_column", "Delete one or more columns from a table", {
|
|
221
|
+
documentName: z.string().describe("Name of the open document"),
|
|
222
|
+
column: z.string().describe("Column letter to delete, e.g. 'A', 'B'"),
|
|
223
|
+
count: z.number().optional().describe("Number of columns to delete (default: 1)"),
|
|
224
|
+
sheetName: z.string().optional().describe("Sheet name (defaults to first sheet)"),
|
|
225
|
+
tableName: z.string().optional().describe("Table name (defaults to first table)"),
|
|
226
|
+
}, async ({ documentName, column, count, sheetName, tableName }) => handleJXA(() => runJXA(`
|
|
227
|
+
const app = Application("Numbers");
|
|
228
|
+
const doc = app.documents.byName(params.documentName);
|
|
229
|
+
const sheet = params.sheetName ? doc.sheets.byName(params.sheetName) : doc.sheets[0];
|
|
230
|
+
const table = params.tableName ? sheet.tables.byName(params.tableName) : sheet.tables[0];
|
|
231
|
+
const colStr = params.column.toUpperCase();
|
|
232
|
+
let colIndex = 0;
|
|
233
|
+
for (let i = 0; i < colStr.length; i++) {
|
|
234
|
+
colIndex = colIndex * 26 + (colStr.charCodeAt(i) - 64);
|
|
235
|
+
}
|
|
236
|
+
colIndex -= 1;
|
|
237
|
+
const n = params.count || 1;
|
|
238
|
+
for (let i = 0; i < n; i++) {
|
|
239
|
+
app.delete(table.columns[colIndex]);
|
|
240
|
+
}
|
|
241
|
+
return JSON.stringify({ deleted: n, newColumnCount: table.columnCount() });
|
|
242
|
+
`, { documentName, column, count: count ?? null, sheetName: sheetName ?? null, tableName: tableName ?? null })));
|
|
157
243
|
// ── Data Reading Tools ──
|
|
158
244
|
server.tool("numbers_read_table", "Read all data from a table as a 2D array. Returns rows of cell values.", {
|
|
159
245
|
documentName: z.string().describe("Name of the open document"),
|
|
@@ -166,14 +252,11 @@ export function registerNumbersTools(server) {
|
|
|
166
252
|
const table = params.tableName ? sheet.tables.byName(params.tableName) : sheet.tables[0];
|
|
167
253
|
const rowCount = table.rowCount();
|
|
168
254
|
const colCount = table.columnCount();
|
|
255
|
+
// Batch read all cell values in one IPC call
|
|
256
|
+
const allValues = table.cells.value();
|
|
169
257
|
const data = [];
|
|
170
258
|
for (let r = 0; r < rowCount; r++) {
|
|
171
|
-
|
|
172
|
-
for (let c = 0; c < colCount; c++) {
|
|
173
|
-
const cell = table.cells[r * colCount + c];
|
|
174
|
-
row.push(cell.value());
|
|
175
|
-
}
|
|
176
|
-
data.push(row);
|
|
259
|
+
data.push(allValues.slice(r * colCount, (r + 1) * colCount));
|
|
177
260
|
}
|
|
178
261
|
return JSON.stringify(data);
|
|
179
262
|
`, { documentName, sheetName: sheetName ?? null, tableName: tableName ?? null })));
|