# Identity Forge [Health: Active]

**Category:** 💻 Developer Tools  
**Repository:** https://github.com/KasayoDotCom/identityforge-mcp  
**GitHub Stars:** 0  
**Views:** 0  
**Installs:** 0  
**Upvotes:** 0  
**Directory Page:** https://allmcps.com/mcp/identity-forge

## Description
Design kits, brand naming, and domain research for coding agents.

## Tools
Capabilities this server exposes over MCP:

- **list_themes** — browse the catalog as compact summaries. Rank by use-case lane with `use`, run ranked search with `q`, page with `offset`, sort by `featured`, `popular`, `recent`, `name`, or `fit`.
- **search_themes** — return the whole catalog unranked, for briefs too subtle to rank against a lane.
- **similar_themes** — given a kit slug, find neighbours by palette, tags, and audience.
- **match_palette** — given existing brand colors, rank kits by perceptual color distance.
- **search_fonts** — browse the Google Fonts catalog by name or category, or pass `like` with a family you already have to find faces that resemble it. Metadata only, and `like` reads no letterform, so confirm the look before promising it.
- **suggest_font_pairings** — the curated heading/body/mono table, or what goes beside one family the user is committed to.
- **get_design_md** — fetch a kit's DESIGN.md, the full design brief.
- **get_tokens** — fetch tokens as `dtcg`, `css`, `tailwind-v3`, `tailwind-v4`, `shadcn-registry`, or `json`.
- **apply_theme** — write DESIGN.md, a tokens file, and an `identityforge.json` stamp into the project. It refuses rather than overwriting a file it did not write, see below.

## Claude Desktop Quick Installation
Install path detected from listing signals. Uses `npx` (confidence: high):

```json
"mcpServers": {
  "identity-forge": {
    "command": "npx",
    "args": ["-y","--yes"]
  }
}
```

## Documentation & README

<p align="center">
  <a href="https://identityforge.io">
    <img src="https://identityforge.io/opengraph-image.png" alt="Identity Forge branding pipeline from names and design kits to agent-ready systems" width="1200">
  </a>
</p>

<h1 align="center">Identity Forge MCP</h1>

<p align="center">Design systems, brand naming, and domain research for coding agents.</p>

<p align="center">
  <a href="#for-people">For people</a> ·
  <a href="#for-agents">For agents</a> ·
  <a href="#mcp-tools">MCP tools</a> ·
  <a href="#cli-commands">CLI reference</a> ·
  <a href="https://identityforge.io/docs">Docs</a>
</p>

<p align="center">
  <a href="https://www.npmjs.com/package/identityforge"><img src="https://img.shields.io/npm/v/identityforge" alt="npm version"></a>
  <a href="https://github.com/KasayoDotCom/identityforge-mcp/actions/workflows/ci.yml"><img src="https://github.com/KasayoDotCom/identityforge-mcp/actions/workflows/ci.yml/badge.svg" alt="CI status"></a>
  <a href="https://github.com/KasayoDotCom/identityforge-mcp/blob/HEAD/LICENSE"><img src="https://img.shields.io/npm/l/identityforge" alt="MIT license"></a>
</p>

**Free to use.** 69 of 79 design kits are free, with all 6 export formats, the CLI, the MCP server, and the API. No account required. Pro unlocks 10 additional kits, 1,000 AI generations/month, and advanced features.

## For people

Identity Forge gives a coding agent a complete visual system before it starts
building. Choose a design kit yourself, or let the agent rank the catalog
against your product and the mood you want. Each kit includes typography,
semantic color tokens, layout, motifs, dos and don'ts, and a `DESIGN.md` the
agent can build from.

The agent can export the kit as CSS, Tailwind v3 or v4, shadcn registry data,
DTCG tokens, or JSON, then apply it with conflict protection. Brand naming,
domain research, and shareable client projects live in the same workflow.

