Skip to main content
Glama
README.md
# content-knowledge-mcp

An MCP server that gives a content agent access to a company's editorial knowledge: brand rules, a visual template catalog, and past posts with their outcomes. The knowledge lives in plain markdown files the company owns; the server only exposes it.

Built as the technical core of my BA thesis on AI agents and workflow automation. The version here is the generic engine, with an invented company as example knowledge.

## Why there is no vector database

The obvious move is to embed the knowledge and retrieve by similarity. This server deliberately does not, for two reasons.

**At this scale, structured search over curated files wins.** A company's editorial rules are tens of blocks, not tens of thousands. Splitting them into chunks and retrieving by cosine similarity adds an indexing step, a store to keep in sync and a class of failure that is hard to see, in exchange for recall you already had.

**Every rule carries an ID, and that is the point.** Rules are `R1`, `R17`, `R905`; templates are `T901`, `T905`; launch records are `L2`. The agent is instructed to cite the IDs it used. That turns each proposal into something a human can audit in seconds: the reviewer reads `rules_used: ["R920", "R903"]` and knows exactly which rules produced that post. An embedding returns a paragraph; it does not return an argument. When the goal is a human gate that works, being auditable beats being clever.

The cost is real and worth stating: search is lexical, so a query that shares no words with a rule will not find it. The server says `NO_MATCH` instead of pretending, which is the behaviour the evaluation cases check.

## Architecture

```
  Claude Desktop / Claude Code ──stdio──┐
                                        ├──▶ content-knowledge-mcp ──▶ KNOWLEDGE_PATH/
  n8n MCP Client Tool ──────────HTTP────┘         (3 tools)              guidelines/*.md   R# rules, L# launch records
       (host.docker.internal:8765)                                       templates/catalog.md   T# catalog
                                                                         past-posts/*.md        past posts and outcomes
```

Three tools, one transport switch, no state:

| Tool | Returns |
|---|---|
| `search_guidelines(query)` | matching rule blocks with their `R#` and `L#` IDs |
| `list_visual_templates(query)` | the template catalog, filtered, with `T#` IDs and usage rules |
| `get_post_examples(query)` | up to three past posts with their outcomes, for tone calibration |

The server owns no content. Point `KNOWLEDGE_PATH` at a different folder and it serves a different company: that is what made it publishable without touching the code.

## Quickstart

```bash
git clone https://github.com/alessandro-martelli/content-knowledge-mcp
cd content-knowledge-mcp
python3 -m venv .venv && .venv/bin/pip install fastmcp

# run the twelve checks against the example knowledge
KNOWLEDGE_PATH=examples/knowledge .venv/bin/python smoke_test.py

# stdio, for Claude Desktop or Claude Code
KNOWLEDGE_PATH=examples/knowledge .venv/bin/python server.py

# HTTP on :8765, for the n8n MCP Client Tool
KNOWLEDGE_PATH=examples/knowledge .venv/bin/python server.py --http
```

The example knowledge under `examples/knowledge/` is entirely invented: a fictional design school, with rules, launch records, a template catalog and three past posts. It exists so the repo runs for anyone, and so the tests have something to bite on.

## Evaluation

**Smoke tests: 12/12.** Each check goes through a real `fastmcp.Client` over the protocol, not through the helper functions, so a break in tool registration or transport shows up here.

**Agent-level protocol: 8 cases, 5 of them adversarial** (conflicting rules, out-of-scope request, tool unavailable, no matching template, underspecified input). Executed August 2026 against the two agents' prompts: **6 of 8 passed**, every output was valid JSON on the first try, and the two failures were defects in the test suite rather than in the agent. Both are written up in [`eval/test-log.md`](eval/test-log.md) with the fix each one needs. The log is kept as it came out: a suite that only ever reports success is not measuring anything.

## Honest limits

- Search is lexical and scores by term frequency. It does not understand synonyms; a rule phrased in words the query does not use will not be found.
- The knowledge folder layout is fixed (`guidelines/`, `templates/catalog.md`, `past-posts/`), and the catalog filename is hardcoded.
- There is no write path and no cache: every call reads the files. That is fine at this size and would not be at ten thousand blocks.
- The two open defects from the evaluation are not fixed in this code yet: `rules_used` cannot cite `L#` records, and the plan schema cannot express a row whose channel is unknown.

## Licence

MIT, see [LICENSE](LICENSE).

TDQS

A4/5.0

Scored across 3 tools

Disambiguation5/5

Each tool targets a distinct knowledge resource: editorial rules, visual templates, and past post examples. The descriptions clearly distinguish search, list, and get operations despite all supporting query. An agent can reliably choose the correct tool for each content creation step.

Naming Consistency5/5

All tool names follow the consistent snake_case verb_noun pattern: search_guidelines, list_visual_templates, get_post_examples. The verbs also accurately reflect the operation type, making the naming predictable and scannable.

Tool Count5/5

With only three tools, the server is tightly focused on content knowledge retrieval. Each tool covers a core knowledge domain for content creation—rules, templates, and examples—without redundant or unnecessary additions.

Completeness4/5

The set covers the main content-making inputs: brand/editorial guidelines, visual template catalog, and performance-calibrated post examples. Minor gaps exist such as fetching a specific rule by ID or retrieving more than three examples, but the tool set supports its purpose effectively.

Maintenance

ActivityMaintained
ResponsivenessNo issues