Skip to main content
Glama
Identity Forge MCP

Identity Forge MCP

Official

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 or read how the agent flow works 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.

Related MCP server: ds-pilot

For agents

Install the local MCP server into the client you use:

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.

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:

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 and the HTTP API (GET /api/v1/kits?use=…&q=…, see 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:

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

GitHub Copilot CLI:

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

Codex and other Agent Skills-compatible clients:

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.

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

{
  "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

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

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.

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:

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:

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:

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.

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

License

MIT

Available Tools

61 tools
add_brand_layerCompose a layer onto a brandA

Put one catalogue record onto a brand project alongside its design kit, so the choice is stored on the user's brand rather than living in this conversation. One tool for all three axes: pass axis to say which. The layers belong to the PROJECT and not to the kit, so swapping the kit later leaves them alone — that independence is the whole point of composing axes separately. The pin records the revision the record is at right now, which is what lets get_brand_layers later report that it moved instead of silently applying someone else's edit to the user's brand. recordId is the record's permanent id from list_image_directions, list_interface_styles or list_page_recipes, never a slug: slugs are mutable handles and a pin keyed on one could come to mean a different record. imageDirection and interfaceStyle hold ONE each, so composing a second is refused with 409 unless you pass replace: true — which is also how you accept a drifted revision after the user has seen what changed. Page recipes are a list and simply accumulate. A Pro record on a key without Pro is refused with 403 and an upgrade path; that is not a conflict and replace will not help. This overwrites live brand state without asking and mints a version recording that your key did it. Requires the kits:write scope.

Inputs: axis (required), recordId (required), projectId (required), replace.

add_brand_variationAdd a brand variationA

Attach one brand proposal to a project: a kit plus an optional brand name, domain, label, and notes. Call it four or five times per project with deliberately contrasting kits, because a client choosing between similar directions cannot tell you much. The kit must be one you can resolve, meaning your own, a catalog kit, or another user's public kit, and a Pro catalog kit needs an entitled key. Variations become visible to the client only once you call share_brand_project. Requires the kits:write scope.

Inputs: kitSlug (required), projectId (required), label, notes, +2 more.

add_name_candidatesPersist externally researched name candidatesA

Persist 1-50 names your own agent, another model, or manual research produced onto the durable project board, so a shortlist never lives only in the chat transcript. This is the free counterpart to generate_names: it stores names rather than authoring them, and spends no AI credits. Each item needs a caller-generated UUID, which makes retries safe. Sending identical data again returns the same row; reusing an id with changed data returns a conflict instead of silently overwriting. Requires the naming:write scope.

Inputs: projectId (required), candidates (required).

apply_themeApply a theme to the current projectA

Write a design kit into a project on disk: DESIGN.md, a tokens file named for the chosen format, and identityforge.json, a stamp recording the applied kit and a hash of every file written. This is the only tool here that touches the filesystem. It reads the stamp before writing, so it can tell its own output from the user's work. A file that already exists but is not recorded in the stamp, or one whose content changed since it was written, is a CONFLICT: by default the tool then writes NOTHING, names every conflicting file, and returns an error, so a hand-written DESIGN.md survives. Files whose content already matches the kit are left untouched. Set preview to plan without writing anything at all, and force to overwrite conflicting files, which destroys their current content permanently with no recovery path. Everything is computed before the first write, so a failed fetch cannot half-apply. Call it once the user has settled on a kit; get_design_md and get_tokens inspect a kit without writing. The stamp also records the kit's permanent id and its version as the export reported them, which is what a later apply diffs against: re-applying tells you whether the kit itself moved to a new version, or whether only the rendered file changed. A version of null means the export did not report one, and must never be read as version 0. Free kits are public, and a Pro kit returns 403 unless the key is entitled.

Inputs: slug (required), dir, force, preview, +2 more.

check_applied_themeHas the applied kit moved since this repo was built?A

Read the identityforge.json stamp in a project on disk and report what has moved since apply_theme wrote it. Takes no kit and no version: the stamp holds both, which is what makes this the tool to reach for when returning to a project rather than reconstructing the arguments for diff_kit_versions by hand. It reports THREE independent movements and never conflates them. kitMoved: the server's own version count differs, so the design itself changed and the brief is worth re-reading. documentMoved: the rendered DESIGN.md bytes differ, which a serializer change alone does to every kit at once and is not by itself a reason to touch code. contractMoved: designMdContract differs, so the document's SHAPE changed and a section was added, renamed or removed. Each is null rather than false when one side cannot answer, with a note saying which. When the kit did move and both versions are numbers, the diff_kit_versions result is included, so one call answers both what moved and how. It also hashes every artifact the stamp recorded against what is on disk, so a DESIGN.md edited by hand shows as modified before anything overwrites it. Read-only: it writes nothing and touches no file, so it is safe to call at the start of any session. Losing a key or hitting a Pro gate degrades it to a local-only report with a note rather than failing.

Inputs: dir.

check_domainsCheck domain evidenceA

Check up to 20 bare domains and return four independent kinds of evidence: RDAP registration records via IANA bootstrap, live DNS, real-time Cloudflare Registrar availability with pricing, and optional search results showing who else already occupies the name. Each is reported separately rather than collapsed into one available or taken verdict, because a domain with no DNS can still be registered and parked. Results are a snapshot: they reserve nothing, and a domain can be taken between this call and checkout. Use search_name_evidence for broader name research that is not domain specific. Requires the naming:read scope.

Inputs: domains (required), market, language, includeSerp, +1 more.

create_brand_projectCreate a brand projectA

Create the container that holds brand variations and the client share link. Do this once per client brief, then attach several directions with add_brand_variation and send the client a link with share_brand_project. Creating a project on its own shows the client nothing, so it is only the first of those three steps. Call list_brand_projects first to avoid making a second project for a client who already has one. Requires the kits:write scope.

Inputs: name (required), brief.

create_naming_projectCreate a naming projectA

Create one durable, project-owned naming board and return its id. Do this ONCE per real naming brief, never once per generation run: every other naming tool takes the resulting projectId, and the board persists the candidate kanban, research evidence, and generation ledger across sessions so the shortlist never lives only in chat. Call list_naming_projects first and reuse an existing board rather than creating a near-duplicate. Write the real brief into description, because generation quality depends on it. Requires the naming:write scope; creating a board spends no AI credits.

Inputs: name (required), description, selectedTlds.

create_themeCreate a design kit (theme)A

Author a new design kit, either from scratch by passing a kit JSON or by forking a published catalog kit with base and applying overrides for tokens, colors, fonts, and facet presets. Use base whenever a catalog kit is close to what you want, since a fork inherits a complete, coherent system and you only state the differences. Authoring from scratch means supplying the whole thing. The result is always PRIVATE and visible only to your key until you publish it from the web Studio; this tool cannot publish. Forking a Pro catalog kit needs an entitled key. Use remix_theme instead when you want several quick variations off one direction. Requires the kits:write scope, so regenerate your key with identityforge login if you get a 403 naming it.

Inputs: name (required), kit, base, overrides.

delete_themeDelete a saved design kitA

Permanently delete one of your saved design kits. This cannot be undone, so pass confirm: true only after you are sure. A kit referenced by a brand project is refused with 409 kit_in_use; retire or repoint those references before trying again. Requires the kits:write scope.

Inputs: slug (required), confirm (required).

diff_brand_project_versionsDiff two brand project versionsA

What changed between two versions of a brand project. Pass from alone to compare against the current version. Owner-scoped, so nothing is redacted: you are reading your own brand. Variation edits appear here as variations.<id>.<field> rather than as a wholesale swap, because a variation is identified by id and can be followed across a reorder. Needs kits:read.

Inputs: projectId (required), to, from.

diff_kit_versionsDiff two kit versionsA

What changed between two versions of a kit: a list of paths with the old and new value, the CSS custom property a token change drives, and a mechanical summary. This is the tool for taking a brand change into a codebase, because it tells you the handful of things to update rather than making you re-read a whole DESIGN.md. Pass from alone to compare against the current version, which is the usual question: from is the version your repo recorded in identityforge.json. Pass both to pin a range. It reports what moved and does not judge how big the change is; whether a token shift matters to your UI is your call, not a number we invent. For a Pro kit you are not entitled to, every change comes back with redacted: true carrying the path, kind and CSS variable but no before or after, and redactedChanges counts them, so you can still see the shape of the change and know exactly what is withheld. Needs kits:read.

Inputs: slug (required), to, from.

export_brandGet the whole brand as one documentA

The brand as ONE document, ready to build from: its design kit's DESIGN.md with every catalogue layer the user pinned written into it. Use this instead of assembling get_design_md plus get_image_direction plus get_interface_style plus get_page_recipe yourself, because merging those four is the part you cannot do correctly — when an interface style asks for translucent panels and the kit specifies flat opaque cards, only we know which wins. The rule is stated in the document itself: the kit owns IDENTITY (its colour tokens, typefaces, spacing and motifs, which nothing below overrides) and a layer owns APPLICATION (what a panel is made of, how a photograph is treated, how a page orders its argument). Follow it rather than re-deciding it, and where a layer would need a kit token changed, keep the token and say so. A brand with nothing pinned returns its kit's DESIGN.md unchanged, which is the honest answer and not an error. A layer this key cannot open is NAMED with its judgment page and an upgrade path, and only its implementation is withheld: build what the kit and the present layers give you and do not invent the missing one, because a guessed implementation looks finished and is not. A brand that has not chosen a kit answers 409 — there is no design system yet, and the placeholder the workspace shows is nobody's choice. Owner-scoped, so the key must own the project; read-only, mints no version, writes nothing. Requires the kits:read scope.

Inputs: projectId (required).

generate_mockupsGenerate brand mockupsA

Queue photographic mockups for selected variations and template scenes. This spends one AI credit for every variation and scene combination after the server resolves the selected kits; failed enqueue attempts are refunded. The response contains the job id and polling URL. Requires kits:write.

Inputs: items (required), projectId (required), variationIds (required), idempotencyKey.

generate_namesGenerate and persist brand namesA

Generate brand names with Identity Forge's own operator-owned model and persist them to the project board's generated column with full model, prompt-version, and credit provenance. SPENDS the key owner's AI credits, one per uniquely persisted name, charged only after the rows commit, so a failed run costs nothing. Always pass a stable idempotencyKey so a retry after a timeout cannot bill twice. Use it when you want Identity Forge to author the names; if your own agent or an offline process produced them, use add_name_candidates instead, which is free. Requires the naming:write scope.

Inputs: projectId (required), recipeIds (required), description (required), count, +3 more.

get_brand_layersRead a brand's compositionA

What a brand project is composed of on top of its design kit: its image direction, its interface style, and its page recipes. Read this BEFORE changing any of them, because it is the only place that tells you what the user already chose and whether it still says what it said. Every reference resolves to the revision the catalogue serves now and carries both numbers — revision is current, chosenRevision is what the project pinned — and drift appears only when they differ, carrying the author's note for what moved. meta.drifted counts them, so a brand with nothing to report answers 0 and you can stop. A record withdrawn from the catalogue since it was pinned comes back with resolved: false rather than vanishing, because a brand must not quietly forget what it points at, and a Pro layer this key cannot open still returns its name, tier and revision with locked: true. links.preview is that exact composition rendered as an image, which is the one thing you can put in front of a person who is not going to read a JSON object. Reading changes nothing: it mints no version and never moves a pin, so accepting a drifted revision stays a decision the user makes through add_brand_layer. Requires the kits:read scope.

Inputs: projectId (required).

get_brand_projectRead one brand projectA

Read one board in full: every variation with its kit, brand name, domain, label and notes, plus the state of the client share and a URL for each direction. list_brand_projects gives you summaries and a variation COUNT; this is how you see what is actually on the board. Use it to check your own work after attaching variations, to answer 'what did we send them' without keeping notes of your own, and to read the share state before you change it — whether a link exists, whether it is still serving, whether it has a password, and how many times the client opened it. A project that is not yours, and an id that could never be one, both answer 404 alike, so this cannot be used to find out what exists for somebody else. Read-only and free. Requires the kits:read scope.

Inputs: projectId (required).

get_brand_project_versionRead one stored brand project versionA

The full snapshot a given version of a brand project recorded. Owner-scoped, like the rest of the brand-project surface. A brand snapshot references its kit rather than embedding it, so this never hands back a Pro kit's tokens by another door. Needs kits:read.

Inputs: version (required), projectId (required).

get_design_mdGet DESIGN.md for a themeA

Fetch the complete DESIGN.md brief for one design kit (theme) by slug: the palette in prose, typography, layout and surface rules, elevation and shape, distinctive motifs, iconography, imagery direction, and explicit do's and don'ts. This is the document you design from. Read it before implementing a kit, or when the user wants to review a direction before committing to it. Read-only: it returns the text and writes nothing to disk (apply_theme is the tool that writes it into a project). Free kits are public; a Pro kit returns 403 with an upgrade path unless the key is entitled, without leaking the brief.

Inputs: slug (required).

get_image_directionGet an image directionA

Retrieve one image direction's full implementation export, as Markdown for reading and briefing or JSON for programmatic use. This is what you follow when generating, sourcing, or art-directing imagery for the project, and it pairs with the design kit rather than replacing any of it. Read-only: it returns the text and writes nothing to disk. Free records are public; a Pro record returns 403 with an upgrade path unless the key is entitled, without leaking the payload.

Inputs: slug (required), format.

get_interface_styleGet an interface styleA

Retrieve one interface style's full implementation export, as Markdown for reading or JSON for programmatic use. The export holds render-grammar rules only, so combine it with a design kit's tokens, typography, motifs, and brand rules; on its own it will not give the UI an identity. Read-only: it returns the text and writes nothing to disk. Free records are public; a Pro record returns 403 with an upgrade path unless the key is entitled, without leaking the payload.

Inputs: slug (required), format.

get_kit_history_eventRead the kit as it stood at one history entryA

The full kit recorded at one line of the ledger, which is what makes the timeline useful rather than decorative: with it you can diff a past state against the current kit, or PATCH the payload back through update_theme to restore it. The response is a whole design kit, so it is large — call list_kit_history first and fetch only the entry you want. Knowing an event id is never sufficient on its own: the event must be yours AND on a kit you still own, and either test failing answers 404 identically, so a 404 here does not tell you which of the two it was. Needs kits:read.

Inputs: slug (required), eventId (required).

get_kit_versionRead one stored kit versionA

The full snapshot a given version recorded, as it was at that moment. Reach for this when you need the old values themselves, for example to see what a token was before an edit replaced it; diff_kit_versions is the cheaper answer when you only need to know what moved. The response is a whole design kit, so it is large. A version number is permanent: version 3 is version 3 forever. This returns the entire payload, so it is gated exactly like an export, and a Pro kit without an entitled key answers 403 rather than a redacted body. Needs kits:read.

Inputs: slug (required), version (required).

get_mockup_jobGet a brand mockup jobA

Poll one mockup job in its project for status, completed count, errors, and result URLs. Read-only. Requires kits:read.

Inputs: jobId (required), projectId (required).

get_naming_research_contextPrepare a naming research handoffA

Load everything you need to plan naming research in one call: the project brief, up to 100 candidates with the evidence already attached to them, which factual checks are available, workflow guidance, and a template for handing bounded questions to sub-tasks. Call it before orchestrating substantial research so you do not re-run checks that already exist on the board. It deliberately does not rank candidates, score them, or tell you which model to delegate to, because that judgement stays with you. Read-only and free. Requires the naming:read scope.

Inputs: projectId (required).

get_page_recipeGet a page recipeA

Retrieve one page recipe's full implementation export, as Markdown for reading or JSON for programmatic use. This is what you build the page's structure and argument from, and it pairs with a design kit, which still supplies the visual and interaction rules. Read-only: it returns the text and writes nothing to disk. Free records are public; a Pro record returns 403 with an upgrade path unless the key is entitled, without leaking the payload.

Inputs: slug (required), format.

get_project_contextRead a project's stored contextA

What this brand project's product actually is: what it does, who it is for, what the design must respect, what has already been ruled out, which screens it has, and what it is built on. Read it before proposing anything for an existing project, and read it before set_project_context, because that call replaces rather than merges. A project that exists but has no context yet answers null, which is a different fact from a project that does not exist; that one is a 404. Free, needs kits:read.

Inputs: projectId (required).

get_tokensGet design tokens for a themeA

Fetch one design kit's machine-readable tokens in the format that matches the target stack. It covers all 28 semantic color roles in both light and dark, plus typography and spacing. Use it to wire a kit into an existing styling layer when you do not need the written brief; pair it with get_design_md when you also need the rules. Read-only: it returns the file contents as text and writes nothing to disk. apply_theme writes tokens and DESIGN.md into a project in one step. Free kits are public; a Pro kit returns 403 unless the key is entitled.

Inputs: slug (required), format.

list_brand_projectsList brand projectsA

List every brand project owned by the connected key, each with its name, brief, variation count, and whether a client share link already exists. Start here to find a projectId before add_brand_variation or share_brand_project, and to check whether a board for this client already exists instead of creating a duplicate. Read-only and free: it takes no arguments, returns all projects at once (no pagination), and changes nothing. Requires the kits:read scope.

Inputs: no named parameters.

list_brand_project_versionsList a brand project's versionsA

The brand project's history, newest first: what changed, when, and by whom. Owner-scoped, so a project you do not own answers 404 exactly as a missing one does, and there is no tier gate. The timeline records the whole brand: its name and domain, its fonts, its pinned layers, its project context, and its variations, including a reorder. Sharing is deliberately absent, because who may see a brand is not what the brand is. An empty timeline means the project has not been written since versioning was wired, not that nothing has happened to it. Free to call, needs kits:read.

Inputs: projectId (required), limit, before.

list_client_commentsRead client feedbackA

Read what the client wrote on a project's variations through the share link, oldest first, with the variation each comment is attached to and the author's display name. This is the return leg of the share loop: without it you can build a brand project, attach directions and send the link, but never learn what the client actually said about them. Call it before revising, then act on it with update_brand_variation, update_theme, or remove_brand_variation. Anonymous commenters appear as 'Guest' rather than an id, and deleted comments are omitted. Read-only, changes nothing, takes no pagination. Requires the kits:read scope.

Inputs: projectId (required).

list_image_directionsList image directionsA

Browse image directions, which decide how a project's photography and illustration should be made: the process, treatment, and subject matter. Use one when a kit is chosen but the imagery still has no direction, which is where most agent-built pages fall back to stock-looking filler. Returns judgment summaries with no export payload, so pick a slug and call get_image_direction for the implementable version. A direction sits alongside the design kit and never replaces it; the kit still owns color, type, and brand rules. Read-only and free, and Pro records appear in the list without exposing their contents.

Inputs: q, use, sort, tier, +1 more.

list_interface_stylesList interface stylesA

Browse interface styles, which decide how surfaces and hierarchy render: how panels stack, how density and depth read, how structure is expressed. A style is a neutral render grammar you apply through a design kit, not a second source of palettes, fonts, or brand rules, so it answers how the UI is built rather than what it looks like. Use one when the kit is settled but the layout still defaults to generic cards on a grid. Returns judgment summaries with no export payload; pick a slug and call get_interface_style for the implementable version. Read-only and free, and Pro records appear in the list without exposing their contents.

Inputs: q, use, sort, tier, +1 more.

list_kit_historyList a kit's history ledgerA

Everything that has happened to one of your saved kits, newest first: its creation, every save, and every time it was applied to a brand. Wider than list_kit_versions, which only sees the events that minted a version — an apply-to-brand event appears here and nowhere else, so this is the tool that answers whether a kit was ever actually used rather than merely edited. Each row carries an event id; pass it to get_kit_history_event for the full kit as it stood at that moment. Metadata only, so no tokens come back here. Only kits saved under an API key have a ledger: a curated catalog kit is shipped rather than edited, and asking for one answers 404 rather than an empty list, because you do not own it. Paged by an OPAQUE cursor, not by a number — hand meta.nextCursor back unchanged rather than constructing one, and a cursor this endpoint did not issue is rejected rather than silently restarting from the top. Free to call, needs kits:read.

Inputs: slug (required), limit, cursor.

list_kit_versionsList a kit's versionsA

The kit's VERSION timeline, newest first: which version, when, by whom, and the author's note. Use it to answer the question a repo built against this kit actually has, which is whether the kit has moved since. It is not the full history: a version is minted only when the kit is created or saved, so applying the kit to a brand appears nowhere here. list_kit_history is the wider record and includes those. Metadata only, so no tokens come back; get_kit_version returns a whole snapshot and diff_kit_versions says what changed between two. Versions exist only for kits saved under an API key: a curated catalog kit is shipped rather than edited, so its timeline is empty and meta.currentVersion is 0. That 0 means no version has been minted, which is a real state and not a missing value. Paginated newest-first through meta.nextBefore. For a Pro kit you are not entitled to, rows still come back but the free-text label is null, because an author's note can restate a token you may not read. Free to call, needs kits:read.

Inputs: slug (required), limit, before.

list_mockup_jobsList brand mockup jobsA

List one brand project's mockup jobs newest first, including status, progress, errors, and completed result URLs. Read-only. Requires kits:read.

Inputs: projectId (required).

list_name_candidatesRead a naming kanban boardA

Read one project's candidate kanban. Returns each persisted name with its status, rank, notes, attached research evidence, originating recipe, generation provenance, and an updatedAt timestamp you pass back to move_name_candidates or rank_name_candidates to guard against stale writes. Filter by status to review a single column, such as just the shortlisted or finalist names. Read-only, paginated, and free. Requires the naming:read scope.

Inputs: projectId (required), limit, offset, statuses.

list_name_generationsRead naming generation provenanceA

Read the generation ledger for one project: every generate_names run with its request fingerprint, recipes and settings, model, prompt version, how many names it produced, how many credits it reserved and actually consumed, final status, and timestamps. Use it to answer where a given set of names came from, or to check whether a run that appeared to fail actually charged anything before retrying. Read-only, paginated, and free. Requires the naming:read scope.

Inputs: projectId (required), limit, offset.

list_naming_projectsList naming projectsA

List the persistent naming boards owned by the connected key, with each project's id, name, brief, researched TLDs, chosen name, and candidate counts. Start here to recover the projectId for an existing brief, since every other naming tool needs one, and only call create_naming_project when nothing here fits. Read-only, paginated, and free. Requires the naming:read scope.

Inputs: limit, offset.

list_naming_recipesDiscover naming recipesA

List every public naming strategy Identity Forge can generate from, with each recipe's id, intent, generation instruction, and settings. Call it before generate_names so you pick 1-8 recipe ids that genuinely fit the brief instead of guessing at strategy names. Recipe ids are stable, so you can skip this once you already know the ones you want. Read-only, free, and needs no arguments.

Inputs: no named parameters.

list_page_recipesList page recipesA

Browse page recipes, which decide how a page argues its case: what it leads with, in what order it earns belief, and what the reader should walk away knowing. Use one when you know what a page must achieve but not how to sequence it, which is the gap that produces hero-features-pricing pages by default. Returns judgment summaries with no export payload; pick a slug and call get_page_recipe for the implementable version. Each record carries a model field: most are legacy-sequence, which prescribes a section order, while communication-idea records state the argument and leave the sequencing to you. Read the model before following a record, since the two ask different things of you. This covers structure and argument, not visuals; the design kit still owns those. Read-only and free.

Inputs: q, goal, sort, tier.

list_themesList design themesA

Browse the published catalog as compact summaries: slug, name, summary, tags, audience, a font and palette glimpse, tier, and computed discovery facets covering use-case fitness from 0 to 100, moods, and industries. This is the main entry point for finding a design kit. Filter by what the user is actually building: use re-orders the catalogue for that surface rather than narrowing it, each kit carrying a fitness score measured on its own tokens, and q runs a synonym-aware ranked search that understands phrases like 'calm fintech dashboard'. Results are paginated and report the total plus the next offset, so page rather than assuming the first response is the whole catalog. Summaries carry no tokens, no DESIGN.md, and no font files; pull one kit with get_design_md or get_tokens, or apply_theme to write it into the project. Prefer search_themes when the brief is too subtle to rank against a lane and you want to weigh the entire catalog yourself. Read-only and free, and it lists Pro kits without exposing their contents.

Inputs: q, use, sort, limit, +1 more.

match_paletteMatch themes to brand colorsA

Rank published kits by how close their palette sits to colors the user already owns, using perceptual color distance rather than string matching. Use it when a brand has existing colors that the design system has to live with, such as an established logo. This ranks on color alone and ignores mood, audience, and use case, so treat the result as a shortlist and check the rest of the fit with get_design_md before committing. When the user has no fixed colors, list_themes or search_themes will serve them better. Read-only and free.

Inputs: colors (required), limit.

move_name_candidatesMove or annotate naming candidatesA

Progress up to 100 candidates through the kanban in one atomic write, and optionally replace their notes and evidence at the same time. Columns run generated, reviewing, shortlisted, finalist, selected, and rejected. This is the tool for recording a decision and why you made it; rank_name_candidates only reorders and leaves status alone. A project can hold exactly one selected candidate, and selecting one also sets the project's chosen brand name, so treat that move as the final call. Pass expectedUpdatedAt from list_name_candidates to reject a write when the row changed underneath you. Requires the naming:write scope.

Inputs: projectId (required), operations (required).

rank_name_candidatesRank naming candidatesA

Assign explicit user-facing priority ranks to up to 100 candidates on one naming board in a single atomic write, so every ranking applies or none does. Rank 1 is the highest priority and ties are allowed. This changes ONLY the rank field: kanban status, notes, and evidence are left untouched, so use move_name_candidates when you want to progress a candidate or record a decision. Use it to express a deliberate shortlist order for the user, not to record research. Requires the naming:write scope; it spends no AI credits.

Inputs: rankings (required), projectId (required).

recommend_kitsRecommend kits for a projectA

Kit candidates for a specific product, grounded in the context stored on its project rather than in a description you re-send. Each candidate comes back with the kit's own case for itself — what it is for, its motifs, its do's and don'ts, its moods and industries, and its computed fitness for the surfaces this product actually has — so you can rank them yourself. With a Pro account and a kits:write key you also get a model-authored ranking with a reason per candidate written against this product; meta.depth says which you got, ranked or candidates, and meta.order says plainly that the free ordering is computed lane fitness and not a recommendation. Two things that differ from the rest of discovery: this costs 3 quota units where list_themes and search_themes cost 1, and it requires an API key where every other discovery route works anonymously. Call set_project_context first: a project with no stored context returns 400 rather than guessing. Creates nothing.

Inputs: projectId (required), limit.

remix_themeRemix a design kitA

Copy an existing kit into a new private kit with overrides applied. The source can be your own kit, a catalog kit, or another user's public kit. This is the fast path when you want three or four variations on one direction: call it repeatedly against the same source with different overrides. The original is never modified. Reach for create_theme instead when you are authoring a kit rather than varying one. A Pro-tier source needs an entitled key, and the copy is private until you publish it from the web Studio. Requires the kits:write scope.

Inputs: slug (required), overrides (required), name.

remove_brand_layerTake a layer off a brandA

Remove one composed record from a brand project. The brand keeps its design kit and every other axis; only this reference goes. Name the record rather than just the axis, so a stale view of the brand cannot clear a layer it never saw — pass the id you read from get_brand_layers rather than one you remember. Safe to repeat: an id that is not composed answers changed: false, changes nothing and mints no version. When the intent is to swap rather than to clear, call add_brand_layer with replace: true instead; removing first leaves the brand briefly without that axis and takes two versions to say one thing. This takes effect on the user's brand immediately and requires confirm: true; without it nothing changes. Requires the kits:write scope.

Inputs: axis (required), confirm (required), recordId (required), projectId (required).

remove_brand_variationRemove a brand variationA

Permanently DELETE one brand proposal from a project. The client stops seeing that direction on their next share view, and the comments they left on it go with it. This cannot be undone, there is no archive, and confirm: true is required, so read list_client_comments first if the feedback on that direction still matters. The surviving variations keep the positions they already had, which leaves a gap in the sequence rather than closing it, so follow with reorder_brand_variations when the order the client meets them in matters. Use update_brand_variation instead when the direction should be revised rather than retired. Requires the kits:write scope.

Inputs: confirm (required), projectId (required), variationId (required).

reorder_brand_variationsReorder brand variationsA

Set the order the client meets the directions in. The share page walks the variations in this order, so the first id is the direction the client sees first, which is worth deciding deliberately rather than leaving on the order you happened to attach them in. This OVERWRITES the stored order of the whole project and takes effect on the client's next view. You must list every variation in the project exactly once: a partial list is rejected with 400 and the expected id set, because writing positions for only some of them would collide with the ones left behind. Get the current ids from the response of add_brand_variation, or from a previous call to this tool, which returns the variations in their new order. Requires the kits:write scope.

Inputs: projectId (required), variationIds (required).

revoke_brand_shareRevoke a client share linkA

Withdraw the client's access permanently. The /p/ URL stops resolving wherever it was pasted, including in an email already sent. NOT UNDOABLE: sharing again mints a new token and deliberately never the old one, so a withdrawn link can not be brought back to life. This tool requires confirm: true; without it nothing changes. Reach for update_brand_share with enabled: false instead when the client should see it again later — that is the reversible one, and it is almost always what is wanted. Revoking is for a link that leaked or an engagement that ended. The project, its variations and the comments the client already left all survive; only the access is withdrawn. Requires the kits:write scope.

Inputs: confirm (required), projectId (required).

search_name_evidenceRun model-authored name searchesA

Run up to 20 web searches you author yourself against a candidate name, for existing-company collisions, market context, meaning, unfortunate readings in another language, negative associations, or official registers. You write the queries because you know what would disqualify this particular name. Returns dated raw results and nothing else: it does not score, rank, decide whether a collision is real, or constitute trademark clearance. Read the results, form your own view, and attach both the evidence and your interpretation to the board with move_name_candidates. For domain registration and DNS evidence use check_domains instead. Requires the naming:read scope.

Inputs: tasks (required).

search_themesGet themes to rank for a productA

Return the entire catalog at once, unranked, as compact summaries carrying each kit's moodSummary, vibeTags, tags, audience, and a font and palette glimpse, so you can judge fit yourself. Despite the name it runs no server-side search: query is echoed back to keep your brief in context, and the ordering is neutral. Use it when the brief is subtle or cuts across categories and you would rather weigh every option than trust a ranking. Prefer list_themes when the brief maps cleanly onto a use case or search phrase, since it ranks the catalog for you and pages rather than returning everything. Neither tool narrows the catalog; the difference is ranked and paged against unranked and all at once. Read the summaries, pick one to three, then get_design_md to read the full brief or apply_theme to write it into the project. Read-only and free.

Inputs: query (required).

search_trademarksSearch EUIPO trademarksA

Screen one owned naming candidate against EUIPO's verbal-element register, optionally within up to 10 Nice classes. This uses Identity Forge's shared EUIPO daily, burst, fair-share, and provider-cooldown quota; a 429 includes the allowance and retry timing. Results are preliminary evidence, not a similarity verdict or legal clearance. Requires naming:read.

Inputs: query (required), projectId (required), nameSuggestionId (required), niceClasses.

set_project_contextReplace a project's contextA

Store what the product is, so every later proposal is grounded in it and you never re-send a paragraph of prose. This REPLACES the whole context: nothing is merged, so any field you leave out is deleted, not 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 the safe way to edit is get_project_context first, then send the whole object back with your change applied. product is the only required field and must be a real sentence rather than a label; a description under 12 characters is refused, because a proposal built on one reads as grounded while being generic. Every string is bounded and an over-long field is refused by name rather than truncated, so nothing is silently cut. Requires the kits:write scope; reading needs only kits:read.

Inputs: product (required), projectId (required), avoid, moods, +5 more.

share_brand_projectShare a brand projectA

Publish a project to a client and return the full /p/ URL to send them. The page is read-only, serves only this project's kits, and lets the client cycle the variations and leave comments without an account. Anyone holding the link can open it, so set a password for sensitive work. Calling it again returns the existing link unchanged unless you pass rotate, which mints a new token and permanently breaks any link already sent. Add the variations before sharing, since the client sees whatever is attached at the moment they open it. Requires the kits:write scope.

Inputs: projectId (required), rotate, password.

similar_themesFind similar themesA

Find published kits close to one you already have, ranked by palette proximity, shared tags, and audience. Use it when the user likes a direction but wants options, or when a candidate is nearly right and you want neighbours to compare. It needs an existing slug, so start from list_themes or search_themes if you do not have one yet. Returns compact summaries with a similarity score; judge the actual fit yourself, since proximity in palette and tags is a starting point rather than a verdict. Read-only and free, and it lists Pro kits without exposing their contents.

Inputs: slug (required), limit.

update_brand_sharePause, resume or password-protect a shareA

Change an existing client link WITHOUT reissuing it. enabled: false pauses it, so the client sees nothing until you resume; password sets one after the fact, and null removes it. The token is untouched, so a link already with the client starts working again the moment you resume. This is the tool to reach for when work is mid-revision and the client should not be looking yet, or when you shared something before realising it was confidential. It takes effect immediately for anyone holding the URL, including a client with the page already open. A project with no share yet answers 404: create one with share_brand_project first. Requires the kits:write scope.

Inputs: projectId (required), enabled, password.

update_brand_variationUpdate a brand variationA

Edit one brand proposal already attached to a project, in place. This OVERWRITES the stored variation, and the client sees the new version the moment they next load the share link, including a client who has the page open right now, so treat it as publishing rather than drafting. Send only the fields that move; passing null for brandName, domain, label or notes clears that field rather than leaving it. Changing kitSlug repoints the proposal at a different design kit, which re-checks that you can resolve that kit and that a Pro kit has an entitled key behind it. Use it to act on client feedback from list_client_comments without making the client re-review a whole new set of directions. Add a new direction with add_brand_variation instead when the old one should stay on the board. Requires the kits:write scope.

Inputs: projectId (required), variationId (required), label, notes, +3 more.

update_themeUpdate a saved design kitA

Edit a design kit you already saved, in place. This OVERWRITES the stored kit without asking: the slug, id and publication state all stay the same, so everything already pointing at that kit follows the edit, including brand variations that reference it, any client share link that serves it, and a repo that installed its registry entry. The overwrite itself has no undo, but it is recorded: every save mints a version, so the state you replaced stays readable through list_kit_versions and get_kit_version, and diff_kit_versions shows exactly what your edit moved. Reach for remix_theme instead when you want the original left alone, which is usually the right call while you are still exploring directions; use this one when the kit is the brand and the brand has genuinely changed. It only edits kits saved under your key. A catalog kit, another user's kit, or an unknown slug all return 404 alike. kit is deep merged over the stored payload, so you state only what moves and everything else survives, and overrides applies on top of that merge. The one thing you cannot change is the slug itself: it is the kit's public handle and moving it would break every link already using it, so a payload carrying a different slug is rejected with 400 rather than quietly ignored. Pass expectedUpdatedAt from the last read to get a 409 instead of silently overwriting a change someone else made in between; the 409 body carries the current marker so you can re-read, reapply and retry. Requires the kits:write scope.

Inputs: slug (required), kit, name, overrides, +1 more.

whoamiWhat this API key can doA

Your plan, the scopes this key holds and the ones it lacks, how much of the monthly quota is left, your AI credit balance, and how many saved-kit slots remain. Call it before promising a user something the key cannot deliver: every one of these limits is otherwise discoverable only by hitting it, as a 403 for a missing scope or a locked Pro kit, a 429 for quota, a 402 for credits, or a refused save at the free tier's kit cap. This call is free. It spends no quota units and no AI credits, and it is deliberately never refused for being over quota, so it still answers after a 429 has already happened and is safe to call first. Any valid key may read its own entitlements, whatever scopes it holds.

Inputs: no named parameters.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    A4.1/5.0

    Scored across 61 tools

    Disambiguation4/5

    Most tools have clearly distinct purposes within their domains, but there are near-duplicate pairs like list_themes/search_themes and list_kit_versions/list_kit_history that could lead to misselection despite detailed descriptions. The descriptions do an excellent job of explicitly disambiguating, so confusion is unlikely for a careful agent.

    Naming Consistency5/5

    Tool names follow a consistent verb_noun pattern (list_, get_, create_, update_, delete_, remove_, etc.) across all domains. The only exception is whoami, which is a common MCP convention and does not break the pattern.

    Tool Count1/5

    With 61 tools, the server is far beyond the typical well-scoped range of 3-15, and exceeds the 50+ threshold for 'extreme mismatch'. While the breadth covers multiple subdomains, the sheer number makes it overwhelming and difficult for an agent to navigate.

    Completeness4/5

    The tool surface is remarkably comprehensive, covering design kit lifecycle, brand project management, naming, mockups, page recipes, image directions, and interface styles. However, there is no way to delete a brand project or naming project, or update a naming project's brief, leaving minor dead ends. Overall, the domain is well-covered.

    Maintenance

    ActivityInactive
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      A
      quality
      D
      maintenance
      An MCP server that allows coding agents to look up contextual rules and patterns on demand, providing just-in-time guidance for specific tasks like writing tests or authoring UI.
      2
      8
      MIT
    • A
      license
      Not graded
      quality
      D
      maintenance
      MCP server that exposes your design system components and tokens to AI agents, preventing duplicate component creation and hardcoded token values.
      4 npm
      9
      MIT
    • A
      license
      Not graded
      quality
      C
      maintenance
      A read-only MCP server that provides AI coding agents with a queryable contract for design system tokens, components, patterns, and anti-patterns.
      24 npm
      1
      Apache 2.0
    • A
      license
      Not graded
      quality
      C
      maintenance
      MCP server for Majico.xyz that enables coding agents to read (and limited write) brand guidelines, design tokens, studio canvas, and export manifests.
      9 npm
      MIT