Blog Knowledge MCP Server

An MCP (Model Context Protocol) server that exposes your blog as a knowledge base. Search past articles and create new drafts directly from Claude Code while working in other repositories.

Views1
PublishedJan 14, 2026

Loading actions...

5 minBeginnerpromptSingle file

Skill content

Main instructions and any bundled files for this skill.

markdown

Blog Knowledge MCP Server

An MCP (Model Context Protocol) server that exposes your blog as a knowledge base. Search past articles and create new drafts directly from Claude Code while working in other repositories.

Why a Domain-Specific MCP?

MCP servers fall on a spectrum:

TypeExampleScope
General-purposeContext7, filesystem, web searchWorks for anyone, any project
Tool-specificGitHub, Slack, Linear MCPsWorks for anyone using that tool
Domain-specificThis blog MCPWorks for your specific data/workflow

This server is domain-specific by design:

  • Tied to a specific blog's frontmatter schema
  • Assumes a particular directory structure (src/content/tech/, src/content/travel/)
  • Optimized for a personal knowledge management workflow
  • Another person would need to fork and modify it for their setup

This is a feature, not a limitation. Domain-specific MCPs are powerful because they can:

  • Make assumptions - knows the exact schema, no configuration needed
  • Be opinionated - enforces your article template and tag taxonomy
  • Integrate deeply - reads your exact content structure, suggests from your tags

The tradeoff compared to general-purpose MCPs:

General-purposeDomain-specific
SetupInstall and goBuild it yourself
FlexibilityWorks everywhereWorks for your workflow
DepthBroad but shallowDeep integration
MaintenanceCommunity/vendorYou

The value here is turning your blog into a queryable knowledge base that follows you across all your projects.

Features

ToolDescription
search_blogSemantic search - finds articles by meaning, not just keywords
draft_articleCreate new posts with proper frontmatter, capture problems/solutions
list_articlesBrowse existing content
list_tagsSee your tag taxonomy with usage counts
suggest_tagsGet tag suggestions based on content
reindex_blogRebuild the semantic search index after adding articles

Search uses AI embeddings (sentence-transformers) to find articles by meaning, not just keyword matching:

You: "how to fix my mobile app build"
→ Finds: "Rider MAUI iOS Targets Greyed Out" (similarity: 0.38)
         "Building a Custom .NET MAUI Docker Image" (similarity: 0.28)

The query doesn't contain "MAUI", "iOS", or "Docker" - but semantic search understands the intent.

How it works:

  1. On first run, all articles are embedded using all-MiniLM-L6-v2 (runs locally on CPU)
  2. Embeddings are cached in .cache/embeddings.json
  3. Only changed files are re-embedded on subsequent runs
  4. Falls back to keyword search if dependencies aren't installed

Project Structure

blog-mcp-server/
├── .gitignore
├── .venv/                    # Virtual environment
├── .cache/                   # Semantic search index (gitignored)
├── README.md
├── INSTALLATION.md           # Detailed setup guide
├── pyproject.toml
├── scripts/
│   └── verify-setup.py       # Pre-flight check script
└── src/blog_mcp/
    ├── __init__.py
    ├── server.py             # MCP server entry point
    ├── services/
    │   ├── __init__.py
    │   └── indexer.py        # Semantic embeddings & search
    └── tools/
        ├── __init__.py
        ├── search.py         # search_blog (uses semantic if available)
        ├── draft.py          # draft_article
        ├── list.py           # list_articles, list_tags
        └── suggest.py        # suggest_tags

Quick Start

# 1. Install
cd /path/to/blog-mcp-server
python3 -m venv .venv
source .venv/bin/activate
pip install -e ".[semantic]"   # Include semantic search (recommended)

# 2. Verify (prints the claude mcp add command if successful)
BLOG_PATH=/path/to/blog BLOG_BASE_URL=https://your-url.com python3 scripts/verify-setup.py

# 3. Configure Claude Code (copy command from verify output)
claude mcp add blog-knowledge ...

# 4. Restart Claude Code and test
# Ask: "List my blog articles"

See INSTALLATION.md for detailed instructions and troubleshooting.

Example Output

You: "Search my blog for iOS simulator"
→ Found: "Rider MAUI iOS Targets Greyed Out or Missing"
  URL: https://your-blog.com/tech/rider-maui-ios-targets-disappeared/
  Tags: rider, maui, ios, dotnet, jetbrains

