> ## Documentation Index
> Fetch the complete documentation index at: https://docs.alakazam.gg/llms.txt
> Use this file to discover all available pages before exploring further.

# Forge MCP

> Operate the entire Forge — datasets, augmentation, world-model fine-tuning — from your agent, with no web UI.

<div className="forge-kicker">◆ FORGE · MCP</div>

The Forge MCP server exposes **every Forge operation as a tool your agent can call
directly** — register a dataset, run augmentation, fine-tune a world model or policy on your
robot, read its gate receipts, deploy it to a serving endpoint and drive it, check
credits, pull the trained weights — without ever opening
[forge.alakazam.gg](https://forge.alakazam.gg). It's a thin, stateless proxy over the
same `/api/workbench`, `/api/aug`, and `/api/billing` surfaces the web app uses; your
bearer is forwarded verbatim and Forge re-verifies every call, so an agent can only
touch your own campaigns.

<Card title="One server, the whole Forge" icon="bolt">
  71 `forge_*` tools across eight areas — account, datasets & embodiment, sources,
  augmentation, world-model fine-tuning, **evaluation & serving**, monitoring &
  diagnostics, and the playground — behind one Streamable-HTTP endpoint. The loop
  closes: a dataset goes in, a served model endpoint comes out.
</Card>

## Connect

The server speaks **MCP over Streamable HTTP** at `/mcp`. Point your agent at it and
supply your Forge credential (see [Authenticate](#authenticate)).

<Tabs>
  <Tab title="Claude Code">
    ```bash theme={null}
    claude mcp add --transport http forge https://mcp.alakazam.gg/mcp \
      --header "Authorization: Bearer <YOUR_FORGE_JWT>"
    ```
  </Tab>

  <Tab title="Cursor / mcp.json">
    ```json theme={null}
    {
      "mcpServers": {
        "forge": {
          "url": "https://mcp.alakazam.gg/mcp",
          "headers": { "Authorization": "Bearer <YOUR_FORGE_JWT>" }
        }
      }
    }
    ```
  </Tab>
</Tabs>

If you don't have a token yet, connect without the header and call
`forge_authenticate` first (below) — every other tool accepts the returned token as an
optional `token` argument.

### The terminal client

The MCP also serves a small CLI, version-locked to the deployed tools — nothing separate
to install or keep updated:

```bash theme={null}
mkdir -p ~/.forge/bin && curl -fsSL https://mcp.alakazam.gg/cli/forge.mjs \
  -o ~/.forge/bin/forge && chmod +x ~/.forge/bin/forge
export FORGE_TOKEN=forge_sk_…

forge status                 # one panel: everything running, with measured ETAs
forge watch                  # the same panel, refreshing until the work finishes
forge upload ./my-dataset    # parallel, resumable, live progress bar
forge diagnose camp_…        # forensics on a fine-tune that looks stuck
```

Your agent reaches for it on its own: `forge_upload_dataset` returns the exact command to
run. Output is a rendered panel in a terminal and plain text when piped, so it is safe to
capture in logs. Add `--json` to any command for raw data.

## Authenticate

**Not sure which method to use? Call `forge_login`** — it returns a short menu to show the
user (email link · API key · password) and routes to the right tool, the way a CLI would.
Everything below is what it routes to.

Forge is owner-scoped by a Supabase JWT **or a `forge_sk_` API key** — both go in the same
`Authorization: Bearer` header and every endpoint accepts either. A headless agent gets one
three ways:

1. **`forge_send_login_code(email)` → `forge_verify_login_link(url)`** — passwordless.
   An email arrives with a **"Log in" button**. Copy the link *address* (right-click → Copy link
   address; do **not** click it — the link is single-use) and pass the whole URL to
   `forge_verify_login_link`. It returns `{ access_token, refresh_token, expires_in }`.
   If your project's email template carries a 6-digit code instead, use
   **`forge_verify_login_code(email, code)`** — same result.
   <Warning>
     **If you signed up with "Continue with Google" or "Sign in with Apple", this is your only
     option.** An OAuth account has no password, so `forge_authenticate` can never work for it.
   </Warning>
2. **`forge_authenticate(email, password)`** → same `{ access_token, … }`, for accounts that
   actually have a password.
3. **Connection header** — set `Authorization: Bearer <jwt>` on the MCP connection
   (above); every tool inherits it, no `token` argument needed.

Renew with **`forge_refresh_token(refresh_token)`** before `expires_in` elapses (\~1h).

`forge_whoami` confirms who a token is; `forge_get_credits` is your affordability
preflight before any paid render.

### No account yet?

**The MCP deliberately cannot create one.** A login tool that mints accounts turns a typo'd
address into a real user, so `forge_send_login_code` sends to existing accounts only. An
unknown address comes back with `reason: "no_account"` and no email is sent.

Sign up once at **[forge.alakazam.gg](https://forge.alakazam.gg)** — email + password, Google,
or Apple all work — then come back and call `forge_send_login_code` with that same address.
New accounts start with a small credit grant; `forge_get_credits` shows it.

<Note>
  If you signed up with Google or Apple, you have **no password** — use the passwordless code
  flow above. `forge_authenticate` cannot work for those accounts, by construction.
</Note>

### Keeping the token

The server is **stateless — it stores nothing**, including your session. Where the token lives
is your client's job:

* **Per-call** — pass `token: "<access_token>"` to each tool. Simple, but the token lives only
  in the agent's context: a fresh session (or a context compaction that drops it) means logging
  in again.
* **On the connection** — put it in the `Authorization: Bearer` header (see [Connect](#connect)).
  Survives across sessions until it expires; every tool inherits it with no `token` argument.

Codes are **single-use, \~1h, and rate-limited**. Each new send invalidates the previous code, so
if a send appears to do nothing, **check the inbox before re-sending** — a retry loop makes it
strictly worse. A rate-limited send returns `reason: "rate_limited"` rather than an opaque error.

### API keys — the credential for anything unattended

A login token expires in about an hour, and renewing it for an OAuth account means another
email. That is fine for a person and wrong for an MCP client that reconnects, a CI job, or a
partner integration. **Log in once, mint a key, use the key forever:**

```
forge_create_api_key(label: "laptop-mcp")
→ { "key": "forge_sk_…", "warning": "This is the ONLY time the key is shown." }
```

Then put it where the token would have gone — it works identically:

```bash theme={null}
claude mcp add --transport http forge https://mcp.alakazam.gg/mcp \
  --header "Authorization: Bearer forge_sk_…"
```

<Warning>
  The raw key is returned **exactly once**. Forge stores only a SHA-256 hash and genuinely
  cannot show it again — if it is lost, revoke it and mint another.
</Warning>

`forge_list_api_keys` shows every key masked, with `last_used_at` so you can spot ones
nothing uses any more. `forge_revoke_api_key` kills one permanently; an already-running
server may honour it for up to a minute while its auth cache expires. Twenty keys per
account.

## The tools

<AccordionGroup>
  <Accordion title="Account, keys & credits (16)">
    | Tool                                                                    | Does                                                            |
    | ----------------------------------------------------------------------- | --------------------------------------------------------------- |
    | `forge_login`                                                           | **Start here** — offers the user the choice of login method     |
    | `forge_send_login_code` · `forge_verify_login_link`                     | Passwordless login — the ONLY path for Google/Apple accounts    |
    | `forge_verify_login_code`                                               | Same, when the email carries a 6-digit code instead of a link   |
    | `forge_authenticate` · `forge_refresh_token`                            | Password login / token renew                                    |
    | `forge_create_api_key` · `forge_list_api_keys` · `forge_revoke_api_key` | **Long-lived API keys** — what unattended clients should use    |
    | `forge_whoami`                                                          | Who the current token is                                        |
    | `forge_get_credits` · `forge_get_credits_history`                       | Wallet balance + ledger                                         |
    | `forge_get_account_usage`                                               | Activity counts (renders / keeps / deliveries)                  |
    | `forge_redeem_access_code`                                              | Redeem a creator access code                                    |
    | `forge_list_credit_packs`                                               | Top-up packs (id / credits / price) — the out-of-credits step 1 |
    | `forge_credits_checkout`                                                | Stripe checkout URL to buy credits — resolves a 402             |
  </Accordion>

  <Accordion title="Datasets & embodiment (24)">
    | Tool                                                                                                 | Does                                                                                                                                               |
    | ---------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
    | `forge_create_campaign`                                                                              | Register a hosted (Hugging Face) dataset                                                                                                           |
    | `forge_import_dataset`                                                                               | Import from **anywhere** — HF, `gs://`, `s3://`, `azure://`, or an https archive                                                                   |
    | `forge_store_source_credential` · `forge_list_source_credentials` · `forge_delete_source_credential` | Manage private-bucket credentials (masked; prefer presigned URLs)                                                                                  |
    | `forge_list_campaigns` · `forge_get_campaign`                                                        | List / read campaigns (the poll target)                                                                                                            |
    | `forge_delete_campaign`                                                                              | Delete a campaign (+ its upload bytes)                                                                                                             |
    | `forge_list_samples` · `forge_open_sample`                                                           | Curated sample datasets → your campaign                                                                                                            |
    | `forge_upload_dataset`                                                                               | **Local folders start here** — returns one shell command that fetches the uploader from this server: 8 parallel streams, resume, live progress bar |
    | `forge_init_upload` · `forge_put_upload_chunk` · `forge_complete_upload`                             | The low-level resumable upload API (small folders only)                                                                                            |
    | `forge_get_embodiment` · `forge_confirm_embodiment`                                                  | **What robot is this?** — detection report (metadata + registry + VLM frame look) and the user's confirmed answer                                  |
    | `forge_get_upload_status` · `forge_list_uploads` · `forge_delete_upload`                             | Manage uploads                                                                                                                                     |
    | `forge_list_episodes` · `forge_get_episode_actions` · `forge_get_episode_partners`                   | Inspect episodes                                                                                                                                   |
    | `forge_get_episode_preview` · `forge_get_episode_video`                                              | Episode media (returns a fetchable URL)                                                                                                            |
  </Accordion>

  <Accordion title="Augmentation (14)">
    | Tool                                                                     | Does                                                     |
    | ------------------------------------------------------------------------ | -------------------------------------------------------- |
    | `forge_start_health` · `forge_set_target_class`                          | Compute eligibility / scope a class                      |
    | `forge_get_transforms` · `forge_get_prevalidation`                       | Readiness checks                                         |
    | `forge_make_proposals` · `forge_save_sample` · `forge_save_plan`         | Mine pairs → pick sources → plan transforms              |
    | `forge_start_run`                                                        | **Run the augmentation** (billing; poll `forge_get_job`) |
    | `forge_submit_review` · `forge_start_delivery` · `forge_download_export` | Review → deliver → download the augmented set            |
    | `forge_get_models` · `forge_get_job` · `forge_cancel_job`                | Engine models + job control                              |
  </Accordion>

  <Accordion title="World-model fine-tuning (4)">
    | Tool                       | Does                                                                                                                                                                                                                                                    |
    | -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
    | `forge_create_world_model` | **Fine-tune Cosmos-3-Edge** on your LeRobot dataset (billing; poll `forge_get_campaign`). `model_mode: "forward_dynamics"` (default) trains a video world model; `model_mode: "wam"` trains a **policy** that denoises action chunks from camera frames |
    | `forge_cancel_world_model` | Stop a running fine-tune                                                                                                                                                                                                                                |
    | `forge_download_weights`   | The trained checkpoint (signed URL)                                                                                                                                                                                                                     |
    | `forge_list_embodiments`   | Valid robot embodiments / free domain ids                                                                                                                                                                                                               |
  </Accordion>

  <Accordion title="Evaluate & serve (5)">
    | Tool                                                    | Does                                                                                                                                         |
    | ------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
    | `forge_get_model_eval`                                  | The gate receipts as data — policy MAE vs a HOLD baseline for `wam`, obedience A/B for `forward_dynamics`                                    |
    | `forge_deploy_model`                                    | **Free at creation** — mints a deployment record + a `wam_sk_` token (shown once); GPU cost starts at the first rollout, scale-to-zero after |
    | `forge_run_rollout`                                     | One inference: conditioning frames (or an mp4) in, the denoised action chunk (or rollout) out                                                |
    | `forge_list_model_deployments` · `forge_undeploy_model` | Inspect / revoke deployments                                                                                                                 |
  </Accordion>

  <Accordion title="Monitor & diagnose (2)">
    | Tool                      | Does                                                                                                                                                                           |
    | ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
    | `forge_list_activity`     | **Everything in flight in one call** — every job you own with stage, progress, measured ETA, spend, `stale_s`, and a `diagnosis` when something needs acting on                |
    | `forge_diagnose_finetune` | Forensics for a fine-tune: verdict (`healthy` / `late_heartbeat` / `zombie_suspected` / `failed` / …), state history, and the training-log tail with error lines pre-extracted |
  </Accordion>

  <Accordion title="Playground (5)">
    | Tool                                                         | Does                                                |
    | ------------------------------------------------------------ | --------------------------------------------------- |
    | `forge_start_playground_op`                                  | One-off render / restyle / distractor add (billing) |
    | `forge_get_playground_clip`                                  | The render output (URL)                             |
    | `forge_delete_playground_op` · `forge_get_distractor_region` | Manage / hint                                       |
    | `forge_warm_gpu`                                             | Pre-warm the render GPU                             |
  </Accordion>
</AccordionGroup>

## Import from anywhere

Your dataset does not have to live on Hugging Face, and it does not have to be uploaded
chunk by chunk. **`forge_import_dataset`** takes a `source_uri` in any of these schemes,
materializes the bytes server-side, and gives you a normal `{campaign_id}` that every other
tool already understands.

The import is **asynchronous**: the call returns `{campaign_id}` immediately, with
`health_status` `"importing"` while the server fetches the bytes. Poll
`forge_get_campaign` until it leaves `"importing"` — `ready` means the dataset is
mineable, `failed` means the fetch did not complete and `health_error` says why. Pass a
stable `idempotency_key` so a retried create returns the same campaign instead of
importing the dataset a second time.

| Source                 | `source_uri`                        | Auth                                                                      |
| ---------------------- | ----------------------------------- | ------------------------------------------------------------------------- |
| Hugging Face           | `hf://owner/name` or `owner/name`   | none (public) · `hf` credential for a private repo                        |
| Google Cloud Storage   | `gs://bucket/prefix`                | `gcs` credential (service-account JSON) · signed URL · allowlisted bucket |
| AWS S3 / S3-compatible | `s3://bucket/prefix`                | `s3` credential (add `endpoint_url` for R2, MinIO, …)                     |
| Azure Blob             | `azure://account/container/prefix`  | `azure` credential (SAS token or account key)                             |
| Any https link         | `https://…/dataset.zip` · `.tar.gz` | none — the link itself is the credential (presigned, SAS, or public)      |
| Local folder           | *(local path)*                      | `forge_upload_dataset` — one command, parallel + resumable + progress bar |

<Tip>
  **Presign first.** An S3 presigned GET, a GCS signed URL, or an Azure SAS link imports with
  **no stored secret at all** — time-boxed, scoped to one object, nothing to rotate or revoke.
  Pass it as `source_uri`, omit `credential_id`, done. Store a credential only when you cannot
  presign (for example importing a whole prefix rather than a single archive).
</Tip>

A private `gs://` path needs a stored `gcs` credential or a signed URL — a credential-less
`gs://` import falls back to the server's own identity and is therefore allowed only for
buckets an operator has explicitly allowlisted.

The same schemes work for a fine-tune: pass the URI as `dataset_ref` to
`forge_create_world_model`, with `credential_id` alongside it when the source is private
and you could not presign.

### Credential flow

When presigning isn't an option, keep a credential on the account and pass it **by reference**:

1. **`forge_store_source_credential(provider, name, payload)`** → `{id, provider, name,
   created_at}`. `payload` holds the provider fields — `s3`: `access_key_id`,
   `secret_access_key`, optional `region` / `endpoint_url` / `session_token`; `gcs`:
   `service_account_json`; `azure`: `account_name` + `sas_token` **or** `account_key`;
   `hf`: `hf_token`.
2. **`forge_import_dataset(source_uri, credential_id=<id>)`** — the server decrypts the
   credential for that one fetch.
3. **`forge_delete_source_credential(credential_id)`** when the import is done.

Credentials are encrypted at rest, owner-scoped, and **never echoed**:
`forge_list_source_credentials` returns only `{id, provider, name, created_at}`, so a lost
secret is re-stored, not recovered. Give each one the narrowest read-only scope that works.

Imports are guarded: https fetches are SSRF-checked (private, loopback, link-local, and
metadata address ranges are refused, redirects capped and re-checked), archives unpack
traversal-safe, and both byte and file counts are capped server-side (defaults 20 GB /
20 000 files). Failures answer `400 unsupported source scheme: <scheme>` or
`400 source fetch failed: <why>`; an unknown `credential_id` answers `404 credential not
found`, and a server with no credential-store key answers `503 credential store not
configured`.

## Long-running work & spend

Runs and fine-tunes are asynchronous. The create tool returns immediately; **poll
`forge_get_campaign`** (and `forge_get_job` for augmentation renders) until a stage is
terminal, then fetch the artifact. For a cross-job view, **`forge_list_activity`** returns
everything you own that is queued or running, with measured ETAs (never guessed — a job
with no observed rate reports `eta: null` and says why).

**Stuck vs. slow.** Read `all_healthy` and `needs_attention` before saying anything is
wrong: a job is a problem only when its row carries a `diagnosis`. Every row also carries
`stale_s` (seconds since it last reported), but staleness alone is not a verdict — the
server compares it against that job's known heartbeat cadence (\~60s for a training box)
and writes the conclusion into `diagnosis`. For fine-tunes, `forge_diagnose_finetune` returns the full
forensics: a verdict (`healthy`, `late_heartbeat` — usually a long checkpoint save,
`zombie_suspected` — runner dead with the box still up and billing), the job's state
history, and the training log's tail with error lines pre-extracted. Zombie boxes are also
auto-remediated server-side: a train job silent for 45+ minutes is failed and its box
deleted; `forge_cancel_world_model` frees the training slot immediately if you'd rather
not wait.

Guardrails, so a looping agent can't run away with your wallet or GPUs:

* **Idempotency** — pass an `idempotency_key` on `forge_start_run`,
  `forge_start_playground_op`, and `forge_create_world_model`; a retry with the same key
  returns the original result instead of billing again.
* **Caps** — a per-owner ceiling bounds concurrent world-model jobs (count and summed
  `$` budget); over it, creation is refused. Budget/steps are clamped server-side.
* **Cancel** — `forge_cancel_world_model` stops a fine-tune and its billable box;
  `forge_cancel_job` stops an augmentation run.
* **Queueing** — training capacity is a shared fleet. A waiting job's campaign note reads
  `waiting for a training slot — position N of M (K training)`; that is normal motion, not
  a hang, and the queue advances whenever a box finishes. The first minutes after create
  may read `created via forge workbench` — the scheduler simply has not ticked yet.
* **Out of credits** — a billable call with an empty wallet fails with HTTP `402` and a body
  `insufficient_credits:need=N:checkout=/api/billing/credits/checkout:packs=/api/billing/credits/packs`.
  To resolve it headlessly: `forge_list_credit_packs` → pick a pack → `forge_credits_checkout`
  → open the returned Stripe `url` → re-check `forge_get_credits` → retry. No web UI required.

## Serve the trained model

The pipeline does not end at a weights archive. Once a fine-tune passes export:

1. **`forge_deploy_model(id)`** — free: writes a deployment record and returns a
   `wam_sk_` deployment token **exactly once** (the server keeps only a hash). No GPU
   runs yet.
2. **`forge_run_rollout(deployment_id, deployment_token, frames|video_b64)`** — the
   first call cold-boots the model (minutes: weights + load); calls within the warm
   window return in seconds. For a `wam` policy you get the denoised action chunk —
   `chunk × action_dim` absolute targets, ready to drive the robot.
3. **`forge_undeploy_model(deployment_id)`** — revokes the token; idle containers drain
   on their own either way.

Serving scales to zero (an idle deployment costs nothing) and each deployment carries a
per-UTC-day GPU-second budget; past it, rollouts refuse until midnight. For sustained
real-time control, talk to us about a dedicated lane — the rollout tool is for testing
and evaluation traffic.

Media tools (`*_preview`, `*_video`, `*_clip`, `forge_download_export`,
`forge_download_weights`) never stream multi-MB payloads through the model — they return
a URL (and, for weights, a short-lived signed URL) you fetch directly.
