import Link from "next/link"; import { listDocuments } from "@mcpedia/core"; import { SECTIONS } from "@mcpedia/config/sections"; import McpConfigSnippet from "@/components/McpConfigSnippet"; export const dynamic = "force-dynamic"; interface TreeNode { name: string; slug: string; title: string; children: TreeNode[]; isLeaf: boolean; } function slugToTitle(segment: string): string { return segment .split(/[-_]/) .map((w) => (w ? w.charAt(0).toUpperCase() + w.slice(1) : "")) .join(" "); } function buildFolderTree(docs: { slug: string; title: string }[], section: string): TreeNode[] { const tree: TreeNode[] = []; const treeIndex = new Map(); for (const doc of docs) { const parts = doc.slug.split("/"); let current = tree; let currentPath = section; for (let i = 1; i < parts.length; i++) { const part = parts[i]; const isLeaf = i === parts.length - 1; currentPath = `${currentPath}/${part}`; let node = current.find((n) => n.name === part); if (!node) { node = { name: part, slug: currentPath, title: isLeaf ? doc.title : slugToTitle(part), children: [], isLeaf: false, }; current.push(node); treeIndex.set(currentPath, node); } if (isLeaf) { node.isLeaf = true; node.title = doc.title; } else if (!node.title) { node.title = slugToTitle(part); } current = node.children; } } function sortNodes(nodes: TreeNode[]): TreeNode[] { return nodes.sort((a, b) => { const aFolder = a.children.length > 0 ? 0 : 1; const bFolder = b.children.length > 0 ? 0 : 1; if (aFolder !== bFolder) return aFolder - bFolder; return (a.title || a.name).localeCompare(b.title || b.name); }); } function sortAll(nodes: TreeNode[]): TreeNode[] { const sorted = sortNodes(nodes); for (const node of sorted) { if (node.children.length > 0) sortAll(node.children); } return sorted; } return sortAll(tree); } function renderTree(nodes: TreeNode[], pathname: string) { return ( ); } interface SectionTreeProps { section: string; docs: { slug: string; title: string }[]; pathname: string; } function SectionTree({ section, docs, pathname }: SectionTreeProps) { const tree = buildFolderTree( docs.filter((d) => d.slug.startsWith(`${section}/`)), section, ); const sectionInfo = SECTIONS.find((s) => s.id === section); if (!sectionInfo) return null; return (
{tree.length > 0 ? ( renderTree(tree, pathname) ) : (

No documents

)}
); } export default async function HomePage() { const all = await listDocuments(); const recent = [...all] .sort( (a, b) => new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime(), ) .slice(0, 6); return (
{/* Hero Section */}
Model Context Protocol + Unified Knowledge Base

Knowledge Base for
Humans and AI Agents

A high-performance, content-first documentation system. Browse hierarchical notes and CTF writeups in your browser, or connect AI coding assistants directly via native MCP tools.

{/* Quick action buttons & stats */}
Browse Documentation → Hybrid Search + Create Document
{/* Stats bar */}
{all.length}
Documents indexed
{SECTIONS.length}
Core sections
RRF Hybrid
FTS + 2048-dim vectors
10 MCP Tools
Streamable HTTP :4021
{/* Browse by Section */}

Browse by Section

{SECTIONS.map((s) => { const sectionDocs = all.filter((d) => d.section === s.id); return (
{s.icon} {sectionDocs.length} docs →

{s.label}

{s.desc}

{/* Inline folder tree */}
({ slug: d.slug, title: d.title }))} pathname="/" />
); })}
{/* Recent Documents */} {recent.length > 0 && (

Recently Updated Knowledge

View all ({all.length}) →
{recent.map((d) => { const sInfo = SECTIONS.find((s) => s.id === d.section); return (
{sInfo?.icon} {d.section}

{d.title}

{d.tags.length > 0 && (
{d.tags.slice(0, 3).map((t) => ( #{t} ))}
)} ); })}
)} {/* MCP Agent Integration Showcase */}
⚡ Native Model Context Protocol (MCP)

Connect AI Coding Assistants

Give Claude Desktop, Cursor, Antigravity, or Zed direct access to your knowledge base via semantic search, read resources, and document tools.

); }