You: "What tags do I use?"
→ astro (7), serverless (4), seo (4), web-dev (3), dotnet (3), maui (3)...

Usage Examples

Once configured, Claude Code can use these tools in any repository:

Search for past solutions

You: "Have I written about iOS simulator issues?"
→ Finds your Rider MAUI article

You: "I'm getting iOS simulator issues in Rider"
Claude: [calls search_blog] "You wrote about this! See 'Rider MAUI iOS Targets
        Greyed Out' - the fix was usually just booting a simulator first..."

Create a draft while working

You: "Draft a blog post about this Docker caching fix"
→ Creates src/content/tech/2025-12-30-docker-caching-fix.md

You: "Draft a blog post about this Docker caching fix we just solved"
Claude: [calls draft_article with context from session]
        "Created draft at src/content/tech/2025-12-30-docker-layer-caching-fix.md
        with the error messages and commands we used."

Explore your content

You: "What tags do I use most?"
→ Lists tags with counts

You: "What have I written about Cloudflare?"
Claude: [calls list_articles with tags=["cloudflare"]]
        "You have 3 articles: Page Counter, Comments System, and Workers Guide"

Get tag suggestions

You: "What tags should I use for this Kubernetes article?"
Claude: [calls suggest_tags] "Based on your existing taxonomy, I suggest:
        docker, serverless, devops. You don't have a 'kubernetes' tag yet."

Tool Details

search_blog

search_blog(
    query: str,              # Search terms
    tags: list[str] = None,  # Filter by tags
    collection: str = None,  # "tech" or "travel"
    limit: int = 5           # Max results
)

Returns ranked results with title, path, description, tags, date, relevance score, and excerpt.

draft_article

draft_article(
    title: str,                    # Required
    collection: str = "tech",      # "tech" or "travel"
    description: str = None,       # SEO description
    tags: list[str] = None,        # Article tags
    problem: str = None,           # Problem section content
    solution: str = None,          # Solution section content
    code_snippets: list = None,    # [{language, code, description}]
    commands: list[str] = None,    # Terminal commands
    error_messages: list[str] = None  # Errors encountered
)

Creates a markdown file with proper frontmatter at src/content/{collection}/{date}-{slug}.md.

list_articles

list_articles(
    collection: str = None,  # Filter to tech/travel
    tags: list[str] = None,  # Filter by tags
    limit: int = 20          # Max results
)

Returns articles sorted by date (newest first).

list_tags

list_tags(
    collection: str = None   # Filter to tech/travel
)

Returns all tags with usage counts, sorted by frequency.

suggest_tags

suggest_tags(
    content: str,                  # Content to analyze
    existing_tags: list[str] = None  # Already selected (excluded from suggestions)
)

Returns suggested tags from your taxonomy plus potential new tags.

Environment Variables

VariableRequiredDescription
BLOG_PATHYesAbsolute path to your local blog repository
BLOG_BASE_URLYesBase URL of your published blog (for generating links)

Both must be set when configuring the MCP server. Search results include:

  • path - local file path for editing
  • url - published URL for referencing

Development

# Activate venv
source .venv/bin/activate

# Install dev dependencies
pip3 install -e ".[dev]"

# Run server directly (for debugging)
python3 -m blog_mcp.server

Testing

# Run all tests
pytest

# Run with verbose output
pytest -v

# Run specific test file
pytest tests/test_search.py

# Run specific test class
pytest tests/test_search.py::TestKeywordSearch

# Run with coverage
pytest --cov=blog_mcp

Test Structure

FileTests
test_search.pyKeyword search, semantic search, filtering, relevance
test_indexer.pyEmbedding generation, incremental indexing, change detection
test_phone_a_friend.pyContext-based search, solution formatting
test_draft.pyArticle creation, frontmatter, slug generation
test_list.pyArticle listing, tag counting, collection filtering
test_suggest.pyTag suggestions, exclusions, new tag detection

Tests use a mock blog with sample articles in a temp directory, so they don't depend on your actual blog content.

Future Enhancements

  • Read article content as MCP resources
  • Git integration (auto-commit drafts)
  • Template selection (how-to, troubleshooting, cheatsheet)
  • Watch mode for auto-reindex on file changes
  • Proactive retrieval (inject relevant context before every response)
Share: