Build a Permission-Aware Knowledge Hub as an MCP Server: the explanation
A working engineering knowledge hub, Wayfinder, taken apart in illustrated modules. Engineers connect the AI assistant they already use (Claude Code, Cursor or Claude Desktop) through the Model Context Protocol and ask "Why does billing retry three times?", "Who owns routing?" or "What did we decide about Kafka?". Wayfinder searches the team's docs, runbooks, postmortems, architecture decisions, issues and pull requests, and returns cited passages that this engineer is allowed to read: the permission filter runs inside the database query, before anything is ranked. The server has no language model of its own; the assistant's model writes the answer from the passages. One write tool files an issue only after the user confirms it, every call lands in an audit log, and a React console lets people search as themselves, connect their client and see who can read what. The demo company, Tidewater Freight, is fictional: 41 people, 6 teams and 403 sources.
Who it is for: anyone who knows a little Python and wants to understand, rebuild or extend a real MCP server with search, sign-in and permissions, from beginners to working engineers. Each module says what to read first.
How each module is laid out
| Section | Answers |
|---|---|
| Where this fits | the same system map in every module, with this module's parts highlighted |
| What it does | the idea in one picture, then each production practice at a glance: what, why, how, when, where |
| Use cases and examples | the same practice at Tidewater Freight and in other industries |
| How it works | the mechanism step by step, one figure per step, with real values |
| Code tour | the real files, short excerpts, every line explained, concept boxes for new ideas, and a "what happens when" trace |
| Design decisions | what was chosen, the alternatives and why, with measured numbers, and when to choose differently |
| What can go wrong | failures and attacks, how the code handles each, and the test that proves it |
| Try it yourself | exact commands and what you should see |
| Check yourself, Key terms | a short quiz and a glossary |
Figures use one colour language: blue is our system, amber is a model (the AI client's model or the embedding model) or anything uncertain, green is correct, safe or allowed, red is failure, attack or hidden from this user, grey is background.
Modules
| # | Module | Main code |
|---|---|---|
| 0 | Project overview: a guided tour of Wayfinder | screenshots of the real console, no code |
| 1 | The problem: knowledge AI assistants cannot see | seed/world.md, prototype/ |
| 2 | The solution: an MCP server with permission-aware retrieval | main.py, mcp/server.py, search.py |
| 3 | MCP in depth: protocol, transports and the SDK | research/spike_mcp_server.py, mcp/server.py, mcp/stdio.py |
| 4 | High-level design | main.py, nginx.conf.template, docker-compose.yml |
| 5 | Low-level design: data, ids, API and schemas | models/, alembic/, types.py, api/routes.py, mcp/models.py |
| 6 | The seed company: Tidewater Freight | seed/, seed/tools/validate.py, index/loader.py |
| 7 | The access model: groups and visibility | access.py, seed/access.md, auth/scopes.py |
| 8 | Indexing and embeddings | index/chunker.py, index/embedder.py, index/indexer.py |
| 9 | Hybrid search and ranking | search.py |
| 10 | Permission filtering before ranking | search.py, knowledge.py, test_security_acl.py |
| 11 | The MCP tools, resources and prompts | mcp/server.py, mcp/models.py, mcp/render.py, knowledge.py |
| 12 | OAuth 2.1 for MCP clients and personal tokens | auth/oauth.py, auth/pages.py, auth/pats.py, auth/sessions.py |
| 13 | Writing safely: create_issue and elicitation | mcp/server.py (create_issue), knowledge.py |
| 14 | The audit log and redaction | audit.py, api/routes.py |
| 15 | The web console | console/src |
| 16 | Connecting Claude Code, Cursor and Claude Desktop | pages/Connect.tsx, mcp/stdio.py, research/claude-code-livetest.md |
| 17 | Evaluating retrieval and the 0-leak gate | evals/, seed/eval/ |
| 18 | Security: threats and fixes | core/middleware.py, core/http.py, core/proxy.py, test_security_review.py |
| 19 | Containers and the local stack | server/Dockerfile, console/Dockerfile, docker-compose.yml |
| 20 | Deploying to Google Cloud with CI/CD | deploy/, .github/workflows/ |