Skip to main content
Glama
S-s-Spudd
by S-s-Spudd
README.md
# Spud Design MCP V2

Local MCP server for evidence-bound Penpot design delivery.

Lifecycle:

`Start -> Direction Commit -> Prototype Submit -> User Approval -> Implementation Submit -> User Approval -> Code Completion`

## Public tools

- `design_session_start`
- `design_direction_commit`
- `design_stage_submit`
- `design_stage_approve`
- `design_code_complete`

All writes require idempotency keys. Direction commit accepts exactly three compact, viable, materially different cards, selects one, and binds a hashed root-relative selected-design inventory under `DESIGN_MCP_CAPTURE_ROOT`. Every inventory item points to byte-verified evidence with declared hash, MIME type, and length before deterministic category `DesignIR` is stored. Full execution and DesignIR detail are on-demand resources, not default tool input. Prototype and implementation PNGs are read from `DESIGN_MCP_CAPTURE_ROOT`, validated from bytes, stored as immutable content-addressed SQLite blobs, rendered deterministically for review, and inspected through MCP image sampling. Both stages require a manifest path, verified server-owned Penpot journal ID, and exact selected named frame. Caller-written scores, hashes, dimensions, and review prose are not accepted.

Connected Codex host is vision provider. Server sends deterministic review rendition and rubric-only prompt through MCP sampling; selected-direction prose never enters sampling instructions. If host cannot inspect image, rejects sampling, returns malformed output, or supplies no pixel-grounded perception evidence, review status is `incomplete`; no axes or score are invented and approval remains blocked. Host returns eight pixel-grounded axes and at most three failed-axis findings. Server orders blocker/major findings before minor polish and assigns contiguous ranks.

Set `DESIGN_MCP_LEGACY_TOOLS=1` only for one transition release to expose exact old eight tools. Default and legacy surfaces never mix.

Intended workflow uses Penpot exports for stage captures and a fixed-viewport browser screenshot for code capture. Server reads `DESIGN_MCP_HOME/penpot-journal.json`; caller has no default manifest-signing secret. Verified journal and export manifest bind stored review sheet to transaction, capability/revisions, session, stage, DesignIR, root PNG, and selected frame. Code completion crops that exact frame, requires matching browser artifact/frame IDs and viewport, and runs strict global/local plus exhaustive file-backed semantic parity. Server still records `originAttestation: unverified`: manifest integrity and pixel fidelity do not independently prove external application identity or aesthetic excellence.

## Run

```powershell
$env:DESIGN_MCP_CAPTURE_ROOT = 'C:\absolute\capture-root'
npm install
npm run typecheck
npm test
npm run build:runtime
npm run package:smoke
npm run benchmark:verify
npm run dev
```

V2 storage defaults to `.design-mcp/design-mcp-v2.sqlite`. Historical V1 data is separate and never pruned during startup.

## Author a Penpot stage

`design-mcp author-stage` is packaged with server. It accepts one JSON request, verifies exact `DesignIR` plus byte-backed assets under capture root, then uses official Penpot MCP `execute_code` and `export_shape` boundaries. Normal stage costs at most three backend calls: snapshot, one atomic apply, one root export. Result is root PNG, `penpot-export-manifest/v1`, and durable verified journal entry used by `design_stage_submit`.

```powershell
$env:DESIGN_MCP_HOME = 'C:\absolute\design-mcp-home'
$env:DESIGN_MCP_CAPTURE_ROOT = 'C:\absolute\capture-root'
$env:PENPOT_MCP_URL = 'http://127.0.0.1:4401'

# Request carries captureRoot, sessionId, stage, DesignIR, exact expected capability,
# and capture-root-relative exportPngPath/manifestPath.
design-mcp author-stage C:\absolute\capture-root\author-stage.json
```

Authoring fails closed on missing endpoint, capability drift, unsupported IR, path/symlink escape, asset mismatch, timeout, ambiguous mutation, or export mismatch. Current automated proof uses deterministic mocked official transports. Live Penpot stack execution remains unverified; see `docs/PENPOT_AUTHORING_ARCHITECTURE.md`.

## Generate standalone code

`design-mcp generate-code` does not add an MCP tool. It reads immutable DesignIR, selected-inventory quality, and verified evidence blobs from V2 SQLite, then requires an exact expected `code-manifest/v2` JSON file under `DESIGN_MCP_CAPTURE_ROOT`. Hash, MIME, byte length, root containment, and symlink checks fail closed. Output is created atomically under `DESIGN_MCP_CODE_ROOT`; existing output is never changed.

```powershell
$env:DESIGN_MCP_HOME = 'C:\absolute\design-mcp-home'
$env:DESIGN_MCP_CAPTURE_ROOT = 'C:\absolute\capture-root'
$env:DESIGN_MCP_CODE_ROOT = 'C:\absolute\generated-code'

# Save expected-code-manifest resource as expected-code-manifest.json under capture root.
@{
  sessionId = 'session-id'
  codeManifestPath = 'expected-code-manifest.json'
  outputDirectory = 'product-ui'
} | ConvertTo-Json | Set-Content "$env:DESIGN_MCP_CAPTURE_ROOT\generate-code.json"

design-mcp generate-code generate-code.json
cd "$env:DESIGN_MCP_CODE_ROOT\product-ui"
npm install
npm run build
npm run smoke
```

Generated package pins `typescript@7.0.2`. Asset files are exact verified immutable bytes under `assets`; runtime uses only those local paths, never inventory `asset.source` URLs. Generated manifest binds every source and binary file by path, SHA-256, MIME type, and byte length.