Skip to content

feat: mirror mode for MCP result-artifact rules#228

Merged
roackb2 merged 2 commits into
mainfrom
feat/mcp-result-artifact-mirror
Jul 9, 2026
Merged

feat: mirror mode for MCP result-artifact rules#228
roackb2 merged 2 commits into
mainfrom
feat/mcp-result-artifact-mirror

Conversation

@roackb2

@roackb2 roackb2 commented Jul 9, 2026

Copy link
Copy Markdown
Owner

Why

Result-artifact capture normally replaces captured values with compact references. That is appropriate for context compaction, but it breaks stateless MCP servers where each tool call must receive the full document returned by the previous call.

Without a non-replacing capture mode, hosts must disable result artifacts and manually inspect raw tool-result JSON to recover the final document.

What

A manual result-artifact rule can now declare mode: 'mirror':

resultArtifacts: [{
  toolName: 'create-deck',
  path: 'structuredContent.result.source',
  mode: 'mirror',
  kind: 'source',
  setCurrent: true,
}]

Mirror mode:

  • persists the artifact with the normal metadata and setCurrent behavior;
  • leaves the declared value inline for downstream stateless tool calls;
  • ignores replacePaths, because no result path is replaced;
  • lets the host read the latest result through engine.artifacts.current(sessionId);
  • takes precedence over a combined auto-capture pass: the mirrored path and its descendants are excluded from auto replacement.

The default 'replace' behavior is unchanged.

Safety

This captures tool results; it does not expose model-generated private output. The host still decides which artifact content becomes user-visible.

Verification

  • Focused MCP host-extension tests: 14 passed
  • Unit: 603 passed
  • Integration: 285 passed
  • yarn lint
  • yarn build

roackb2 and others added 2 commits July 9, 2026 17:42
Replacement compaction breaks hosts whose MCP server is stateless — each tool
call takes the current document as input and returns the updated one, so the
model must keep the full value inline for the next call. Those hosts had to
disable resultArtifacts and hand-extract the outcome from raw tool results.

A manual rule can now set `mode: 'mirror'`: the artifact is persisted exactly
as before (including setCurrent), but the value stays inline and untouched.
The host then reads the turn's outcome via engine.artifacts.current(...)
instead of spelunking tool-result JSON. `replacePaths` is ignored in mirror
mode; default behavior ('replace') is unchanged.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CjFdZgZhov8wdwFinVTfjz
@roackb2 roackb2 merged commit f86075c into main Jul 9, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant