Skip to main content
Glama
Plugins.tsx3.34 kB
import { useQuery } from '@tanstack/react-query'; import { CheckCircle, AlertTriangle, Settings, Activity } from 'lucide-react'; export default function Plugins() { const { data: plugins, isLoading } = useQuery({ queryKey: ['plugins'], queryFn: async () => { const res = await fetch('/api/plugins'); const data = await res.json(); return data.plugins; }, refetchInterval: 10000, }); if (isLoading) { return <div className="text-center py-12">Loading plugins...</div>; } const groupedPlugins = plugins?.reduce((acc: any, plugin: any) => { if (!acc[plugin.category]) { acc[plugin.category] = []; } acc[plugin.category].push(plugin); return acc; }, {}); return ( <div className="space-y-6"> <div className="flex items-center justify-between"> <div> <h1 className="text-3xl font-bold text-gray-900 dark:text-white">Plugins</h1> <p className="mt-1 text-sm text-gray-500 dark:text-gray-400"> Manage and monitor OPNsense MCP plugins </p> </div> <div className="flex items-center space-x-2"> <span className="text-sm text-gray-500"> {plugins?.length || 0} plugins loaded </span> </div> </div> {/* Plugin Groups */} <div className="space-y-6"> {Object.entries(groupedPlugins || {}).map(([category, categoryPlugins]: [string, any]) => ( <div key={category} className="card"> <h2 className="text-xl font-semibold mb-4 capitalize text-gray-900 dark:text-white"> {category} Plugins </h2> <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4"> {categoryPlugins.map((plugin: any) => ( <PluginCard key={plugin.id} plugin={plugin} /> ))} </div> </div> ))} </div> </div> ); } function PluginCard({ plugin }: { plugin: any }) { return ( <div className="p-4 rounded-lg border border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-800 hover:shadow-md transition-shadow"> <div className="flex items-start justify-between mb-3"> <div className="flex items-center space-x-3"> <div className="p-2 bg-blue-100 dark:bg-blue-900/20 rounded-lg"> <Settings className="w-5 h-5 text-blue-600" /> </div> <div> <h3 className="font-medium text-gray-900 dark:text-white">{plugin.name}</h3> <p className="text-xs text-gray-500 dark:text-gray-400">{plugin.version}</p> </div> </div> {plugin.health?.healthy ? ( <CheckCircle className="w-5 h-5 text-green-500" /> ) : ( <AlertTriangle className="w-5 h-5 text-yellow-500" /> )} </div> <p className="text-sm text-gray-600 dark:text-gray-300 mb-3 line-clamp-2"> {plugin.description} </p> <div className="flex items-center justify-between"> <span className={`badge ${plugin.state === 'running' ? 'badge-success' : 'badge-warning'}`}> {plugin.state} </span> <button className="text-xs text-blue-600 hover:text-blue-700 dark:text-blue-400 font-medium"> View Details → </button> </div> </div> ); }

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/vespo92/OPNSenseMCP'

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