The ResourceViewer component provides intelligent display of file and resource content from MCP (Model Context Protocol) tools with syntax highlighting, fullscreen support, and adaptive rendering.
ResourceViewer automatically detects when MCP tools return file content references and fetches the actual content for display. It supports multiple rendering modes based on file type and provides a rich viewing experience with syntax highlighting powered by CodeMirror.
- ๐จ Syntax Highlighting - Powered by CodeMirror with support for JavaScript, HTML, CSS, JSON, Markdown, Python, XML, and more
- ๐ฑ Fullscreen Mode - Toggle fullscreen for better viewing of large files
- ๐ Smart Caching - Caches fetched content for 5 minutes to improve performance
- ๐ Retry Mechanism - Automatic retry functionality when resource fetching fails
- ๐ Metadata Display - Shows file type, content type, and source server information
- ๐ฏ Adaptive Rendering - Chooses optimal rendering mode based on file type and hints
ResourceViewer is automatically triggered when MCP tools return responses matching the FileViewerResult
schema:
// Example MCP tool response that triggers ResourceViewer
{
"output": {
"resourcePointer": {
"sourceKey": "path/to/file.js",
"contentType": "application/javascript",
"fileType": "javascript",
"renderHint": {
"preferredRenderer": "code",
"syntaxHighlight": true,
"lineNumbers": true
}
},
"sourceKey": "path/to/file.js",
"fileType": "javascript"
}
}
The main response type that triggers ResourceViewer:
type FileViewerResult =
| { output: FileViewerResponse }
| { error: string; output: null };
interface FileViewerResponse {
resourcePointer: ResourcePointer;
sourceKey: string;
fileType: ResourcePointer['fileType'];
}
interface ResourcePointer {
sourceKey: string; // Path/key to the resource
contentType: string; // MIME type (e.g., "application/javascript")
fileType: FileType; // Detected file type for syntax highlighting
renderHint: RenderHints; // Rendering preferences
}
interface RenderHints {
preferredRenderer: 'native' | 'code' | 'text';
syntaxHighlight: boolean;
lineNumbers: boolean;
}
javascript
- JavaScript files (.js, .jsx, .ts, .tsx)html
- HTML files (.html, .htm)css
- CSS files (.css, .scss, .sass)json
- JSON files (.json)markdown
- Markdown files (.md, .mdx)python
- Python files (.py)xml
- XML files (.xml, .svg)text
- Plain text filesunknown
- Fallback for unrecognized types
- Uses CodeMirror editor with syntax highlighting
- Supports line numbers when
lineNumbers: true
- Best for source code files
- Renders HTML/XML content in an iframe
- Provides native browser rendering
- Best for HTML documents and SVG files
- Plain text display with optional line numbers
- Best for configuration files and plain text
ResourceViewer automatically resolves the MCP server name by matching the tool_use_id
from mcp_tool_result
blocks with corresponding mcp_tool_use
blocks:
// In Message.tsx
const toolUseBlock = findToolUseBlock(blocks, blk.tool_use_id);
const serverName = toolUseBlock?.server_name;
Resources are fetched using the MCP client's readResource()
method:
const client = mcpClients.find(client =>
client.serverInfo?.name === serverName
);
const content = await client.readResource(sourceKey);
- Resources are cached in component state for 5 minutes
- Cache key format:
${serverName}_${sourceKey}
- Cache is cleared on retry to force fresh fetch
ResourceViewer provides comprehensive error handling:
- Parse Errors - Invalid FileViewerResult schema
- Server Not Found - MCP server unavailable
- Resource Not Found - Resource doesn't exist
- Network Errors - Connection issues
Error states show:
- Clear error message
- Retry button
- Expandable metadata for debugging
ResourceViewer uses CSS classes for styling:
.resource-viewer
- Main container.resource-viewer-header
- Header with metadata and controls.resource-viewer-content
- Content area.resource-viewer-error
- Error state styling.resource-viewer.fullscreen
- Fullscreen mode
{ "output": { "resourcePointer": { "sourceKey": "src/components/App.tsx", "contentType": "application/typescript", "fileType": "javascript", "renderHint": { "preferredRenderer": "code", "syntaxHighlight": true, "lineNumbers": true } }, "sourceKey": "src/components/App.tsx", "fileType": "javascript" } }
{ "output": { "resourcePointer": { "sourceKey": "public/index.html", "contentType": "text/html", "fileType": "html", "renderHint": { "preferredRenderer": "native", "syntaxHighlight": false, "lineNumbers": false } }, "sourceKey": "public/index.html", "fileType": "html" } }
{ "output": { "resourcePointer": { "sourceKey": "package.json", "contentType": "application/json", "fileType": "json", "renderHint": { "preferredRenderer": "code", "syntaxHighlight": true, "lineNumbers": true } }, "sourceKey": "package.json", "fileType": "json" } }
- ResourceViewer is integrated into the Message component's
renderAnthropicBlocks()
function - Detection happens in the
mcp_tool_result
case after NextSteps and before HTML detection - CodeMirror extensions are loaded dynamically based on file type
- Fullscreen mode uses fixed positioning with high z-index
- Mobile-responsive design with touch-friendly controls
- Memoized MCP Client Resolution - Client lookup is memoized to prevent unnecessary re-renders
- Stable Reference Management - MCP clients array is memoized in the parent hook to prevent reload loops
- Simplified Dependency Chains - Reduced nested useCallback dependencies to minimize effect re-executions
- Optimized useEffect Dependencies - Removed function dependencies that caused infinite reload loops
- CodeMirror 6 - Syntax highlighting and code editing
- React 18 - Component framework
- MCP Client - Resource fetching from MCP servers
- Binary File Support - Display images, PDFs, etc.
- Diff Viewer - Compare file versions
- Search/Find - In-file search functionality
- Download Support - Save resources locally
- Collaborative Editing - Real-time editing capabilities