<h1 align="center">
<a href="https://prompts.chat">
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.
Sign in to like and favorite skills
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.
MCP servers fall on a spectrum:
| Type | Example | Scope |
|---|---|---|
| General-purpose | Context7, filesystem, web search | Works for anyone, any project |
| Tool-specific | GitHub, Slack, Linear MCPs | Works for anyone using that tool |
| Domain-specific | This blog MCP | Works for your specific data/workflow |
This server is domain-specific by design:
src/content/tech/, src/content/travel/)This is a feature, not a limitation. Domain-specific MCPs are powerful because they can:
The tradeoff compared to general-purpose MCPs:
| General-purpose | Domain-specific | |
|---|---|---|
| Setup | Install and go | Build it yourself |
| Flexibility | Works everywhere | Works for your workflow |
| Depth | Broad but shallow | Deep integration |
| Maintenance | Community/vendor | You |
The value here is turning your blog into a queryable knowledge base that follows you across all your projects.
| Tool | Description |
|---|---|
| Semantic search - finds articles by meaning, not just keywords |
| Create new posts with proper frontmatter, capture problems/solutions |
| Browse existing content |
| See your tag taxonomy with usage counts |
| Get tag suggestions based on content |
| Rebuild 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:
all-MiniLM-L6-v2 (runs locally on CPU).cache/embeddings.jsonblog-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
# 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.
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)...
Once configured, Claude Code can use these tools in any repository:
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..."
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."
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"
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."
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( 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( 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( collection: str = None # Filter to tech/travel )
Returns all tags with usage counts, sorted by frequency.
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.
| Variable | Required | Description |
|---|---|---|
| Yes | Absolute path to your local blog repository |
| Yes | Base 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 editingurl - published URL for referencing# Activate venv source .venv/bin/activate # Install dev dependencies pip3 install -e ".[dev]" # Run server directly (for debugging) python3 -m blog_mcp.server
# 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
| File | Tests |
|---|---|
| Keyword search, semantic search, filtering, relevance |
| Embedding generation, incremental indexing, change detection |
| Context-based search, solution formatting |
| Article creation, frontmatter, slug generation |
| Article listing, tag counting, collection filtering |
| Tag 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.