# Connect your AI coding agent to your Yeja Atelier

1. **Add the server.** `https://yeja-ai.com/mcp`. Add no key and no header.
   You do this once, and it works for any profile.
2. **Give your agent your profile and a key.** In the chat, paste your profile
   link and a key from **Developer Access**, for example *"Connect to my Yeja
   profile https://yeja-ai.com/atelier/<your-username> with key yeja_atl_…"*.
   The agent connects with `connect_profile`, and every result names the
   profile it is working on.
3. **Ask for something.** *"Show me my Atelier and suggest three improvements."*

**Changes wait for you.** An agent stages a draft; you preview it and press
Publish. Two kinds of change are **live** the moment they run: the curation
tools, which need the separately ticked `atelier:curate` permission, and the
two undo tools (`restore_snapshot`, `rollback_freeform`),
`reset_atelier_theme`, `unpublish_freeform` and `unpublish_atelier`. Every
live tool is marked in the tool list.

Prefer signing in to pasting a key? Use `https://yeja-ai.com/mcp/oauth` and
approve in the browser. See *Keys and Sign-In*.

---

## Install

Your Atelier is your public artist page at `https://yeja-ai.com/atelier/<your-username>`.
The server is `https://yeja-ai.com/mcp`, and it speaks MCP over **POST only**
(streamable HTTP, no SSE stream).

Every client gets the same entry: the address and nothing else. No key goes in
the settings, so one install serves every profile, and the agent connects a
profile at the start of each chat. Every client wants a slightly different
shape, and four of them fail *silently* when given the wrong one. Use your own
client's section, not the nearest-looking one.

### Claude Code

```bash
claude mcp add --transport http yeja-atelier https://yeja-ai.com/mcp
```

Then start a chat and give the agent your profile link and key.

**Do not add `--header "Authorization: …"`.** A key in the settings ties the
server to that one account in every chat. Any `Authorization` header also
**turns off OAuth fallback** in Claude Code, and the header is read once when
the process starts, so changing it later means restarting Claude Code. To sign
in instead of using a key, add `https://yeja-ai.com/mcp/oauth`, then run
`/mcp`, pick the server and choose **Authenticate**.

### Claude Desktop and Claude.ai

Add it as a custom connector: open **Connectors** in Claude's settings, press
**+**, choose **Add custom connector**, paste `https://yeja-ai.com/mcp` and
press **Add**. Then start a chat and give Claude your profile link and key. The
same connector is available in Claude Desktop and on claude.ai, and it works
for any profile.

**If an older Yeja connector is signed in**, it can only ever work on the
account it signed in as. Check the account on the dashboard's **Connected
Agents** list, and remove the connector if it is not yours.

Custom connectors are available on every Claude plan; the Free plan allows
one. On Team and Enterprise, an organization Owner adds the connector first and
members then press **Connect**.

#### Advanced: A Key In The Settings

Claude Desktop's config file **cannot send a custom header** to a remote
server, so a key needs the `mcp-remote` bridge:

```json
{
  "mcpServers": {
    "yeja-atelier": {
      "command": "npx",
      "args": [
        "-y", "mcp-remote", "https://yeja-ai.com/mcp",
        "--header", "Authorization: Bearer yeja_atl_YOUR_KEY_HERE"
      ]
    }
  }
}
```

### Cursor

```json
{
  "mcpServers": {
    "yeja-atelier": {
      "url": "https://yeja-ai.com/mcp"
    }
  }
}
```

In `~/.cursor/mcp.json`, or `.cursor/mcp.json` inside a project. Remote
entries need no `type` field. Then give the agent your profile link and key
in the chat.

#### Advanced: A Key In The Settings

```json
{
  "mcpServers": {
    "yeja-atelier": {
      "url": "https://yeja-ai.com/mcp",
      "headers": { "Authorization": "Bearer yeja_atl_YOUR_KEY_HERE" }
    }
  }
}
```

The dashboard's Developer Access card also has a one-click install link for
Cursor, which is easier than editing this file.

### VS Code and GitHub Copilot

```json
{
  "servers": {
    "yeja-atelier": {
      "type": "http",
      "url": "https://yeja-ai.com/mcp"
    }
  }
}
```

In `.vscode/mcp.json`, or in your user configuration (**MCP: Open User
Configuration**). Note this client uses `servers`, not `mcpServers`. Then
give the agent your profile link and key in the chat.

#### Advanced: A Key In The Settings

```json
{
  "inputs": [
    {
      "type": "promptString",
      "id": "yeja-key",
      "description": "Yeja Atelier API Key",
      "password": true
    }
  ],
  "servers": {
    "yeja-atelier": {
      "type": "http",
      "url": "https://yeja-ai.com/mcp",
      "headers": { "Authorization": "Bearer YEJA_KEY_PLACEHOLDER" }
    }
  }
}
```

Replace `YEJA_KEY_PLACEHOLDER` with an input reference so VS Code prompts for
the key rather than storing it in the file: a dollar sign, then
`{input:yeja-key}`. The dashboard's Developer Access card also has a
one-click install link for VS Code.

### Codex CLI

```bash
codex mcp add yeja-atelier --url https://yeja-ai.com/mcp
```

Then give the agent your profile link and key in the chat.

#### Advanced: A Key In The Settings

```bash
codex mcp add yeja-atelier --url https://yeja-ai.com/mcp \
  --bearer-token-env-var YEJA_API_KEY
```

**Codex takes the NAME of an environment variable, not the key itself.** Set
`YEJA_API_KEY` in your shell to the key, and pass the name here. Pasting the
key where the name belongs fails in a way that does not say so. A bearer token
takes precedence over sign-in when both are set. The file form, in
`~/.codex/config.toml`:

```toml
[mcp_servers.yeja-atelier]
url = "https://yeja-ai.com/mcp"
bearer_token_env_var = "YEJA_API_KEY"
```

### Antigravity and Windsurf

```json
{
  "mcpServers": {
    "yeja-atelier": {
      "serverUrl": "https://yeja-ai.com/mcp"
    }
  }
}
```

**Use `serverUrl`, not `url`.** `serverUrl` works in both clients, while
some versions ignore a plain `url` for a remote server, and an ignored entry
looks exactly like a server that is not responding.

Antigravity reads `~/.gemini/config/mcp_config.json`. Windsurf is now
**Devin Desktop**, which reads `~/.config/devin/mcp_config.json`. Then give
the agent your profile link and key in the chat.

#### Advanced: A Key In The Settings

Add `"headers": { "Authorization": "Bearer yeja_atl_YOUR_KEY_HERE" }` beside
`serverUrl`.

### Zed

```json
{
  "context_servers": {
    "yeja-atelier": {
      "url": "https://yeja-ai.com/mcp"
    }
  }
}
```

**Zed calls them `context_servers`, not `mcpServers`.** Open the file with
**zed: open settings file**. Then give the agent your profile link and key in
the chat.

#### Advanced: A Key In The Settings

Add `"headers": { "Authorization": "Bearer yeja_atl_YOUR_KEY_HERE" }` beside
`url`.

### Cline

```json
{
  "mcpServers": {
    "yeja-atelier": {
      "type": "streamableHttp",
      "url": "https://yeja-ai.com/mcp"
    }
  }
}
```

Then give the agent your profile link and key in the chat.

**`streamableHttp` is case-sensitive.** Writing `streamable-http`, or leaving
`type` out, makes Cline fall back to SSE, and this server answers SSE with a
405 that does not explain itself.

### Check It Works

```bash
curl -s -X POST https://yeja-ai.com/mcp \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
```

A list of tools coming back means the server is reachable. The agent then
connects a profile in the chat; until it does, every tool except the
connection tools answers `not_connected`. A `401` means a key in your
client's settings is wrong or revoked.

## Keys and Sign-In

**One profile per chat, named every time.** At the start of each chat the agent
passes your profile and a key to `connect_profile`. The server checks that the
key belongs to that profile and refuses anything else, and every result carries
`acting_as`, the profile it is working on. If it is not the profile you
meant, stop the agent. One chat works on one profile: to work on another,
start a new chat.

To create a key:

1. Open https://yeja-ai.com/dashboard/?app=profile&view=portfolio
2. Scroll to **Developer Access**
3. Name the key after the agent or computer that will use it.
4. Both boxes start ticked: **Allow This Key To Propose Changes** and **Allow
   This Key To Change Pinned Works Immediately**. Untick what you do not want;
   with both unticked the key is read-only.
5. Press **Create API Key** and copy the key immediately. It is shown once.

**A key does not expire, and you can hold up to 10.** Creating a key never touches
the others. Revoke one on its own from the same card, and every chat it
connected stops at once. **Connected Agents**, on the same page, lists every
chat and signed-in app using your Atelier, with **Disconnect** for each.

**Signing in instead (OAuth 2.1).** A client that supports it can use
`https://yeja-ai.com/mcp/oauth`. You approve on a consent screen that shows the
account you are signing in as, with **Switch Account** if it is the wrong one.
That connection belongs to that account: the agent still connects the profile,
and any other profile is refused. Access renews itself every hour; if the
client goes unused for 30 days, you sign in again.

**A key in the client's settings** (`Authorization: Bearer yeja_atl_…`, under
*Advanced* in each client's section) still works, and ties that entry to one
account in the same way. Name such an entry after the profile, for example
`yeja-atelier-<username>`.

| Permission | What it lets an agent do | Sign-in starts | Key starts |
|---|---|---|---|
| Read (`atelier:read`) | See your Atelier, works, drafts and measurements. Changes nothing. | Always on | Always on |
| Propose (`atelier:write`) | Stage drafts, build Freeform pages, import an image with your permission, and restore or roll back your live page | Ticked | Ticked |
| Curate (`atelier:curate`) | Change pins, hero, timeline, custom sections, products and theme listings, most of them **live** | Unticked | Ticked |

## What an Agent Can Change

**An agent cannot publish.** It stages; you press Publish in your dashboard.
The only way anything reaches your public page without that is a tool marked
**Live** below.

| Staged: waits for Publish | Live: changes your public page immediately |
|---|---|
| Headline, bio, layout, palette, banner and SEO fields (`propose_atelier`) | Pins and hero (`pin_artwork`, `reorder_pins`, `set_hero`…) |
| Custom CSS (`propose_custom_css`) | Timeline entries and custom sections, edited one row at a time |
| Freeform pages, including clones | Products and theme listings, once set to available |
| Whole collections through `stage_collection` | `restore_snapshot`, `rollback_freeform`, `reset_atelier_theme`, `unpublish_freeform` and `unpublish_atelier` |

Pins, timeline, sections and products can be changed two ways. The staged way,
`stage_collection`, sends the whole intended list and waits for Publish;
`get_staged_collection` reads back what to edit. The older per-row tools take
effect at once. Prefer the staged way, and ask for it by name: *"stage this,
don't publish it."*

### Undo

A snapshot is taken automatically **before every publish**. `restore_snapshot`
rolls your live page back to one, takes a snapshot of the current state first
so the restore can itself be undone, and clears any pending draft. A good agent
confirms with you before calling it.

For a Freeform page, `rollback_freeform` re-publishes an earlier version
through the full publish gate. An artwork you have deleted since does not come
back.

Staged work you no longer want: `discard_staged_rows` and
`discard_freeform_draft`. Your live page is untouched by both.

To start the theme over, `reset_atelier_theme` puts your Atelier back on the
default Yeja theme: palette, type, corner radius, background and custom CSS are
cleared, and an installed or agent-built Freeform page is taken down and its
draft discarded. Your works, statement, timeline, sections and widgets stay.
Called without `confirm: true` it only lists what would change. It snapshots
first, so `restore_snapshot` undoes it, except a discarded Freeform draft.

To take only the Freeform page down, `unpublish_freeform` puts visitors back on
the classic Atelier and keeps the draft and every version; `rollback_freeform`
brings it back. To take the whole Atelier offline, `unpublish_atelier` does what
Unpublish Atelier in the dashboard does: nothing is deleted, and only you can
publish it again. Both are dry runs until called with `confirm: true`.

### What Curation Refuses

- **Pinning a work with no published image.** It would render as a blank card.
  Publish the image in My Studio first.
- **Pinning a trashed work.**
- **A partial reorder.** `reorder_pins` needs every pin named, in order.
- **Deleting a product with orders.** Archive it instead.

`remove_timeline_entry` cannot be undone; `remove_section` can, with
`restore_section`.

## What to Ask For

Once connected, talk to your agent normally:

- *"Build out my whole Atelier. Ask me for anything you need."*
- *"Read my Atelier and tell me what a first-time visitor sees."*
- *"My work is quiet and monochrome. Propose a palette and layout that match."*
- *"Rewrite my headline to be less generic. Keep it under 80 characters."*
- *"Make my Atelier look like this site: <address>. Take the layout, not the art."*

Many clients also list this server's six ready-made prompts, such as
*interview_artist* and *rebuild_from_reference*, in their prompt or slash-command
menu.

### It Should Interview You First

A good agent starts with six questions: what the page is *for*, who lands on
it, what a visitor should do, how it should feel, what must appear, and which
sites you want it to resemble. About two minutes. An agent can see your
artworks but none of that, and that is what decides the layout.

`draft_from_reference` refuses to build until the six are answered. Say
plainly that you want to skip the questions and the agent can proceed; that it
did is recorded. `replicate_site` does not wait: it fills only the answers you
have not given with **provisional** ones, marked in your dashboard as the
agent's and not yours, so check and correct them. Your answers are saved, so
the interview happens once; say *"start over"* to rethink the page. **None of
this is public.**

### Filling the Whole Atelier

Ask for everything and a good agent fills every surface, not just the banner
and a grid:

| Surface | What goes there |
|---|---|
| Banner + headline | An image of yours, or a Yeja pattern, with the line that sits over it |
| Pinned Showcase | The works you want seen first, in order |
| Artist Statement | The writing, plus an image beside it |
| Medium & Process | Up to three images, each with a note on how you work |
| Professional Timeline | Exhibitions, residencies, study, commissions |
| Skills & Technical Stack | Tools, mediums and specialized capabilities |
| Verifiable Collaborations | Projects with another artist, shown once both confirm |
| Get In Touch | The contact panel and its actions: Create An RFP, Share Profile, Export CV As PDF, Send A Quick Inquiry |
| Social Links | Where else your work lives |
| Support | Monthly pledges from people who follow your work |
| Atelier Style | Palette, type, corner radius and background pattern |

A section you fill but never switch on stays invisible, so an agent should turn
on whatever it populates. And it should **ask you** for anything it does not
have (dates, collaborators, a statement) rather than writing something
plausible. A made-up exhibition history is worse than an empty one.

### Custom Sections

| Type | For |
|---|---|
| `rich_text` | An about section, a teaching philosophy, a positioning statement |
| `announcement` | One upcoming thing, with an image: a workshop, a launch, an opening |
| `event_list` | Several dates: a workshop calendar, a tour, a run of classes |
| `offer_list` | Classes, courses, prints, books: a name, a description and a price |
| `testimonials` | Quotes from people you have actually taught or worked with |
| `faq` | Questions you answer often: what to bring, who it is for |
| `image_row` | Process shots, a lookbook, a gallery |

Your agent is instructed by the server **never to invent a testimonial, a
price, a class date, a venue or a credential**. Without the real thing from
you, it leaves the section out and says so. Still read anything an agent writes
about *facts* before you keep it.

### Products and Themes

**Selling through Yeja is coming soon.** The Yeja Wallet is under development;
once it is live, you will be able to sell your work and your themes directly
through Yeja. Until then, point visitors at wherever you already sell.

**Products** (a class, a course, a workshop seat, a book, a print, a download)
can be created, priced and shown on your page. Put an outside shop link in
`external_url`. New products start as drafts, invisible until set to
available.

**Atelier Themes:** `package_current_freeform_as_theme` turns your
published Freeform design into a listing with your artworks, bio and products
replaced by marked placeholders. It starts as a draft; `show_theme_listing`
puts it on **Art Board**, where other artists can browse it. Visitors who want
it can reach you through your Atelier's "Request a Theme" link.
`install_theme` writes a purchased theme into the buyer's own Freeform
**draft**, never their live page.

### Seeing and Measuring the Page

- `inspect_atelier_render` screenshots your page at desktop, tablet and mobile,
  in light or dark. It shows the **published** page by default, whether that is
  your standard Atelier or a published Freeform page, and says which in
  `live_mode`. Pass `preview: true` to screenshot your unpublished standard
  draft, or `freeform: true` for your Freeform draft.
- `inspect_layout_metrics` finds sideways scrolling, failed images and heading
  skips. `inspect_accessibility` measures contrast on the colors that actually
  painted; run it in both themes.
- `create_preview_link` makes a link to your staged standard-Atelier draft,
  rendered exactly as visitors would see it, with a banner across the top. It
  refuses when nothing is staged, and it does not show staged collections
  (`compare_public_and_draft` lists those). It lasts 24 hours by default,
  7 days at most, and is **revoked the moment you publish or discard that
  draft**.
- `atelier_audit` ranks what to fix. When your live page is a Freeform page, it
  also checks that page for unfilled placeholder text.
- `analyze_artworks` reports pixel size, 300dpi print size and dominant color
  for your images; videos are listed as skipped, not as failures. The
  centimeters on an artwork are what you entered; they are never derived from
  the file.
- `get_atelier_views` reports visits, sources and countries. It says "no data
  yet" rather than zero for pages older than 2026-08-26, has no per-artwork
  numbers, and stores no raw IP address or browser string.

### Search and Sharing (SEO)

`inspect_seo` reports what a crawler and a link preview receive, including a
missing share image and any drift between your saved SEO fields and the page.
`propose_seo` suggests values from your own bio, skills and pinned works and
writes nothing; an agent stages them with `propose_atelier`, and nothing
reaches a crawler until you press **Save SEO** yourself.

### Writing Copy

There is no language model behind this server; your agent writes, and the
server checks. `check_copy` says whether a line survives the save unchanged:
a headline is at most 80 characters of plain text, a bio at most 600 characters
with simple formatting. `review_alt_text` reports what each work announces to
a screen reader. That text **is the artwork's title**, so a weak title should be
raised with you, not renamed.

## Rebuilding a Page Like Another Site

**Take inspiration, not artwork.** The MCP rebuilds a site's **presentation**:
its layout, section rhythm, grid, type scale, palette and navigation. It fills
that shape with **your** works and **your** words. It is not for reproducing
another artist's work or another brand's identity:

- Measuring a reference downloads **no images, fonts or copy** from it.
- `import_artwork_from_url` brings in an image only when it is yours or
  licensed to you. The agent must ask you first and record where it came from.
- A reference's logo and brand name are left out, and the "Artist Name"
  placeholder is yours to replace.

### How to Do It

1. **Tell your agent the address and what you like about it.** *"Make my
   Atelier look like <address>. I like the big image grid and the quiet
   navigation. Use my own works."*
2. **It checks the site first** with `classify_reference_site`: supported,
   supported with fallbacks (with the exact fallback for each feature), or
   unsupported.
