Tool Result
What a tool actually returned, rendered by content type. An MCP result is a list of blocks that can mix text, images and embedded resources — JSON.stringify turns a returned screenshot into four thousand characters of base64.
src/components/ui/tool-result.tsxAbout
From the component's own source, where it was written.
What a tool actually returned, rendered by content type.
ToolCall shows the invocation. This shows the payload coming back, which is where MCP gets awkward: a single result is a *list* of content blocks, and they can mix — text, an image, an embedded resource — in one response. Rendering JSON.stringify(result) is the usual shortcut and it turns a returned screenshot into four thousand characters of base64.
So each block is rendered as what it is, and only text and JSON are copyable, because those are the ones anyone wants on the clipboard.
**isError is part of the payload, not the transport.** An MCP tool reports failure with a normal, successful response carrying isError: true — so a UI that only styles transport errors shows a failed tool call as a success. This takes the flag explicitly.
Install
npx astralyx-ui add tool-result
Usage
import { ToolResult } from '@/components/ui/tool-result'
<ToolResult tool="search_docs" content={result.content} isError={result.isError} durationMs={120} />Composer
Change the props and the source below follows.
search_docs120msFound 3 matching documents in the help centre.
{
"hits": [
{
"id": "doc_18",
"score": 0.94,
"title": "Refund policy"
},
{
"id": "doc_41",
"score": 0.71,
"title": "Chargebacks"
}
]
}file:///docs/refunds.md
# Refund policy Refunds are issued to the original payment method within 5 working days.
<ToolResult
tool="search_docs"
content={result.content}
isError={false}
durationMs={120}
/>Examples
Mixed content blocks
<ToolResult tool="search_docs" content={result.content} />API
Generated from the source, so it cannot fall behind the code. One table per exported component, then hooks, functions and types.
ToolResult
Extends Omit<ComponentProps<'div'>, 'content'>.
| Prop | Type | Default | Description |
|---|---|---|---|
| content | ToolContent[] | required | Blocks of { type: 'text' | 'json' | 'image' | 'resource' }. Each is rendered as what it is — an image is a picture, not base64. |
| isError | boolean | false | Part of the payload, not the transport: MCP reports tool failure with a successful response carrying isError. A UI that only styles transport errors shows a failed call as a success. |
| tool | string | — | Tool name, shown in the header. |
| durationMs | number | — | — |
| maxBlocks | number | 3 | Collapses the rest behind a disclosure. |
| errorLabel | string | 'Tool reported an error' | — |
| emptyLabel | string | 'Returned nothing.' | — |
| moreLabel | (hidden: number) => string | (hidden) => `Show ${hidden} more block${hidden === 1 ? '' : 's'}` | — |
| copyLabel | string | 'Copy' | — |
Types
| Type | Definition | Description |
|---|---|---|
ToolContent | | { type: 'text'; text: string }
| { type: 'json'; value: unknown }
| { type: 'image'; data: string; mimeType?: string; alt?: string }
| { type: 'resource'; uri: string; mimeType?: string; text?: string } | What a tool actually returned, rendered by content type. |
Behaviour
| Topic | Detail | Description |
|---|---|---|
| copying | text and JSON only | Those are the blocks anyone wants on the clipboard. |