Skip to main content
Glama
featured-apps.tsx4 kB
"use client" import { Badge } from "@repo/ui/components/ui/badge" import { Button } from "@repo/ui/components/ui/button" import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "@repo/ui/components/ui/card" import { ArrowRight, Star } from "lucide-react" import Image from "next/image" import Link from "next/link" import { useState } from "react" import { trpc } from "@/lib/trpc/client" import { getAssetUrl } from "@/lib/utils" export function FeaturedApps() { const { data: featuredApps, isLoading } = trpc.mcpRecommendations.getFeaturedApps.useQuery({ limit: 6 }) const [visibleCount, setVisibleCount] = useState(6) const loadMore = () => { setVisibleCount((prev) => prev + 6) } return ( <div className="space-y-6"> <div className="grid gap-6 sm:grid-cols-2 lg:grid-cols-3"> {featuredApps && featuredApps.map((app) => ( <Card key={app.slug} className="flex flex-col overflow-hidden"> <CardHeader className="p-4"> <div className="flex items-start justify-between"> <div className="flex items-center space-x-2"> <div className="h-10 w-10 rounded-md bg-muted flex items-center justify-center overflow-hidden"> {app.icon ? ( <Image src={getAssetUrl(app.icon) || "/placeholder.svg"} alt={app.name} width={40} height={40} className="object-cover" /> ) : ( <div className="text-lg font-bold">{app.name.charAt(0)}</div> )} </div> <div> <CardTitle className="text-base">{app.name}</CardTitle> <div className="flex items-center mt-1"> <Badge variant={app.type === "client" ? "default" : app.type === "server" ? "secondary" : "outline"} className="text-xs" > {app.type === "client" ? "客户端" : app.type === "server" ? "服务器" : "应用"} </Badge> {app.stars && ( <div className="flex items-center ml-2 text-xs text-muted-foreground"> <Star className="h-3 w-3 mr-0.5 text-yellow-400 fill-yellow-400" /> {app.stars} </div> )} </div> </div> </div> </div> </CardHeader> <CardContent className="flex-1 p-4 pt-0"> <CardDescription className="line-clamp-4">{app.description}</CardDescription> <div className="flex flex-wrap gap-1 mt-3"> {app.tags?.slice(0, 3).map((tag) => ( <Badge key={tag.id} variant="outline" className="text-xs"> {tag.tag.name} </Badge> ))} {app.tags && app.tags.length > 3 && ( <Badge variant="outline" className="text-xs"> +{app.tags.length - 3} </Badge> )} </div> </CardContent> <CardFooter className="p-4 pt-0"> <Button variant="outline" size="sm" className="w-full" asChild> <Link href={`/apps/${app.slug}`}> 查看详情 <ArrowRight className="ml-1 h-3 w-3" /> </Link> </Button> </CardFooter> </Card> ))} </div> {visibleCount < (featuredApps ? featuredApps?.length : 0) && ( <div className="flex justify-center mt-8"> <Button variant="outline" onClick={loadMore}> 加载更多 </Button> </div> )} </div> ) }

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/metacode0602/open-mcp'

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