3. **It builds a first draft** with `replicate_site`. That is the starting
   point, not the result. A run can take a few minutes; the agent checks back
   with `check_replication_job`.
4. **It compares and corrects.** Each `compare_round` puts the reference and
   your draft side by side at desktop and mobile and scores them on a
   nine-point visual rubric. The agent fixes the biggest difference and repeats,
   stopping at **80% on both** with no serious finding and no dead links or
   menus. It changes the look for two rounds at most (round 2 is the last
   appearance round, and it stops sooner when a round makes no visible
   difference), then only repairs anything still broken, up to round 4, and it
   should tell you honestly if it stopped short.
5. **You open the preview link, touch up, and publish.**

The scores in the examples below are the agent's own screenshot rubric,
reviewed by eye. The structural measurements beside them are diagnostic, not a
pass or fail. Treat any number as a prompt to look, never as a guarantee.

### Example: An Awards Landing Page

Deep-color field, logo pill with a menu button, a staggered wall of tiles.
Classed **supported** (97% predicted).

- **First draft 17%.** Plain white instead of the deep field, no logo pill,
  tiles overlapping on mobile.
- **Round 2: 50%**, held down by one real defect: platform text at 1.12:1
  contrast on the colored field. Fixed.
- **Round 3: 94%** (0.938 desktop, 0.944 mobile). Column stagger within a few
  pixels of the reference, 11 working links, the menu opens, nothing dead.
- **Touch-ups left:** the catalog has no stencil typeface, so a monospace
  stands in, and the wordmark is one line where the reference stacks two. The
  artist had 5 works, so they repeat across 24 tiles.

**Takeaway:** a well-supported page type gets close in three rounds. Upload
enough works to fill a big grid; the tool will not invent more.

### Example: A Design Studio's Project Grid

Wordmark and navigation, a large title, an asymmetric grid of narrow and wide
project tiles. Classed **supported with fallbacks** (83% predicted).

- **The loop reached 100% desktop, 94% mobile in 2 rounds.** Grid, captions
  and title matched; the only mark lost was a slightly larger mobile title.
- **The first draft now scores 94% on its own**, after the 2026-09-30 generator
  improvement. Before it, the first draft scored 0.
- **The cost of making every link work:** navigation dropped to 2 links where
  the reference has 6, because pages the artist does not have were left out
  rather than linked nowhere. That, plus a plain-list mobile menu, gives a
  final 94% on both.

**Takeaway:** grids, spacing and type carry over best. Count the navigation
links yourself and ask for any you want back.

### Example: An Event Listings Page

A search bar, a filter column, category chips and rows of events with share
and save icons. Classed **supported with fallbacks** (62% predicted); booking
cannot be rebuilt.

- **First draft 56%** (0.625 desktop, 0.556 mobile).
- **After 4 rounds: 100% desktop, 94% mobile.** Header, breadcrumb, filter
  column, chips and event rows all in place.
- **Behavior repair: 94% on both.** Search, filters, chips and share/save are
  **static look-alikes**: they look right and do nothing, because a published
  Atelier runs no custom script. "Updates" and "Help Center" were dropped, and
  on mobile the icons sit below the image instead of over it.

**Takeaway:** interactive features come across as appearance only. For
anything a visitor must *do*, like buy a ticket or get in touch, use a real
link.

### Which Sites Work

`classify_reference_site` recognizes eight kinds of page: exhibition or
gallery, photography portfolio, architecture studio, editorial lookbook, design
agency, artist portfolio, event landing page, and professional profile. Pages
built around a WebGL scene, or behind a password, are **unsupported**. Forms,
sign-in, booking, carts, file uploads and cross-origin embeds come back with a
named fallback.

### What Doesn't Carry Over

- **Anything that needs script:** a reference's own forms are replaced by the
  platform contact form, which sends to your inquiries; search, filters, carts
  and booking become static; a self-advancing carousel and WebGL do not work.
- **Fixed bars:** `position: fixed` is not allowed, so a newsletter or cookie
  bar is dropped.
- **Typefaces** map to the six in the catalog.
- **Some images are missed:** slides in a clipped carousel, and some
  lazy-loaded hero photographs.
- **Brand marks** can land in the wrong place, and a reference's own poor
  contrast can be copied faithfully.
- **Some sites refuse to be measured** (a 403), and nothing can be built from
  them.

### Touch-Ups to Expect

- **Navigation:** count the links against the reference.
- **Placeholders:** replace "Artist Name" and any marked placeholder text.
- **Enough works** to fill the grid without repeats.
- **The mobile menu:** open it on a phone.
- **Contrast in both themes.**
- **The hero image** is actually there.
- **Contact:** every "Contact" or "Commissions" link points at the page's
  contact form.
- Then ask for `atelier_audit` and fix what it ranks first.

### Adding Your Widgets After a Clone

A clone copies a layout; it does not know about your Yeja widgets. Ask for them
explicitly: *"After the clone, add every widget I can support."* The agent
calls `get_widget_inventory`, which reports each one as present, empty,
supportable or not supportable:

| Widget | What it shows | Who fills it |
|---|---|---|
| Get In Touch (Inquiry) | The platform's contact form | Always available; the agent only switches it on or off |
| Verifiable Collaborations | Projects with another artist | Read-only: both artists confirm |
| Social Links | Where else your work lives | The agent, up to 8 |
| Classes & Products | Your catalog | The agent, once you opt in |
| At Auction, Live Campaign, Next Drop | Auctions, fundraisers and drops | Other Yeja apps: the agent must ask you |
| Search & Sharing | Your title and share preview | The agent proposes; you save |
| Support | Monthly pledges | Only once Stripe is connected |

An agent should place every widget with real content and never fabricate one.

### How a Match Is Scored

The rubric has nine criteria, each scored 0, 0.5 or 1: opening composition,
navigation, section order, proportions, image treatment, type scale, whitespace
rhythm, color, and on mobile, responsive behavior. A round's similarity is the
lower of desktop and mobile. `compare_round` also counts dead links and menus
that do not open, and will not call a round passed while any remain.

The structural checks (`compare_to_reference`,
`check_replication_fidelity`) measure section rhythm, grid shape, type scale,
palette and navigation. A page can score well there and still look wrong, so
if an agent quotes you a percentage, ask to see the screenshots beside the
reference.

### Motion and Interaction

Almost everything that makes a page feel alive is CSS, and CSS is allowed:
hover states, transitions, transforms, keyframe animation and blend modes.
Menus, in-page anchors and disclosure panels work on published pages. Fifteen
named effects can be attached to an element. Ten compile to CSS:

