--- name: mmd-studio description: Create, read, update, delete, and share Mermaid diagrams on mmd.studio for the signed-in user via a REST API. Use when the user asks to manage diagrams on mmd.studio, wants to create or edit a Mermaid diagram hosted there, or shares an https://mmd.studio/d/ link. --- # MMD Studio -- agent skill MMD Studio is a browser-based [Mermaid](https://mermaid.js.org) diagram editor at [mmd.studio](https://mmd.studio). This skill lets you (an agent) create, read, update, delete, and share diagrams on behalf of a signed-in user via a REST API and a per-user API token. ## Installing this skill There are two ways to use this skill, depending on which agent is calling it and how often. **Option A -- fetch on demand (any agent, zero setup).** Tell the agent to read `https://mmd.studio/SKILL.md` at the start of the conversation and to use the user's `MMD_TOKEN` on every request. Works for Claude Code, Claude Desktop, ChatGPT, Cursor, or anything with a web-fetch tool. Nothing to install. **Option B -- install locally (Claude Code, persistent).** Save the skill into `~/.claude/skills/` so Claude Code auto-loads it every session: ```sh mkdir -p ~/.claude/skills/mmd-studio curl -sS https://mmd.studio/SKILL.md -o ~/.claude/skills/mmd-studio/SKILL.md # Put the token somewhere persistent so every shell has it. echo 'export MMD_TOKEN="mmd_..."' >> ~/.zshrc # or ~/.bashrc ``` After that, the user can say "use the mmd-studio skill to ..." and Claude Code will route to this file automatically without being told to fetch it. ## When to use this Use this skill when the user asks you to: - **Create** a new diagram (flowchart, sequence, class, state, ER, gantt, pie, mindmap, timeline, sankey, xy, block, packet, kanban, architecture, C4, journey, requirement, git graph, quadrant, etc.). - **List** or **fetch** their existing diagrams. - **Edit** a diagram -- rename, rewrite the source, replace with a new version. - **Delete** a diagram. - **Share** a diagram (flip visibility to link-shareable, return the URL they can send to a collaborator). - **Read a publicly shared diagram** that someone sent them a link to (no auth required for this one). ## Prerequisites 1. The user needs to sign in at [mmd.studio](https://mmd.studio) and create an API token via **your email -> Settings -> API tokens -> Create token**. The raw token is shown exactly once on creation; if they've lost it they need to make a new one. 2. Put the token in an env var. This skill assumes `$MMD_TOKEN`: ```sh export MMD_TOKEN="mmd_..." ``` 3. Every authed request sends it in the `Authorization` header: ``` Authorization: Bearer $MMD_TOKEN ``` ## Base URL ``` https://mmd.studio/api ``` ## The diagram resource Every authed endpoint returns diagrams in this shape: ```json { "id": "f47ac10b-58cc-4372-a567-0e02b2c3d479", "title": "User signup flow", "code": "flowchart TD\n A[Start] --> B[Fill form]\n B --> C[Submit]", "visibility": "private", "linkAccess": "read", "updatedAt": "2026-04-14T22:15:49.862Z" } ``` - **`id`** -- a UUID v4. **The agent generates this client-side** when creating a new diagram (see below). - **`title`** -- 1-200 characters, free-form. - **`code`** -- the Mermaid source. <=100,000 characters. See the Mermaid syntax reference at . - **`visibility`** -- `"private"` (default, only the owner), `"link"` (anyone with the URL can view), or `"invite"` (reserved, not yet active). - **`linkAccess`** -- `"read"` (the default for link-shared diagrams) or `"edit"` (reserved, not yet active). Only meaningful when `visibility === "link"`. - **`updatedAt`** -- ISO-8601 timestamp. **Last-write-wins**: when updating an existing diagram, the server compares the `updatedAt` you send against the stored one and takes the newer. If your write is stale, the server ignores it and returns its canonical copy in the response. ## ID generation Diagram IDs are UUIDs. Generate one per diagram you create: ```sh # Linux/macOS uuidgen | tr '[:upper:]' '[:lower:]' # Node node -e "console.log(crypto.randomUUID())" # Python python -c "import uuid; print(uuid.uuid4())" ``` ## Endpoints ### List all diagrams ```sh curl -sS -H "Authorization: Bearer $MMD_TOKEN" \ https://mmd.studio/api/diagrams ``` Response: ```json { "diagrams": [ { "id": "...", "title": "...", "code": "...", "visibility": "...", "linkAccess": "...", "updatedAt": "..." } ], "deleted": [ { "id": "...", "deletedAt": "..." } ] } ``` `deleted` is a list of tombstones for recently deleted diagrams -- you can usually ignore it unless you're syncing local state. ### Fetch a single diagram ```sh curl -sS -H "Authorization: Bearer $MMD_TOKEN" \ https://mmd.studio/api/diagrams/$ID ``` Returns `{ "diagram": { ... } }` or **404** if the diagram doesn't exist or isn't yours. ### Create or update a diagram The same `PUT` endpoint handles both. If the ID is new, it creates; if it exists and the incoming `updatedAt` is newer, it updates. ```sh ID=$(uuidgen | tr '[:upper:]' '[:lower:]') NOW=$(date +%s000) # milliseconds since epoch curl -sS -H "Authorization: Bearer $MMD_TOKEN" \ -H "Content-Type: application/json" \ -X PUT "https://mmd.studio/api/diagrams/$ID" \ -d "{ \"title\": \"User signup flow\", \"code\": \"flowchart TD\n A[Start] --> B[Fill form]\n B --> C[Submit]\", \"updatedAt\": $NOW, \"visibility\": \"private\", \"linkAccess\": \"read\" }" ``` Request fields: | Field | Type | Required | Notes | | ------------ | --------------------- | :------: | ----------------------------------------------------- | | `title` | string (1-200) | x | | | `code` | string (<=100k) | x | Mermaid source | | `updatedAt` | number (ms) or ISO | x | Last-write-wins; use `Date.now()` for new writes | | `visibility` | `private\|link\|invite` | - | Defaults to `private` on create, preserved on update | | `linkAccess` | `read\|edit` | - | Defaults to `read` on create, preserved on update | Response: `{ "diagram": { ... } }` with the canonical server state. If your `updatedAt` was older than the server's, the response reflects the server's (unchanged) copy and your write was ignored. Status codes: - **200** -- upsert succeeded (or ignored as stale; read the response). - **400** -- invalid id, title, code, or updatedAt. - **403** -- you're trying to write a diagram owned by someone else. - **410** -- the diagram has a newer tombstone; it's been deleted and your write was rejected. ### Delete a diagram ```sh curl -sS -H "Authorization: Bearer $MMD_TOKEN" \ -H "Content-Type: application/json" \ -X DELETE "https://mmd.studio/api/diagrams/$ID" \ -d "{\"deletedAt\": $(date +%s000)}" ``` `deletedAt` is optional -- if omitted, the server uses `now()`. It's a soft delete: a tombstone is written so offline clients can reconcile. ### Fetch a publicly shared diagram (no auth) ```sh curl -sS https://mmd.studio/api/diagrams/$ID/public ``` Returns the diagram along with owner + access info **if and only if** `visibility !== "private"`; otherwise **404**. No `Authorization` header required. ```json { "diagram": { "id": "...", "title": "...", "code": "...", "visibility": "link", "linkAccess": "read", "updatedAt": "..." }, "owner": { "email": "alice@example.com" }, "access": "read" } ``` ## Sharing a diagram -- full flow A common ask: "create a new sequence diagram and give me a link I can share with someone." ```sh ID=$(uuidgen | tr '[:upper:]' '[:lower:]') NOW=$(date +%s000) # 1. Create the diagram (private by default). curl -sS -H "Authorization: Bearer $MMD_TOKEN" \ -H "Content-Type: application/json" \ -X PUT "https://mmd.studio/api/diagrams/$ID" \ -d "{ \"title\": \"Auth handshake\", \"code\": \"sequenceDiagram\n Client->>Server: login\n Server-->>Client: token\", \"updatedAt\": $NOW }" # 2. Flip it to link-shareable. curl -sS -H "Authorization: Bearer $MMD_TOKEN" \ -H "Content-Type: application/json" \ -X PUT "https://mmd.studio/api/diagrams/$ID" \ -d "{ \"title\": \"Auth handshake\", \"code\": \"sequenceDiagram\n Client->>Server: login\n Server-->>Client: token\", \"updatedAt\": $(date +%s000), \"visibility\": \"link\", \"linkAccess\": \"read\" }" # 3. The shareable URL is: echo "https://mmd.studio/d/$ID" ``` ## Editing an existing diagram Fetch the current state first so you don't blow away a field you didn't mean to touch, then PUT the full object back with a fresh `updatedAt`: ```sh ID="f47ac10b-58cc-4372-a567-0e02b2c3d479" # Read. CURRENT=$(curl -sS -H "Authorization: Bearer $MMD_TOKEN" \ "https://mmd.studio/api/diagrams/$ID") # Extract fields with jq (or use your preferred JSON tool). TITLE=$(echo "$CURRENT" | jq -r '.diagram.title') VISIBILITY=$(echo "$CURRENT" | jq -r '.diagram.visibility') LINK_ACCESS=$(echo "$CURRENT" | jq -r '.diagram.linkAccess') # Write a new code value, preserving everything else. NEW_CODE='flowchart TD\n A[Start] --> B[End]' curl -sS -H "Authorization: Bearer $MMD_TOKEN" \ -H "Content-Type: application/json" \ -X PUT "https://mmd.studio/api/diagrams/$ID" \ -d "{ \"title\": \"$TITLE\", \"code\": \"$NEW_CODE\", \"updatedAt\": $(date +%s000), \"visibility\": \"$VISIBILITY\", \"linkAccess\": \"$LINK_ACCESS\" }" ``` ## Errors All errors return JSON of the form `{"error":"message"}`. - **400 Bad Request** -- validation failed (title/code/updatedAt/id). - **401 Unauthorized** -- token missing or invalid. - **403 Forbidden** -- the diagram exists but you don't own it. - **404 Not Found** -- the diagram doesn't exist (or you don't own it -- the server doesn't distinguish for privacy). - **410 Gone** -- the diagram has been deleted and your write was rejected by a newer tombstone. ## Tips - **Prefer short IDs in logs.** Refer to diagrams by their title in user-facing output. The user probably doesn't care about the UUID. - **Don't hardcode `updatedAt`.** Use the current time (`Date.now()` or equivalent) on every write. Last-write-wins relies on monotonic timestamps. - **Validate Mermaid syntax** before writing -- a diagram with invalid source persists fine on the server but renders as an error in the UI. If the user describes the diagram in natural language, translate carefully and consider showing them the source before saving. - **Private is the default.** A newly created diagram is only visible to the owner until they (or you) explicitly set `visibility`.