eat(sync): generate homepage index markdown file listing all posts

This commit is contained in:
Wayne Sutton
2025-12-24 00:00:08 -08:00
parent 54e9dcc88c
commit a9d500ca4f
3 changed files with 163 additions and 9 deletions

View File

@@ -0,0 +1,115 @@
# MCP Server for markdown-site
Add MCP server capability so this blog can serve as a content source for AI tools like Cursor. When users fork the repo, they can run their own MCP server connected to their Convex deployment.
## Architecture
```mermaid
flowchart LR
subgraph local [Local Machine]
Cursor[Cursor/AI Client]
MCP[MCP Server]
end
subgraph cloud [Convex Cloud]
Convex[(Convex DB)]
Queries[Existing Queries]
end
Cursor -->|MCP Protocol| MCP
MCP -->|ConvexHttpClient| Queries
Queries --> Convex
```
## Files to create
### 1. MCP Server Script
Create `scripts/mcp-server.ts`
- Connects to Convex using `ConvexHttpClient` (same pattern as `scripts/sync-posts.ts`)
- Implements MCP protocol via stdio transport
- Exposes tools that wrap existing Convex queries:
- `list_posts` calls `api.posts.getAllPosts`
- `get_post` calls `api.posts.getPostBySlug`
- `list_pages` calls `api.pages.getAllPages`
- `get_page` calls `api.pages.getPageBySlug`
- `search_content` calls `api.search.search`
- `export_all` returns all posts with full content
### 2. Package updates
Update `package.json`
- Add dependency: `@modelcontextprotocol/sdk`
- Add script: `"mcp": "tsx scripts/mcp-server.ts"`
## Files to update
### 3. Documentation
Update `README.md` with MCP Server section:
- How to start the MCP server
- Cursor configuration example
- Available tools list
Update `content/pages/docs.md` with MCP documentation
Update `files.md` with new script description
Update `changelog.md` with new feature
## MCP Tools specification
| Tool | Description | Convex Query |
|------|-------------|--------------|
| `list_posts` | Get all published posts | `api.posts.getAllPosts` |
| `get_post` | Get post by slug | `api.posts.getPostBySlug` |
| `list_pages` | Get all published pages | `api.pages.getAllPages` |
| `get_page` | Get page by slug | `api.pages.getPageBySlug` |
| `search_content` | Full text search | `api.search.search` |
| `export_all` | Batch export all content | Multiple queries |
## User workflow after fork
```bash
# Install dependencies
npm install
# Start MCP server (reads VITE_CONVEX_URL from .env.local)
npm run mcp
```
Cursor config (`~/.cursor/mcp.json`):
```json
{
"mcpServers": {
"my-blog": {
"command": "npm",
"args": ["run", "mcp"],
"cwd": "/path/to/blog",
"env": {
"VITE_CONVEX_URL": "https://deployment.convex.cloud"
}
}
}
}
```
## Security
- Read-only access only (no mutations exposed)
- Uses existing Convex queries (same access as public API)
- Each user runs their own MCP server locally
- No authentication needed (blog content is public)
## Implementation todos
1. Add `@modelcontextprotocol/sdk` dependency to package.json
2. Create `scripts/mcp-server.ts` with MCP protocol implementation
3. Add `mcp` script to package.json
4. Add MCP Server section to README.md
5. Add MCP documentation to content/pages/docs.md
6. Add mcp-server.ts to files.md
7. Add MCP feature to changelog.md

42
public/raw/index.md Normal file
View File

