engineering-knowledge-mcp
Provides coding agents with a shared, Markdown-based engineering knowledge base to search, capture, create, and update internal conventions, API details, infrastructure configs, and development setup via lightweight MCP tools.
README
Engineering Knowledge MCP
A very lightweight local MCP server that gives coding agents (Claude Code, GitHub Copilot, etc.) a shared engineering knowledge base to search and update — internal conventions, API details, infra config, auth flows, local dev setup, and so on.
Knowledge lives as plain Markdown files in this Git repo. The MCP server is a thin, stateless read/write layer over the filesystem — nothing more.
1. What this does
- Coding agents can search the knowledge base instead of guessing at internal conventions or asking the user to repeat themselves.
- Agents can capture new facts with almost no friction (one tool call, no need to know where the fact belongs).
- Agents can create and update structured knowledge documents deterministically.
- Everything is Markdown in Git, so it's useful even without the MCP server — grep it, read it, edit it, review diffs, commit it, PR it, exactly like code.
2. Architecture
engineering-knowledge-mcp/
├── knowledge/ # the knowledge base itself (Markdown, organized by topic area)
│ ├── api/
│ ├── cloud/
│ ├── data/
│ ├── frontend/
│ └── general/
├── inbox/
│ └── knowledge-inbox.md # low-friction capture target; triage manually into knowledge/
├── src/
│ ├── index.ts # MCP server entrypoint (stdio transport)
│ ├── paths.ts # path sanitization / traversal protection
│ ├── knowledge.ts # search, get, create, update, capture logic
│ └── tools/index.ts # MCP tool registration + input schemas
├── test/ # node:test unit tests
├── CLAUDE.md # agent instructions auto-loaded by Claude Code when working in this repo
├── package.json
└── tsconfig.json
Design choices, deliberately:
- MCP over stdio only. No HTTP server, no Express — the client (Claude Code, Copilot, MCP Inspector) spawns this process and talks JSON-RPC over stdin/stdout.
- No database, no embeddings, no vector store. Search is case-insensitive token matching over Markdown sections, computed on demand. This is fine at the scale of tens-to-hundreds of small documents, and it means there's no index to keep in sync with the files on disk — the files are the source of truth, always.
- No in-memory index, no filesystem watching. Every tool call reads what it needs from disk at call time. Simpler, and cheap at this scale.
- No automatic git commits. Tool calls only touch the working tree. Review and commit/push are up to you. (The design leaves room to add auto-commit or PR creation later without changing the tool contracts.)
Official SDK note
The brief mentioned @modelcontextprotocol/server; the actual published package is
@modelcontextprotocol/sdk
(v1.30+), which is what this project uses (McpServer + StdioServerTransport).
3. How knowledge is stored
Each document is a Markdown file under knowledge/<area>/<topic>.md, with optional
minimal frontmatter:
---
title: APIM
tags:
- api
- apim
---
# APIM
## Base paths
Internal modelling APIs use ...
## Authentication
...
## Local development
...
No required schema beyond that — frontmatter is optional, headings are just normal
Markdown ## sections. search_knowledge and update_knowledge use ##-level (and
deeper) headings as the unit of a "section," so structuring documents with clear
headings makes both search results and updates more precise.
Captured-but-untriaged knowledge goes to inbox/knowledge-inbox.md as timestamped
entries. Periodically (by hand, or by asking an agent to help) move/organize entries
from the inbox into proper knowledge/ documents.
4. Running it
Requires Node.js 20+.
npm install
npm run build
npm start
For local iteration (runs directly from TypeScript via tsx, no build step):
npm run dev
Both start the server on stdio and wait for a client to connect — you won't see protocol traffic on the terminal; only startup/diagnostic logs (written to stderr, never stdout, since stdout is reserved for MCP protocol messages).
5. Testing with MCP Inspector
Interactive UI:
npx @modelcontextprotocol/inspector npm run dev
This opens a browser UI where you can call search_knowledge, list_knowledge_topics,
get_knowledge, capture_knowledge, create_knowledge, and update_knowledge by
hand and inspect their JSON Schemas and responses.
Non-interactive / scriptable:
npx @modelcontextprotocol/inspector --cli node dist/index.js --method tools/list
npx @modelcontextprotocol/inspector --cli node dist/index.js \
--method tools/call --tool-name search_knowledge --tool-arg query="apim authentication"
6. Example MCP client configuration
Claude Code / most MCP clients use a config block like:
{
"mcpServers": {
"engineering-knowledge": {
"command": "node",
"args": ["/absolute/path/to/engineering-knowledge-mcp/dist/index.js"]
}
}
}
For GitHub Copilot's MCP support, use the equivalent command/args stdio server
entry in its MCP configuration file. Run npm run build first so dist/index.js
exists, or point command/args at npx tsx /absolute/path/to/src/index.ts to run
from source directly.
7. How an agent should use the tools
This repo ships a CLAUDE.md with the instruction below, which Claude Code loads automatically whenever it's working inside this repo. For other clients (Copilot, etc.), add the equivalent instruction to their system prompt / instructions file:
Before asking the user about internal engineering conventions, infrastructure, APIs, authentication, platform configuration, or established development patterns, search the engineering knowledge MCP. Do not invent internal configuration values. If the user explicitly asks to remember, capture, or add durable engineering knowledge, use the knowledge MCP write tools.
Tool-by-tool guidance:
search_knowledge(query)— first stop for "how do we usually...", "what's our convention for...", "what's the base URL / auth flow for...". Returns ranked sections with file paths, not whole documents. Also searches not-yet-triaged entries ininbox/knowledge-inbox.md, so a recent capture is findable even before it's been filed under a proper topic. Among documents that already match on body/heading text, one whose frontmattertagsalso match a query word ranks higher — tags boost ranking, they don't create a match on their own.list_knowledge_topics()— no arguments; lists every document's path, title, and tags without full content. Use this to browse what exists when you don't have a good search term yet, or to check whether a topic already exists before callingcreate_knowledge.get_knowledge(topicOrPath)— once you know (orsearch_knowledgetold you) which document you want, fetch it in full. Accepts loose references:"apim","api/apim", or"knowledge/api/apim.md".capture_knowledge(content, suggestedTopic?)— use when the user says "remember this" / "note that" / states a fact worth keeping, and you don't want to make them figure out where it belongs. It just appends to the inbox.create_knowledge(topic, title, content)— use when adding a genuinely new topic that doesn't exist yet. Fails loudly if the topic already exists (useupdate_knowledgeinstead).update_knowledge(topicOrPath, heading, content, mode)— the deliberately not natural-language write tool. See the design note below.
Why update_knowledge takes heading + mode instead of a free-text change
The brief flagged this as something needing careful design: the goal is for the
agent (which has an LLM) to decide what a natural-language change means, not for
this server to run its own AI interpretation of instructions. So update_knowledge
takes a structural, deterministic target instead:
topicOrPath— which document.heading— the exact##/###/etc. heading text identifying a section. If it doesn't exist, a new##section with that heading is appended at the end of the document (so updates never silently fail against slightly-stale documents).content— the literal Markdown to write.mode:"append"(default) addscontentto the end of the section,"replace"overwrites the whole section body.
This means the calling agent is expected to have already turned "update the
local-dev section to mention the new port" into concrete Markdown content and picked
append/replace — exactly the kind of judgment call an LLM-backed client is
positioned to make, and exactly the kind of judgment call this lightweight server
should not be making from a raw string.
8. Importing an existing knowledge base
If you already have notes somewhere (a personal wiki, a folder of .md files, a
Notion export, a big "tribal knowledge" doc, Slack threads you've saved, etc.), there's
no import tool and no special format to convert to — this is deliberately just a
folder of Markdown files. Two ways to get started, roughly in order of how much of
your existing structure is worth preserving:
A. Drop files in directly (best when your notes are already reasonably organized)
- Copy your existing
.mdfiles intoknowledge/, sorted into whichever ofapi/ cloud/ data/ frontend/ general/fits best (or add new topic folders — nothing enforces the initial five). - Add minimal frontmatter (
title, optionallytags) to each if it doesn't have any — not required, but it's cheap andget_knowledge/search results read better with a title. - Break very long documents into headed
##sections if they aren't already —search_knowledgeandupdate_knowledgeboth operate at the heading level, so a 10,000-word single-section wall of text will search/update worse than the same content split under a few clear headings. - Run
npm test(sanity check nothing broke) and try a fewsearch_knowledge/get_knowledgecalls via the Inspector (§5) against your real content. - Review the diff and commit it yourself, same as any other change to this repo.
B. Let an agent do the migration for you (best for messy/unstructured source material)
Point Claude Code (or another coding agent, once this MCP is configured for it) at your existing notes and ask it to migrate them using the write tools. For example:
I have engineering notes in
~/notes/engineering/. Read through them and usecreate_knowledgeto turn them into proper documents underknowledge/, grouped by topic. Where something doesn't cleanly fit an existing topic, usecapture_knowledgeinstead so it lands in the inbox for me to review.
This works well because turning messy prose into "a title, some tags, a few clear
## sections" is exactly the kind of judgment call an LLM-backed agent is good at —
the same reasoning behind why update_knowledge pushes that judgment to the caller
rather than the server (see §7). The agent still can't write outside knowledge//
inbox/, and every resulting file shows up as a normal untracked/modified file for
you to review before committing — nothing is auto-committed.
Either way, treat the first pass as a rough draft: it's fine (expected, even) to
have capture_knowledge produce a long inbox you triage over a few sessions rather
than trying to get a perfect taxonomy up front.
9. Security notes
- All reads/writes are restricted to
knowledge/andinbox/under the repo root. Every caller-supplied path goes throughsafeResolve(src/paths.ts), which rejects absolute paths,..traversal, null bytes, and anything that resolves outside the allowed directory. create_knowledgesanitizes thetopicinto a safe filename segment before use.- No document content is ever executed, evaluated, or shelled out to.
- No tool ever runs a shell command based on MCP input.
- Errors are explicit (e.g. "no knowledge document found matching X") rather than falling back to guesses.
Recommended Servers
playwright-mcp
A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.
Audiense Insights MCP Server
Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.
Magic Component Platform (MCP)
An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.
VeyraX MCP
Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.
graphlit-mcp-server
The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.
Kagi MCP Server
An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.
Neon Database
MCP server for interacting with Neon Management API and databases
Exa Search
A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.
Qdrant Server
This repository is an example of how to create a MCP server for Qdrant, a vector search engine.
E2B
Using MCP to run code via e2b.