fix(mcp): fix three correctness issues from Codex review

parsers.ts: the early-return guard for empty content was firing before the
synthetic UIResource block, so tools returning only structuredContent (no
content items) never produced an app resource. Now the guard skips the early
return when a synthetic app is expected. Also, the synthetic block was not
appending the \ui{resourceId} marker to the text, leaving the LLM without an
ID to place; fixed by mirroring the marker lines that the non-synthetic
resource handler already emits.

ToolCall / MCPUIResource: "Loading interactive view..." was a hardcoded
string; replaced with com_ui_loading_interactive_view from the localization
layer in both components, per project convention.
This commit is contained in:
Dustin Healy 2026-06-23 16:39:58 -07:00
parent c3b002cf18
commit b1fa8221ef
4 changed files with 10 additions and 3 deletions

View file

@ -29,6 +29,7 @@ const MCPAppView = React.memo(function MCPAppView({
app: UIResource;
args: string | Record<string, unknown>;
}) {
const localize = useLocalize();
const iframeRef = useRef<HTMLIFrameElement>(null);
const [height, setHeight] = useState<number | undefined>(undefined);
const [loaded, setLoaded] = useState(false);
@ -82,7 +83,7 @@ const MCPAppView = React.memo(function MCPAppView({
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"
/>
</svg>
Loading interactive view...
{localize('com_ui_loading_interactive_view')}
</div>
)}
<iframe

View file

@ -57,7 +57,7 @@ export function MCPUIResource(props: MCPUIResourceProps) {
<span className="mx-1 inline-block w-full align-middle">
{!loaded && (
<div className="flex items-center gap-2 rounded-lg border border-border-light bg-surface-secondary px-4 py-3 text-sm text-text-secondary">
Loading interactive view...
{localize('com_ui_loading_interactive_view')}
</div>
)}
<iframe

View file

@ -1199,6 +1199,7 @@
"com_ui_live": "live",
"com_ui_load_more": "Load more",
"com_ui_loading": "Loading...",
"com_ui_loading_interactive_view": "Loading interactive view...",
"com_ui_locked": "Locked",
"com_ui_logo": "{{0}} Logo",
"com_ui_low": "Low",

View file

@ -154,7 +154,9 @@ export function formatToolContent(
}
const content = result?.content ?? [];
if (!content.length) {
const hasSyntheticApp =
metadata?.resourceUri != null && metadata.serverName != null && metadata.toolName != null;
if (!content.length && !hasSyntheticApp) {
return ['(No response)', undefined];
}
@ -253,6 +255,9 @@ export function formatToolContent(
csp: metadata.csp,
permissions: metadata.permissions,
});
currentTextBlock +=
(currentTextBlock ? '\n\n' : '') +
`UI Resource ID: ${resourceId}\nUI Resource Marker: \\ui{${resourceId}}`;
}
if (uiResources.length > 0) {