engineering-knowledge-mcp

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.

Category
Visit Server

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 in inbox/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 frontmatter tags also 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 calling create_knowledge.
  • get_knowledge(topicOrPath) — once you know (or search_knowledge told 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 (use update_knowledge instead).
  • 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) adds content to 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)

  1. Copy your existing .md files into knowledge/, sorted into whichever of api/ cloud/ data/ frontend/ general/ fits best (or add new topic folders — nothing enforces the initial five).
  2. Add minimal frontmatter (title, optionally tags) to each if it doesn't have any — not required, but it's cheap and get_knowledge/search results read better with a title.
  3. Break very long documents into headed ## sections if they aren't already — search_knowledge and update_knowledge both 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.
  4. Run npm test (sanity check nothing broke) and try a few search_knowledge / get_knowledge calls via the Inspector (§5) against your real content.
  5. 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 use create_knowledge to turn them into proper documents under knowledge/, grouped by topic. Where something doesn't cleanly fit an existing topic, use capture_knowledge instead 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/ and inbox/ under the repo root. Every caller-supplied path goes through safeResolve (src/paths.ts), which rejects absolute paths, .. traversal, null bytes, and anything that resolves outside the allowed directory.
  • create_knowledge sanitizes the topic into 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

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.

Official
Featured
TypeScript
Audiense Insights MCP Server

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.

Official
Featured
Local
TypeScript
Magic Component Platform (MCP)

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.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
graphlit-mcp-server

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.

Official
Featured
TypeScript
Kagi MCP Server

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.

Official
Featured
Python
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
Exa Search

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.

Official
Featured
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured
E2B

E2B

Using MCP to run code via e2b.

Official
Featured