| Effect | What it does |
|---|---|
| `reveal_on_scroll` | Fades and slides content in as it enters the viewport |
| `scroll_progress` | A thin bar showing how far down the page you are |
| `hover_lift` | Lifts and slightly scales a card under the pointer |
| `parallax_background` | Background drifts slower than the page |
| `glitch_bands` | Bands of the element shift sideways in a loop |
| `cursor_lens` | A grid lens that follows the pointer over the element |
| `scroll_scrub` | Ties opacity, movement, scale or rotation to scroll position |
| `pin_section` | Holds a section in place while the page scrolls past it |
| `sticky_heading` | A heading that pins while its section scrolls past |
| `disclosure` | A menu that opens on hover, focus or tap |

Five run one of the platform's own signed scripts, which a published page is
allowed to load: `cursor_follower`, `smooth_scroll`, `ambient_audio`,
`scroll_linked_columns` and `scroll_linked_columns_endless`. Check
`get_freeform_runtime_capabilities` before using one: it says which are
deployed.

A page may carry up to 30 effects, and up to 3 on any one element. Out-of-range
values are refused rather than clamped, and every effect stops under reduced
motion.

### Contact and Support Blocks

**Both work on a published page.** A `contact_form` renders a real form (name,
email, message) that sends straight to your inquiries; the page allows that one
destination and no other. A support block renders one link per amount, and the
pledge completes in the signed-in Yeja app, once Stripe payouts are connected.

## Freeform: Building the Page Yourself

The tools above edit a page Yeja lays out for you. Freeform is the other
option: your agent writes the structure and the stylesheet, and Yeja renders
exactly that. A clone is a Freeform page.

A published page runs **no script except the platform's own signed bundles**,
such as the artwork viewer. Interactions compile to CSS. That is what keeps a
page safe on the same domain as your dashboard.

### Start With the Schema and the Runtime

`get_freeform_schema` lists every node type, the nesting limits and what the
stylesheet may contain. Then call `get_freeform_runtime_capabilities`
**before** designing: the schema says what *validates*, the runtime report says
what actually *renders* in this deployment, and they differ. Before handing
over a preview, `validate_freeform_draft` checks a tree or the saved draft
without writing anything, and flags embeds of artwork you do not own.

`create_freeform_draft` validates before storing. `update_freeform_draft`
patches only what it is sent. `patch_freeform_css` adds a rule or two without
rewriting the stylesheet.

**A version holds a site, not a page:** extra pages go under a `__pages` key
and publish together. **Components** let one card be defined once and placed
forty times, styled by one rule.

### Galleries

`build_artwork_gallery` writes a whole wall of your works: columns, embeds,
grid CSS and mobile breakpoints, generated from the same numbers so they cannot
disagree. It returns the tree by default. With `apply: true` it **adds** the
gallery to your existing draft; only `mode: "replace_page"` replaces the whole
page. A gallery card is an image, so video works are refused: place each one
with a `video` node (`list_artworks` lists them as `usable_video_ids`).

`motion: "scroll_linked_columns"` makes alternating columns drift as the page
scrolls, without capturing the wheel. `scroll_linked_columns_endless` loops the
columns and does read the wheel, but only while the gallery fills most of the
screen, and it gives the wheel back after about 900px. Neither runs under
reduced motion.

### Fonts

Inter, Playfair Display, JetBrains Mono, Plus Jakarta Sans, **Yuyu** and
**Geist Pixel** are self-hosted. Naming any other family is a **rejection**,
not a silent fallback. Generic families (`serif`, `sans-serif`,
`monospace`, `system-ui`…) are always fine. Yuyu (handwriting) and Geist
Pixel (pixel display) each have one weight, 400; use Geist Pixel for headings,
not body text.

There is no font upload and no Google Fonts import; both are refused with
`FONT_UPLOAD_UNAVAILABLE`. Adding a family is a request to the Yeja team.

### Artworks Open in the Native Viewer

Use `embed_artwork` for a work a visitor should be able to open. It renders the
real image server-side, and the platform's viewer opens it **in place**, over
the page you built: zoom, drag to pan, previous and next across every embed,
Escape to close. A detail panel shows the work's own title, artist,
availability, medium, year and provenance, and leaves out anything you never
filled in. It has no comments, share or report controls, because a published
page cannot make requests.

It degrades to the image, never to a blank space. `artworkId` must be a work
you own (`list_artworks`); any other id renders nothing at all. It is for
images: a video in `embed_artwork` or an `image` node shows as a broken
image, and `validate_freeform_draft` warns about it.

### One Node Type Renders Nothing

A generic `embed` (a third-party page in a frame) publishes as an empty
space, because a published page cannot load outside content. Leave it out, or
use a labelled static section instead. The other widget nodes work:
`contact_form` is a real form, and `embed_product` renders a card for one of
your products (title, price or "Enquire", and a link to where you sell it) with
no buy button.

### Previews, Publishing and Versions

`preview_freeform` renders the draft, reports whether it would pass the
publish gate, and returns a **fingerprint**. Publishing without a fingerprint
is refused, and any edit changes it, so an approval cannot carry over to a
changed draft. `get_go_live_link` gives you the dashboard link where **you**
publish.

A Freeform preview link keeps working until it expires, and always shows what
the draft holds **now**. After the Freeform draft is published or discarded, the
link shows your published page, with a banner saying so. Publishing or
discarding your **standard** draft revokes every preview link. `refresh_preview_link`
mints a new one. `snapshot_round` pins a link to one round of a clone, so it
keeps showing that round after the draft moves on.

`list_freeform_versions` shows every version, `get_freeform_history` every
publish, rollback and unpublish, and `rollback_freeform` puts an earlier
version live again.

## Tools

95 tools. **Needs** is the permission it requires. **Effect** is what it does
to your page: *Read* changes nothing, *Staged* waits for Publish, and **Live**
changes your public page the moment it runs. On a deployment with Freeform
switched off, the 23 Freeform-only tools are hidden.

### Start Here

| Tool | What it does | Needs | Effect |
|---|---|---|---|
| `connect_profile` | Connects this chat to the profile you named. Called first; every other tool waits for it. | None | Read |
| `get_connection` | Which profile this chat is connected to, and how. | None | Read |
| `disconnect_profile` | Ends this chat's connection to its profile. | None | Read |
| `atelier_audit` | One prioritized list of what to fix, including placeholder text left on a live Freeform page. | Read | Read |
| `get_atelier` | Your current Atelier, including any unpublished draft. | Read | Read |
| `get_atelier_schema` | The document schema plus the constraints that are not obvious. | Read | Read |
| `get_operating_instructions` | How this server expects an agent to work, for clients that do not surface it. | Read | Read |
| `list_artworks` | Your artworks and the image ids an agent may use. | Read | Read |
| `get_widget_inventory` | Which priority widgets you can support, with a count and visibility for each. | Read | Read |
| `compare_public_and_draft` | Exactly what publishing would change: each staged field before and after, staged collections, and any Freeform draft. | Read | Read |
| `get_go_live_link` | The dashboard link where you publish. No tool can publish for you. | Propose | Read |

### Seeing and Measuring

| Tool | What it does | Needs | Effect |
|---|---|---|---|
| `inspect_atelier_render` | Screenshots of your live page (standard or Freeform) at desktop, tablet and mobile, light or dark; `preview` or `freeform` shows a draft. | Read | Read |
| `inspect_layout_metrics` | Overflow, broken images, missing alt text, heading order. | Read | Read |
| `inspect_accessibility` | Contrast, landmarks, headings, unnamed controls and skip link, on the rendered page. | Read | Read |
| `inspect_seo` | What search engines and link previews see, and drift from your saved SEO fields. | Read | Read |
| `propose_seo` | Suggested title, description, job title and share image from your own content. | Read | Read |
| `analyze_artworks` | Pixel size, print guidance and dominant color for your images. | Read | Read |
| `get_atelier_views` | Visitor numbers, sources and countries for your published page. | Read | Read |
| `review_alt_text` | What each work's image announces to a screen reader. | Read | Read |
| `check_copy` | Whether a headline or bio survives the save unchanged. | Read | Read |

### Drafts, Previews and Undo

| Tool | What it does | Needs | Effect |
|---|---|---|---|
| `propose_atelier` | Stages a change to your Atelier as a draft. `dryRun: true` checks without saving. | Propose | Staged |
| `create_preview_link` | A temporary link showing your staged standard draft as a real page. Refuses when nothing is staged. | Propose | Staged |
| `list_snapshots` | Point-in-time copies of your Atelier, newest first. | Read | Read |
| `restore_snapshot` | Rolls your page back to a snapshot and clears any pending draft. | Propose | **Live immediately** |

### Pins and Hero

| Tool | What it does | Needs | Effect |
|---|---|---|---|
| `list_pins` | Your Pinned Showcase, in order, with ids. | Read | Read |
| `pin_artwork` | Adds a work to your Pinned Showcase. | Curate | **Live immediately** |
| `unpin_artwork` | Removes a work from your Pinned Showcase. | Curate | **Live immediately** |
| `reorder_pins` | Sets the order of your Pinned Showcase. | Curate | **Live immediately** |
| `set_hero` | Chooses what leads the page: top pin, a specific work, or nothing. | Curate | **Live immediately** |

### Timeline

| Tool | What it does | Needs | Effect |
|---|---|---|---|
| `list_timeline` | Your exhibitions, shows, residencies and education, in order. | Read | Read |
| `add_timeline_entry` | Adds an exhibition, show, residency or milestone. | Curate | **Live immediately** |
| `update_timeline_entry` | Changes one timeline entry. | Curate | **Live immediately** |
| `remove_timeline_entry` | Deletes a timeline entry. Not recoverable. | Curate | **Live immediately** |
| `reorder_timeline` | Sets the order your timeline is displayed in. | Curate | **Live immediately** |

### Custom Sections

| Tool | What it does | Needs | Effect |
|---|---|---|---|
| `get_section_schema` | Every section type you can add, with its fields and limits. | Read | Read |
| `list_sections` | Your custom sections, in order, with ids. | Read | Read |
| `add_section` | Adds a workshop, class list, events, testimonials, an FAQ… | Curate | **Live immediately** |
| `update_section` | Rewrites a custom section, or hides it. | Curate | **Live immediately** |
| `remove_section` | Takes a custom section off. `restore_section` undoes it. | Curate | **Live immediately** |
| `restore_section` | Puts back a section `remove_section` took off. | Curate | **Live immediately** |
| `reorder_sections` | Sets the order of your custom sections. | Curate | **Live immediately** |

### Staging Collections

| Tool | What it does | Needs | Effect |
|---|---|---|---|
| `get_staged_collection` | The list to edit: your staged draft if you have one, otherwise your live rows. | Read | Read |
| `stage_collection` | Stages the complete list for sections, timeline, products or pins. The one to prefer. | Curate | Staged |
| `discard_staged_rows` | Throws away staged collection changes. | Curate | Staged |

### Custom CSS

| Tool | What it does | Needs | Effect |
|---|---|---|---|
| `get_custom_css` | Your Atelier's custom CSS, and which properties survive sanitizing. | Read | Read |
| `validate_custom_css` | Checks standard-Atelier CSS without applying it. Not the Freeform validator. | Read | Read |
| `propose_custom_css` | Stages custom CSS onto your Atelier. | Curate | Staged |
| `validate_freeform_css` | Checks Freeform page CSS, with a line number for every rejection. | Read | Read |

### Products

| Tool | What it does | Needs | Effect |
|---|---|---|---|
| `list_products` | Your catalog with prices, seats and status. | Read | Read |
| `add_product` | Adds a class, course, book or print. Starts as a draft. | Curate | **Live** once available |
| `update_product` | Changes a product, or makes it available. | Curate | **Live immediately** when available |
| `remove_product` | Deletes a product. Refused if it has orders. | Curate | **Live immediately** |

### Themes

| Tool | What it does | Needs | Effect |
|---|---|---|---|
| `list_my_theme_listings` | Your own Atelier Theme listings, any status. | Read | Read |
| `package_current_freeform_as_theme` | Packages your published Freeform design as a listing, content replaced by placeholders. | Curate | Draft listing |
| `update_theme_listing` | Changes a listing's title, price or status. | Curate | **Live** on Art Board once available |
| `show_theme_listing` | Puts a listing on Art Board for other artists to browse. | Curate | **Live immediately** |
| `hide_theme_listing` | Takes a listing off Art Board without deleting it. | Curate | **Live immediately** |
| `browse_atelier_themes` | Theme listings on Art Board, for a buyer's agent. | Read | Read |
| `install_theme` | Installs a theme you bought into your Freeform draft. Requires a completed purchase. | Propose | Staged |
| `reset_atelier_theme` | Reset To Factory: back to the default Yeja theme, removing every theme adjustment and any installed page. Dry run unless confirmed. | Propose | **Live immediately** |
| `unpublish_atelier` | Takes the whole Atelier offline. Nothing is deleted; only you can publish it again. Dry run unless confirmed. | Propose | **Live immediately** |

