Enterprise AI assistant: RAG, AI agent with tool calling, Model Context Protocol (MCP) server, and evaluations. TypeScript monorepo — NestJS, React, PostgreSQL + pgvector, Vercel AI SDK.
Overview
An enterprise-style that answers questions over a company's . It demonstrates a production-shaped implementation of , an with , a server, and an — built on a monorepo with . Portfolio project. The AI provider sits behind an interface (a seam), so the whole system runs today against a and swaps in by setting a single environment variable. See PENDING.md. - — document ingestion (PDF, Markdown, plain text), recursive text chunking, vector embeddings, and on with an index. - — a multi-step agent (max 5 steps) that chooses between four read-only and a tool using the . - — exposes the same business tools over the official , reusing the exact same domain logic as the HTTP API (one source of truth). - — a 22-case dataset scoring , and , runnable in CI. - — framework-agnostic business logic behind ports and adapters, making the code , and provider-agnostic. - — (unit + integration) and an end-to-end stack verified against real PostgreSQL. The repository is a .
README
AI Business Assistant
An enterprise-style AI assistant that answers questions over a company’s internal documentation and business data. It demonstrates a production-shaped implementation of Retrieval-Augmented Generation (RAG), an AI agent with tool calling, a Model Context Protocol (MCP) server, and an evaluation suite — built on a TypeScript monorepo with hexagonal architecture.
Portfolio project. The AI provider sits behind an interface (a seam), so the whole system runs today against a deterministic mock and swaps in OpenAI by setting a single environment variable. See PENDING.md.
Highlights
- RAG pipeline — document ingestion (PDF, Markdown, plain text), recursive text chunking, vector embeddings, and cosine-similarity semantic search on PostgreSQL + pgvector with an HNSW index.
- AI agent with tool calling — a multi-step agent (max 5 steps) that chooses between four read-only business-data tools and a documentation search tool using the Vercel AI SDK.
- Model Context Protocol (MCP) server — exposes the same business tools over the official MCP TypeScript SDK, reusing the exact same domain logic as the HTTP API (one source of truth).
- Evaluation suite — a 22-case dataset scoring retrieval hit rate, tool-selection accuracy and answer accuracy, runnable in CI.
- Hexagonal architecture — framework-agnostic business logic behind ports and adapters, making the code testable, AI-navigable and provider-agnostic.
- Fully typed, fully tested — 51 automated tests (unit + integration) and an end-to-end Docker Compose stack verified against real PostgreSQL.
Tech stack
| Area | Technologies |
|---|---|
| Language | TypeScript (strict), Node.js 20 |
| Frontend | React 19, Vite, @ai-sdk/react (streaming chat UI) |
| Backend | NestJS, Vercel AI SDK (ai, @ai-sdk/openai) |
| RAG | LangChain text splitters, OpenAI embeddings (mocked for now) |
| Database | PostgreSQL, pgvector, Prisma ORM, raw SQL for vector search |
| Protocol | Model Context Protocol (@modelcontextprotocol/* SDK) |
| Testing | Jest, Supertest (HTTP + MCP integration) |
| Tooling | pnpm workspaces, SWC, Docker Compose, GitHub Actions CI |
Architecture
The repository is a pnpm monorepo. Business logic is written once and reused by both the HTTP API and the MCP server.
┌────────────┐ HTTP/stream ┌─────────────────────────────┐
│ React UI │ ───────────────────▶ │ NestJS API (apps/api) │
│ (apps/web) │ /api proxy (nginx) │ ┌───────────────────────┐ │
└────────────┘ │ │ AI agent + tool calling│ │
│ │ RAG retrieval + ingest │ │
┌────────────┐ stdio / MCP │ │ business use-cases │ │
│ MCP client │ ───────────────────▶ │ └───────────┬───────────┘ │
└────────────┘ └──────────────┼──────────────┘
▲ apps/mcp reuses the same ───────────────┘
│ business services ┌───────────────────────┐
└─────────────────────────────────────│ PostgreSQL + pgvector │
└───────────────────────┘
apps/web— React + Vite streaming chat UI; talks only to the API, so AI provider keys never reach the browser.apps/api— NestJS. Hexagonal layers:business/(use-cases + ports),rag/(chunking, embeddings, retrieval, indexing),agent/(tools, system prompt, chat service),http/(controllers), adapters for Prisma/pgvector.apps/mcp— MCP server exposing the four read-only business tools.packages/shared— Zod schemas, domain types, tool contracts, pricing.
Key features in detail
Retrieval-Augmented Generation
Documents are uploaded, extracted page-by-page (PDF via pdf-parse), split into
overlapping chunks (LangChain RecursiveCharacterTextSplitter), embedded, and
stored in pgvector. At query time the question is embedded and the nearest
chunks are retrieved with cosine distance (``) over an HNSW index.
AI agent & tool calling
The agent is given five read-only tools — getProduct, getStock,
getLowStock, getSales, and searchDocuments — with Zod-validated inputs
shared across the API, the agent, and MCP. Documents and tool results are treated
as untrusted data, never as instructions (prompt-injection hardening).
Model Context Protocol
apps/mcp publishes the same business tools through the MCP TypeScript SDK and is
covered by an integration test using a real MCP Client over an in-memory
transport — proving the tools are callable by any MCP-compatible host.
Evaluations
pnpm --filter @ai-assistant/api eval runs the dataset and reports:
retrievalHitRate 100.0% (8/8)
toolSelectionAccuracy PENDING (needs OPENAI_API_KEY) (0/8)
answerAccuracy PENDING (needs OPENAI_API_KEY) (0/6)
retrievalHitRate is verified deterministically against the mock embeddings in
CI; the agent metrics activate once a real model is configured.
Getting started
Run the whole stack with Docker
cp .env.example .env
docker compose up --build
This starts PostgreSQL + pgvector, applies migrations, seeds demo data (products, sales, and three example documents including a real PDF), and serves:
- Frontend:
- API:
Local development
pnpm install
docker compose up -d db # PostgreSQL + pgvector only
pnpm --filter @ai-assistant/api prisma:deploy
pnpm --filter @ai-assistant/api db:seed
pnpm --filter @ai-assistant/api start:dev # API on :3000
pnpm --filter @ai-assistant/web dev # UI on :5173
Enabling the real AI model
Set OPENAI_API_KEY in .env. No code changes are required — the OpenAI adapter
replaces the mock behind the EmbeddingProvider / model seam.
Testing
pnpm -r test # unit tests (shared + api)
pnpm --filter @ai-assistant/api test:int # API + RAG integration (needs DB)
pnpm --filter @ai-assistant/mcp test:int # MCP integration (needs DB)
51 tests: 34 unit (domain rules, pricing, services, agent, RAG) and 17
integration (Prisma/pgvector repositories, HTTP endpoints, full RAG pipeline, MCP
server). Continuous integration runs the full matrix — lint, typecheck, unit,
integration, evaluations, and build — against a real pgvector service
(.github/workflows/ci.yml).
Project structure
apps/
web/ React + Vite streaming chat UI
api/ NestJS API: agent, RAG, business use-cases, Prisma + pgvector
mcp/ Model Context Protocol server (reuses api business services)
packages/
shared/ Zod schemas, domain types, tool contracts, model pricing
Engineering notes
- Provider-agnostic by design: AI embeddings and the chat model are injected behind interfaces; a deterministic mock powers development, tests, and CI.
- Read-only business access: all database queries from tools are read-only; there is no authentication because the MVP is localhost-only.
- Single source of truth: the HTTP API and MCP server share one set of business use-cases and one set of Zod tool contracts.
Install
This server does not publish a one-line install command.
Open the repository installation guide