patch_artifact
Modify an existing HTML artifact using JSON Patch operations, with delivery options for static HTML, MCP app, or resource references.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| input | Yes |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
| artifact_id | Yes | ||
| delivery | Yes | ||
| title | Yes | ||
| html | No | ||
| resource_uri | No | ||
| byte_size | Yes | ||
| warnings | Yes | ||
| revision | Yes |
Implementation Reference
- src/web_gui_mcp/mcp_tools.py:90-117 (handler)The main handler for the patch_artifact tool. Retrieves the stored artifact by ID, applies JSON Patch operations (delta) to the spec, re-renders the artifact to HTML, replaces the stored artifact (incrementing revision), and returns the updated artifact output.
def patch_artifact_handler( input_data: PatchArtifactInput, store: MemoryArtifactStore, ) -> PatchArtifactOutput: stored = store.get(input_data.artifact_id) if stored is None: raise ValueError(f"Unknown artifact_id: {input_data.artifact_id}") original = stored.spec.model_dump(mode="json", by_alias=True) patched_payload = apply_json_patch(original, input_data.delta) patched_spec = ArtifactSpec.model_validate(patched_payload) options = RenderOptions( delivery=input_data.delivery, density=patched_spec.density, theme=patched_spec.theme, ) rendered = render_artifact_to_html(patched_spec, options) updated = store.replace(input_data.artifact_id, patched_spec, rendered.html) resource_uri = f"{RESOURCE_PREFIX}/{updated.artifact_id}" return PatchArtifactOutput( artifact_id=updated.artifact_id, delivery=input_data.delivery, title=patched_spec.title, html=rendered.html if input_data.delivery == "static_html" else None, resource_uri=resource_uri if input_data.delivery in {"mcp_app", "resource_only"} else None, byte_size=rendered.byte_size, warnings=rendered.warnings, revision=updated.revision, ) - Input schema (PatchArtifactInput) with artifact_id, delta (list of JsonPatchOp), and delivery mode. Output schema (PatchArtifactOutput) extending RenderArtifactOutput with an additional revision field.
class JsonPatchOp(ToolBaseModel): op: Literal["add", "replace", "remove"] path: str value: Any | None = None class PatchArtifactInput(ToolBaseModel): artifact_id: str delta: list[JsonPatchOp] delivery: DeliveryMode = "resource_only" class PatchArtifactOutput(RenderArtifactOutput): revision: int - src/web_gui_mcp/mcp_tools.py:184-186 (registration)Registration of the patch_artifact tool via @mcp.tool() decorator, wiring it to patch_artifact_handler with the store.
@mcp.tool() def patch_artifact(input: PatchArtifactInput) -> PatchArtifactOutput: return patch_artifact_handler(input, store) - The apply_json_patch utility that performs JSON Patch operations (add, replace, remove) on a document dict, used by patch_artifact_handler to apply delta patches.
def apply_json_patch(document: dict[str, Any], patch: list[Any]) -> dict[str, Any]: data = deepcopy(document) for op in patch: op_name = getattr(op, "op", None) or op.get("op") path = getattr(op, "path", None) or op.get("path") value = getattr(op, "value", None) if hasattr(op, "value") else op.get("value") if not isinstance(path, str) or not path.startswith("/"): raise JsonPatchError(f"Invalid JSON pointer path: {path!r}") parent, token = _resolve_parent(data, path) if op_name == "add": _add(parent, token, value) elif op_name == "replace": _replace(parent, token, value) elif op_name == "remove": _remove(parent, token) else: raise JsonPatchError(f"Unsupported patch operation: {op_name!r}") return data - The replace method on MemoryArtifactStore, called by patch_artifact_handler to save the patched artifact and automatically bump the revision.
def replace(self, artifact_id: str, spec: ArtifactSpec, html: str) -> StoredArtifact: if artifact_id not in self._artifacts: raise KeyError(f"Unknown artifact_id: {artifact_id}") return self.save(spec, html, artifact_id=artifact_id)