### Freeform Pages

| Tool | What it does | Needs | Effect |
|---|---|---|---|
| `get_freeform_schema` | Node types, nesting limits, what the stylesheet may contain. | Read | Read |
| `get_freeform_runtime_capabilities` | What the deployed runtime actually renders, and why some nodes do not. | Read | Read |
| `validate_freeform_draft` | Checks a tree and stylesheet without saving. | Read | Read |
| `get_freeform_draft` | Your Freeform draft: tree, stylesheet and version. | Read | Read |
| `create_freeform_draft` | Starts a Freeform page from a page tree. | Propose | Staged |
| `update_freeform_draft` | Patches the draft; omitted fields are left alone. | Propose | Staged |
| `patch_freeform_css` | Adds a rule or two without rewriting the stylesheet. | Propose | Staged |
| `build_artwork_gallery` | A multi-column gallery of your images (videos are refused). Returns it; with `apply`, adds it to the draft. | Read (Propose to apply) | Read or Staged |
| `preview_freeform` | Renders the draft, reports the publish gate, returns a preview link and the fingerprint. | Propose | Staged |
| `refresh_preview_link` | A fresh preview link when one stopped working. | Propose | Staged |
| `discard_freeform_draft` | Throws away the unpublished draft. | Propose | Staged |
| `list_freeform_versions` | Every version, and which can be rolled back to. | Read | Read |
| `get_freeform_history` | Every publish, rollback and unpublish, with evidence. | Read | Read |
| `rollback_freeform` | Puts an earlier version's content live again. | Propose | **Live immediately** |
| `unpublish_freeform` | Turns the live Freeform page off; visitors get the classic Atelier. Dry run unless confirmed. | Propose | **Live immediately** |

### Images and Content Fields

| Tool | What it does | Needs | Effect |
|---|---|---|---|
| `list_freeform_image_slots` | The picture spaces in your draft, filled and empty. | Read | Read |
| `fill_freeform_image_slot` | Puts one of your works (image, video or audio) into a field, or empties it. | Propose | Staged |
| `fill_dynamic_content_text_field` | Writes text into a text field, or clears it. | Propose | Staged |
| `add_dynamic_content_field` | Adds a text, image, video or audio field. | Propose | Staged |
| `remove_dynamic_content_field` | Deletes a field. | Propose | Staged |
| `set_dynamic_content_field_kind` | Changes what a field holds, and empties it. | Propose | Staged |
| `import_artwork_from_url` | Brings an image you may use into My Studio as a work you own, with its source recorded. | Propose | Adds to your account |

### Rebuilding From a Reference

| Tool | What it does | Needs | Effect |
|---|---|---|---|
| `classify_reference_site` | Whether a site can be rebuilt, before building. Call it first. | Read | Read |
| `ingest_reference_site` | Measures a site's structure. Copies no images, fonts or text. | Read | Read |
| `describe_reference_design` | Records a design you showed as a screenshot, to build from. | Propose | Staged |
| `replicate_site` | Builds the first draft from a site's address and returns preview and publish links. | Propose | Staged |
| `check_replication_job` | Checks on a rebuild that is still running. | Read | Read |
| `compare_round` | One screenshot round: reference and draft side by side, the rubric, a pinned snapshot. | Propose | Staged |
| `snapshot_round` | Freezes the draft as a round and pins a preview link to it. | Propose | Staged |
| `draft_from_reference` | Builds a complete draft from an already measured reference. | Propose | Staged |
| `compare_to_reference` | Structural comparison against a reference, with what to change next. | Read | Read |
| `check_replication_fidelity` | How close the draft is to its reference, structurally. | Read | Read |
| `record_clone_result` | Records the agent's own rubric scores for a clone; other kinds are for the platform's bench account only. | Propose | Platform record |

### The Brief

| Tool | What it does | Needs | Effect |
|---|---|---|---|
| `start_brief` | Begins the interview and returns the next question. | Read | Read |
| `answer_brief` | Records one answer. Private; never public. | Propose | Private |
| `get_brief` | Every answer so far, and what is missing. | Read | Read |
| `reset_brief` | Clears the brief and starts again. | Propose | Private |

## FAQ

### Does My API Key Expire?

No. A key lasts until you revoke it, and you can hold up to 10. Sign-in renews
itself hourly; if a client goes unused for 30 days, you sign in again.

### Can an Agent Work on the Wrong Account?

Not without saying so. Each chat names its profile with `connect_profile`. The
server checks the key belongs to that profile, and a connection signed in as
one account refuses every other profile. Every result names the profile it
acted on in `acting_as`.

### Can an Agent Publish My Page?

No. It stages a draft and gives you a preview and a publish link; you press
Publish. The exceptions are the tools marked **Live**: curation (pins, hero,
timeline, sections, products, theme listings) and the two undo tools.

### What Can Change My Live Page Without Me?

With **Curate**: the per-row curation tools. With **Propose**: only
`restore_snapshot`, `rollback_freeform`, `reset_atelier_theme`,
`unpublish_freeform` and `unpublish_atelier`, which a good agent confirms with
you first. With Read alone: nothing.

### My Agent Lost Its Connection. Why?

If it signed in, let it retry; it refreshes itself. If it connected with a key,
the key was revoked, or the chat's connection ended: a chat stays connected for
up to 7 days, or a day without use. Give the agent the profile and key again.
A key in a client's settings is read once at start-up, so restart the client
after changing it.

### Will It Copy Someone Else's Art or Words?

No. Rebuilding measures a site's layout and style and downloads none of its
images, fonts or text. Your page shows your works and words in a similar shape.
An outside image comes in only through `import_artwork_from_url`, when it is
yours or licensed to you, with its source recorded.

### Can It Use an Image That Is Not in My Account Yet?

Yes, with your permission: `import_artwork_from_url` adds it to My Studio as
a work you own, and records where it came from. A public-domain painting does
not make a museum's photograph of it free to use; say which source is yours to
use.

### Why Doesn't My Clone Look Exactly the Same?

Because it uses your art, your words and the catalog's typefaces, and because
anything that needs script becomes static. In the recorded examples, three or
four correction rounds took a first draft to about 94%, and a few touch-ups
remained every time.

### How Long Does a Clone Take?

The first draft takes a few minutes. The agent then runs comparison rounds,
correcting in between: the look changes through round 2, and any further round,
up to round 4, only repairs something still broken. Expect one session, plus
your own touch-ups.

### Does a Contact Form Work on a Freeform Page?

Yes. A `contact_form` node renders a real form that sends to your inquiries,
with no custom script involved. A clone puts one on the page even when the
reference had none, and points its "Contact" links at it.

### Can I Clone a Site With a Shop or Booking?

The look, yes; the checkout or booking, no. Those parts become static or a
link. Point a button at wherever you already sell.

### Can People Buy My Products or My Theme?

Soon. The Yeja Wallet is under development, and once it is live you will be
able to sell your work and your themes directly through Yeja. Until then, link
to wherever you already sell.

### What Is My Interview, and Who Sees It?

Before building a full page, your agent asks you six short questions: what the
page is for, who visits it, what you want a visitor to do, how it should feel,
what must appear on it, and which sites you would like it to resemble. It takes
about two minutes. Your answers are saved as a **brief**, so the agent only asks
once and every later session starts from them. Say *"start over"* to answer
again.

The brief is **private**. It shapes the layout your agent builds, and no visitor
ever sees it.

### Which Agents Work?

Any client that speaks MCP over streamable HTTP. The Install section covers
Claude Code, Claude Desktop and claude.ai, Cursor, VS Code, Codex, Antigravity,
Windsurf, Zed and Cline.

## Troubleshooting

| What you see | What it means |
|---|---|
| `not_connected` | The agent has not connected a profile in this chat. Give it your profile link and key. |
| `connect_failed` | The profile and key do not match, or the key was revoked. Check both on the Developer Access card. |
| `identity_mismatch` | The connection is signed in as a different account from the profile you named. Nothing was changed. Use a connection without sign-in and that profile's key, or sign in as that profile. |
| `profile_not_declared` | A signed-in connection has not named its profile yet. The agent should call `connect_profile`. |
| `session_missing` | Your client did not keep the session the server gave it. Restart the client. |
| Claude Code says the server needs authentication, with no key in its settings | An old sign-in is stored under that server name from before. Run `/mcp`, pick the server and clear its authentication, or remove it with `claude mcp remove yeja-atelier` and add it again. |
| `401` from `/mcp/oauth` with a `www-authenticate` header | Normal. The server is asking your client to sign in. |
| `401` "A valid Atelier credential is required" | A wrong or revoked key, or a `yeja_live_` partner key, which belongs to a different system. |
| `401` "has expired" | Only a key deliberately given a short lifetime through the API, or a sign-in mid-refresh. Create a new key, or let the client retry. |
| "This key is read-only" | For a key: create one with **Allow This Key To Propose Changes** ticked. For sign-in: sign in again and tick Propose. |
| "must reference an image already in this artist's account" | The agent used an outside image address. Import it with `import_artwork_from_url`, with your permission, or upload it. |
| `405` when connecting | The client tried SSE. Set its transport to HTTP (Cline: `streamableHttp`). |
| Nothing changed on your public page | Correct. Proposals are drafts; press Publish in the dashboard. |
| A preview link stopped working | It expired, or your standard draft was published or discarded. Ask for `refresh_preview_link`. |
| A preview link shows the live page | The Freeform draft it showed was published or discarded. The banner says so. |

## Rules an Agent Must Follow

These are enforced server-side, not merely requested. A proposal that breaks
them is rejected or corrected, and the reason is returned to the agent.

- **Connect the profile the user named, before anything else.** `connect_profile`
  with the profile exactly as the user gave it. Every other tool refuses until
  it succeeds, and a signed-in connection refuses any profile but its own. On
  `identity_mismatch`, stop and tell the user; never work on the signed-in
  account instead.
- **`portfolio_process_scale` and `portfolio_statement_scale` are the image's
  share of the row, not a zoom level.** Values near 100 make the image take the
  whole row and push the page past the viewport. Keep them between 40 and 70.
- **An agent cannot introduce a new image URL.** A page may only reference media
  already in your account. An outside image must first be imported with
  `import_artwork_from_url`, with your permission and its source recorded.
- **`portfolio_headline` is at most 80 characters**; the bio is at most 600
  characters of text.
- **`portfolio_grid_columns` is 2 to 5.** At most 3 process images and 8 social
  links.
- **`portfolio_sections` stores only the OFF flag.** An absent key means the
  section is visible; set a key to `false` to hide it.
- **`portfolio_section_order` sets the order**, top to bottom, from `works`,
  `exhibitions`, `statement`, `about`, `skills`, `collaborations`,
  `inquire`, `socialLinks`, `products`, `auctions`, `campaign`, `drop`,
  `support` and `custom`. A section left out keeps its default place at the
  end; leaving it out never hides it.
- **Never invent a fact about an artwork.** No dimension, price, material, date,
  exhibition or provenance detail that was not supplied.

## Reference

- **Endpoint:** `https://yeja-ai.com/mcp` (POST, JSON-RPC 2.0)
- **Protocol:** MCP specification revision 2025-06-18, streamable HTTP, single JSON response, no SSE. Older revisions are negotiated.
- **Auth:** none to connect to `/mcp`. Each chat calls `connect_profile` with a profile and its `yeja_atl_…` key; the binding lives with the `Mcp-Session-Id` the server issued, for up to 7 days or 24 hours idle, and ends when the key is revoked. OAuth 2.1 on `/mcp/oauth`: PKCE S256, dynamic client registration, discovery at `/.well-known/oauth-protected-resource/mcp/oauth`, revocation at `/oauth/revoke`; access tokens last 1 hour, refresh tokens 30 days, rotating. A static `Authorization: Bearer yeja_atl_…` header still works. A signed-in connection must still call `connect_profile`, and only for its own profile. Up to 10 keys per artist; they do not expire by default.
- **Permissions:** `atelier:read`, `atelier:write` (Propose), `atelier:curate` (Curate).
- **Prompts:** `interview_artist`, `rebuild_from_reference`, `complete_my_atelier`, `audit_and_fix`, `add_background_image`, `verify_before_handoff`.
- **Dashboard:** https://yeja-ai.com/dashboard/?app=profile&view=portfolio
- **This guide as Markdown:** https://yeja-ai.com/mcp?format=md
- **This guide last updated:** 2026-10-19
