# ly.img/codesign (npm · @imgly/codesign-mcp)

Local design engine for AI agents: create, edit and export real, editable designs.

- Trust score: 69/100 (medium)
- Registry status: active
- Liveness: live
- Owner verified: no
- Last scored: 2026-09-20

## Components

- npm · `@imgly/codesign-mcp`: 69/100 (this document), [markdown](https://verifymcp.io/servers/ly-img-codesign/imgly-codesign-mcp.md), [page](https://verifymcp.io/servers/ly-img-codesign/imgly-codesign-mcp)

## Channel facts

- Registry: `npm`
- Package: `@imgly/codesign-mcp`
- Version: `0.3.6`
- Transport: `stdio`

## Trust breakdown

How this component scores in each security and reliability category. Every signal is checked automatically from public evidence about the published package, including repeated runs of it in an isolated sandbox, and we only credit what we can confirm. Scores are 0–100 per category. Scoring method: https://verifymcp.io/docs/scoring (what has changed: https://verifymcp.io/docs/scoring/changelog)

Scored 2026-09-20.

- **Supply Chain Security**: 98/100
  - No malware found by supply-chain analysis.
  - No known CVEs affecting this package version or its production dependencies.
  - No install/post-install scripts declared.
  - 63 of 214 dependencies flagged as unhealthy (1 deprecated).
- **Provenance & Transparency**: 32/100
  - Source repository is publicly reachable at the declared URL.
  - Provenance check failed: no build-provenance attestation is published.
  - License check failed: the license (SEE LICENSE IN LICENSE.md) isn't a recognized OSI-approved license.
  - Actively maintained (last published 1 days ago).
  - Disclosure check failed: no security disclosure policy was found in the source repository.
- **Schema Quality & AI Usability**: 75/100
  - 100% of prompts and resources have a non-trivial description (not blank, and not just the item's name).
  - AI-judged instruction clarity (excellent).
  - Context-footprint check failed: tool/resource definitions use about 9210 tokens (~484/item across 19 items; 19 tools + 0 resources), over budget; trim descriptions and params.
  - Usage-examples check failed: none of the tools include examples.
- **Stability & Change Management**: 17/100
  - Stability observed for 5 of 30 days with no destabilising changes; credit accrues until the full window elapses.
- **Tool Coverage**: 96/100
  - 100% of tools have a non-trivial description (not blank, and not just the tool's name).
  - 89% of tool parameters carry a description.
- **Tool Safety**: 100/100
  - No prompt-injection markers were found in the server instructions, tool names or descriptions we captured.
  - We read all 19 captured tool definition(s), and no name or description among them implies an irreversible operation.
  - An AI judge read all 20 captured unit(s) of tool text and found none that tries to manipulate the model reading it.
- **Capabilities**: 100/100
  - Implements a supported MCP spec version (2025-11-25); the latest is 2026-07-28.

## Install

### How do I install the ly.img/codesign MCP server?

ly.img/codesign runs locally as an npm package, launched with npx -y @imgly/codesign-mcp. Ready-made configuration for Claude, Cursor, VS Code, Codex and 5 more is on this page, copied from each client's own documentation.

### Claude

```bash
claude mcp add ly-img-codesign -- npx -y @imgly/codesign-mcp
```

### Cursor

```json
{
  "mcpServers": {
    "ly-img-codesign": {
      "command": "npx",
      "args": [
        "-y",
        "@imgly/codesign-mcp"
      ]
    }
  }
}
```

### VS Code

```json
{
  "servers": {
    "ly-img-codesign": {
      "command": "npx",
      "args": [
        "-y",
        "@imgly/codesign-mcp"
      ]
    }
  }
}
```

### Codex

```bash
codex mcp add ly-img-codesign -- npx -y @imgly/codesign-mcp
```

### opencode

```json
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "ly-img-codesign": {
      "type": "local",
      "command": [
        "npx",
        "-y",
        "@imgly/codesign-mcp"
      ],
      "enabled": true
    }
  }
}
```

### OpenClaw

```bash
openclaw mcp add ly-img-codesign --command npx --arg -y --arg @imgly/codesign-mcp
```

### Hermes

```yaml
mcp_servers:
  ly-img-codesign:
    command: "npx"
    args: ["-y", "@imgly/codesign-mcp"]
```

### Netclaw

```json
{
  "McpServers": {
    "ly-img-codesign": {
      "Transport": "stdio",
      "Command": "npx",
      "Arguments": [
        "-y",
        "@imgly/codesign-mcp"
      ]
    }
  }
}
```

### Vellum

```bash
assistant mcp add ly-img-codesign -t stdio -c npx -a -y @imgly/codesign-mcp
```

### Other

```json
{
  "mcpServers": {
    "ly-img-codesign": {
      "command": "npx",
      "args": [
        "-y",
        "@imgly/codesign-mcp"
      ]
    }
  }
}
```

## Changelog

Every change recorded for this component, newest first. Days that predate change tracking, or that we cannot explain, say so: "we were watching and nothing happened" and "we were not watching" are different claims.

### 2026-09-19 (score 69, +26)

- [security improvement] Malware scan: unverified → pass
- [security improvement] Known CVEs: unverified → pass
- [functional improvement] Dependency health: unverified → 0.85

### 2026-09-18 (score 43, −25)

- [security regression] Known CVEs: pass → unverified
- [security regression] Malware scan: pass → unverified
- [functional regression] Dependency health: 0.85 → unverified
- [functional] Package version: 0.3.4 → 0.3.6
- [functional] Package version: 0.3.4 → 0.3.5

### 2026-09-17 (score 68, +1)

No change was recorded against any check on this day. Stability & Change Management went from 3 to 7. That category is still filling its 30-day observation window: 1 days of observed history at the previous scan, 2 at this one. The score rises as the window fills, whether or not the server changes.

### 2026-09-16 (score 67, +15)

- [security regression] Tool safety: pass → unverified
- [security improvement] Malware scan: unverified → pass
- [security] Stability: Stability not yet verified: we do not have a sandbox capture of the MCP schema this version of the package serves yet.
- [functional regression] Capabilities: pass → unverified
- [functional regression] Tool coverage: 100 → unverified
- [functional regression] Schema quality: 100 → unverified
- [functional improvement] Stability: unverified → 0.03
- [functional] Package version: 0.3.2 → 0.3.4
- [functional] Package version: 0.3.2 → 0.3.3

### 2026-09-15 (score 52)

First indexed and scored.

## MCP tools (19)

### `skill` (~2196 tokens)

Load a skill — an instruction document that teaches you how to work with this server. Read the relevant skill BEFORE attempting work it covers. Intended sequence: (1) call with just `name` to get the entry document — it ends with an index of the bundled files; (2) pass `query` (a regex, like Grep) to search the bundled files for the rules you need, scoping with `path` when you know the file; (3) full-read a file via `path` only when it is small (the index shows line counts) or after a search missed twice — slice large files with `offset` (skip count: offset=10 starts at line 11) and `limit`. Entry documents are always returned whole (offset/limit are ignored for them).

\<available_skills>
\<skill name="handbook">
The CoDesign design loop, tool contract, workspace cheatsheet, typeface
schema, common operations cheatsheet, and the full design-quality rubric.
\**Read this skill before any edit call** — it contains the 5-step Loop
(decide parent → read API → exec → preview → judge), the tool roster and
cross-tool rules, the workspace revision model (list / history / rename),
rewind-recovery procedure, the typeface shape text.font declarations need,
and §6: the design-rules index — the full enforceable rubric (typography,
hierarchy, composition, craft) ships as this skill's design-rules.md, the
runtime-quirk reference as its quirks.md, and the input-resolution contract
every skill follows as its intake.md, all read on demand.

Triggered for any task using this server's `edit` or `preview` tools.
\</skill>
\<skill name="api">
Authoritative TypeScript signatures for the CE.SDK CreativeEngine. Use this
skill whenever you need the exact signature, parameter types, or return type
of an `engine.*` method — especially before calling a method you haven't
used yet. This is THE source of truth for signatures: generated from the
\`.d.ts` shipped with the same `@cesdk/node` package the engine runs, while
prose docs (the `guide` skill) can drift.

Reading this skill with no path returns…

Input parameters:

- `context` (integer): Context lines around each match, like grep -C (default 2; 0 = bare match lines). Only valid with `query`.
- `limit` (integer): Maximum number of lines to return.
- `maxResults` (integer): Maximum search matches to return (default 50, max 200).
- `name` (string, required): Skill to load.
- `offset` (integer): Lines to skip before reading (offset=10 starts at line 11). Use with `limit` to slice large files.
- `path` (string): Optional sub-file within the skill. Defaults to the entry document.
- `query` (string): Search the skill instead of reading it: a regular expression matched per line (like Grep). Smart-case: all-lowercase pattern → case-insensitive; any uppercase → case-sensitive. An invalid pattern is…

### `edit` (~955 tokens)

Edit the CE.SDK canvas by running JavaScript against the live CreativeEngine, then commit the result as a new revision.

⚠ Call `skill({ name: 'handbook' })` BEFORE your first `edit`. It documents the design loop, the typeface schema, and the engine recipes; on cryptic errors, query its quirks.md.

REQUIRED: `parent` is a revision id (returned by a previous edit), or the JSON null literal (no quotes) to start a new design. Omitting it is an error — there is no implicit 'continue from wherever'. In a fresh conversation, a request for a new design means `parent: null` — never resume a workspace design the user didn't reference.

Returns: the first content part is JSON `{ revision, parent, names? }` — store `revision` so you can pass it as `parent` on the next edit. `names` lists every named block in the committed scene: those are exactly the strings `engine.design.findByName(name)` resolves in your NEXT edit, so name what you build and re-find it instead of matching copy. When the edit changed the scene, the result also ends with a downscaled render of the (first) changed page — verify your work from it instead of spending a `preview` call. `preview` remains required for full-size judging (the judge loop) and multi-page review; set `render: false` to skip the image on read-only/diagnostic edits.

\`code` return contract (STRICT): return `undefined` (no message back), `{ type: "text", text }`, `{ type: "image", data: "<base64>", mimeType }`, or an array of those. Anything else (raw strings, Blobs, plain objects) is rejected.

DIALECT (enforced): mutations go through `engine.design` (create/build/setProps/…). Code that mutates via engine.block.* is rejected before execution with the equivalent calls; `// engine.block: <reason>` opts out for calls the facade lacks.

\`code` scope: `engine` (with `engine.design`), plus `findText(copy)` / `findAllText(copy)` for reaching a block by its text. Use them instead of comparing text strings with `===` — the copy on the page routin…

Input parameters:

- `code` (string, required): Async JS body. `engine` is in scope, plus `engine.design` — the preferred nested-props facade; EVERY member returns a Promise (await it): create({ type, name?, props?, children? }, { parent? }), setP…
- `fork` (boolean): Set true ONLY when the user explicitly asked to discard their own browser-editor changes and branch from an older revision. Without it, `edit` refuses a parent whose path to the head contains a save…
- `note` (string): Freeform descriptive text — what this edit accomplished. Metadata only; never load-bearing.
- `parent` (string|null, required): Parent revision id from a previous edit (a string). To start a new design root, use the JSON null literal. REQUIRED — there is no implicit default.
- `render` (boolean): Default true: a mutating edit's result ends with a downscaled render of the (first) changed page. Set false to skip the image on read-only or diagnostic edits where seeing the canvas adds nothing.
- `title` (string): Display name for the design. Set only when parent=null (creating a new design). For mid-chain renames use the `rename` tool.

### `preview` (~383 tokens)

Render blocks (almost always pages) to inline images so you can see the result.

\`revision` is REQUIRED — pass the revision the blocks belong to, the id `edit` returned. `blockIds` is a LIST, rendered in the order you give it: `[pageId]` for one page, `[a, b]` for a subset, or OMIT it entirely to preview every page of the design in document order.

The given `revision` is loaded before rendering, so the ids always resolve against the right scene — never against a different design another agent may have loaded on a shared server.

Preview several blocks at once when REVIEWING or capturing a finished design — a whole deck in one call, or just the pages a fix touched. While BUILDING a multi-page design, keep previewing each page right after you build it: batching there does not avoid the bugs, it only delays finding them.

Output is always PNG (lossless — thin lines render exactly). EACH block gets the full 0.25 megapixel budget, adjusted to its own aspect ratio — a square page renders 512×512, a 1:4 page 256×1024. There are no size or format knobs, and at most 10 blocks render per call.

To eyeball fine detail, preview the suspect BLOCK directly — the pixel budget concentrates on it (an effective zoom). For native-resolution certainty, `export` the page and open its `httpUrl`.

Input parameters:

- `blockIds` (array): Blocks to render, in the order you want them back — almost always page ids, not the scene root. Omit to preview every page of the design in document order. At most 10 render per call.
- `revision` (string, required): Revision id the blocks belong to (from `edit`). Loaded before rendering so the ids resolve against the right scene.

### `export` (~822 tokens)

Export a revision to a final deliverable — `format` picks it: `pdf` (print PDF), `png`/`jpeg`/`webp` (image), `svg` (vector SVG), `pdfx` (print-ready PDF/X), `html` (responsive HTML5), `imgly` (editable design file). Renders `blockId` — or the whole document when `blockId` is omitted — and writes the result into the workspace under `exports/<shard>/<rev>/` (revision-pinned, deterministic).

Returns JSON: `{ uri, httpUrl, bytes, format, revision }` (plus `path` when you pass `outPath`). `uri` (a `workspace://` URI) is the durable handle. `httpUrl` is a fetch link tied to this process — fetch it to download the bytes to disk, or hand it to the user.

\`outPath` (optional, absolute path including the filename): ALSO write the artifact to that local path — the workspace copy is still written, and the response then carries `path`. Use it when the file is wanted on disk, and always when your environment cannot fetch localhost URLs (sandboxed harnesses, e.g. Claude Cowork — target your session's outputs folder there).

\`format=svg` is the engine's vector export: text is outlined into paths (renders identically everywhere, but is not editable text in the SVG), and raster images are embedded in the file at source resolution — an SVG of a photo-heavy design can be much larger than its source images.

\`format=imgly` writes a portable, self-contained `.imgly` design file (scene + all asset bytes bundled) — the inverse of `import`, and the only format that stays editable. Whole-design only: `blockId` is not accepted. Every `edit` already auto-persists to the workspace, so you never need this to keep your work — use it to take an editable copy OUT: hand it to a human, back it up, move it between servers.

\`format=pdfx` runs the print PDF through a PDF/X conversion (Ghostscript): CMYK with an embedded ICC profile and PDF/X conformance markers, ready for a print shop. Tune it via the optional `pdfx` object — conformance standard (X-4 default / X-3), output profile (fogra39/gracol/s…

Input parameters:

- `blockId` (integer): The page or block to render. Omit to export the whole document — for `format=pdf` a multi-page PDF, for an image format one composite image of all pages. Required for format=html (pass a page id).
- `format` (required): The deliverable: pdf → print PDF; png/jpeg/webp → image; svg → vector SVG; pdfx → print-ready PDF/X; html → HTML5 page; imgly → editable design file.
- `html` (object): Options for `format=html` only (invalid with any other format).
- `outPath` (string): Absolute path (including filename) to ALSO write the artifact to — the workspace copy is still written, and the response then carries `path`. Use when you need the file on disk and cannot fetch local…
- `pdfx` (object): Options for `format=pdfx` only (invalid with any other format). Omit entirely for sensible print defaults: PDF/X-4, fogra39, embedded ICC.
- `revision` (string, required)

### `import` (~507 tokens)

Import a design FILE as a NEW design root revision — a native CE.SDK `.imgly` design file (also the legacy `.scene` and `.zip` forms); a foreign design file: Photoshop (`.psd`/`.psb`), InDesign (`.idml`), PowerPoint (`.pptx`), or PDF; or a plain image (PNG/JPEG/WebP/GIF) or SVG, which becomes a one-page design sized to the image (`format`: `"image"`/`"svg"`). The inverse of `export({ format: 'imgly' })`. To make a media file (image/font/video/audio) available for use INSIDE a design instead of becoming one, use `asset_add`.

Source: `{ url }` (http/https), `{ demo }` (a design bundled with this server — ids: `"cybernews"`) or `{ path }` (absolute local file path; Local only). Archives are ingested: bundled asset bytes are extracted into the workspace as content-addressed `assets/<sha>.<ext>` files, so the loaded design is durable and behaves exactly like a natively-built one.

Returns JSON `{ revision, title, format }` — continue with `edit({ parent: revision, … })`. Foreign-format imports may add `warnings` (importer notes about what did not survive — substituted fonts, unsupported features): treat them as your touch-up list — `preview` the pages, then repair with `edit`; find replacement fonts via `asset_search`. Bare scene-file loads (no bundled assets) additionally return `assets`: a classification of every referenced asset URI by scheme (`workspace` / `external` / `bundle` / `transient` / `other`). External URLs are NOT fetched; `transient` entries WILL be lost on the next save — replace or relocate them before committing further work.

Engine caveat: InDesign and PDF import need the WASM engine (`IMGLY_CESDK_ENGINE=wasm`) — on the native engine `import` errors cleanly for those two formats; Photoshop and PowerPoint import work on both.

Input parameters:

- `source` (object, required): The design to load. Provide exactly one of `url` (http/https), `demo` (a bundled demo design), `path` (absolute local file path; Local only).
- `title` (string): Display name for the new design. Defaults to the source file's basename.

### `list` (~153 tokens)

List designs in the workspace. Returns an array of `{ rootRevision, title, latestLeaf, updatedAt, headOrigin?, headNote? }` sorted newest-first; the `head*` fields describe `latestLeaf`. `headOrigin: "editor"` means the last hand on that design was the user's, in the browser editor — read `headNote` (the engine-computed diff of their save) before you change anything, and build from `latestLeaf` so their work is not discarded. Use when the user asks what designs exist or wants to resume earlier work. Seeing a design here is never by itself a reason to continue it — for a new design request pass `parent: null` to `edit`.

### `history` (~119 tokens)

Walk back from `revision` to the root, returning the chain (root first). Each entry has `{ revision, parent, note?, origin?, createdAt }` — `origin: "editor"` marks a revision the user saved from the browser editor. Use this to re-ground after a rewind: read the notes, pick the revision you want to continue from, pass it as `parent` to your next `edit`. Continue a prior design only when the user asked for it — never because it is the newest entry.

Input parameters:

- `revision` (string, required)

### `changes` (~168 tokens)

Check whether the user changed a design in the browser editor since you last touched it.

Pass the revision you believe is current — normally the one your last `edit` returned. The reply says whether it is still the design head and lists what was written since, oldest first, with each revision's diff note and whether it came from the editor (`origin: "editor"`) or from your own `edit`.

Call this before your first `edit` of a design whenever the user may have had the `view` page open: `edit` REJECTS a parent whose path to the head contains one of the user's editor saves, so this is how you find the parent to build on.

Input parameters:

- `revision` (string, required): Revision you believe is current — normally the one your last `edit` returned.

### `inspect` (~198 tokens)

Read one revision in full: parent, note, createdAt, title (root only), and the JS code that produced it (when written via `edit`).

Use this after `history` when you've picked a revision and want to know HOW it got there — the code is the precise operation; `note` is the agent's summary.

Returns JSON `{ revision, parent, note?, origin?, createdAt, title?, code? }` — `origin: "editor"` marks a revision the user saved from the browser editor. `code` is omitted for revisions not produced by `edit` (e.g. future import paths).

⚠ Past code reveals the PATTERN of an edit (which APIs were called, what kind of block was targeted), NOT the block ids. Block ids are session-scoped — re-discover them in the current engine; don't replay the literal numeric ids.

Input parameters:

- `revision` (string, required): Revision id to inspect.

### `rename` (~56 tokens)

Rename a design. `revision` may be any revision in the lineage; the root's title is updated. Use this when the title set at design creation no longer fits.

Input parameters:

- `revision` (string, required)
- `title` (string, required)

### `scorecard` (~225 tokens)

Record the verdict of a judge loop you have COMPLETED for a revision — the final step of the `judge` skill. Recording is a claim about work already done: never call this without having scored the axes against actual `preview` renders of this exact revision's content.

\`verdict: 'pass'` — every applicable axis scored ≥ 8; the design may be delivered. `verdict: 'fail'` — you are stopping with an axis below 8 (e.g. the user cut remediation short); the failure stays on record.

The latest scorecard is what `export` checks: delivering a revision it does not cover (content changed since, or no scorecard at all) adds a reminder to its result. Judging again after further edits? Record a new scorecard for the re-judged revision.

Input parameters:

- `revision` (string, required): The revision the judge loop scored — the id whose renders you previewed.
- `verdict` (string, required): 'pass' when every applicable axis scored ≥ 8, 'fail' when stopping below the gate.

### `checklist` (~334 tokens)

Register the brief's ACCEPTANCE CHECKLIST for a design — the machine-checkable claims that must hold before the work counts as done. Do this right after intake, before the first edit: extract from the brief every required output file, every string of approved copy that must land verbatim, and note the constraints only you can check.

Item kinds:
\- { kind: 'output', path } — a file that must exist when the design is delivered (absolute path, e.g. every variant the brief orders exported).
\- { kind: 'copy', text } — approved copy that must appear VERBATIM in the design's text (whitespace variants are folded before comparing; wording, case and punctuation are exact).
\- { kind: 'note', text } — a self-check the server cannot verify (e.g. "layout structure unchanged from master"). Kept on record; never machine-checked.

Every `export` verifies the current checklist against the deliverable and lists unmet items in its result — treat an unmet item exactly like a failing test: finish the work, or re-register the checklist without the item if it is genuinely obsolete. Calling `checklist` again REPLACES the whole list for this design.

Returns: { ok, itemCount, rootRevision } — or the current checklist when called with only `revision` (no items).

Input parameters:

- `items` (array): The full checklist (max 64 items) — replaces any previously registered list. Omit to read the current checklist instead.
- `revision` (string, required): Any revision id of the design (the checklist attaches to the design's whole lineage).

### `view` (~170 tokens)

Get a URL the human can open to view and edit the design in CE.SDK. Returns the design's stable URL — the viewer keeps it live, re-rendering as you `edit`, so print it ONCE and don't re-emit a fresh URL every turn. Add `pin: true` for a frozen permalink to that exact revision (for 'look at exactly this' or comparing revisions). The page is a full editor; when the human clicks 'Save', their edits land as a new revision whose note carries an engine-computed change summary — continue from that revision.

Input parameters:

- `pin` (boolean): When true, return a frozen permalink to this exact revision instead of the live design URL.
- `revision` (string, required): Any revision in the design; resolved to its root and opened at the design head.

### `asset_search` (~833 tokens)

Discover the asset sources registered on the CreativeEngine and search the assets they contain. Read-only — never creates a revision.

Without `sourceId`: lists every source id with its supported MIME types.

With `sourceId`: returns one page of assets as JSON `{ total, currentPage, nextPage, assets: [{ id, label, groups, uri, thumbUri, width, height, uploadedAt }] }`. Typeface assets (e.g. the `ly.img.gfonts` Google Fonts source) additionally carry a compact `typeface: { name, weights, styles }` summary. `query` fuzzy-matches labels and tags.

The `ly.img.workspace.images` source is this workspace's own image store: every image the agent generated or imported AND every image the human uploaded in the browser editor, newest first. Uploads carry their original filename as `label` (the human will refer to it — "use logo-final.png" — so search that name), plus `groups: ["uploads"]` and an `uploadedAt` timestamp. "The image the user just uploaded" = the `uploads`-group asset with the newest `uploadedAt`.

⚠ Asset sources are deployment configuration — where their content lives (IMG.LY CDN, a customer host) is the server's business. NEVER fetch asset manifests (`content.json`) or hardcode `cdn.img.ly` URLs yourself; this tool and `engine.asset.*` are the only correct path. A source missing from the no-arg listing is not available on this server — say so instead of working around it.

To USE a result, apply it inside `edit` code — re-find it there, then either:
(A) new block: `const id = await engine.asset.apply(sourceId, (await engine.asset.findAssets(sourceId, { query, page: 0, perPage: 1 })).assets[0])` — then, if you resize the frame, set `engine.block.setContentFillMode(id, "Cover")` (resizing does NOT update the crop; without Cover a portrait photo forced into a landscape frame gets squished);
(B) existing block: `const fill = engine.block.createFill("image"); engine.block.setString(fill, "fill/image/imageFileURI", asset.meta.uri); engine.block.setFill(blockId, fil…

Input parameters:

- `page` (integer): Page index. Default 0.
- `perPage` (integer): Results per page. Default 20, max 50.
- `query` (string): Fuzzy search over asset labels and tags.
- `sourceId` (string): Asset source id. Omit to list all sources.

### `asset_add` (~340 tokens)

Add a local image or font file to the workspace so it can be used in a design. Copies the file bytes into the content-addressed asset store at `assets/<sha>.<ext>`. The bring-your-own arm of the asset family: `asset_search` finds an existing asset, `asset_generate` makes one, `asset_add` takes one off your disk — all three return a `workspace://` uri to embed in `edit`. (To turn a design FILE into a new design, use `import`.)

Returns JSON: `{ uri, httpUrl, mimeType, kind, bytes, note? }`. `uri` (a `workspace://` URI) is the durable handle — embed it in a subsequent `edit` (image fill, or `engine.asset.apply`; for a font, as both `setFont`'s uri and `typeface.fonts[].uri`), NEVER `httpUrl` and NEVER the original `file://` path, so the design stays loadable after a restart or rewind. `httpUrl` is a fetch link for opening the asset now.

Files are classified by content (magic bytes) first, extension second: a misnamed file is stored under its actual type, and `note` explains any correction, rescue, or unverifiable content.

Make-available only: it never edits a scene and never creates a revision — do the placement in `edit`.

Source: `{ path }` — an absolute path to a file the server can read. Local-only (this backend shares your disk); on a hosted server this arm is not offered.

Input parameters:

- `source` (object, required)

### `asset_generate` (~459 tokens)

Generate images (text-to-image, image-to-image) via the IMG.LY AI gateway.

Call with NO arguments first: returns the model catalog — pick a model, then call again with `model` + `prompt` (+ optional `format` aspect like "16:9"). Before writing the prompt, read `skill({ name: 'models' })`: how to prompt each model and what its result looks like.

For image-to-image, pass `image_uris` with `workspace://` URIs (from `import` or earlier generations).

The first content part is JSON: `{ uri, httpUrl, mimeType, bytes }`. `uri` (a `workspace://` URI) is the durable handle — embed it in subsequent `edit` calls. `httpUrl` opens the asset directly. The parts after it are a labeled thumbnail of each generated image — look at them; the JSON alone does not tell you what was drawn.

Multi-output models (layerize-class: decompose an input image into layers) add an `assets` array to that JSON — one entry per image, `{ index, uri, httpUrl, mimeType, bytes }`, in stack order (residual background first, then cutout layers). The top-level fields mirror `assets[0]`. Single-output results carry no `assets` array. Any non-image output the model produced is passed through VERBATIM under `metadata` — read it, it binds semantics to the assets (layerize, for example, ships a layers list in `assets` order with names, z order and bounding boxes in source pixels; cutouts are cropped to content, so place them by their bounding box).

Requires a free IMG.LY sign-in (the `login` tool); all other design tools work without an account.

Input parameters:

- `format` (string): Aspect ratio, e.g. "16:9" or "1:1".
- `image_uris` (array): workspace:// image URIs used as inputs (image-to-image models).
- `model` (string): Model id from the catalog (call with no arguments to list). Required to generate.
- `prompt` (string): What to generate. Required together with `model`.

### `diagnostics` (~95 tokens)

Inspect this codesign MCP server: `status` (default) reports what is running (build id, CE.SDK engine version, non-secret config); `summary` returns a bounded digest of recent activity (counts, recent errors, slowest calls); `open` returns a clickable local viewer URL with a Download-ZIP button to send diagnostics to IMG.LY.

Input parameters:

- `action` (string): status (default) | summary | open

### `login` (~87 tokens)

Sign in with your IMG.LY account (opens the system browser). The session saves automatically once the user finishes in the browser; call login again anytime to confirm — safe to repeat, it does not restart the flow or invalidate the open link. Pass switch_account=true to sign in as a different user.

Input parameters:

- `switch_account` (boolean): Force a fresh sign-in screen even if a session exists.

### `logout` (~25 tokens)

Sign out of your IMG.LY account (revokes the session and clears local credentials).

## Diagnostics

Captured diagnostic sections: Provenance, Dependencies. The full working is on the page: https://verifymcp.io/servers/ly-img-codesign/imgly-codesign-mcp#diagnostics

## Score history

- 2026-09-20: 69
- 2026-09-19: 69
- 2026-09-18: 43
- 2026-09-17: 68
- 2026-09-16: 67
- 2026-09-15: 52

## Common questions

### What is the ly.img/codesign MCP server?

ly.img/codesign is an MCP server listed in the public MCP registry as ly.img/codesign. Local design engine for AI agents: create, edit and export real, editable designs. This page covers its npm package (@imgly/codesign-mcp).

### Is the ly.img/codesign MCP server safe to use?

ly.img/codesign scores 69 out of 100 on VerifyMCP. We found no known CVEs affecting it as of 20 September 2026. It declares no install or post-install scripts. That is a record of what we were able to check automatically, not an endorsement. The category breakdown on this page shows every signal behind the number, including the ones we could not confirm.

### What tools does the ly.img/codesign MCP server expose?

ly.img/codesign exposes 19 tools: skill, edit, preview, export, import, and 14 more. Their descriptions and schemas cost roughly 8,125 tokens of context every time the server is loaded.

### Is the ly.img/codesign MCP server still maintained?

ly.img/codesign is still listed as active in the MCP registry. We last reached this channel on 20 September 2026. Those dates come from our own scans of the registry and the channel itself, not from anything the publisher announced.

## Links

- npm package: https://www.npmjs.com/package/@imgly/codesign-mcp
- Socket report: https://socket.dev/npm/package/@imgly/codesign-mcp
- Repository: https://github.com/imgly/codesign
- Changelog RSS feed: https://verifymcp.io/servers/ly-img-codesign/imgly-codesign-mcp.xml
- Changelog JSON feed: https://verifymcp.io/servers/ly-img-codesign/imgly-codesign-mcp.json
- HTML version of this page: https://verifymcp.io/servers/ly-img-codesign/imgly-codesign-mcp
