AI
Vercel AI SDK with Anthropic for chat and Google Gemini for embeddings, RAG over pgvector, and a small MCP server.
The AI stack lives in packages/ai and apps/admin/app/(authed)/chat.
Models
- Chat —
@ai-sdk/anthropicwith Claude. The chat UI is inapps/admin(behind auth). - Embeddings —
@ai-sdk/googlewith Gemini's text-embedding model. Cheap, fast, good enough for RAG.
Switching providers is a one-line change in packages/ai/src/models.ts — the rest of the code talks to the AI SDK abstraction, not the provider.
RAG
bun run rag:ingest walks content/ and apps/docs/content/, chunks the markdown, embeds each chunk with Gemini, and writes rows into the embedding table (pgvector). At query time, the chat route does a cosine-similarity search and feeds the top chunks into the system prompt.
The embeddings.user_id column scopes rows to their owner. Ingested docs are written under RAG_USER_ID, and the chat route's similarity search filters WHERE user_id = <caller> — a user only retrieves chunks they own.
MCP
apps/mcp is a small Model Context Protocol server exposing the API as tools. It runs in two modes:
- stdio — for local agents (Claude Desktop, etc.)
- HTTP — for hosted clients, via
StreamableHTTPServerTransportovernode:http
Auth headers are picked from MCP_AUTH_HEADER / MCP_AUTH_HEADER_<N> env vars so the same binary works with cookies, bearer tokens, or whatever else the project has wired up.
Agent example
See docs/agent-example.md for a worked example of pointing Claude Desktop at the MCP server and calling shipkit endpoints as tools.