import type { Metadata } from 'next'; import Link from 'next/link'; import { Dash, IntelListing, str } from '@/components/intelligence/listing-table'; import { EntityBadge } from '@/components/ui/badges'; import { EntityLink, QualityMark } from '@/components/ui/entity'; import { api } from '@/lib/api'; import { fmtAgo, fmtInt, num } from '@/lib/format'; import { routes, SITE_NAME, SITE_URL } from '@/lib/site'; export const metadata: Metadata = { title: 'AI tools, products and MCP servers', description: 'Developer tools, products and MCP servers in the atlas with category, language, license, stars and publisher from their official sources.', alternates: { canonical: routes.tools() }, openGraph: { title: `AI tools | ${SITE_NAME}`, url: `${SITE_URL}${routes.tools()}`, siteName: SITE_NAME } }; export const revalidate = 300; export default async function ToolsPage({ searchParams }: { searchParams: Promise> }) { const sp = await searchParams; return ( Coding tools, MCP servers and products built on the models above. Metadata comes from repositories, package registries and official pages. Agents have their own listing at /agents.} basePath="/tools" searchParams={sp} fetch={(q) => api.explore('tool', q)} sorts={[ { value: 'updated', label: 'Recently updated' }, { value: 'stars', label: 'Stars' }, { value: 'name', label: 'Name' }, { value: 'quality', label: 'Data quality' }, ]} filters={sp.org ? [{ kind: 'hidden', name: 'org', value: sp.org }] : []} connectors={['github (tool repositories)', 'pypi / npm', 'official product pages']} emptyHint={<>The tool type is declared but no connector has produced a row yet — the navigation lists this page under Agents & Tools for that reason. In the meantime, related software is under Frameworks and Repositories.} columns={[ { key: 'name', label: 'Tool', primary: true, render: (e) => ( <> {e.description && {e.description}} ), }, { key: 'kind', label: 'Category', className: 'text-ink-2', render: (e) => str(e.attributes?.category) ?? str(e.attributes?.kind) ?? }, { key: 'language', label: 'Language', className: 'text-ink-2', render: (e) => str(e.attributes?.language) ?? }, { key: 'stars', label: 'Stars', num: true, className: 'tnum', render: (e) => (num(e.attributes?.['metric.stars']) === null ? : fmtInt(e.attributes['metric.stars'])) }, { key: 'license', label: 'Licence', className: 'max-w-[10rem] truncate text-ink-2', render: (e) => str(e.attributes?.license) ?? }, { key: 'org', label: 'Organization', className: 'text-ink-2', render: (e) => (e.organization ? {e.organization.name} : ) }, { key: 'updated', label: 'Updated', className: 'text-ink-2 whitespace-nowrap', render: (e) => {fmtAgo(e.updated_at)} }, { key: 'quality', label: 'Quality', num: true, render: (e) => }, ]} note="Tools cover several entity types (tool, MCP server, product) — the badge on each row says which." /> ); }