Files

92 lines
4.4 KiB
Markdown

# Workflow Artifacts as MCP Apps
OpenWork exposes Workflow results as portable, standards-based
MCP Apps. A supporting MCP host can render an artifact inline; every other MCP
client still receives a useful Markdown result.
## Product flow
1. Code Mode produces data and a deterministic Markdown rendering.
2. The result can be saved as an immutable Workflow snapshot with a receipt,
schema validation, result digest, and exact Workflow version.
3. A person or an Automation may run the Workflow again. Automations only
refresh the data snapshot; they do not create or execute UI code.
4. The read-only `render_workflow_artifact` tool loads the latest successful
snapshot, or an exact receipt when requested.
`render_dynamic_artifact` remains as a deprecated alias for one release.
5. MCP Apps hosts resolve the linked `ui://` resource and inject the tool's
structured result. Other hosts show the Markdown fallback.
This keeps execution, scheduling, data, and presentation separate:
```text
Workflow ──run──> immutable snapshot ──read──> MCP tool result
▲ ▲ ├─ Markdown fallback
│ │ └─ ui:// MCP App
explicit run Automation refresh
```
The MCP App never runs a Workflow, mutates an artifact, or introduces another
scheduler. It only presents an already-authorized snapshot.
## MCP Apps conformance
The agent MCP server implements the `io.modelcontextprotocol/ui` extension and
the `2026-01-26` MCP Apps protocol:
- server capability: `extensions.io.modelcontextprotocol/ui.mimeTypes`
contains `text/html;profile=mcp-app`;
- tool metadata: `_meta.ui.resourceUri` points to
`ui://openwork/workflow-artifact/v1/view.html` (with the compatibility metadata
emitted by the official MCP Apps server helpers);
- resource delivery: `resources/read` returns one self-contained HTML5 document
with MIME type `text/html;profile=mcp-app`;
- view lifecycle: the document performs `ui/initialize`, sends
`ui/notifications/initialized`, receives tool input/result/cancellation and
host-context notifications, reports size changes, and acknowledges teardown;
- data delivery: the tool returns versioned `structuredContent`, lightweight
lineage in result `_meta`, and a complete text fallback;
- security: the resource declares an empty network/frame/base-URI CSP, loads no
external code, performs no network requests, and inserts artifact values with
DOM text APIs rather than HTML interpolation.
The shared payload schema lives in `@openwork/types/workflows` so a host
can validate the data contract independently of this presentation resource.
## UI behavior
The self-contained view is intentionally data-first and framework-neutral. It
adapts the Preview tab to common result shapes:
- arrays of records become a bounded table;
- flat objects become metric cards;
- nested or irregular values fall back to formatted JSON;
- Data always exposes the full structured result, with a rendering-size guard;
- Lineage shows the immutable receipt, Workflow/version IDs, source, digest,
renderer, and Automation run when present.
The view follows host theme/style context, uses responsive HTML, and caps large
tables and rendered JSON without changing the underlying tool result.
## Authorization and failure behavior
The renderer uses the same organization membership, team grants, and saved
Workflow authorization path as the existing artifact APIs. It does not accept a
plugin or result payload from the caller. The caller supplies only a saved
Workflow ID, an optional exact receipt, and an optional freshness threshold.
Only readable, successful, non-deleted snapshots can be rendered. Missing,
failed, deleted, or unauthorized results fail closed with a non-sensitive text
error. A stale snapshot remains renderable and is labeled stale; a failed
refresh leaves the last successful artifact available with a needs-attention
state.
## Next interoperable slice
The provider side is deliberately usable without an OpenWork-specific host.
The next slice is a generic MCP Apps host in the desktop conversation surface:
negotiate the UI extension with upstream MCP servers, preserve tool/resource
metadata and structured results through the runtime, sandbox `ui://` resources,
and bridge the standard JSON-RPC lifecycle. That host should consume the same
standard contract rather than adding a custom React artifact format.