feat(mcpedia): Phase 1 MVP — monorepo, Core, Web UI, MCP server, Postgres FTS
- bun workspaces + Turborepo monorepo (apps/web, apps/mcp; packages/*, scripts) - @mcpedia/core single business-logic layer (Document/Content/Search services) - @mcpedia/db Drizzle schema: documents + weighted tsvector (GIN) for FTS - @mcpedia/parser frontmatter, @mcpedia/search Postgres FTS (ts_rank+ts_headline) - Next.js 16 Web UI (home/doc SSG, search dynamic) + react-markdown render - MCP server (stdio) with 4 tools + in-memory smoke test - scripts/indexer walks content/ -> upserts into Postgres - 4 seed docs; README + PHASES status
This commit is contained in:
@@ -0,0 +1,108 @@
|
||||
# MCPedia
|
||||
|
||||
> A content-first knowledge base — readable as Markdown/MDX in Git, queryable by
|
||||
> humans via a Web UI and by AI agents via the Model Context Protocol (MCP).
|
||||
|
||||
MCPedia keeps content as plain Markdown files under `content/`. A Git-tracked
|
||||
source of truth, indexed into PostgreSQL (metadata + a `tsvector` full-text
|
||||
column) and served through a single **Core** layer that every interface
|
||||
(Web, MCP) shares — no business logic duplicated per surface.
|
||||
|
||||
## Monorepo layout
|
||||
|
||||
```
|
||||
mcpedia/
|
||||
├── apps/
|
||||
│ ├── web/ # Next.js 16 (Turbopack) — human-facing docs UI + search
|
||||
│ └── mcp/ # MCP server (stdio) — AI-agent interface
|
||||
├── packages/
|
||||
│ ├── types/ # shared domain types (DocSection, Document, SearchHit, ...)
|
||||
│ ├── config/ # loads .env (repo root) as authoritative dev config
|
||||
│ ├── db/ # Drizzle ORM schema + client + drizzle-kit config
|
||||
│ ├── parser/ # frontmatter (gray-matter) parsing
|
||||
│ ├── search/ # Postgres FTS query (ts_rank + ts_headline)
|
||||
│ └── core/ # Document/Content/Search services — the only business logic
|
||||
├── content/ # docs/ writeups/ research/ notes/ (the knowledge base)
|
||||
└── scripts/ # indexer.ts (walks content/ -> upserts into Postgres)
|
||||
```
|
||||
|
||||
## Architecture principle
|
||||
|
||||
```
|
||||
Web ─┐
|
||||
├──► Core ──► Repository (@mcpedia/db) ──► PostgreSQL
|
||||
MCP ─┘
|
||||
```
|
||||
|
||||
All interfaces go through `@mcpedia/core`. Nothing outside `packages/db` and
|
||||
`packages/core` touches the database directly.
|
||||
|
||||
## Quick start
|
||||
|
||||
```bash
|
||||
bun install # install workspace deps
|
||||
cp .env.example .env # set DATABASE_URL (dev uses imrnes Postgres :6432)
|
||||
bunx turbo run build # typecheck + build every package
|
||||
|
||||
bun run index # walk content/ -> upsert into Postgres
|
||||
bun --cwd apps/web run dev # Web UI on :3000
|
||||
bun run mcp # MCP server on stdio (pipe to an MCP client)
|
||||
```
|
||||
|
||||
### Database
|
||||
|
||||
Phase 1 uses Postgres FTS only. Schema is defined in `packages/db/src/schema.ts`
|
||||
(a `documents` table with a `search_vector` generated `tsvector` column + GIN
|
||||
index). Apply it with:
|
||||
|
||||
```bash
|
||||
bunx --cwd packages/db drizzle-kit push
|
||||
```
|
||||
|
||||
> Note: on imrnes (PgBouncer `:6432`) a leaked `DATABASE_URL` shell var can
|
||||
> shadow `.env`. `@mcpedia/config` loads `.env` **last** so the repo config
|
||||
> always wins for local/dev.
|
||||
|
||||
## Content
|
||||
|
||||
Each Markdown file carries YAML frontmatter:
|
||||
|
||||
```yaml
|
||||
---
|
||||
id: websocket-contract
|
||||
title: WebSocket Contract
|
||||
type: documentation
|
||||
tags: [typescript, websocket, rpc]
|
||||
status: published
|
||||
author: asep
|
||||
created_at: 2026-08-19
|
||||
updated_at: 2026-08-19
|
||||
---
|
||||
```
|
||||
|
||||
`slug` = relative path under `content/` (e.g. `docs/websocket/contract`). The
|
||||
`body` shown in the UI is always read from the on-disk file (source of truth);
|
||||
the DB stores metadata + the search vector.
|
||||
|
||||
## MCP tools (Phase 1)
|
||||
|
||||
| Tool | Purpose |
|
||||
| --------------------- | ------------------------------------------------ |
|
||||
| `search_documents` | Postgres FTS over the corpus (ranked + snippet) |
|
||||
| `get_document` | Full markdown body by slug |
|
||||
| `list_documents` | List, optionally filtered by section |
|
||||
| `get_related_documents` | Docs sharing tags with a given slug |
|
||||
|
||||
Smoke test (in-memory transport, real JSON-RPC):
|
||||
|
||||
```bash
|
||||
bun --cwd apps/mcp run smoke
|
||||
```
|
||||
|
||||
## Status
|
||||
|
||||
**Phase 1 — MVP (DONE):** monorepo, Core, Web UI (home/doc/search), MCP server,
|
||||
Postgres FTS keyword search, content indexing.
|
||||
|
||||
See `PHASES.md` for Phase 2–4 (pgvector semantic/hybrid search, tRPC/Hono API,
|
||||
auth, Redis/BullMQ background workers, revisions, scale-out).
|
||||
Reference in New Issue
Block a user