Skip to main content
Glama
ResourcesTab.js6.96 kB
/** * WordPress dependencies */ import { Card, CardHeader, CardBody, Spinner, Button, Modal, } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; import { useState, useEffect } from '@wordpress/element'; import apiFetch from '@wordpress/api-fetch'; /** * Pretty prints JSON data * * @param {Object} data The data to pretty print * @return {string} Formatted JSON string */ const prettyPrintJson = ( data ) => { try { // If data is a string, try to parse it as JSON if ( typeof data === 'string' ) { try { const parsedData = JSON.parse( data ); return JSON.stringify( parsedData, null, 2 ); } catch ( parseError ) { // If parsing fails, return the original string return data; } } // If data is an object with a text property that looks like JSON if ( data && typeof data === 'object' && data.text && typeof data.text === 'string' ) { try { const parsedText = JSON.parse( data.text ); return JSON.stringify( parsedText, null, 2 ); } catch ( parseError ) { // If parsing fails, continue with normal formatting } } // Default case: format the object directly return JSON.stringify( data, null, 2 ); } catch ( error ) { return 'Error formatting JSON: ' + error.message; } }; /** * Resources Tab Component */ const ResourcesTab = () => { const [ resources, setResources ] = useState( [] ); const [ loading, setLoading ] = useState( true ); const [ error, setError ] = useState( null ); const [ selectedResource, setSelectedResource ] = useState( null ); const [ resourceDetails, setResourceDetails ] = useState( null ); const [ detailsLoading, setDetailsLoading ] = useState( false ); const [ detailsError, setDetailsError ] = useState( null ); const [ parsedJsonData, setParsedJsonData ] = useState( null ); useEffect( () => { const fetchResources = async () => { try { setLoading( true ); const response = await apiFetch( { path: '/wp/v2/wpmcp', method: 'POST', data: { jsonrpc: '2.0', method: 'resources/list', params: {}, }, } ); if ( response && response.resources ) { setResources( response.resources ); } else { setError( __( 'Failed to load resources data', 'wordpress-mcp' ) ); } } catch ( err ) { setError( __( 'Error loading resources: ', 'wordpress-mcp' ) + err.message ); } finally { setLoading( false ); } }; fetchResources(); }, [] ); /** * Fetch detailed information about a resource * * @param {Object} resource The resource to fetch details for */ const fetchResourceDetails = async ( resource ) => { try { setDetailsLoading( true ); setDetailsError( null ); setParsedJsonData( null ); const response = await apiFetch( { path: '/wp/v2/wpmcp', method: 'POST', data: { jsonrpc: '2.0', method: 'resources/read', uri: resource.uri, }, } ); if ( response && response.contents ) { setResourceDetails( response.contents ); // Try to parse JSON text if it exists if ( response.contents.text && typeof response.contents.text === 'string' ) { try { const parsedData = JSON.parse( response.contents.text ); setParsedJsonData( parsedData ); } catch ( parseError ) { // If parsing fails, leave parsedJsonData as null console.log( 'Failed to parse JSON text:', parseError ); } } } else { setDetailsError( __( 'Failed to load resource details', 'wordpress-mcp' ) ); } } catch ( err ) { setDetailsError( __( 'Error loading resource details: ', 'wordpress-mcp' ) + err.message ); } finally { setDetailsLoading( false ); } }; /** * Handle viewing a resource * * @param {Object} resource The resource to view */ const viewResource = ( resource ) => { setSelectedResource( resource ); fetchResourceDetails( resource ); }; /** * Close the resource details modal */ const closeModal = () => { setSelectedResource( null ); setResourceDetails( null ); setParsedJsonData( null ); setDetailsError( null ); }; return ( <Card> <CardHeader> <h2>{ __( 'Available Resources', 'wordpress-mcp' ) }</h2> </CardHeader> <CardBody> <p> { __( 'List of all available resources in the system.', 'wordpress-mcp' ) } </p> { loading ? ( <div className="wordpress-mcp-loading"> <Spinner /> <p>{ __( 'Loading resources...', 'wordpress-mcp' ) }</p> </div> ) : error ? ( <div className="wordpress-mcp-error"> <p>{ error }</p> </div> ) : resources.length === 0 ? ( <p> { __( 'No resources are currently available.', 'wordpress-mcp' ) } </p> ) : ( <table className="wordpress-mcp-table"> <thead> <tr> <th>{ __( 'Name', 'wordpress-mcp' ) }</th> <th>{ __( 'URI', 'wordpress-mcp' ) }</th> <th> { __( 'Description', 'wordpress-mcp' ) } </th> <th>{ __( 'Actions', 'wordpress-mcp' ) }</th> </tr> </thead> <tbody> { resources.map( ( resource ) => ( <tr key={ resource.name }> <td> <strong>{ resource.name }</strong> </td> <td>{ resource.uri }</td> <td>{ resource.description || '-' }</td> <td> <Button variant="secondary" onClick={ () => viewResource( resource ) } > { __( 'View', 'wordpress-mcp' ) } </Button> </td> </tr> ) ) } </tbody> </table> ) } { selectedResource && ( <Modal title={ __( 'Resource Details', 'wordpress-mcp' ) } onRequestClose={ closeModal } className="wordpress-mcp-resource-modal" > { detailsLoading ? ( <div className="wordpress-mcp-loading"> <Spinner /> <p> { __( 'Loading resource details...', 'wordpress-mcp' ) } </p> </div> ) : detailsError ? ( <div className="wordpress-mcp-error"> <p>{ detailsError }</p> </div> ) : resourceDetails ? ( <div className="wordpress-mcp-resource-details"> <h3> { resourceDetails.name || selectedResource.name } </h3> <div className="wordpress-mcp-resource-json"> <h4> { __( 'Full Resource Data', 'wordpress-mcp' ) } </h4> <pre className="wordpress-mcp-json-display"> { prettyPrintJson( resourceDetails ) } </pre> </div> </div> ) : ( <p> { __( 'No details available for this resource.', 'wordpress-mcp' ) } </p> ) } </Modal> ) } </CardBody> </Card> ); }; export default ResourcesTab;

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Automattic/wordpress-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server