@@ -0,0 +1,42 @@
# Homepage
This is the homepage index of all published content.
## Blog Posts (11)
- **[Netlify edge functions blocking AI crawlers from static files](/raw/netlify-edge-excludedpath-ai-crawlers.md)** - Why excludedPath in netlify.toml isn't preventing edge functions from intercepting /raw/* requests, and how ChatGPT and Perplexity get blocked while Claude works.
- Date: 2025-12-21 | Reading time: 4 min read | Tags: netlify, edge-functions, ai, troubleshooting, help
- **[Visitor tracking and stats improvements](/raw/visitor-tracking-and-stats-improvements.md)** - Real-time visitor map, write conflict prevention, GitHub Stars integration, and better AI prompts. Updates from v1.18.1 to v1.20.2.
- Date: 2025-12-21 | Reading time: 5 min read | Tags: features, stats, convex, updates, analytics
- **[Configure your fork in one command](/raw/fork-configuration-guide.md)** - Two options to set up your forked markdown framework: automated JSON config with npm run configure, or step-by-step manual guide.
- Date: 2025-12-20 | Reading time: 4 min read | Tags: configuration, setup, fork, tutorial
- **[v1.18.0 release: 12 versions of shipping](/raw/raw-markdown-and-copy-improvements.md)** - Everything new from v1.7 to v1.18.0. Automated fork setup, GitHub contributions graph, write page, mobile menu, aggregates, and more.
- Date: 2025-12-20 | Reading time: 8 min read | Tags: release, features, updates, developer-tools
- **[New features: search, featured section, and logo gallery](/raw/new-features-search-featured-logos.md)** - Three updates that make your markdown framework more useful: Command+K search, frontmatter-controlled featured items, and a scrolling logo gallery.
- Date: 2025-12-17 | Reading time: 4 min read | Tags: features, search, convex, updates
- **[About This Markdown Framework](/raw/about-this-blog.md)** - How this open source framework works with Convex for real-time sync and Netlify for deployment.
- Date: 2025-12-14 | Reading time: 4 min read | Tags: convex, netlify, open-source, markdown, ai, llm
- **[How to Publish a Blog Post](/raw/how-to-publish.md)** - A quick guide to writing and publishing markdown posts using Cursor after your framework is set up.
- Date: 2025-12-14 | Reading time: 3 min read | Tags: tutorial, markdown, cursor, IDE, publishing
- **[Writing Markdown with Code Examples](/raw/markdown-with-code-examples.md)** - A complete reference for writing markdown with links, code blocks, images, tables, and formatting. Copy examples directly into your posts.
- Date: 2025-12-14 | Reading time: 5 min read | Tags: markdown, tutorial, code
- **[Setup Guide - Fork and Deploy Your Own Markdown Framework](/raw/setup-guide.md)** - Step-by-step guide to fork this markdown sync framework, set up Convex backend, and deploy to Netlify in under 10 minutes.
- Date: 2025-12-14 | Reading time: 8 min read | Tags: convex, netlify, tutorial, deployment
- **[Using Images in Blog Posts](/raw/using-images-in-posts.md)** - Learn how to add header images, inline images, and Open Graph images to your markdown posts.
- Date: 2025-12-14 | Reading time: 4 min read | Tags: images, tutorial, markdown, open-graph
- **[Git commit message best practices](/raw/git-commit-message-best-practices.md)** - A guide to writing clear, consistent commit messages that help your team understand changes and generate better changelogs.
- Date: 2025-01-17 | Reading time: 5 min read | Tags: git, development, best-practices, workflow
## Pages (5)
- **[Docs](/raw/docs.md)**
- **[About](/raw/about.md)** - An open-source publishing framework for AI agents and developers.
- **[Projects](/raw/projects.md)**
- **[Contact](/raw/contact.md)**
- **[Changelog](/raw/changelog.md)**
---
**Total Content:** 11 posts, 5 pages
All content is available as raw markdown files at `/raw/{slug}.md`

View File

@@ -341,7 +341,7 @@ function generateRawMarkdownFile(
date: string,
tags: string[],
readTime?: string,
type: "post" | "page" = "post"
type: "post" | "page" = "post",
): void {
// Ensure raw output directory exists
if (!fs.existsSync(RAW_OUTPUT_DIR)) {
@@ -375,10 +375,7 @@ function generateRawMarkdownFile(
}
// Generate homepage index markdown file listing all posts
function generateHomepageIndex(
posts: ParsedPost[],
pages: ParsedPage[]
): void {
function generateHomepageIndex(posts: ParsedPost[], pages: ParsedPage[]): void {
const publishedPosts = posts.filter((p) => p.published);
const publishedPages = pages.filter((p) => p.published);
@@ -448,7 +445,7 @@ function generateHomepageIndex(
// Generate all raw markdown files during sync
function generateRawMarkdownFiles(
posts: ParsedPost[],
pages: ParsedPage[]
pages: ParsedPage[],
): void {
console.log("\nGenerating static markdown files in public/raw/...");
@@ -473,7 +470,7 @@ function generateRawMarkdownFiles(
post.date,
post.tags,
post.readTime,
"post"
"post",
);
}
@@ -488,7 +485,7 @@ function generateRawMarkdownFiles(
new Date().toISOString().split("T")[0], // pages don't have date
[], // pages don't have tags
undefined,
"page"
"page",
);
}
@@ -496,7 +493,7 @@ function generateRawMarkdownFiles(
generateHomepageIndex(posts, pages);
console.log(
`Generated ${publishedPosts.length} post files, ${publishedPages.length} page files, and 1 index file`
`Generated ${publishedPosts.length} post files, ${publishedPages.length} page files, and 1 index file`,
);
}