Two undocumented bugs in MCP Apps I found building a task panel for Claude
I spent a week building Wingman , an open source MCP server that renders a persistent task panel inline in Claude conversations using MCP Apps (SEP-1865). The spec is solid. The SDK is solid. But I hit two bugs that cost me most of a weekend each, and neither is documented anywhere I could find. Writing them up here in case they save someone else the time. Bug 1: resourceUri has two valid-looking locations, and only one works MCP Apps needs a way to tell the host "render this resource as a UI for this tool call." That pointer lives in _meta.ui.resourceUri . The question is: meta on what? I started with a parameterized resource template, ui://wingman/panel/{plan_name} , registered per plan. That was my first mistake. Parameterized templates get listed under resources/templates/list , not resources/list , and hosts do not prefetch or render anything from the templates list. The fix was straightforward once I found it: register one static resource, ui://wingman/panel , and pass the actual plan data through structuredContent on the tool result instead of baking it into the URI. That fix surfaced the real bug. My show_plan tool was returning a plain Python dict: return { " plan " : plan_data , " _meta " : { " ui " : { " resourceUri " : " ui://wingman/panel " }} } This looks correct. It is not. FastMCP's result conversion takes a returned dict and serializes the whole thing into structuredContent , verbatim, including any _meta key the dict happens to carry. So the actual wire result looked like this: result . structuredContent [ " _meta " ][ " ui " ][ " resourceUri " ] # == "ui://wingman/panel", but wrong place result . meta # None — this is what the host actually reads MCP Apps hosts read resourceUri off the top-level _meta on the CallToolResult , not off whatever ended up inside structuredContent . With that pointer effectively missing, the host had nowhere to bind the iframe. The visible symptom was strange: actions in the UI would update on screen but nothing persist