Skill: Getting Started with Benchy
Teach your agent the whole Benchy surface — MCP connection, tokens, bio profiles, shop listings, model uploads, and running the family locally.
What it teaches
The foundation skill: how the hub-and-spoke family fits together and how an agent connects to it. Covers the MCP endpoint and transport, personal access tokens and OAuth, error handling and concurrency, and the core flows on every spoke — bio profiles, shop listings, and model uploads.
Load it into Claude Code, Codex, Cursor, Grok, or any MCP-capable agent alongside a Benchy connection (setup guide), and the agent gains this entire operating manual as working knowledge.
What your agent can do
- Connect to mcp.benchy.studio over Streamable HTTP with a PAT or hosted OAuth
- Take a bio profile from empty to live: quota check, handle check, create, content, audit, publish
- Stage shop products through the upload-first flow and start Stripe Connect onboarding
- Upload 3D models to benchy.world, publish new versions, and use benchy-cli for heavy files
- Handle errorCode-driven retries, expectedUpdatedAt concurrency, and dry-run previews
- Run the entire family locally — hub, spokes, agent, workers, and the Rust mesh engine
Get the skill
For Claude Code, install it as a project skill:
shell
mkdir -p .claude/skills/getting-started-with-benchy
curl -o .claude/skills/getting-started-with-benchy/SKILL.md https://benchy.world/skills/getting-started-with-benchy.mdThe full SKILL.md
The complete document, ready to copy:
getting-started-with-benchy.md
---
name: getting-started-with-benchy
description: Manage a user's entire Benchy account as an agent — connect to the Benchy MCP server, authenticate with personal access tokens or OAuth, build and publish bio profiles, manage shop listings, upload 3D models to benchy.world (CLI for heavy files), customize the Benchy agent, and run the whole family locally. Use whenever a user asks you to set up, operate, or automate anything on benchy.studio, benchy.bio, benchy.shop, or benchy.world.
title: Getting Started with Benchy
date: 2026-07-12
author: Benchy
tags: [benchy, mcp, agents, 3d-printing, skill]
license: MIT
metadata:
version: "1.0.0"
surface: "mcp.benchy.studio · benchy-cli · BenchyStudio dashboard agent panel"
---
# Getting started with Benchy (for agents)
Benchy is a hub-and-spoke family. The hub (`benchy.studio`) owns identity, credits, the canvas, and the family-wide MCP server. The spokes are `benchy.bio` (link-in-bio profiles), `benchy.shop` (creator commerce), and `benchy.world` (3D model hosting). Every spoke runs its own Convex deployment and trusts hub-minted JWTs. You, the agent, manage all of it through one MCP endpoint.
## 1. Connect to the Benchy MCP server
| | |
|---|---|
| Endpoint | `https://mcp.benchy.studio/api/mcp` (prod) · `http://localhost:3000/api/mcp` (dev) |
| Transport | Streamable HTTP only — SSE is explicitly disabled |
| Spec | MCP `2025-11-25` |
| Auth | `Authorization: Bearer bnchy_...` PAT, or hosted OAuth (`authorization_code` + PKCE S256, opaque `bnchy_oauth_...` access tokens) |
| Tools | 154 registered across six prefixes: `bio_*` (49), `canvas_*` (19), `world_*` (33), `shop_*` (40), `writer_*` (5), and knowledge — `skills_*` + `memories_*` (8 together). Counts read from `BenchyStudio/scripts/ci/check-mcp-tool-surface.ts` `EXPECTED_COUNTS`, which CI asserts against the live registry (checked 2026-07-25) |
Client config for a PAT (Claude Code, Cursor, scripts):
```json
{
"mcpServers": {
"benchy": {
"url": "https://mcp.benchy.studio/api/mcp",
"headers": { "Authorization": "Bearer bnchy_..." }
}
}
}
```
Hosted connectors (ChatGPT, Claude hosted) cannot paste a PAT — they use OAuth discovery: protected-resource metadata at `https://mcp.benchy.studio/.well-known/oauth-protected-resource`, authorization server `https://id.benchy.studio` (Dynamic Client Registration at `/oauth/register`, PKCE S256, scopes `mcp:read mcp:write offline_access`).
If several agent sessions share one PAT, send `X-Benchy-Agent: <short name>` (max 40 chars) — Bio presence then shows a separate actor chip per agent. This header affects attribution only, never authorization.
Pin the zero-token MCP resources before writing anything. There are 13 (11 static + 2 templates, checked 2026-07-25): `benchy://schema/bento-types`, `benchy://schema/backgrounds`, `benchy://schema/grid`, `benchy://schema/limits`, `benchy://schema/design-guidance`, `benchy://schema/colors`, `benchy://schema/social-platforms`, `benchy://schema/canvas-scene`, `benchy-shop://schema/product-formats`, `benchy-shop://schema/limits`, `benchy-world://schema/truecost`, plus two templates, `benchy://profile/{handle}` and `benchy-shop://product/{productId}`. All 5 server prompts: `/draft_launch_profile`, `/redesign_bento`, `/audit_profile`, `/draft_seller_onboarding`, `/seller_sales_audit`.
## 2. Auth: personal access tokens
- The user mints a PAT at `https://www.benchy.studio/dashboard/profile?tab=api-keys` (**Profile → API keys**). Format is `bnchy_` + 32 base62 chars; the plaintext is shown **once** and only its SHA-256 hash is stored. Max 20 active tokens per user; expiry options are 30/90/365 days or never (default 90).
- Two scopes: **Full access** or **Read-only** (`scope: "read" | "full"` on the `personalAccessTokens` table). Read-only tokens can call every read tool; every write is refused at the hub AND hard-rejected by spoke deployments via the JWT's `mcpScope` claim. Don't try to route around it.
- Under the hood, each MCP call exchanges the PAT for a **120-second hub JWT** (`POST https://id.benchy.studio/api/mcp/exchange`) carrying `sites`, `shopBuyer`, `plan`, and `mcpScope` claims. Spokes verify against the hub JWKS at `https://id.benchy.studio/.well-known/jwks.json`.
- Access is gated per site by the hub `siteAccess` table (`status: "active" | "waitlist" | "blocked"` per site key `studio|bio|shop|world`). If a tool fails with `errorCode: "unauthorized"`, the user may need to visit `/request-access?site=<spoke>` — you cannot grant site access yourself.
- Shop is special: `sites:["shop"]` means seller access; `shopBuyer:"1"` (any non-blocked member) is enough to buy and use the library.
## 3. Error handling and concurrency
Failed tools set `structuredContent.errorCode`. Retry in-loop only for `concurrency_conflict` (re-read for a fresh `updatedAt`, retry) and `elicitation_unsupported` (re-call with the explicit arg — `allowedValues` lists the enum). `not_found`, `validation`, `cap_reached`, `rate_limited`, `unauthorized`, `upload_failed`, `tool_exception` need a state change or the user.
Mutations accept `expectedUpdatedAt` from your last `bio_get_my_profile`; the spoke rejects stale writes. Destructive tools (`bio_remove_bento_item`, `bio_restore_my_version`, `shop_delete_product`) accept `dryRun: true` — always dry-run before destructive changes the user didn't explicitly script. Every call lands in the hub `mcpAuditLog` (tool, status, duration — never args).
## 4. Manage bio profiles
Zero-to-live with only a PAT:
1. `bio_get_site_quota` — confirm a slot is free.
2. `bio_check_handle_availability { handle }` — before consuming a create.
3. `bio_create_site { handle, name, visibility: "private" }` — returns the profile; use its `id` as `profileId` below.
4. Content: `bio_add_bento_items` + `bio_update_bento_items` (batch up to 12 per write), or `bio_build_site_draft` → `bio_promote_draft` for a full generated page. Keep **at least 4 blocks** — public pages under 4 are noindex'd and skipped in the sitemap.
5. `bio_audit_my_profile_quality` — fix warnings before going live.
6. `bio_set_site_visibility { profileId, visibility: "public" }` — the deploy step. The page serves at `https://benchy.bio/<handle>` within seconds (ISR cache busted on the transition). Do not depend on `https://<handle>.benchy.bio` — wildcard domains were removed.
Media is a two-step flow: `bio_request_upload` (with REQUIRED `contentType` + `byteSize`) returns `{ uploadUrl, assetId, key, cdnUrl }` → PUT bytes to R2 with the matching Content-Type → `bio_attach_uploaded_file({ assetId, kind })` → then reference it from a bento item. The Bio `3d-model` upload kind is GLB-only and used for `model-file` cards; STL/OBJ/USDZ belong on World/Shop/Canvas.
Style tools are bounded: `bio_set_background` (19 presets), `bio_set_corner_roundness`, `bio_set_surface_elevation`. Drafts (cap 10/user) let you propose variants without touching the live page; `bio_promote_draft` auto-snapshots the previous live for rollback via `bio_restore_my_version`.
## 5. Manage shop listings
Always call `shop_get_connect_status` FIRST in any seller flow — it returns cached `chargesEnabled` / `payoutsEnabled` / `onboardingComplete` plus Stripe live/test `environmentMatches`. If onboarding is incomplete, `shop_start_onboarding` creates the Stripe Connect Express account and returns an Account Link for the user.
Product creation is upload-first: `shop_request_upload` (`purpose: "product_file"` max 500 MB private, or `purpose: "cover_image"` max 20 MB public) → PUT → `shop_attach_uploaded_file` (mandatory — an unsynced PUT leaves an orphaned object) → `shop_create_product` with the returned `fileKey`. Pass `recurringInterval: "month" | "year"` for subscriptions (immutable after create). Full seller operations are covered in the companion skill `manage-your-benchy-shop`.
## 6. Upload 3D models to benchy.world
Via MCP tools:
1. `world_request_model_upload` — ingest grant for `.glb/.gltf/.stl/.obj/.usdz/.3mf`, max 250 MB (server-enforced). Pass `units: "um" | "mm" | "cm" | "m" | "in" | "ft"` for STL/OBJ before transfer. Returns `grantToken` + `putObjectUrl`.
2. PUT the file bytes, then `world_finalize_model_upload` — promotes pending → models bucket, returns `modelKey`.
3. Optional media: `world_request_thumbnail_upload` / `world_request_model_media_upload` + `world_finalize_media_upload`.
4. `world_create_model` — one-byte-probes the key actually landed in R2, then creates the row (stamped `source: "mcp"` for the “Uploaded via MCP” badge). For STL/OBJ, pass the same choice as `print: { units }`. Public intent requires an explicit `isGenerative: true | false`; omission is not treated as human-created. Accepts `categoryAssignments` (call `world_list_model_categories` first — exact MakerWorld/Thangs/Cults3D keys are checked), `tagLabels`, creator print guidance, and provenance/remix fields.
5. New revisions: `world_publish_new_version` (bumps `currentVersion`, notifies watchers, object-probe runs before the bump).
For heavy files or bulk work, use **benchy-cli** — a single-file Bun binary that speaks Streamable HTTP MCP directly (`benchy-cli/src/benchy.ts`). Auth: `export BENCHY_PAT='bnchy_...'` (or `--pat`); PATs never land on disk. Install: `cd benchy-cli && bun install && bun link`. Core commands: `benchy whoami`, `benchy upload <file> --title "..."`, `benchy list`, `benchy get`, `benchy update`, `benchy publish <modelId> <file> --note "..."`, `benchy download <modelId> --out ./model.glb`, `benchy sell-link <modelId> --product <shopProductId>`, plus `raw <tool> '<json>'` for any MCP tool. Endpoint overrides: `--mcp` / `BENCHY_MCP_URL`, `--cdn` / `BENCHY_CDN` (defaults `https://mcp.benchy.studio/api/mcp` and `https://models.benchy.world/models`).
Boundary to respect: World listings take structured metadata only (title, description, tags, categories, license, print details, media, provenance). Never invent world-side `price`, CSS, or layout fields — selling happens in `shop_*`, then `world_link_shop_product` attaches the CTA (the hub verifies the product exists and is owned by the caller before writing the link). For paid delivery, finalize to protected storage, create the model as Private, link with `enableShopOnVerification: true`, and only then request Public or Unlisted visibility; this order prevents an unlinked source-delivery window.
## 7. Customize the Benchy agent
The family agent is the **Benchy panel in the Studio dashboard**, served by
BenchyStudio itself at `POST /api/agent/chat` on the AI SDK. Things you can
tune:
- Write access: `BENCHY_MCP_ENABLE_WRITE_TOOLS` defaults off. When set to `1`,
mutating MCP tools become visible but **still pause for human-in-the-loop
approval** — the panel shows Approve/Deny, and the composer stays locked
until you answer.
- The agent forwards each user's own hub JWT to the MCP server, so users don't
need PATs for the in-product agent and it holds no shared super-token.
> **Retired.** Until 2026-07-24 this was a separate hosted "Eve" runtime at
> `agent.benchy.studio` (repo `benchy-agent`) mounted at `/eve/v1/*`, tuned via
> `BENCHY_AGENT_MODEL` / `BENCHY_AGENT_REASONING` and
> `agent/instructions.md` + per-subagent instruction files. That host, that
> repo, and those variables are gone. Do not try to reach `/eve/v1/*`.
## 8. Run Benchy locally
The family root is a multi-repo workspace manifest, not a monorepo (each child keeps its own git repo, lockfile, and secrets):
```bash
git clone git@github-benchystudio:benchystudio/benchyfamily.git benchyfamily
cd benchyfamily
bun run bootstrap # clone/verify child repos (bootstrap:install also runs bun install everywhere)
bun run status # branch + latest commit per repo (status:fetch to fetch/prune first)
bun run check # validate manifest, remotes, branches, clean states
```
Per app (each is Next.js + its own Convex deployment; two terminals each):
```bash
# Hub — BenchyStudio (port 3000)
cd BenchyStudio
bun install
cp .env.example .env.local # fill CONVEX + AUTH_GOOGLE/GITHUB values
bunx convex dev # terminal 1
bun run dev # terminal 2 → http://localhost:3000
```
Family ports: hub `3000`, shop `3001`, world `3004`, bio `3010`. There is no
separate agent server any more — the agent panel is part of Studio on `3000`.
R2 credentials (`R2_ENDPOINT`, `R2_ACCESS_KEY_ID`, `R2_SECRET_ACCESS_KEY`,
`R2_BUCKET_*`) and JWT keys live in **Convex env**, not `.env.local`.
Studio's Canvas and Writer multiplayer additionally need the collaboration
relay, which lives in `benchy-edge`, not in Studio:
```bash
cd benchy-edge
bun run dev:collab # wrangler dev → ws://localhost:8787
```
Without it, both surfaces log WebSocket connection-refused and quietly fall
back to single-player while still rendering.
The agent's model runs through Vercel AI Gateway (`xai/grok-4.5`). On Vercel,
gateway auth rides the project's OIDC token; locally, provide an AI Gateway key
as `AI_GATEWAY_API_KEY`.
Workers and mesh engine:
```bash
cd benchy-edge && bun install && bun run test && bun run typecheck # dev:aeo / dev:world / dev:shop per worker
cd benchy-mesh && cargo test -p benchy-mesh-core
cargo run -p benchy-mesh-cli -- validate --json path/to/model.stl
```
Dev gotcha for `benchy download` against a local hub: the prod model gateway is bound to the prod R2 bucket, so also set `BENCHY_CDN` to the world spoke's `.convex.site/r2/models` httpAction (the CLI warns about this mismatch).
## 9. Operating rules
- Read before you write: fetch current state (`bio_get_my_profile`, `world_get_model`, `shop_get_connect_status`) at the start of every flow.
- Prefer drafts and dry-runs; confirm with the user before publish, delete, or anything touching payment.
- Respect caps published in `benchy://schema/limits` and `benchy-shop://schema/limits` rather than discovering them via `cap_reached`.
- Keep uploads inside Benchy's two-step request/attach flows — never invent raw bucket access.Use ← and → to move between pages.