Skip to main content
Glama
ServerCard.tsx5.68 kB
import { useDomainIcon } from "@/hooks/useDomainIcon"; import { CatalogMCPServerItem } from "@mcpx/shared-model"; import McpIcon from "./SystemConnectivity/nodes/Mcpx_Icon.svg?react"; import { cn } from "@/lib/utils"; import { Button } from "../ui/button"; import { useMemo } from "react"; import { Plus } from "lucide-react"; import GitHubLogo from "./icons/GitHubLogo.svg?react"; import GitHubLogoSolid from "./icons/GitHubLogoSolid.svg?react"; import { getServerStatusBackgroundColor, getServerStatusText, getServerStatusTextColor, } from "./helpers"; import { getMcpColorByName } from "./constants"; export type ServerCardProps = { server: CatalogMCPServerItem; className?: string; onAddServer: ( config: Record<string, unknown>, serverName: string, withEnvs?: boolean, ) => void; status?: string; }; interface ConfigValue { command?: string; env?: Record<string, string>; } export const ServerCard = ({ server, className, status, onAddServer, }: ServerCardProps) => { const domainIconUrl = useDomainIcon(server?.name || ""); const badges = useMemo(() => { function getCommand(config: Record<string, unknown>): string | undefined { const configValue = Object.values(config).find( (c) => (c as ConfigValue).command, ) as ConfigValue | undefined; return configValue?.command; } const command = getCommand(server.config ?? {}); if (!command) { return ["Remote"]; } { return ["Local", command]; } }, [server]); function getEnvs(config: Record<string, unknown>): string[] { const configValue = Object.values(config ?? {}).find( (c) => (c as ConfigValue).env, ) as ConfigValue | undefined; return Object.keys(configValue?.env ?? {}); } const envs = useMemo(() => getEnvs(server.config), [server.config]); return ( <div className={cn( "border flex bg-card flex-col gap-4 rounded-xl p-4", className, )} > <div className="flex items-start justify-between gap-2 text-foreground font-semibold"> <div className="flex items-center gap-2"> <div> {domainIconUrl ? ( <img src={domainIconUrl} alt="Domain Icon" className="min-w-12 h-12 rounded-md object-contain p-1 " /> ) : ( <McpIcon style={{ color: getMcpColorByName(server.displayName) }} className="min-w-12 h-12 rounded-md p-1" /> )} </div> <div className="flex flex-col"> <span>{server.displayName}</span> <div className="flex items-center gap-1"> {badges.map((badge, index) => ( <p key={index} className="text-[10px] w-fit font-semibold text-muted-foreground border border-[#7D7B98] rounded-[4px] px-1" > {badge} </p> ))} </div> </div> </div> {status && ( <div className={`flex whitespace-nowrap gap-1 overflow-hidden items-center h-6 px-2 rounded-full text-xs font-medium ${getServerStatusBackgroundColor(status)} ${getServerStatusTextColor(status)} `} > <div className="bg-current w-2 min-w-2 h-2 min-h-2 rounded-full"></div> <span className="line-clamp-1 text-ellipsis"> {getServerStatusText(status)} </span> </div> )} {!status && ( <Button className="text-lg max-w-6 max-h-6 px-1.5 py-1.5 font-normal" variant="primary" size="sm" onClick={() => onAddServer(server.config, server.displayName, !!envs?.length) } > <Plus className="w-4 h-4" /> </Button> )} </div> <div className="line-clamp-2 mb-auto text-sm font-normal text-primary"> {server.description} </div> {!!envs?.length && ( <div className="flex flex-col gap-1"> <div className="text-sm text-primary font-semibold"> ENVIRONMENT VARIABLES </div> <div className="flex flex-wrap gap-2"> {envs.map((env) => ( <div className="font-semibold text-[#5147E4] px-1.5 py-0.5 rounded bg-[#EBE6FB] text-[10px]" key={env} > {env} </div> ))} </div> </div> )} <hr className="border-border" /> <div className="flex items-center justify-between"> <div className="flex items-center gap-1 text-muted-foreground"> {server.link && ( <a href={server.link} target="_blank" rel="noopener noreferrer"> {server.link.includes("github.com") && !server.link.includes("github.io") ? ( <GitHubLogoSolid /> ) : ( <span className="flex items-center gap-1 text-sm font-normal"> <GitHubLogo /> Docs </span> )} </a> )} {server.doc && ( <a href={server.doc} target="_blank" rel="noopener noreferrer" className="flex items-center gap-1 text-sm font-normal" > <GitHubLogo /> Docs </a> )} </div> {/* <div className="text-sm text-muted-foreground"> {server.tools || 0} Tools </div> */} </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/TheLunarCompany/lunar'

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