Skip to content

nano-step/open-design-mcp

Repository files navigation

open-design-mcp

Website · Changelog · npm · GitHub

A stdio Model Context Protocol server that bridges coding agents (OpenCode, Claude Code, Cursor, Zed) to a running Open Design daemon — so you can list projects, fetch artifacts, and (in upcoming releases) generate full design artifacts via BYOK from inside your editor.

Status

v0.17.0 — 13 MCP tools live. The server activates the full Open Design feature surface: list/inspect projects, save and lint artifacts, persist files inside projects, format Turn 3 prompts, and generate designs via BYOK with the full upstream system-prompt fidelity. See open OpenSpec changes for in-flight work and closed changes for historical decisions.

Tools

Tool Verb Env vars required Description
od_list_projects read OD_DAEMON_URL List all projects from the OD daemon. Returns {projects: [{id, name, kind?, status?}, …]}.
od_get_project read OD_DAEMON_URL Fetch a project + its artifact files. Merges GET /api/projects/:id and GET /api/projects/:id/files. Now also surfaces customInstructions, fidelity, skillId, designSystemId, createdAt, updatedAt when set on the project (#56).
od_create_project write OD_DAEMON_URL Create a new project. Requires a client-supplied id matching /^[A-Za-z0-9._-]{1,128}$/ plus name; optional kind, fidelity, customInstructions, skillId, designSystemId, pendingPrompt. Returns the project details and an auto-seeded conversation ID. customInstructions is also mirrored to metadata.customInstructions for daemon compat (#43).
od_update_project write OD_DAEMON_URL Update a project's name, custom instructions, or metadata. At least one mutable field is required. customInstructions is also mirrored to metadata.customInstructions for daemon compat (#43).
od_delete_project write OD_DAEMON_URL PERMANENTLY delete a project (database row + on-disk directory). Cannot be undone.
od_save_artifact write OD_DAEMON_URL Persist an HTML artifact to the daemon's global artifact store at /app/.od/artifacts/<timestamp>-<identifier>/index.html. Args: identifier (URL-safe slug, /^[a-z0-9-]+$/, 3–64 chars), title (human-readable, 1–200 chars), html (full document). NOT project-scoped — saved artifacts do not appear in od_get_project.files. Returns the saved path + URL.
od_save_project_file write OD_DAEMON_URL Persist a file inside a project so it appears in od_get_project.files[] and renders in the daemon UI. Wraps POST /api/projects/:id/files. Args: projectId (1–128 chars), name (file name, no path separators, 1–255 chars), content (string, max ~5 MB). Unlike od_save_artifact (global store), this is project-scoped — use it when you want the file to show up under the project's viewer.
od_extract_design_system read none Parse a design-system.html artifact and return the JSON manifest + the three CSS blocks (od-tokens, od-components, od-layout). Pure function — no network calls, no env vars. Part of the design-system-first workflow.
od_generate_design_system generate (streaming) OD_DAEMON_URL + BYOK_BASE_URL + BYOK_API_KEY + BYOK_MODEL Generate a design system artifact (design-system.html) via BYOK. Produces tokens, components, and layout CSS plus a JSON manifest and human-reviewable gallery. Post-generation validation ensures the output has all required marker slots.
od_update_design_system write OD_DAEMON_URL (delta mode: none; semantic mode: + BYOK vars) Update an existing design system. Two modes: semantic (BYOK-driven natural-language patch) and delta (deterministic JSON merge, no network). Bumps data-od-version on every successful update.
od_lint_artifact validate OD_DAEMON_URL Lint a raw HTML document. Takes { html } only — inline content, not a project/slug reference. Returns findings + agent message. New optional arg designSystemHtml enables design-system-specific checks (DS001–DS005).
od_compose_brief format none Format a Turn 3 prompt for od_generate_design. Combines form answers, brand spec, and page brief into a string upstream Open Design recognizes. Pure function — no network, no env vars. New optional arg designSystemSummary for including design system context in the Turn 3 prompt.
od_generate_design generate (streaming) OD_DAEMON_URL + BYOK_BASE_URL + BYOK_API_KEY + BYOK_MODEL (BYOK_PROVIDER optional, defaults to openai) Generate a design via the BYOK pipeline. Composes the upstream Open Design system prompt and proxies through the OD daemon's /api/proxy/<provider>/stream. Returns the accumulated text. Reads customInstructions from metadata.customInstructions first, then top-level field (#43). Accepts maxTokens (default 64000) to control completion length — see #36. When projectId resolves a project with designSystemId, auto-injects the design system contract. New optional arg designSystemMode (strict/advisory/off).

Only od_generate_design and od_generate_design_system require the BYOK vars. The other 11 tools work with just OD_DAEMON_URL (or no env vars in the case of od_compose_brief and od_extract_design_system).

od_save_project_file vs od_save_artifact: These two write tools serve different storage scopes. od_save_artifact writes to the daemon's global artifact store — useful for shareable URLs that aren't tied to a project. od_save_project_file writes inside a project's directory so the file appears in od_get_project.files[] and renders in the daemon's project UI. Use od_save_project_file when you want the generated design to live inside the project; use od_save_artifact for standalone, project-unaware artifacts.

How it works

When you invoke od_generate_design with a PRD-style prompt, the MCP server composes a ~20–50 KB system prompt locally (vendored composeSystemPrompt injects designer charter + kind-specific rules), then POSTs to the OD daemon's /api/proxy/<provider>/stream endpoint. The daemon is a thin pass-through proxy — it forwards to your BYOK provider, transcodes the upstream stream into its own SSE format, and streams tokens back. The MCP server accumulates deltas and emits notifications/progress every 25 tokens (only when the client supplied a progressToken, per MCP spec).

Typical timing: ~10 seconds for small sections (single hero, paragraph rewrite); 1–5 minutes for full pages; up to 10 minutes for complex multi-section designs. Set maxTokens (default 64000) to control completion length — full pages typically need 30000+ tokens; the daemon's silent default was 8192 (#36). Server timeout defaults to 10 minutes (OD_GENERATE_TIMEOUT_MS, configurable). On abort or timeout mid-stream, accumulated tokens are returned as partial HTML with a trailing <!-- Generation timed out... --> comment marker and isError: true — pair with od_save_artifact to checkpoint partial progress.

Full reference with file:line citations: docs/architecture/generate-design-flow.md.

sequenceDiagram
    autonumber
    participant E as Editor
    participant M as open-design-mcp
    participant D as OD daemon
    participant P as BYOK proxy
    E->>M: tools/call od_generate_design
    M->>M: composeSystemPrompt + lazy BYOK load
    M->>D: POST /api/proxy/openai/stream
    D->>P: POST /chat/completions stream true
    loop SSE tokens
        P-->>D: delta
        D-->>M: event delta
    end
    M-->>E: tool result HTML
Loading

Design-System-First Workflow

For multi-page projects, generate a design system before any individual pages to ensure visual consistency:

  1. Generate a design system: od_generate_design_system with your brand brief.
  2. Save it inside the project: od_save_project_file with name: "design-system.html".
  3. Link it: od_update_project with designSystemId: "design-system.html".
  4. Generate pages: Every subsequent od_generate_design call with that projectId auto-injects the design system contract (strict mode by default).

The designSystemMode argument on od_generate_design controls enforcement:

  • strict (default when linked) — pages MUST use documented tokens and components; violations caught by od_lint_artifact.
  • advisory — prefer documented tokens; deviations should be justified.
  • off — no injection, equivalent to pre-v0.17 behavior.

Use od_lint_artifact with designSystemHtml to verify pages conform (findings DS001–DS005). Use od_update_design_system to evolve the system over time without regenerating all pages.

This workflow is fully opt-in — projects without a linked design system behave exactly as before.

Known limitation in v0.17.0: Step 4 (auto-injection via designSystemId linkage) is currently a runtime no-op. The daemon's files-list endpoint returns metadata only — not file content — so od_generate_design cannot yet fetch and inject the linked design system. Until v0.18 adds a content endpoint, enforce design system adherence via od_lint_artifact + designSystemHtml (post-generation static checks DS001–DS005) and via od_compose_brief + designSystemSummary (Turn 3 prompt enrichment). Both paths are fully functional. See CHANGELOG.md v0.17.0 "Known Limitations".

Installation

Add the following entry to your MCP client config (OpenCode / Claude Code / Cursor / Zed):

{
  "mcp": {
    "open-design": {
      "command": "npx",
      "args": ["-y", "open-design-mcp"],
      "env": {
        // Pick the line that matches your deployment (see "Choosing OD_DAEMON_URL" below)
        "OD_DAEMON_URL": "http://ai-open-design:7456",
        "OD_API_TOKEN": "",                            // optional; bearer token if your daemon requires it
        // BYOK vars — only needed if you call od_generate_design
        "BYOK_BASE_URL": "https://your-ai-proxy.example.com/v1",
        "BYOK_API_KEY": "<provider-api-key>",
        "BYOK_MODEL": "open-design",
        "BYOK_PROVIDER": "openai"                      // optional; one of openai/anthropic/azure/google/ollama
      }
    }
  }
}

The server boots successfully with only OD_DAEMON_URL set — the BYOK vars are validated lazily when od_generate_design is invoked. This lets users explore via od_list_projects / od_get_project before wiring an AI provider.

Choosing OD_DAEMON_URL

The right value depends on where the Open Design daemon is running relative to the MCP server (which itself runs wherever your coding agent spawns it):

Your setup OD_DAEMON_URL
MCP server + OD daemon both run as containers on a shared Docker network (e.g. via ai-sandbox-wrapper with --network ai-sandbox) — most common http://ai-open-design:7456
MCP server runs inside a Docker container, OD daemon runs natively on the host (exposed on host port 7456) http://host.docker.internal:7456 (macOS / Windows Docker Desktop)
http://172.17.0.1:7456 (Linux bridge gateway)
MCP server and OD daemon both run natively on the host (no Docker) http://localhost:7456
OD container started via ai-run open-design start --expose --port N to host port N http://host.docker.internal:N (from inside another container)
http://localhost:N (from host)

Quick diagnostic (run from the environment where the MCP server will spawn):

curl -fsS http://ai-open-design:7456/ && echo " OK"          # shared docker network
curl -fsS http://host.docker.internal:7456/ && echo " OK"    # host gateway
curl -fsS http://localhost:7456/ && echo " OK"               # native

Whichever one returns 200 is your correct OD_DAEMON_URL.

Environment Variables

Variable Purpose Required by Default
OD_DAEMON_URL Open Design daemon base URL — see Choosing OD_DAEMON_URL above all tools (validated eagerly at startup)
OD_API_TOKEN Bearer token the OD daemon enforces when bound to non-loopback optional "" (no auth header sent)
OD_AUTH_MODE Auth mode: none, bearer, or basic. Auto-derived if unset (token set → bearer; basic creds set → basic; neither → none) optional inferred
OD_BASIC_USER HTTP Basic Auth username OD_AUTH_MODE=basic
OD_BASIC_PASS HTTP Basic Auth password OD_AUTH_MODE=basic
OD_GENERATE_TIMEOUT_MS Server-side timeout for od_generate_design, in milliseconds. Raised from the previous 120s after #33 confirmed full-page generations legitimately exceed it. optional 600000 (10 min)
BYOK_BASE_URL OpenAI-compatible AI provider base URL od_generate_design only (validated lazily)
BYOK_API_KEY Provider API key forwarded via OD's /api/proxy/*/stream od_generate_design only
BYOK_MODEL Model id (e.g. open-design, claude-sonnet-4-6) od_generate_design only
BYOK_PROVIDER One of openai / anthropic / azure / google / ollama optional openai

The server fails fast with a clear stderr message if OD_DAEMON_URL is missing or invalid. BYOK vars are checked only when od_generate_design is called — a missing var yields a friendly tool-level error (isError: true, text "BYOK not configured: missing ..."), never a crash.

Hosted Open Design deployment (HTTP Basic Auth)

If the OD daemon is behind a reverse proxy with HTTP Basic Auth (e.g. the publicly-hosted instance at https://od.thnkandgrow.com/), set OD_AUTH_MODE=basic with the matching credentials:

{
  "mcp": {
    "open-design": {
      "command": "npx",
      "args": ["-y", "open-design-mcp"],
      "env": {
        "OD_DAEMON_URL": "https://od.thnkandgrow.com/",
        "OD_AUTH_MODE": "basic",
        "OD_BASIC_USER": "<your-username>",
        "OD_BASIC_PASS": "<your-password>"
      }
    }
  }
}

The server emits Authorization: Basic <base64(user:pass)> on every request to the OD daemon. Embedded credentials in the URL (https://user:pass@host/) are rejected at startup — use the env vars instead.

Development

nvm use            # picks Node 20 per .nvmrc
npm install
npm run lint
npm run typecheck
npm test
npm run build
npm run test:integration   # spawns dist/src/server.js, mocks the OD daemon, exercises all 8 tools

The engineering harness (docs/HARNESS.md) requires every feature, fix, or refactor to go through an OpenSpec proposal → deep-design → specs → implement → validate → review → PR → archive cycle. See docs/stories/ for in-flight stories.

Vendored Dependencies

This project vendors a subset of source from nexu-io/open-design (Apache License 2.0) so we can compose the same systemPrompt the Open Design web UI builds for its BYOK chat turns — without depending on the upstream's private @open-design/contracts package.

Path Upstream License Notes
vendor/od-contracts/ nexu-io/open-design packages/contracts/src/ Apache-2.0 13 files (7 runtime + 6 type-only). Pinned commit + re-sync instructions in vendor/od-contracts/VENDORED_FROM.md. Sync script at scripts/vendor-sync.sh.

License compliance:

All vendored code is redistributed under the same Apache License 2.0.

License

Apache License 2.0. See LICENSE for the full text and NOTICE for attribution.

Copyright (c) 2026 kokorolx kokoro.lehoang@gmail.com.

About

Bridges MCP-compatible coding agents (OpenCode, Claude Code, Cursor) to Open Design daemon. Full BYOK flow with composeSystemPrompt fidelity.

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors