{ "_meta": { "description": "D6 fixtures for spring-ai / mcp-apps", "sourceFile": "d5-all.json", "copiedFrom": "langgraph-python", "created": "2026-05-21", "_shape_note": "Follow-up legs are keyed on the emitted toolCallId and MUST come before their emit fixtures (first-match-wins) — loop safety comes solely from that ordering. Deliberately NO turnIndex/hasToolResult gates: spring-ai's MessageListFilter reshapes prior-turn messages, making assistant counts and whole-thread tool-result checks unreliable (see tool-rendering-custom-catchall.json).", "updated": "2026-06-11" }, "fixtures": [ { "_comment": "D5 mcp-apps suggestion pill #2 (\"Sketch a system diagram\") — follow-up after create_view ran. Keyed on the emitted toolCallId so it fires on the post-tool leg regardless of thread history (the old hasToolResult:true gate is a whole-thread check that breaks in multi-pill sessions). MUST come before the emit fixture below so iteration 2 of the loop hits this branch instead of re-emitting.", "match": { "userMessage": "Open Excalidraw and sketch a system diagram", "toolCallId": "call_d5_mcp_apps_create_view_sysdiag_001", "context": "spring-ai" }, "response": { "content": "Sketched a three-box system diagram (Client → Server → Database). Tap the iframe to open it in Excalidraw." } }, { "_comment": "D5 mcp-apps scripted probe / suggestion pill #2 (\"Sketch a system diagram\") — emit leg. The probe (d5-mcp-apps.ts buildTurns) sends the verbatim pill message \"Open Excalidraw and sketch a system diagram with a client, server, and database.\" and asserts the MCP iframe mounts — which only happens after a real create_view tool call. Loop-safe via ordering: the toolCallId-gated follow-up above matches the post-tool leg first.", "match": { "userMessage": "Open Excalidraw and sketch a system diagram", "toolName": "create_view", "context": "spring-ai" }, "response": { "content": "Sketching a client–server–database system diagram in Excalidraw.", "toolCalls": [ { "id": "call_d5_mcp_apps_create_view_sysdiag_001", "name": "create_view", "arguments": "{\"elements\":[{\"id\":\"title\",\"type\":\"text\",\"x\":300,\"y\":40,\"text\":\"System Diagram\",\"fontSize\":24},{\"id\":\"client\",\"type\":\"rectangle\",\"x\":80,\"y\":160,\"width\":160,\"height\":70,\"label\":{\"text\":\"Client\",\"fontSize\":18}},{\"id\":\"server\",\"type\":\"rectangle\",\"x\":320,\"y\":160,\"width\":160,\"height\":70,\"label\":{\"text\":\"Server\",\"fontSize\":18}},{\"id\":\"database\",\"type\":\"rectangle\",\"x\":560,\"y\":160,\"width\":160,\"height\":70,\"label\":{\"text\":\"Database\",\"fontSize\":18}},{\"id\":\"a1\",\"type\":\"arrow\",\"x\":240,\"y\":195,\"endX\":320,\"endY\":195},{\"id\":\"a2\",\"type\":\"arrow\",\"x\":480,\"y\":195,\"endX\":560,\"endY\":195},{\"id\":\"camera\",\"type\":\"cameraUpdate\",\"x\":40,\"y\":0,\"width\":800,\"height\":600}]}" } ] } }, { "_comment": "D5 mcp-apps suggestion pill #1 (\"Draw a flowchart\") — follow-up after create_view ran. Keyed on the emitted toolCallId and ordered BEFORE the emit fixture below: the post-tool leg still carries the same last-user text with create_view still listed, so without this ordering the emit fixture re-matched and re-emitted the same toolCallId until the iteration cap, leaving this narration unreachable.", "match": { "userMessage": "draw a simple flowchart", "toolCallId": "call_d5_mcp_apps_create_view_flowchart_001", "context": "spring-ai" }, "response": { "content": "Drew a three-step flowchart (Start → Process → End). Tap the iframe to open it in Excalidraw." } }, { "_comment": "D5 mcp-apps suggestion pill #1 (\"Draw a flowchart\") — emit leg. Sends the verbatim suggestion message \"Use Excalidraw to draw a simple flowchart with three steps.\" The distinctive substring \"draw a simple flowchart\" prevents collision with feature-parity.json's generic `{userMessage: \"steps\"}` fixture, which would otherwise absorb the prompt and return a tool-call-free planning blurb (breaking the iframe). Emits `create_view` with three-step flowchart elements so the MCP middleware fetches the Excalidraw UI resource and mounts the iframe. Loop-safe via ordering: the toolCallId-gated follow-up above matches the post-tool leg first.", "match": { "userMessage": "draw a simple flowchart", "toolName": "create_view", "context": "spring-ai" }, "response": { "reasoning": "The user wants a simple three-step flowchart. I'll call create_view once with three labelled rectangles connected by arrows and a title, framed by a cameraUpdate.", "content": "Drawing a simple three-step flowchart in Excalidraw.", "toolCalls": [ { "id": "call_d5_mcp_apps_create_view_flowchart_001", "name": "create_view", "arguments": "{\"elements\":[{\"id\":\"title\",\"type\":\"text\",\"x\":300,\"y\":40,\"text\":\"Flowchart\",\"fontSize\":24},{\"id\":\"step1\",\"type\":\"rectangle\",\"x\":80,\"y\":160,\"width\":160,\"height\":70,\"label\":{\"text\":\"Start\",\"fontSize\":18}},{\"id\":\"step2\",\"type\":\"rectangle\",\"x\":320,\"y\":160,\"width\":160,\"height\":70,\"label\":{\"text\":\"Process\",\"fontSize\":18}},{\"id\":\"step3\",\"type\":\"rectangle\",\"x\":560,\"y\":160,\"width\":160,\"height\":70,\"label\":{\"text\":\"End\",\"fontSize\":18}},{\"id\":\"a1\",\"type\":\"arrow\",\"x\":240,\"y\":195,\"endX\":320,\"endY\":195},{\"id\":\"a2\",\"type\":\"arrow\",\"x\":480,\"y\":195,\"endX\":560,\"endY\":195},{\"id\":\"camera\",\"type\":\"cameraUpdate\",\"x\":40,\"y\":0,\"width\":800,\"height\":600}]}" } ] } }, { "_comment": "Content-only fallback for the generic \"Use Excalidraw to sketch\" prompt. No turnIndex gate (spring-ai assistant counts are unreliable — see _shape_note); comes last so the tool-emitting fixtures above win for the pill prompts.", "match": { "userMessage": "Use Excalidraw to sketch", "context": "spring-ai" }, "response": { "content": "Sketched a simple system diagram for you above — three boxes (frontend, runtime, agent) connected by arrows showing the request flow. Ask if you'd like a different shape or more detail." } } ] }