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:
asepharyana
2026-08-19 17:40:14 +07:00
commit ec3a2867d4
60 changed files with 3723 additions and 0 deletions
+43
View File
@@ -0,0 +1,43 @@
---
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
---
# WebSocket Contract
The WebSocket contract defines how clients establish a bidirectional connection
and exchange RPC-style messages with the server. It is the foundation for the
type-safe API described in the tRPC integration notes.
## Handshake
A client opens a single WebSocket connection and sends an `init` frame携带 an
auth token. The server answers with `ready` or closes the socket with code 4401
if the token is invalid.
## Message envelope
Every frame uses a JSON envelope:
```json
{ "id": "req-1", "method": "echo", "params": { "text": "hi" } }
```
The server replies with a matching `id` and either a `result` or an `error`
field. This request/response correlation is what makes the protocol feel like
RPC even though it rides on a single socket.
## Timeouts
If the server does not answer within the negotiated timeout, the client should
re-send with the same `id` rather than opening a new connection. See the
debugging writeup for a common timeout pitfall when proxies buffer frames.
+36
View File
@@ -0,0 +1,36 @@
---
id: typescript-patterns
title: TypeScript Patterns
type: note
tags:
- typescript
- patterns
status: published
author: asep
created_at: 2026-08-19
updated_at: 2026-08-19
---
# TypeScript Patterns
A notebook of small, reusable TypeScript patterns that keep code honest.
## Branded types for ids
```ts
type DocId = string & { readonly __brand: "DocId" };
const asDocId = (s: string) => s as DocId;
```
Branding prevents passing an arbitrary string where a document id is expected.
## Discriminated unions over inheritance
Prefer a closed set of variants with a `kind` field. Exhaustiveness checks with
`switch` catch missing cases at compile time instead of at runtime.
## Prefer composition
When two modules share behavior, extract a function. Avoid inheritance trees
that couple unrelated code. This matches the MCPedia Core principle: one layer
owns the logic, interfaces only call into it.
+34
View File
@@ -0,0 +1,34 @@
---
id: mcp-architecture
title: MCP Architecture Notes
type: research
tags:
- mcp
- architecture
- ai
status: published
author: asep
created_at: 2026-08-19
updated_at: 2026-08-19
---
# MCP Architecture Notes
The Model Context Protocol (MCP) lets an AI client treat a knowledge base as a
first-class context source instead of yet another REST API. The server exposes
tools and resources; the client decides what to read.
## Tools vs resources
- Tools are actions the model calls (`search_documents`, `get_document`).
- Resources are addressable content the model can pull (`mcpedia://docs/...`).
## Why it matters here
MCPedia exposes both. The Web UI is for humans; the MCP server is for agents.
Both go through the same Core layer, so there is exactly one copy of the
business logic and one search implementation.
## Reference
Related reading: the WebSocket contract and the tRPC type-safe API notes.
@@ -0,0 +1,36 @@
---
id: websocket-timeout
title: Debugging a WebSocket Timeout Behind a Proxy
type: writeup
tags:
- websocket
- debugging
- proxy
status: published
author: asep
created_at: 2026-08-19
updated_at: 2026-08-19
---
# Debugging a WebSocket Timeout Behind a Proxy
A recurring incident: the browser WebSocket connects, sends one frame, then
silently times out. The server logs show no error. Root cause: the reverse
proxy was buffering frames and only flushing on connection close.
## Symptoms
- Connection opens (101 Switching Protocols).
- First message never reaches the upstream.
- Client hits its own 30s timeout and reconnects, creating a storm.
## Fix
Disable proxy buffering for the WebSocket upgrade route and ensure the proxy
does not apply an idle timeout shorter than the application's heartbeat
interval. After that, frames flowed immediately and the timeout disappeared.
## Lesson
Always confirm at the proxy layer whether frames are buffered before assuming
the application server is at fault.