Public Free kits work without an account. [Browse the design kits](https://identityforge.io/kits)
or [read how the agent flow works](https://identityforge.io/for-agents) before
installing anything.

### Watch it work

The three-minute lifecycle film follows a design system from the first choice
through product imagery, an ecommerce rebuild, a later brand update, an
older-site rebuild, and team review. The Aubade storefront and Shiftly rebuild
are complete one-shot agent builds from real Identity Forge design systems. The
Commonkeep review uses synthetic showcase data in the real review experience.

https://github.com/user-attachments/assets/fc3cdba2-4876-46e5-a92a-09ce6d7071ff

[Download the full-resolution 1080p WebM](https://github.com/KasayoDotCom/identityforge-mcp/releases/download/v0.3.10/identity-forge-design-system-lifecycle.webm).

## For agents

Install the local MCP server into the client you use:

```bash
npx --yes identityforge@latest install --client claude-code   # Claude Code
npx --yes identityforge@latest install --client cursor        # Cursor
npx --yes identityforge@latest install --client vscode        # VS Code / Copilot
npx --yes identityforge@latest install --client codex         # Codex
```

Also supported: `gemini`, `opencode`, `pi`. Every client runs the same local
stdio server, and `install` merges into your existing config rather than
replacing it. Config paths for all seven are in
[Install into an agent](#install-into-an-agent).

Public Free kits work immediately, without a key. Tell your agent:

> Use Identity Forge to pick a theme that fits this product, apply it, and follow the DESIGN.md.

Sign in for persistent projects, saved work, authenticated quota, or Pro access:

```bash
npx --yes identityforge@latest login
```

No account yet? In the browser, sign up, complete the security check, select
`Send verification email`, and open its link. Then select
`Confirm email and continue`, approve the resumed authorization, and the CLI
receives the key automatically.

## Use-case discovery

Every use-case lane has two checks. First, the kit's authored audience or `bestFor` must name that kind of product. Then concrete token measurements such as text contrast, chart-series distinctness, and information density rank the eligible kits. Visual tags help search but do not establish product fit. A high technical score cannot put an unrelated kit into a lane. The per-lane prose justification is switched off catalogue-wide pending re-enrichment, so a score arrives without a sentence explaining it.

- `list_themes({ use: "data-dashboard" })` returns kits authored for dashboards, ordered by their measured dashboard fit.
- `list_themes({ q: "calm fintech dashboard" })` runs a synonym-aware ranked search across moods, industries, and use cases.
- `search_themes` returns the whole catalog unranked so the agent can weigh a subtle brief itself.

Use the lane to shortlist and the order to compare. Do not turn the score into an explanation: it ranks technical fit after authored intent, but does not say why the kit suits a particular brief.

For the data lanes there is a better answer than the score. Every kit summary carries a `charts` block measured on the mode the kit ships in: `minDeltaE` and `cvdMinDeltaE` (the closest pair of series colors, plain and under colorblind simulation), `distinct`, `hueFamilies`, `severityHeadroom` (how close any series comes to the destructive, warning and success roles — 0 means a category color IS a status color), `sequentialReady`, and `designed`, which is `false` when the kit defines no chart slots and the five were cycled from its brand roles. Those are measurements, so unlike the fitness score they can be stated to a user as the reason for a recommendation.

Use-case lanes: `data-dashboard`, `admin-internal-tool`, `saas-marketing`, `landing-page`, `ecommerce-store`, `portfolio`, `editorial-blog`, `docs-knowledge-base`, `mobile-app`, `business-services`, `community-social`, `ai-agent-chat`.

The same discovery runs the [kit gallery](https://identityforge.io/kits) and the [HTTP API](https://identityforge.io/api/v1) (`GET /api/v1/kits?use=…&q=…`, see [llms.txt](https://identityforge.io/api/v1/llms.txt)).

## Install into an agent

`install --client <name>` writes the MCP server config for that agent, merging into any existing config:

| Client | `--client` | Config file |
| --- | --- | --- |
| Claude Code | `claude-code` | `.mcp.json` |
| Cursor | `cursor` | `.cursor/mcp.json` |
| Codex | `codex` | `~/.codex/config.toml` |
| Gemini CLI | `gemini` | `.gemini/settings.json` |
| VS Code / Copilot | `vscode` | `.vscode/mcp.json` |
| opencode | `opencode` | `opencode.json` |
| Pi | `pi` | `.pi/agent/mcp.json` |

All of them run the same local stdio server via `npx -y identityforge@latest mcp`.
After installation, `identityforge doctor --client <name>` checks that the client
points at the rolling package and initializes the package's MCP server without
calling the Identity Forge API or spending quota.

### Install the agent plugin and skill

The repository also bundles the MCP server with an Agent Skill that tells the agent when
to use Identity Forge, how free and authenticated access differ, and how to guide a human
through `Send verification email` before the pending browser authorization resumes.

Claude Code:

```bash
claude plugin marketplace add KasayoDotCom/identityforge-mcp
claude plugin install identity-forge@identity-forge
```

GitHub Copilot CLI:

```bash
copilot plugin marketplace add KasayoDotCom/identityforge-mcp
copilot plugin install identity-forge@identity-forge
```

Codex and other Agent Skills-compatible clients:

```bash
npx skills add KasayoDotCom/identityforge-mcp
```

Cursor metadata is included for directory distribution. Until it is listed there, use
the `install --client cursor` command above to connect the same MCP server.

## MCP tools

Once connected, your agent gets 63 tools. Browsing free kits needs no key; scopes are noted where they apply.

### Find a design kit

- `list_themes`: browse the catalog as compact summaries. Rank by use-case lane with `use`, run ranked search with `q`, page with `offset`, sort by `featured`, `popular`, `recent`, `name`, or `fit`.
- `search_themes`: return the whole catalog unranked, for briefs too subtle to rank against a lane.
- `similar_themes`: given a kit slug, find neighbours by palette, tags, and audience.
- `match_palette`: given existing brand colors, rank kits by perceptual color distance.

### Choose typography outside a kit

A kit already names its heading, body, and mono faces. These two answer the cases where it does not.

- `search_fonts`: browse the Google Fonts catalog by name or category, or pass `like` with a family you already have to find faces that resemble it. Metadata only, and `like` reads no letterform, so confirm the look before promising it.
- `suggest_font_pairings`: the curated heading/body/mono table, or what goes beside one family the user is committed to.

### Read and apply one

- `get_design_md`: fetch a kit's DESIGN.md, the full design brief.
- `get_tokens`: fetch tokens as `dtcg`, `css`, `tailwind-v3`, `tailwind-v4`, `shadcn-registry`, or `json`.
- `apply_theme`: write DESIGN.md, a tokens file, and an `identityforge.json` stamp into the project. It refuses rather than overwriting a file it did not write, see below.

## What `apply` writes, and what it will not overwrite

`apply_theme` (and `identityforge apply`) writes three files into the target directory:

Identity Forge requests carry one random reference that lasts only for the
current CLI or MCP process. A local apply reports one bounded result: files
written, artifacts already current, a safe conflict refusal, or the stage where it failed. The report
contains counts and classifications, never local paths or error prose. Running
as an MCP server, requests also carry the client name
your editor or agent already sends in the MCP handshake (`claude-code`,
`cursor-vscode`, `codex`), so usage can be attributed to a product rather than to
nothing. None of this includes paths, filenames, prompts, file contents,
repository names, exception text, or a persistent installation identifier. Set
`IDENTITYFORGE_TELEMETRY=0` to omit the process reference and local outcome
reports; ordinary API requests still appear in server access logs.

| File | What it is |
| --- | --- |
| `DESIGN.md` | the design brief the agent builds from |
| `<slug>.css` / `.json` / `.js` | the tokens, named for the format you asked for |
| `identityforge.json` | the stamp: which kit was applied, at which version, and a SHA-256 of every file written |

The stamp belongs to your repository, not to the kit. It records what this codebase was built against, which is a fact the server cannot know, so commit it. It is also what makes applying safe: before writing anything, `apply` compares what is on disk against the hashes in the stamp.

- A file that does not exist gets created.
- A file whose content already matches the kit is left alone.
- A file the last apply wrote, still byte-identical, is updated when the kit has moved.
- A file that is **not recorded in the stamp**, for example a `DESIGN.md` you wrote yourself, or one that **changed since it was written**, is a **conflict**.

On a conflict the default is to write nothing at all, name every conflicting file, and exit non-zero. Nothing is written until every file is planned, so a failed fetch cannot leave the directory half applied.

```bash
identityforge apply acid-signal-black --preview   # plan only, writes nothing
identityforge apply acid-signal-black             # refuses if anything conflicts
identityforge apply acid-signal-black --force     # overwrites, content is lost
```

`--force` is destructive and unrecoverable: the current content of the conflicting files is gone, and the report names each one. Preview first, show the person what would change, and let them decide.

### What the stamp records, and how a later apply reads it

```jsonc
{
  "stampVersion": 1,          // shape of this file, so a reader never has to guess
  "designMdContract": "1.0",  // shape of the DESIGN.md you built against — not the kit's
                              // revision and not this file's. Three different versions
                              // live here; flattening any two invents a baseline.
  "kit": {
    "id": "c2d13a12-…",       // permanent. diff against this, never the slug
    "slug": "sage-slate-editorial",
    "version": 0,             // the kit's monotonic revision, as the export reported it
    "designMdDigest": "sha256:…"
  },
  "layers": [],
  "artifacts": [{ "path": "DESIGN.md", "hash": "sha256:…", "writtenAt": "…" }],
  "integration": { "tokensEntry": null },
  "appliedAt": "…"
}
```

`kit.version` has three distinct meanings and they must not be collapsed. A number is the kit's revision. **`0` means the kit exists and has no minted version yet.** **`null` means the export did not report a version at all**, which is a different fact, and reading it as `0` would put a baseline in your repository that was never true. Identity is copied from the export's own front matter; nothing here is inferred.

Re-applying reads that back:

- **The version moved** — the server's own count says the kit changed. Re-read the brief.
- **Same version, different rendered file** — the `DESIGN.md` serializer changed, not the kit. No action.
- **No version on both sides** — only the digest is available, and it cannot tell those two cases apart, so it says so rather than guessing.

Because the id is the durable handle, renaming a kit's slug is not reported as "you applied a different kit". A stamp written by a newer CLI than yours is refused rather than half-understood: every file counts as unrecorded, so the apply stops instead of overwriting on a record it cannot fully read.

### `status`: ask the stamp what moved

```bash
identityforge status              # the current directory
identityforge status --dir apps/web
```

It takes no kit and no version, because the stamp already holds both. `themes diff --from N` needs you to know the kit and read the number out of the JSON yourself; `apply --preview` needs the slug and fetches a whole write plan to answer a read-only question. `status` reads `identityforge.json`, asks the server by **id**, and reports the three movements the stamp implies, separately:

- **`kitMoved`** — the server's own version count differs. The design changed.
- **`documentMoved`** — the rendered `DESIGN.md` bytes differ. A serializer change alone does that to every kit at once, so on its own it is not a reason to touch your code.
- **`contractMoved`** — `designMdContract` differs. The document's *shape* changed: a section added, renamed, or removed. That is a third question, and neither of the other two answers it.

Each is `null` rather than `false` when one side cannot answer, and a note says which side was missing. If the kit did move and both versions are numbers, the same diff `themes diff` would have printed is included. It also hashes every artifact the stamp recorded against what is on disk, so a `DESIGN.md` you have since edited by hand shows as `modified` before you re-apply over it.

It writes nothing and never touches the working tree. Losing your key or hitting a Pro gate degrades it to a local-only report with a note, rather than failing. JSON goes to stdout and the human summary to stderr, so `identityforge status | jq .moved` works while a person still sees the sentence.

### Complementary collections

These answer questions a kit does not. None of them replace the kit.

- `list_image_directions` / `get_image_direction`: choose and export how the project's imagery should be presented and repeated.
- `list_interface_styles` / `get_interface_style`: choose and export a neutral render grammar for surfaces and hierarchy, applied through a kit.
- `list_page_recipes` / `get_page_recipe`: choose and export how a page should argue its case.

When the user supplies a real product, person, or object, use the approved image as fixed input to a
reference-preserving image editor. Shape project-specific presentation routes around it: setting,
supporting elements, composition, lighting, surfaces, crop, finish, and variation rules. Keep the
source identity exact, compare every result with it at full resolution, and avoid recreating an
existing product from text or placing a cutout over a separately generated background. If the
current agent cannot perform reference-led editing, hand the source image and exported direction to
a product-image workflow. Identity Forge provides the brief; it does not render the images in this
flow.

### Author kits and brands (`kits:write`)

- `create_theme`: author a private kit from scratch or by forking a catalog kit with overrides covering tokens, colors, fonts, and facet presets.
- `remix_theme`: copy a resolvable kit into a new private kit with overrides applied.
- `update_theme`: edit one of your saved kits in place, keeping its slug and publication state so existing consumers follow the change. Overwrites the stored kit, but every save mints a version, so the replaced state stays readable through the version tools below. The slug itself cannot be renamed here, and `expectedUpdatedAt` turns a concurrent edit into a 409 instead of a silent overwrite.
- `delete_theme`: permanently delete one of your saved kits. Pass `confirm: true`; a kit still referenced by a brand project is refused with `409 kit_in_use`, so retire or repoint those references first.
- `create_brand_project` and `list_brand_projects`: the container for brand variations and a client share.
- `add_brand_variation`: attach a proposal to a project, with a kit plus optional name, domain, label, and notes.
- `update_brand_variation`: revise one proposal in place, including repointing it at a different kit. The client sees it on their next view.
- `remove_brand_variation`: permanently delete one proposal and its comments. Pass `confirm: true`; it is not undoable.
- `revoke_brand_share`: permanently withdraw a client link. Pass `confirm: true`; sharing again mints a new token.
- `reorder_brand_variations`: set the order the client meets the directions in. Must list every variation exactly once.
- `share_brand_project`: create or rotate a read-only `/p/<token>` client share link, optionally password protected.
- `list_client_comments` (`kits:read`): read what the client wrote on each variation. The return leg of the share loop.

### Compose the other axes onto a brand

A brand is a design kit plus an image direction, an interface style, and any number of page recipes. Those references live on the PROJECT, not the kit, so swapping the kit leaves them alone.

- `get_brand_layers` (`kits:read`): what a brand is composed of, with both revision numbers on every reference and `drift` present only where the record has moved since it was pinned. `meta.drifted` counts them, and `links.preview` is the composition rendered as an image. Reads nothing into the brand: no version is minted and no pin moves.
- `add_brand_layer`: compose one record onto the brand, recording the revision it is at now so a later read can report a change rather than apply it silently. One tool for all three axes via `axis`. Image direction and interface style hold one each; a second is refused with 409 unless you pass `replace: true`, which is also how you accept a drifted revision.
- `remove_brand_layer`: take one off. Pass `confirm: true`; it names the record rather than the axis, so a stale view cannot clear a layer it never saw, and repeating it is a no-op.
- `export_brand` (`kits:read`): the brand as ONE document, ready to build from — the kit's `DESIGN.md` with every pinned layer written into it, under the precedence rule that decides which wins when they disagree (the kit owns identity, a layer owns application). Use it instead of merging the kit and each layer yourself. A layer the key cannot open is named with its page and an upgrade path rather than dropped; a brand with no chosen kit answers 409 instead of returning a placeholder nobody picked.

### Describe the product once, then get proposals grounded in it

- `get_project_context` / `set_project_context`: store what the product is — what it does, who it is for, its constraints, what has been ruled out, its screens, its stack — on a brand project. Every later proposal is grounded in it, including in a session that never saw the description.
- `recommend_kits({projectId})`: candidates for that product, each carrying the kit's own evidence and its judged fitness for the surfaces the product actually has. With Pro and a `kits:write` key you also get a model ranking with a reason per candidate; `meta.depth` is `ranked` or `candidates`.

Two things that surprise people:

- **`set_project_context` REPLACES.** The endpoint is `PUT`, not `PATCH`, so a field you omit is deleted rather than kept. That is deliberate — a merging update would let you drop a surface from the list and silently keep the old one — but it means you read with `get_project_context` first and send the whole object back with your edit applied.
- **`recommend_kits` costs 3 quota units and needs a key**, where `list_themes` costs 1 and every other discovery route works anonymously. The reasoning is in the route's own docstring: it takes a free-text body rather than query parameters, and it is the one route that can grow into a metered model call. Writing a context needs `kits:write`; reading one needs only `kits:read`.

### Has it changed since I built? (read-only)

- `list_kit_versions`, `get_kit_version`, `diff_kit_versions`: a kit's version timeline, one past snapshot in full, and what moved between two versions. `diff_kit_versions({slug, from})` with no upper bound compares against the current version, which is the question a repo with an `identityforge.json` actually has.
- `list_brand_project_versions`, `get_brand_project_version`, `diff_brand_project_versions`: the same three for a brand project, owner-scoped.
- `list_kit_history`, `get_kit_history_event`: the same kit's ledger, which is a wider record than its version timeline. `kit_history_events` carries three event types — created, saved, and applied to a brand — and only the first two mint a version, so an apply appears in the ledger and nowhere else. Ask the ledger whether a kit was ever actually used; ask the timeline what its tokens were. It pages by an opaque cursor rather than a version number, because an event has no ordinal to page below.
**Share: pause or withdraw.** `update-share` is the reversible one and almost always the
right one — `--disable` pauses the link, the token is untouched, and a URL already with the
client works again the moment you resume. `revoke-share` is permanent: the `/p/<token>` URL
stops resolving wherever it was pasted, including in an email already sent, and sharing
again mints a new token and deliberately never the old one. It refuses without `--yes`.

- `whoami`: plan, granted and missing scopes, remaining quota, AI credits, and saved-kit slots. Free, and never refused for being over quota, so it still answers after a 429.

None of these writes anything. Restoring an old state is an `update_theme` call you make deliberately.

**What actually has history.** Saved kits and managed catalog kits accumulate versions. A static catalog fallback stays at version `0` until it is promoted into the managed catalog. The separate kit history ledger remains owner-only and records creation, saves, and applications to a brand. On brand projects the whole brand is recorded: name and domain, fonts, pinned layers, project context, and the variations, including a reorder. What is deliberately not recorded is sharing, because who may see a brand is not what the brand is.

**What a Pro gate does to them.** For a kit you are not entitled to, the timeline still lists versions but the author's free-text note is `null`, and a diff returns each change marked `redacted: true` with its path and CSS variable but no before or after, plus a `redactedChanges` count. `get_kit_version` returns the whole payload, so it answers 403 instead.

### Name a brand (`naming:read` / `naming:write`)

- `list_naming_recipes`: the full naming strategy catalog.
- `list_naming_projects` and `create_naming_project`: reuse or create a durable board.
- `generate_names`: generate with Identity Forge's own model. Spends AI credits only when unique candidates persist.
- `add_name_candidates`: persist names from the active agent, an authorized offline process, or manual research, using stable caller UUIDs. Spends no credits.
- `list_name_candidates`: read the kanban board with provenance and evidence.
- `list_name_generations`: audit model, prompt, request, and credit provenance.
- `move_name_candidates` and `rank_name_candidates`: atomically review, shortlist, rank, and select.
- `get_naming_research_context`: read the brief, board, evidence, capabilities, and small-task handoff contract, without server ranking.
- `search_name_evidence`: run bounded model-authored searches through self-hosted SearXNG and return evidence without verdicts. One account-wide monthly unit per query.
- `check_domains`: DNS plus distinct RDAP, registrar, and optional self-hosted SERP evidence. Basic research costs one unit per unique domain; SERP adds one. Absent DNS records only mean a domain might be available.
- `assess_domain_acquisition`: state whether the goal is a new registration, an aftermarket purchase, or either. It reports registrar registration evidence and bounded public landing-page evidence separately, including literal sale, marketplace, reserved-page, and visible-price signals. It never validates the seller or guarantees purchase. Aftermarket evidence adds one unit per unique domain; an exact successful repeat within ten minutes costs zero.

Trademark screening remains a separate manual step through the official registers for each relevant jurisdiction. Record the query, classes, source URL, result wording, and date. This is preliminary research, not legal clearance.

### Build a brand and share it with a client

The `kits:write` tools let an agent build a whole brand package end to end:

1. `create_theme` or `remix_theme` to compose four or five contrasting directions, either forking a catalog kit and overriding colors, fonts, and facets, or authoring from scratch.
2. `create_brand_project`, one project per client brief.
3. `add_brand_variation` to attach each direction with a brand name, domain, and label.
4. `share_brand_project` to hand the client a `/p/<token>` link, optionally password protected, where they cycle the variations and comment.
5. `list_client_comments` to read what came back, then `update_theme`, `update_brand_variation`, `remove_brand_variation`, and `reorder_brand_variations` to revise the same board rather than starting a second one.

Everything an agent creates it can also revise. The write tools change live, client-visible state; destructive tools require `confirm: true`, so read the feedback before acting on it.

New keys carry `kits:write` by default. A key minted before that scope existed will 403 until you re-run `identityforge login` or create a new scoped key.

The MCP server also ships connect-time instructions describing this workflow, so a connected agent knows how to go from intent to an applied kit without being told the steps.

## How an agent picks a kit

When you ask your agent for a look and feel, it should:

1. **Gather intent**: what the product is, who it is for, and the mood you want, for example "fintech dashboard for SMBs, calm and trustworthy".
2. **Find candidates**: `list_themes({ use })` when the build target maps to a use-case lane, `list_themes({ q })` for ranked search, or `search_themes` to rank the whole catalog against a subtle brief. If you already have brand colors, `match_palette({ colors })` finds the closest kits.
3. **Review**: each result is a compact summary with name, tags, a font and color glimpse, tier, and judged fitness. `similar_themes(slug)` offers neighbours, and `get_design_md(slug)` reads the full brief before committing.
4. **Apply**: `apply_theme(slug)`, optionally with a `tokensFormat` matching your stack, writes `DESIGN.md`, a tokens file, and the `identityforge.json` stamp into the project. If the project already has files it did not write, it shows you the conflict instead of overwriting them.
5. **Implement**: follow `DESIGN.md` and wire the tokens into your styling layer, whether CSS variables, a Tailwind `@theme` block, or shadcn.

The more concrete your description, the better the match.

### Ids and slugs

Every kit has an opaque `id` and a `slug`, and either one addresses it directly, so once you have a kit you can skip discovery. They differ in durability:

- The **id** never changes. It is minted once, is never reassigned, and always resolves to the same kit.
- The **slug** is a public handle its owner can rename. A retired slug keeps resolving through an alias, so a rename alone does not break you. But a different kit can later claim that freed slug, and the live kit wins, so a stored slug can quietly start resolving to a **different** kit rather than failing loudly.

Pass the slug when a person typed it. Store the id for anything your agent keeps: a config value, a version stamp, a choice it repeats in a later session. `list_themes` prints both.

Image directions, interface styles, and page recipes carry ids too, and the same advice applies more strongly: they have no alias table, so a renamed slug there simply stops resolving.

## CLI commands

```bash
npx -y identityforge@latest login    # browser sign-in (PKCE loopback)
identityforge login --key ifk_…      # or paste a key (headless)
identityforge whoami                 # plan, scopes, quota, credits, saved-kit slots (free)
identityforge usage                  # alias for whoami
identityforge update-check           # current/latest package version as JSON
identityforge doctor --client codex  # verify config and MCP capabilities without API usage
identityforge logout                 # remove stored credentials
identityforge themes                 # list kits
identityforge themes -q "fintech dashboard, calm and trustworthy"
identityforge themes get <id|slug>   # print DESIGN.md to stdout, writing nothing
identityforge themes get <id|slug> --format tailwind-v4 > tokens.css
identityforge themes get <id|slug> --format json      # the whole kit
identityforge themes get <id|slug> --marker           # stale-write marker only

# Author, fork, and find neighbours (kits:write for the first two)
identityforge themes create --name "Acme" --base bento-noir --overrides o.json
identityforge themes remix <id|slug> --overrides o.json   # copies; original untouched
identityforge themes delete <id|slug> --yes                # permanent; refuses kits still in use
identityforge themes similar <id|slug>                    # nearby published kits
identityforge themes match "#1d4ed8" "#f97316"            # kits closest to colors you hold

# Typography, for the cases a kit does not already settle
identityforge fonts search grotesk --category sans-serif   # Google Fonts metadata, no files
identityforge fonts similar Inter                          # faces that resemble one you have
identityforge fonts pairings Fraunces --role heading       # curated table + contrast suggestions

# Has this kit moved since I built against it? (read-only)
identityforge themes versions <id|slug>               # version timeline, newest first
identityforge themes version <id|slug> 3              # one past snapshot, whole kit
identityforge themes diff <id|slug> --from 3          # what changed since version 3

# Everything that happened to it, which is a wider record (read-only)
identityforge themes history <id|slug>                # + every apply-to-brand
identityforge themes history <id|slug> --cursor "$NEXT"
identityforge themes snapshot <id|slug> <event-id>    # the kit at that entry

# Build a client brand project and read the feedback back (kits:write)
identityforge brand create --name "Acme rebrand" --brief "Calm fintech"
identityforge brand add-variation --project <uuid> --kit <id|slug> --brand-name Acme --label "Direction A"
identityforge brand share --project <uuid> --password hunter2
identityforge brand update-share --project <uuid> --disable   # pause; token survives
identityforge brand revoke-share --project <uuid> --yes       # permanent, new token next time
identityforge brand get --project <uuid>              # one project in full
identityforge brand layers --project <uuid>           # pinned catalogue records
identityforge brand add-layer --project <uuid> --axis imageDirection --record <id>
identityforge brand remove-layer --project <uuid> --axis imageDirection --record <id> --yes
# The kit's DESIGN.md with every pinned layer composed into it: the one document to build from
identityforge brand export --project <uuid> > DESIGN.md
identityforge brand comments --project <uuid>
identityforge brand projects
# Describe the product once, then ask for grounded proposals
identityforge brand context --project <uuid>          # read the stored context
identityforge brand set-context --project <uuid> --file context.json   # REPLACES it
identityforge brand recommend --project <uuid>        # candidates (3 units, needs a key)
# Queue mockups: one AI credit per variation and scene combination
identityforge brand mockups generate --project <uuid> --variation <uuid> --item tshirt:front
identityforge brand mockups list --project <uuid>
identityforge brand mockups get --project <uuid> --job <uuid>

identityforge brand versions --project <uuid>         # project history
identityforge brand version 3 --project <uuid>        # one stored version, in full
identityforge brand diff --project <uuid> --from 2

# Act on the feedback: revise, retire, reorder (kits:write)
identityforge brand update-variation --project <uuid> --variation <uuid> --label "Warmer" --clear notes
identityforge brand remove-variation --project <uuid> --variation <uuid> --yes
identityforge brand reorder --project <uuid> <variation-uuid> <variation-uuid> <variation-uuid>
identityforge themes update <id|slug> --name "Acme v2" --expected-updated-at "$MARKER"
identityforge image-directions list  # list public imagery judgments
identityforge image-directions get <slug> --format markdown
identityforge interface-styles list  # list public render-grammar judgments
identityforge interface-styles get <slug> --format markdown
identityforge page-recipes list      # list public page communication judgments
identityforge page-recipes get <slug> --format markdown
identityforge apply <slug>           # write DESIGN.md + tokens + stamp into the current dir
identityforge apply <slug> --preview # plan it first, writing nothing
identityforge status                 # read the stamp: has the kit, the document, or its shape moved?
identityforge status --dir apps/web
identityforge mcp                    # run the MCP server over stdio

# Naming commands always print JSON
identityforge naming recipes
identityforge naming projects
identityforge naming create-project --name "My product" --description "Product, audience, market, desired character"
identityforge naming generate --project <uuid> --description "..." --recipes compoundWords,metaphor --count 12 --idempotency-key my-product-run-1
# Persist candidates proposed by the active agent or an authorized offline process (1-50 items)
identityforge naming add-candidates --project <uuid> --file candidates.json
# The same command accepts a JSON array or {"candidates":[...]} on stdin
identityforge naming add-candidates --project <uuid> --file - < candidates.json
identityforge naming candidates --project <uuid> --status shortlisted,finalist
identityforge naming generations --project <uuid>
identityforge naming research-context --project <uuid>
identityforge naming search --file research-tasks.json
identityforge naming acquisition candidate.com --intent either
identityforge naming move <candidate-uuid> --project <uuid> --status finalist --notes "Strong market fit"
identityforge naming rank <candidate-uuid>=1 <candidate-uuid>=2 --project <uuid>
identityforge naming domains candidate.de candidate.com --serp --market "Germany heating retail" --language de-DE
# Registrar evidence alongside DNS and RDAP, the closest this gets to an availability answer
identityforge naming domains candidate.de --registrar
# Record WHY a candidate moved, not only that it did
identityforge naming move <candidate-uuid> --project <uuid> --status rejected --evidence why.json
```

**Guarding a naming write.** `naming move` and `naming rank` take
`--expected-updated-at`, so a candidate that changed since you read it answers `409` instead of
being silently overwritten. Take the marker from `naming candidates`, pass it back byte for byte,
and never parse it: it looks like a timestamp and is compared as an opaque string.

```bash
identityforge naming candidates --project <uuid> --status finalist   # read updatedAt from the row
identityforge naming move <candidate-uuid> --project <uuid> --status selected \
  --expected-updated-at "<marker>"
```

The marker guards **one** candidate, so passing it with several ids is refused before anything is
sent rather than applied to all of them: each row has its own marker, and spreading one across a
batch would guard the wrong rows. Move the guarded candidate on its own. This matters most for
`--status selected`, which also sets the project's chosen brand name.

`--evidence` is different: it is not row-specific, so it applies to every candidate in the batch.
It takes a path or `-` for stdin, and a file that will not parse is refused rather than sent as an
empty object, which would record "no evidence" as though it were the considered answer.

## Editing a saved kit without clobbering a concurrent edit

`PATCH` accepts an `expectedUpdatedAt` marker and answers `409` rather than overwriting a kit that moved since you read it. Read the current marker with `themes get --marker`:

```bash
MARKER=$(identityforge themes get my-kit --marker)
identityforge themes get my-kit --format json > kit.json
# ... edit kit.json, then guard the write with the marker you read
identityforge themes update my-kit --kit kit.json --expected-updated-at "$MARKER"
```

`--kit` is deep merged over the stored kit, so a file holding only what changed is enough. Leave `slug` as it is: it is the kit's public handle, and a payload carrying a different one is rejected with `400 slug_rename_unsupported` rather than quietly ignored. Omitting `--expected-updated-at` still works and still writes; it just overwrites whatever is stored, including an edit someone made since your read, so the command says so on stderr.

**The marker is opaque. Echo it back byte for byte and never parse it.** It crosses the wire as a raw Postgres timestamp rather than ISO-8601, and the guard compares strings, so a client that parses it into a `Date` and serialises it back never matches and gets `409` forever. Parsing also drops the microseconds, so a comparison that normalises both sides can falsely match and let a genuinely stale write through. A curated catalog kit has no marker, because it has no row and cannot be edited.

## Authentication

Commands authenticate with an Identity Forge API key (`ifk_…`). `login` stores it in `~/.identityforge/config.json` with mode `600`. You can also set it per shell:

```bash
export IDENTITYFORGE_API_KEY=ifk_…
export IDENTITYFORGE_API_URL=https://identityforge.io   # override the API base
export IDENTITYFORGE_TELEMETRY=0                        # optional: disable apply-completion counting
```

Free kits and naming-recipe discovery work without a key. Sign in to keep persistent projects and saved work under an authenticated quota. Owned naming projects and domain research use `naming:read`, generation and board edits use `naming:write`, reading design systems uses `kits:read`, and creating or remixing kits plus building shareable brand projects uses `kits:write`. API calls count against one account-wide monthly API quota shared by all keys, while generation separately spends AI credits for successfully persisted unique candidates. Manage keys at <https://identityforge.io/account/api-keys>.

After a successful local apply, the client sends one metadata-only completion request so aggregate builds can be counted. It includes the kit identifier plus the client name and version already present in every API request. It never sends the repository path or file contents, never changes the apply result, and can be disabled with `IDENTITYFORGE_TELEMETRY=0`.

Existing design-only keys are not silently upgraded. If a key reports that it is missing `naming:read` or `naming:write`, create a scoped key or run browser login again.

## Docker

The MCP server also runs as a container over stdio:

```bash
docker build -t identityforge-mcp .
docker run -i --rm -e IDENTITYFORGE_API_KEY=ifk_… identityforge-mcp
```

The image contains no kit payloads. The key is optional: without one, the server still starts and fetches published Free kits from the Identity Forge platform API. Pro kits, saved work, and writes require an account key.

## Links

- [Source and agent plugin](https://github.com/KasayoDotCom/identityforge-mcp): the public CLI and MCP implementation.
- [Kit gallery](https://identityforge.io/kits): browse every kit with live previews, authored-intent use-case filters, and search.
- [For agents](https://identityforge.io/for-agents): the full agent integration story.
- [API manifest](https://identityforge.io/api/v1) and [llms.txt](https://identityforge.io/api/v1/llms.txt).
- [Official MCP Registry record](https://registry.modelcontextprotocol.io/v0.1/servers?search=io.identityforge%2Fmcp) and [Glama listing with independent build and security analysis](https://glama.ai/mcp/servers/KasayoDotCom/identityforge-mcp/score).

If Identity Forge earns a place in your workflow, a GitHub star helps other builders find it.

## License

MIT

