Use this when the user wants to create, inspect or change anything in their open Adobe InDesign documents (Sidekick for InDesign).
Execute JavaScript code in InDesign via UXP (NOT ExtendScript). The code has access to the full InDesign DOM via require('indesign'). The 'app' object is NOT a global — you must import it: const { app } = require('indesign'). Use 'return' to return values.
Capabilities:
- Full InDesign DOM access (documents, pages, text frames, styles, etc.)
- Async/await supported - Promises are awaited before returning
- File operations via UXP storage APIs (with sandbox restrictions)
Units (IMPORTANT):
- Always specify units explicitly as strings: "12pt", "1in", "5mm", "6p" (picas)
- Bare numbers use the document's current measurement units - this causes unpredictable results
- Examples: fontSize = "11pt", leading = "14pt", margins = "0.5in", textFrameHeight = "200pt"
- WRONG: fontSize = 11 (will be interpreted as 11 of whatever unit the doc uses)
Limitations:
- File system is sandboxed - cannot freely access arbitrary paths; doc.fullName returns a Promise that may fail
- No shell command execution (no app.system())
- No inter-app communication (no BridgeTalk)
- Return values must be JSON-serializable
- Text encoding limited to UTF-8
InDesign DOM quirks:
- Many properties are type-dependent; accessing a property that doesn't apply throws "The property is not applicable in the current state" - always check object type first or use try/catch
- Text variables have different variableOptions depending on variableType (e.g., CUSTOM_TEXT_TYPE has contents, others don't)
- COLLECTION INDEXING: Bracket notation does NOT work in UXP (doc.pages[0] returns undefined). Use these instead:
- doc.pages.item(0) - for single item by index
- doc.pages.firstItem() / doc.pages.lastItem() - for first/last
- doc.pages.everyItem().getElements() - to get a real JS array for forEach/map/filter
- OBJECT COMPARISON: UXP DOM objects and enums don't support === or ==. U
輸入參數code必填actionsdescription
Capture a snapshot of a page or spread from the active InDesign document. Returns the image as base64-encoded JPEG, rendered at the resolution a vision model can actually use (you do not set dpi).
Pass an optional `region` ([x0,y0,x1,y1], normalized 0..1 over the page) to zoom into part of a page at full detail — use this when a whole-page snapshot is too coarse to read an image or fine type. To capture one specific object by id, use `snapshot_object` instead.
Pass `preview: true` for a cheap low-resolution thumbnail — use it for quick 'did the layout roughly change / is the block where I dropped it' checks where you don't need to read detail. Omit it to read detail.
IMPORTANT: Use this tool only when YOU need to verify your work or when the user explicitly requests a snapshot. The user is viewing changes directly in InDesign - they do not need snapshots in the chat unless they ask for them.
輸入參數index必填regiontarget必填previewdescription
Capture a single page item (frame, image, group, …) from the active InDesign document as a base64 JPEG, at the resolution a vision model can use (you do not set dpi).
By default it renders the object **as it appears on the page** — including anything overlapping it, and with any parts hidden by content in front left hidden (so it reflects what's actually visible). Pass `isolate: true` to render **only the object itself**: this strips overlapping items, but also reveals any parts of the object that are covered on the page — so it shows the object's full content rather than just the visible portion.
For alt text: if nothing overlaps the image, `isolate: true` is the cleanest input. If something overlaps/occludes it, prefer the default — alt text should describe what's visible, not content hidden in the layout. The returned note lists overlapping items so you can decide.
Get `pageItemId` from `get_layout({ includeItems: true })`.
輸入參數isolatepageItemId必填description
Capture a snapshot and PRESENT it inline in the chat for the user to see. Returns the same base64 JPEG as `snapshot`, but in MCP Apps hosts (e.g. Claude Desktop) it also renders as a full inline preview with fit-to-width and zoom — no need to expand the tool accordion.
Use this ONLY when the user asked to see a result, or when showing a finished result is genuinely useful to them. For your own iterative verification ('did the layout change', 'is the block where I dropped it'), use `snapshot` / `snapshot_object` instead — those stay collapsed and won't clutter the chat.
Targets mirror the other snapshot tools: a page/spread (with optional `region` zoom-box), or a single object by `pageItemId`. Pass `pageItemId` to present one object; otherwise pass `target` + `index`.
輸入參數indexregiontargetisolatepreviewpageItemIddescription
Internal to the show_snapshot viewer: renders a sharper close-up of the part of a snapshot the user zoomed into. Not for assistants: use `snapshot` with `region` for a close-up.
輸入參數pageIdregion必填maxPixels必填pageIndex必填documentId必填snapshotKey必填documentNamemaxLongEdgePx必填
Get comprehensive layout information for the active InDesign document. Returns page dimensions, margins, and pre-calculated content area coordinates for accurate text frame placement.
Use this BEFORE placing text frames to get correct coordinates. The contentArea bounds can be used directly for geometricBounds.
Returns:
- facingPages: whether document uses facing pages
- measurementUnits: horizontal and vertical units (use values as-is, no unit suffix needed)
- pages: array with bounds, margins, and contentArea for each page (max 20)
- contentArea accounts for page side (recto/verso) automatically
- items (when includeItems is true): each page's items with id, type, bounds, and hasGraphic — pass an id to snapshot_object to capture that item
geometricBounds format is [top, left, bottom, right].
輸入參數includeItems
Get comprehensive font metrics for a specified font. Returns all available metrics including x-height, cap-height, ascender, descender, line gap, underline/strikeout positions, subscript/superscript sizes, and bounding box.
The tool searches system fonts (including .ttc collections such as Helvetica), the fonts bundled with InDesign (e.g. Minion Pro, Myriad Pro), and Adobe Fonts installed via Creative Cloud.
IMPORTANT: Adobe Fonts limitation - Some Adobe Fonts are loaded on-demand by Adobe apps and may not be locally cached in the CoreSync folder. If a font is available in InDesign but not found by this tool, the user should:
1. Open Adobe Creative Cloud → Fonts
2. Find the font and click the Download icon to install it locally
3. Use refresh=true after installation to rebuild the font cache
Parameters:
- fontIdentifier: Font name to search for (family name, PostScript name, or full name)
- style: Optional style specifier to disambiguate (e.g., "Bold", "Italic")
- refresh: Force rebuild of font cache (use after installing new fonts)
All metric values are in font units. Divide by unitsPerEm and multiply by point size to get actual measurements.
Example: For a 12pt font with unitsPerEm=1000 and xHeight=500:
Actual x-height = (500 / 1000) * 12 = 6pt
輸入參數stylerefreshfontIdentifier必填
Use this to see the user's saved Sidekick actions and the built-in ones: what each does and the params it takes. Call it before run_action when you need an action's params, when the user asks what actions there are, or when a task looks like one a saved action might already do. It reads the actions folder fresh, so it includes actions saved since this conversation began, from any assistant. set_configuration sets the user's own actions folder (actionsDir) and shared folders (sharedActionsDirs). If set_configuration has no such settings, the user's Sidekick is older than actions: ask the user to update Sidekick (https://sidekick.eastpole.nl/install) and the Sidekick UXP plugin in InDesign from Adobe Exchange, which also brings the Sidekick Actions panel.
無需輸入參數。
Use this to run a saved Sidekick action by name in the user's open InDesign document. An action is JavaScript the user (or Sidekick) saved earlier, with a header that names it, describes it and types its params.
Pass the params as one object; leave a param out to use its default. The answer is the action's report as text (summary, rows, what a changeCount means for this run's mode), any problems the report has, its log, and the report as JSON with at most 200 rows. When an action fails, the answer carries the error, the stack (lines refer to the action's file) and the numbered source, so a fix needs no second call. Fix the action, run it again, and ask the user before saving the fix. An action with an apply param is not finished until both modes have run; ask the user before a trial run with the param on, and undo it afterwards with Edit › Undo when the answer shows an Undo line; without one, run the trial on a copy of the document instead, as an older Sidekick plugin does not make the run one undo step.
Actions as of the last scan: alt-text-audit (built-in), dutch-typography (built-in), overset-hunt (built-in), rich-black-sweep (built-in). list_actions reads the folders fresh and shows the params; call it when a name you expect is missing.
輸入參數name必填params
Use this to read the source of a saved Sidekick action, for example before changing it at the user's request. Returns the file as it is, header included. list_actions lists the actions.
輸入參數name必填
Use this to save code as a Sidekick action the user can run again by name, from this or any other assistant, and from the Sidekick Actions panel in InDesign when the user's Sidekick plugin has it. Save only when the user asks, or agrees after you offered; never on your own initiative. When saving a fix to an action that failed, say what changed.
The source is one JavaScript file: a header, then an async function main(params, sidekick) and any helpers it needs. Saving under an existing name replaces that action.
/* @sidekick
{
"name": "alt-text-audit",
"description": "Lists every placed image without alt text",
"params": {
"scope": { "type": "string", "enum": ["document", "selection"], "default": "document",
"description": "Which images to check" }
}
}
*/
function hasAltText(frame) {
const options = frame.objectExportOptions;
const source = String(options.altTextSourceType);
if (source === "SOURCE_CUSTOM") return options.customAltText.trim() !== "";
return source !== "SOURCE_XML_STRUCTURE"; // InDesign's default; for an untagged document it means none
}
async function main({ scope }, sidekick) {
const { app } = require("indesign");
const doc = sidekick.doc();
const graphics = scope === "selection" ? app.selection : doc.allGraphics;
const items = [];
for (const graphic of graphics) {
const frame = graphic.parent;
if (hasAltText(frame)) continue;
const image = graphic.itemLink ? graphic.itemLink.name : "embedded image";
items.push(sidekick.item(frame, image, "No alt text"));
}
return {
summary: items.length === 0 ? "All images have alt text" : items.length + " images without alt text",
items,
};
}
Header rules: name is kebab-case (a lower-case letter, then 1-63 lower-case letters, digits or hyphens); description is one line of at most 200 characters, best about 100: what the action does, the most important first, without repeating what a param's description says (the Sidekick Actions panel s
輸入參數source必填
Use this to delete one of the user's saved Sidekick actions. Deleting cannot be undone from Sidekick, so always ask the user to confirm first, naming the action. Built-in actions and actions in a shared folder cannot be deleted, nor can a locked (read-only) file; deleting a saved action that replaced a built-in or a shared one brings that one back.
輸入參數name必填
Get current Sidekick configuration settings.
無需輸入參數。
Update Sidekick configuration settings.
輸入參數pinnedobserverstelemetryactionsDirsharedActionsDirs
Use this when the user asks for "sidekick health", whether Sidekick or InDesign is connected, or why InDesign commands fail. Returns Sidekick's health and status: server version/role and the InDesign plugin connection.
無需輸入參數。