Employee Knowledge Assistant
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Employee Knowledge AssistantHow many WFH days are allowed?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Employee Knowledge Assistant
RAG + MCP proof-of-concept: an internal assistant that answers employee policy questions using retrieval-augmented generation exposed through an MCP server, optionally summarized by Claude.
What this is
This repo is a TypeScript proof of concept for an Employee Knowledge Assistant at a fictional company, Nimbus Retail Inc. It retrieves passages from markdown policy docs, exposes that retrieval as an MCP search_knowledge tool (plus company://policies/* resources), and can have Claude answer only from those passages. A small Next.js App Router chat UI in apps/web is the human front end; the same MCP server can also be run standalone. The project is a growth exercise in wiring RAG, MCP, and Claude together—not a production HR system.
Claude is optional. Search, indexing, and MCP all run locally with no API key. Without ANTHROPIC_API_KEY, the chat UI still works in retrieval-only mode: it shows the matched policy snippets instead of a Claude summary.
Related MCP server: mcp-business-bot
Prerequisites
Node.js 20+ and npm (the MCP SDK requires Node 18+; the Next.js 16 app in
apps/webis happiest on 20+)Commands must be run from the
employee-knowledge-assistant/directory (the folder that contains thispackage.json), not fromDocuments/MCPor your home directoryAnthropic API key — optional. Retrieval and
npm run mcp:devnever call Anthropic. Add a key only if you want Claude to write a short answer. Create one at console.anthropic.com → API keys (paid / trial credits; there is no lasting free Claude API)
Setup
Clone this repository and
cdintoemployee-knowledge-assistant.Install root dependencies:
npm install.If you will run the chat UI, also install the Next.js app:
npm --prefix apps/web install.Copy environment defaults:
cp .env.example .envLeave
ANTHROPIC_API_KEYempty for free retrieval-only chat, or paste a key for Claude summaries. Optional:CLAUDE_MODEL(defaults toclaude-sonnet-4-6) andVECTOR_STORE_PATH(defaults to./data/vector-store.json).Build the local TF-IDF index from
knowledge/:npm run build:indexYou should see a chunk count and
Index built successfully at ….
Then run it in one of two ways:
(a) MCP server only — useful with an MCP inspector or any MCP client:
npm run mcp:devThis starts tsx mcp/server.ts on stdio. Success looks like:
employee-knowledge-assistant MCP server listening on stdio (37 chunks, 7 resources)The process then waits silently for a client. That is expected — it is not a website and will not open a browser. Stop it with Ctrl+C. It loads the vector store from VECTOR_STORE_PATH and markdown from knowledge/. It does not call Claude.
(b) Full chat UI — Next.js spawns the MCP server itself:
npm run dev:web(equivalent: npm --prefix apps/web run dev)
Open http://localhost:3000. Do not start mcp:dev in parallel for this path. The first POST /api/ask calls getMcpClient(), which runs npx tsx mcp/server.ts once per Next.js process and reuses that subprocess.
Keep the root .env at the repository root. The API route also loads ../../.env when the Next.js cwd is apps/web. There is a copy of the template at apps/web/.env.example. After changing .env, restart the Next.js process.
Project structure
employee-knowledge-assistant/
├── apps/web/ # Next.js App Router chat UI and POST /api/ask
├── server/
│ ├── rag/ # Load, chunk, TF-IDF embed, vector store, retrieve
│ ├── claude/ # Anthropic client + grounded system/user prompts
│ └── orchestrator/ # MCP client + answerQuestion() pipeline
├── mcp/
│ ├── server.ts # Stdio MCP server (tool + resources)
│ ├── tools/ # search_knowledge Zod schemas and handler
│ └── resources/ # company://policies/* URI map and readers
├── knowledge/ # Nimbus Retail policy markdown (the corpus)
├── scripts/ # build-index.ts — write the JSON vector store
├── tests/ # Vitest unit tests + gated e2e
├── docs/ # Architecture, data flow, interview notes
├── .env.example
├── package.json
└── tsconfig.jsonExample questions
These match facts in knowledge/. With a Claude key, wording varies but the numbers should not. Without a key, you get the raw retrieved passages (same facts).
Question | Expected |
How many WFH days are allowed? | Answered: 2 WFH days per week, requested in WorkSync at least 24 hours ahead. Sources typically include |
How many annual leave days do employees get? | Answered: 18 days per year for full-time staff. |
What happens if I submit an expense claim late? | Answered: submit in ExpenseFlow within 30 days; late reports are rejected unless Finance grants an exception. |
What is the domestic hotel allowance for business travel? | Answered: $180 per night domestic, booked through Nimbus Travel Desk. |
How long does a standard insurance claim take to process? | Answered: 15 business days after a complete HealthPortal submission. |
What is the company dress code policy? | Not in the knowledge base. Retrieval should fail the 0.05 score floor ( |
What is the cafeteria menu? | Same as above — out of scope for these policies. |
Running tests
npm test # vitest run — fast, mocked; e2e file self-skips
npm run test:watch
npm run test:e2e # RUN_E2E_TESTS=true; real Claude + real MCP (needs a key; costs a little)npm test covers loaders, chunking, TF-IDF, vector-store round-trip, retriever ranking, MCP tool/resource helpers, orchestrator assembly, retrieval-only mode, and error-handling fallbacks. tests/e2e.test.ts is skipped unless RUN_E2E_TESTS=true. It also skips (does not fail) if ANTHROPIC_API_KEY is unset. The e2e suite builds a temporary index so it does not overwrite ./data/vector-store.json.
Architecture
A question hits the Next.js UI, then POST /api/ask, which reuses one MCP stdio client. The orchestrator calls the MCP search_knowledge tool, which runs TF-IDF retrieval against the JSON store. If ANTHROPIC_API_KEY is set, Claude sees only those chunks (or an explicit “no context” user message). If the key is missing, answerQuestion() returns the retrieved passages directly. Either path yields an AnswerResult with answer, sources, and sufficientContext. Tools vs full-document resources, layering, and why TF-IDF is used here are in docs/architecture.md. A numbered request trace is in docs/data-flow.md.
Troubleshooting
Symptom | What the code is doing | Fix |
|
|
|
MCP prints | Stdio server is idle waiting for an MCP client | Expected. Use an inspector, or use the chat UI ( |
MCP process exits immediately: |
| From the repo root, run |
Chat answer: “I'm having trouble accessing the knowledge base right now…” |
| Ensure |
Chat starts with “No Anthropic API key is set, so this is the retrieved policy text…” | Retrieval-only mode ( | Optional. Add a key to |
Chat answer: “I couldn't generate a response right now. Please try again.” | Claude | Check the key at console.anthropic.com, billing/credits, and |
HTTP 400 |
| Send JSON |
HTTP 504 |
| Retry. For a hung MCP child, restart |
HTTP 500 | Uncaught error in the route (often MCP connect failing before | Same as spawn issues: index present, |
Next.js | Turbopack does not map NodeNext |
|
Answer says the knowledge base has no information; UI shows “No sources” | Retriever | Rephrase toward words that appear in |
Low-quality or off-topic snippets | Cosine similarity over TF-IDF bags of words, | Rebuild index after corpus changes. This POC does not use neural embeddings. |
What I'd change for production
Replace local TF-IDF with a real embeddings model (API or local) so retrieval is semantic, not token-overlap.
Replace
data/vector-store.jsonwith a real vector database (indexes, filters, concurrent writers).Add authentication and authorization on
POST /api/ask(there is none today).Wire real end-to-end cancellation (the 30s
Promise.racedoes not abort Claude or the MCP child).Structured logging and monitoring (tool latency, retrieval scores, Claude errors) instead of
console.erroronly.Run the MCP server as a long-lived process (or pool), not one stdio subprocess per Next.js server instance, so it can scale independently of the web tier.
This server cannot be deployed
Maintenance
Related MCP Connectors
- docs2mcpOAuthcom.docs2mcp
Query your own PDFs and documents from any MCP client. Every answer cites the page it came from.
Query any docs site via MCP. Submit a URL, ask questions, get cited answers.
Judged, citation-checked policy corpus over MCP. Keyless public reads; API key for AI tools.
Query your warehouse or a CSV with Claude/ChatGPT over MCP, governed by table-level ACL + audit.
Related MCP Servers
- FlicenseNot gradedqualityCmaintenanceConnects policy documents to Claude.ai via vector search, allowing natural language querying and retrieval of indexed documents.-
- FlicenseNot gradedqualityCmaintenanceEnables querying company knowledge base using RAG, providing accurate answers from internal documents via MCP.-
- FlicenseNot gradedqualityBmaintenanceEnables grounded question-answering over internal documents via a single MCP tool that retrieves relevant passages and generates answers with citations, returning sources and diagnostics.-
- FlicenseNot gradedqualityBmaintenanceEnables MCP clients to ask plain-language questions and receive answers grounded only in documents the configured role is cleared to read, with the same access-controlled tools available across any client.-