Architecture & mockups
Pulse exposes 17 of its 216 MCP tools for visual design artifacts:
- 12 architecture-design tools (
server.py:6824–7503) — structured system designs with entities, interfaces, and diagrams (Excalidraw, Mermaid, draw.io, SVG, PNG).
- 5 screen-mockup tools (
server.py:9436–9710) — HTML+Tailwind page mockups, modals, drawers, popovers, and panels.
Both artifact types attach to any pipeline entity — ideation, refinement, spec, or card — and both have a dedicated copy tool that takes a deep-copy snapshot from a spec onto a card so an implementer’s context is self-contained.
Source-of-truth citations: okto-pulse-feature-inventory.md:378–410 and :429–445.
When to use which
| Artifact | Captures | Authoring tools |
|---|
| Architecture Design | Services, modules, databases, queues, events, runtime boundaries, API contracts, data flows | Schema-validated payload (entities + interfaces + diagrams), with optional Excalidraw imports. |
| Screen mockup | A single page, modal, drawer, popover, or panel rendered as sanitized HTML+Tailwind. | Free-form HTML; supports text annotations from reviewers. |
Use architecture designs to encode runtime topology and ownership boundaries that downstream cards must respect. Use screen mockups for visual UI references the implementer renders against. They are independent — one spec can have both.
Architecture designs
Authoring loop
The architecture model is critiqued by the server before it accepts a write. Skip the validation step and you get rejected with contextual paths like entities[0].name or diagrams[0].adapter_payload.elements[2].linkedEntityId — fix the cited field and retry.
The recommended loop for non-trivial payloads:
Fetch the schema once per session
okto_pulse_get_architecture_design_schema returns allowed enums, entity/interface contracts, Excalidraw adapter rules, bad and good examples, and a complete minimal payload.Input:
board_id: "brd_abc123"
Output (truncated):
{
"success": true,
"schema": {
"entity_types": ["web_app", "mobile_app", "api", "service", "database",
"queue", "topic", "external_system", ...],
"interface_directions": ["source_to_target", "target_to_source",
"bidirectional", "none"],
"connection_types": ["direct", "elbow"],
...
}
}
Dry-run critique
okto_pulse_validate_architecture_design_payload (server.py:6933) runs the same critique the create/update path runs but persists nothing. It returns:
valid — whether the payload would be rejected
issues — blocking errors with JSON paths
warnings — non-blocking gaps that hurt downstream clarity
suggested_fixes — concrete corrections for common mistakes
summary — counts of entities, interfaces, diagrams, elements, links
Pass parent_type + parent_id for create-mode validation. Pass design_id (and only the fields you intend to change) for update-mode — omitted fields are merged from the existing design before critique.Persist after `valid: true`
Call okto_pulse_add_architecture_design (server.py:7049) or okto_pulse_update_architecture_design (server.py:7207) with the same payload. Warnings are not blockers, but each one usually marks a detail a downstream implementer or validator would otherwise have to guess.
Specs are locked once validation passes. Attempting to add or update an architecture design on a spec whose current validation outcome == "success" returns "Spec is locked because validation passed. Move it back to draft or approved to edit architecture." Move the spec back to draft or approved first.
| Tool | Line | Purpose |
|---|
okto_pulse_get_architecture_design_schema | 6905 | Returns the JSON schema, examples, and enums. Call once per session. |
okto_pulse_validate_architecture_design_payload | 6933 | Dry-run critique. Returns valid, issues, warnings, suggested_fixes, summary. Persists nothing. |
okto_pulse_list_architecture_designs | 6824 | List designs for an ideation / refinement / spec / card. Pass include_payloads="true" to embed diagram bytes (heavier, requires render permission). |
okto_pulse_get_architecture_design | 6870 | Get one design by ID. include_payloads honored as above. |
okto_pulse_add_architecture_design | 7049 | Create a design with title, global_description, and any of entities / interfaces / diagrams (JSON arrays or native lists). |
okto_pulse_update_architecture_design | 7207 | Partial update. Omitted fields are left unchanged. change_summary is recorded on the new version. |
okto_pulse_delete_architecture_design | 7298 | Hard delete. |
okto_pulse_import_excalidraw_architecture_diagram | 7329 | Import an Excalidraw JSON scene. Pass replace_diagram_id to overwrite an existing diagram, or omit to append. |
okto_pulse_dump_architecture_diagram | 7408 | Load a diagram payload through its adapter and return the raw payload plus an adapter-formatted dump string. |
okto_pulse_copy_architecture_to_card | 7460 | Deep-copy snapshot from spec → card. Empty design_ids copies all. |
okto_pulse_archive_tree | 6733 | Cascading soft-delete of an entity and its descendants. |
okto_pulse_restore_tree | 6777 | Reverse of archive_tree. |
Payload anatomy
okto_pulse_add_architecture_design accepts three structured arrays.
entities — runtime boundaries
Categorical entity_type plus a concrete name. The API rejects payloads where name duplicates entity_type after normalization (e.g. name="API", entity_type="api") because ownership and task boundaries become ambiguous.
[
{
"id": "entity-web-app",
"name": "Customer Portal",
"entity_type": "web_app",
"responsibility": "Collects checkout input and displays order status.",
"technologies": ["React", "Vite"]
},
{
"id": "entity-checkout-api",
"name": "Checkout API",
"entity_type": "api",
"responsibility": "Validates checkout commands and orchestrates payment authorization.",
"technologies": ["FastAPI", "SQLAlchemy"]
},
{
"id": "entity-orders-db",
"name": "Orders DB",
"entity_type": "database",
"responsibility": "Persists orders, payment state, and idempotency keys.",
"technologies": ["PostgreSQL"]
}
]
interfaces — contracts on the wire
endpoint is optional but recommended (API path, RPC method, event name, queue name). direction must be one of source_to_target, target_to_source, bidirectional, none.
Interfaces do not own source/target — diagram connections do, via sourceElementId / targetElementId.
[
{
"id": "interface-create-order",
"name": "Create order",
"endpoint": "POST /orders",
"description": "Customer Portal sends a checkout request to Checkout API.",
"direction": "source_to_target",
"protocol": "REST",
"contract_type": "OpenAPI",
"request_schema": {"type": "object", "required": ["cart_id"]},
"response_schema": {"type": "object", "required": ["order_id"]}
}
]
diagrams — visualization
Excalidraw is first-class. Edges link to interfaces via linkedInterfaceIds (one connector can carry several contracts). connectionType accepts only "direct" and "elbow" — "curved" is rejected.
[
{
"id": "diagram-runtime-context",
"title": "Runtime context",
"diagram_type": "context",
"format": "excalidraw_json",
"adapter_payload": {
"type": "excalidraw",
"version": 2,
"elements": [],
"appState": {},
"files": {}
}
}
]
Excalidraw round-trip
Authoring agents can ship a complete Excalidraw scene without touching the structured arrays first.
Input to okto_pulse_import_excalidraw_architecture_diagram:
board_id: "brd_abc123"
design_id: "ad_7f3a"
title: "Runtime context (v2)"
payload_json: { "type": "excalidraw", "elements": [...], "appState": {...} }
diagram_type: "context"
Output:
{
"success": true,
"architecture_design": {
"id": "ad_7f3a",
"version": 4,
"diagrams": [
{ "id": "dg_91", "title": "Runtime context (v2)",
"format": "excalidraw_json", "diagram_type": "context", ... }
],
...
}
}
To export, pair okto_pulse_dump_architecture_diagram with the diagram ID — it loads the payload through its adapter and returns both the raw payload and an adapter-formatted dump string.
Screen mockups
| Tool | Line | Purpose |
|---|
okto_pulse_add_screen_mockup | 9436 | Add a screen to any entity. screen_type ∈ page / modal / drawer / popover / panel. Script tags and on* event attributes are stripped before persistence. |
okto_pulse_update_screen_mockup | 9502 | Partial update — empty strings mean “no change”. |
okto_pulse_annotate_mockup | 9561 | Append a reviewer annotation (text + author_id) to an existing screen. |
okto_pulse_list_screen_mockups | 9620 | Paginated list. screen_type filter optional; limit capped at 200. |
okto_pulse_delete_screen_mockup | 9667 | Remove one mockup. |
entity_type is universal
All five screen-mockup tools accept entity_type ∈ spec / ideation / refinement / card (default spec). The same shape works whether you are sketching a page during ideation discovery, locking it on a spec, or attaching the final reference to an implementation card.
Authoring example
Input to okto_pulse_add_screen_mockup:
board_id: "brd_abc123"
entity_id: "spec_XYZ"
entity_type: "spec"
title: "Checkout — payment step"
screen_type: "page"
description: "Shown after cart review when the user clicks Pay."
html_content: "<div class='p-6 max-w-md mx-auto bg-white rounded-xl shadow'>...</div>"
Output:
{
"success": true,
"entity_type": "spec",
"screen": {
"id": "sm_a1b2c3d4",
"title": "Checkout — payment step",
"description": "Shown after cart review when the user clicks Pay.",
"screen_type": "page",
"html_content": "<div class=\"p-6 max-w-md mx-auto bg-white rounded-xl shadow\">...</div>",
"annotations": [],
"order": 0
}
}
The HTML sanitizer drops <script> blocks and any on* event attribute (onclick, onload, etc.). Style classes, inline style attributes, and Tailwind utilities pass through untouched.
Annotations
Reviewers add design notes without editing the HTML. Each annotation gets a stable id and records the author_id.
Input to okto_pulse_annotate_mockup:
board_id: "brd_abc123"
entity_id: "spec_XYZ"
screen_id: "sm_a1b2c3d4"
text: "Show the saved-card option above the new-card form by default."
Output:
{
"success": true,
"annotation": {
"id": "an_e5f6g7h8",
"text": "Show the saved-card option above the new-card form by default.",
"author_id": "agent_ux_lead"
}
}
Spec → card propagation
When a sprint slices a spec into implementation cards, attach the relevant architecture and mockup context to each card so the implementer’s view is self-contained. Two tools snapshot from the spec onto the card.
| Tool | Line | What it copies |
|---|
okto_pulse_copy_architecture_to_card | 7460 | Architecture designs as deep-copy snapshots (preserves provenance to the source spec). Empty design_ids copies all. |
okto_pulse_copy_mockups_to_card | 7504 | Screen mockups onto card.screen_mockups. Empty screen_ids copies all. Existing mockups on the card are preserved (by ID). |
Both tools accept multi-value IDs as a native list (["scr_a", "scr_b"]), a JSON string, or pipe-separated. Comma-only input is rejected — see okto_pulse.core.mcp.helpers.coerce_to_list_str (okto-pulse-feature-inventory.md:395).
Input to okto_pulse_copy_mockups_to_card:
board_id: "brd_abc123"
spec_id: "spec_XYZ"
card_id: "card_001"
screen_ids: ["sm_a1b2c3d4"]
Output:
{
"success": true,
"copied": 1,
"total_on_card": 1
}
This is the mandatory card-level attachment pattern — agents reading okto_pulse_get_task_context see the architecture and mockups inline rather than chasing pointers back to the spec.
Permissions
All architecture and mockup tools resolve through the granular permission registry (server.py:_mcp_check_architecture_permission and Permissions.SPECS_UPDATE). The actions checked per call:
| Tool family | Permission action |
|---|
list / get (without payloads) | read on parent type |
list / get (with include_payloads=true) | render on parent type |
add / update / import | create / edit on parent type |
delete | delete on parent type |
copy_*_to_card | dedicated architecture_copy permission |
| Screen mockups (all writes) | Permissions.SPECS_UPDATE |
A blocked call returns {"error": "FORBIDDEN", "message": "...", ...} — flip the agent’s permission preset in Board → Agents → Edit.
See Permissions for the preset reference.
Errors
Architecture and mockup writes return the standard MCP error envelope:
{
"error": "VALIDATION_ERROR",
"message": "entities[0].name duplicates entity_type after normalization.",
"detail": {"path": "entities[0].name", "value": "api"}
}
Common codes for this domain:
| Code | Meaning | Most common cause |
|---|
VALIDATION_ERROR | Payload rejected by critique | Skipped the dry-run; check entities[*].name, interfaces[*].direction, diagrams[*].adapter_payload.elements[*]. |
CONFLICT | Spec is locked | Validation outcome=success — move spec back to draft or approved. |
NOT_FOUND | Wrong board | Design or screen exists on a different board. |
FORBIDDEN | Permission preset doesn’t allow this action | See permission table above. |
Next steps
MCP reference index
All 216 tools across 8 domains.
ADLC pipeline
Where architecture and mockups attach in the ideation → spec → card flow.