Skip to main content
Glama

šŸš€ Medium Blog MCP Server

AI-powered blog generation system built with FastMCP. Automates research, content generation, quality checks, and Medium export for technical blog posts.

✨ Features

  • šŸ” Multi-Source Research: Automatically gathers content from Wikipedia, arXiv, web search, and images

  • šŸ¤– AI Content Generation: Uses Claude API to generate high-quality blog posts

  • šŸ“Š Image Processing: Downloads and describes images with AI-generated descriptions

  • šŸ“ Quality Analysis: Comprehensive readability, citation, and SEO checks

  • āœ… Plagiarism Tracking: Hybrid manual/automated plagiarism checking workflow

  • šŸ“¤ Medium Export: One-click export to Medium-ready markdown format

  • šŸ’¾ SQLite Storage: Persistent storage of all drafts and research

Related MCP server: blog-generator-mcp

šŸ—ļø Architecture

Medium Blog MCP Server
ā”œā”€ā”€ Research Engine (Wikipedia, arXiv, Web, Images)
ā”œā”€ā”€ AI Content Generator (Claude API)
ā”œā”€ā”€ Image Handler (Download + AI Description)
ā”œā”€ā”€ Quality Analyzer (Readability, Citations, SEO)
ā”œā”€ā”€ Medium Exporter (Markdown + Assets)
└── SQLite Database (Sessions, Drafts, Research)

šŸ“‹ Prerequisites

šŸš€ Quick Start

1. Clone and Install

# Clone repository
git clone <your-repo-url>
cd medium-blog-mcp

# Activate virtual environment
uv init
uv sync

# Install dependencies
uv add -r requirements.txt

# use these uv commands to test , run mcp servers
Test the server - uv run fastmcp dev main.py
Run the server - uv run fastmcp run main.py
Add the server to claude desktop - uv run fastmcp install
claude-desktop main.py

2. Configure Environment

# Copy environment template
cp .env.example .env

# Edit .env and add your DB URL
# DATABASE_URL=YOUR_SQLITE_DB_URL

3. Run the Server

python main.py

The MCP server will start and be available for Claude Desktop or other MCP clients.

šŸ”§ Configuration for Claude Desktop

Add to your Claude Desktop claude_desktop_config.json:

{
  "mcpServers": {
    "medium-blog-generator": {
      "command": "[Your/Path/to/uv]",
      "args": [
        "--directory",
        "C:\\medium_mcp",
        "run",
        "fastmcp",
        "run",
        "main.py"
      ],
      "env": {},
      "transport": "stdio",
      "type": null,
      "cwd": null,
      "timeout": null,
      "description": null,
      "icon": null,
      "authentication": null
    }
  }
}

Config locations:

  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json

  • Windows: %APPDATA%\Claude\claude_desktop_config.json

šŸ“– Complete Workflow

Step 1: Create Session

create_blog_session(topic="Latest AI Model Advancements", target_length="medium")

Step 2: Research Phase ⭐ USER CHECKPOINT

research_topic(session_id="abc123", depth="comprehensive")
get_research_summary(session_id="abc123")  # Review research
approve_research(session_id="abc123")       # Approve to continue

Step 3: Outline Generation ⭐ USER CHECKPOINT

generate_outline(session_id="abc123", style="technical", num_sections=5)
# Review outline, optionally modify
approve_outline(session_id="abc123")

Step 4: Content Generation

generate_full_content(session_id="abc123")
get_full_draft(session_id="abc123")  # Review full draft

Step 5: Plagiarism Checking ⭐ USER CHECKPOINT (Manual)

prepare_plagiarism_chunks(session_id="abc123")
# Copy chunks to Grammarly/QuillBot/GPTZero manually
record_plagiarism_result(session_id="abc123", chunk_id=1, 
                        plagiarism_score=2.3, ai_detection_score=8.5, 
                        tool_used="Grammarly")

Step 6: Quality Analysis ⭐ USER CHECKPOINT

run_quality_analysis(session_id="abc123")  # Get detailed QA report
approve_final_draft(session_id="abc123")   # Final approval

Step 7: Export to Medium

export_to_medium(session_id="abc123")

šŸ› ļø Available MCP Tools

Session Management

  • create_blog_session - Start new blog project

  • get_session_status - Check progress

  • list_sessions - List all sessions

Research

  • research_topic - Multi-source research

  • get_research_summary - Review findings

  • add_custom_source - Add manual sources

  • approve_research - ⭐ Proceed to outline

Outline

  • generate_outline - AI-generated structure

  • modify_outline - Make changes

  • approve_outline - ⭐ Proceed to writing

Content Generation

  • generate_full_content - Generate blog

  • get_full_draft - Review content

  • regenerate_section - Improve specific section

Plagiarism Checking

  • prepare_plagiarism_chunks - Split for checking

  • record_plagiarism_result - ⭐ Record manual checks

  • get_plagiarism_summary - View all results

Quality & Export

  • run_quality_analysis - Comprehensive QA

  • approve_final_draft - ⭐ Final approval

  • export_to_medium - Generate export files

šŸ“ Project Structure

medium-blog-mcp/
ā”œā”€ā”€ main.py                   # FastMCP server (all tools)
ā”œā”€ā”€ database.py               # SQLAlchemy models & DB operations
ā”œā”€ā”€ research.py               # Multi-source research engine
ā”œā”€ā”€ content_generator.py      # Claude API content generation
ā”œā”€ā”€ image_handler.py          # Image download & AI descriptions
ā”œā”€ā”€ quality.py                # Quality analysis & readability
ā”œā”€ā”€ exporter.py               # Medium markdown export
ā”œā”€ā”€ config.py                 # Configuration management
ā”œā”€ā”€ requirements.txt          # Python dependencies
ā”œā”€ā”€ .env.example              # Environment variables template
ā”œā”€ā”€ README.md                 # This file
└── data/                     # Generated data (auto-created)
    ā”œā”€ā”€ blog_database.db      # SQLite database
    ā”œā”€ā”€ sessions/             # Session-specific data
    │   └── {session_id}/
    │       └── images/       # Downloaded images
    ā”œā”€ā”€ exports/              # Final exports
    │   └── {session_id}/
    │       ā”œā”€ā”€ blog_post.md
    │       ā”œā”€ā”€ images/
    │       ā”œā”€ā”€ citations.txt
    │       ā”œā”€ā”€ metadata.json
    │       └── qa_report.txt
    └── images/               # Image storage

šŸŽÆ Usage Example

Here's a complete example of generating a blog about AI models:

# 1. Create session
create_blog_session(topic="GPT-4 vs Claude 3: Technical Comparison", target_length="medium")
# Returns: {"session_id": "abc123", ...}

# 2. Research
research_topic(session_id="abc123", depth="comprehensive")
get_research_summary(session_id="abc123")
# Review the 15-20 sources gathered
approve_research(session_id="abc123")

# 3. Generate outline
generate_outline(session_id="abc123", style="technical", num_sections=5)
# Review outline structure
approve_outline(session_id="abc123")

# 4. Generate content
generate_full_content(session_id="abc123")
get_full_draft(session_id="abc123")
# Review the ~2500 word blog with images

# 5. Check plagiarism manually
prepare_plagiarism_chunks(session_id="abc123")
# Copy chunks to Grammarly, check, then:
record_plagiarism_result(session_id="abc123", chunk_id=1, 
                        plagiarism_score=1.8, ai_detection_score=7.2, 
                        tool_used="Grammarly")

# 6. Quality analysis
run_quality_analysis(session_id="abc123")
# Review QA report
approve_final_draft(session_id="abc123")

# 7. Export
export_to_medium(session_id="abc123")
# Get Medium-ready markdown + all assets!

Total time: 30-45 minutes for a complete 2500-word blog!

šŸ” Quality Checks

The system automatically checks:

Readability

  • Flesch Reading Ease score

  • Flesch-Kincaid Grade Level

  • Average sentence length

  • Passive voice percentage

Citations

  • All sources properly cited

  • Citation format validation

  • Unused sources identified

Images

  • All images have descriptions

  • Alt text present

  • Proper placement

SEO

  • Title length (50-70 chars optimal)

  • Header hierarchy (H1, H2, H3)

  • Keyword presence

  • Meta information

Structure

  • Word count vs target

  • Section balance

  • Overall organization

šŸ“Š Database Schema

Tables

  • sessions - Blog sessions

  • research_sources - Research data

  • outlines - Generated outlines

  • blog_drafts - Blog content versions

  • images - Downloaded images

  • plagiarism_checks - Manual check results

  • quality_checks - QA reports

All data persists across sessions and can be resumed.

šŸ› Troubleshooting

Database Issues

# Reset database (WARNING: deletes all data)
rm data/blog_database.db
python main.py  # Will recreate database

Image Download Failures

  • Check internet connection

  • Some images may be behind authentication

  • System will create fallback descriptions

šŸ”„ Development Roadmap

Current Version (v1.0)

  • āœ… Multi-source research

  • āœ… AI content generation

  • āœ… Image processing

  • āœ… Quality analysis

  • āœ… Medium export

Future Enhancements (v2.0+)

  • šŸ”² Automated plagiarism APIs

  • šŸ”² Multiple format exports (HTML, PDF)

  • šŸ”² Note-taking app integrations (Obsidian, Notion)

  • šŸ”² Multi-blog management

  • šŸ”² SEO optimization suggestions

  • šŸ”² Social media snippet generation

šŸ“ License

MIT License - feel free to use and modify for your needs.

šŸ¤ Contributing

Contributions welcome! Please:

  1. Fork the repository

  2. Create a feature branch

  3. Make your changes

  4. Submit a pull request

šŸ’¬ Support

For issues or questions:

  • Open an issue on GitHub

  • Check the documentation

  • Review example workflows

šŸ™ Credits

Built with:


Happy blogging! šŸš€

Available Tools

23 tools
add_custom_sourceAdd Custom SourceC

Add additional source manually

Inputs: url (required), session_id (required), source_type. Returns: object

approve_final_draftApprove Final DraftB

⭐ USER FINAL APPROVAL - Mark blog as ready for export

Inputs: session_id (required). Returns: object

approve_outlineApprove OutlineA

⭐ USER APPROVES outline to proceed with content generation

Inputs: session_id (required). Returns: object

approve_researchApprove ResearchC

⭐ USER APPROVES research to proceed to outline generation

Inputs: session_id (required), feedback. Returns: object

create_blog_sessionCreate Blog SessionC

Start a new blog writing session

Inputs: topic (required), target_length. Returns: object

export_to_mediumExport To MediumC

Export blog to Medium-ready markdown format

Creates:

  • Medium-formatted markdown file

  • Images folder with all images

  • Citations/References section

  • Metadata JSON

  • QA Report

Inputs: session_id (required). Returns: object

generate_full_contentGenerate Full ContentA

Generate complete blog post - Claude Desktop will write the blog based on outline

This tool provides the outline and research context. Claude (you) should:

  1. Review the approved outline and research

  2. Write the complete blog post in markdown

  3. Call save_draft() with the generated content

Inputs: session_id (required). Returns: object

generate_outlineGenerate OutlineB

Generate blog outline - Claude Desktop will create the outline based on research

This tool provides the research context and instructions. Claude (you) should:

  1. Review the research sources and images

  2. Create a comprehensive outline in JSON format

  3. Call save_outline() with the generated outline

Inputs: session_id (required), style, num_sections. Returns: object

get_export_filesGet Export FilesC

Retrieve all export files for download

Inputs: session_id (required). Returns: object

get_full_draftGet Full DraftA

Retrieve the complete generated blog post

Inputs: session_id (required). Returns: object

get_plagiarism_summaryGet Plagiarism SummaryC

Summary of all plagiarism checks performed

Inputs: session_id (required). Returns: object

get_research_summaryGet Research SummaryB

⭐ USER CHECKPOINT: Review all research before proceeding

Returns detailed summary of all sources, images, themes, and credibility scores

Inputs: session_id (required). Returns: object

get_session_statusGet Session StatusC

Check current progress of a blog session

Inputs: session_id (required). Returns: object

list_sessionsList SessionsC

List all blog sessions

Inputs: status_filter. Returns: object

modify_outlineModify OutlineB

Modify outline sections, titles, or structure

Inputs: session_id (required), modifications (required). Returns: object

prepare_plagiarism_chunksPrepare Plagiarism ChunksB

Split content into <10k character chunks for external plagiarism tools

Inputs: session_id (required). Returns: object

record_plagiarism_resultRecord Plagiarism ResultC

⭐ USER records results from external plagiarism check

Inputs: chunk_id (required), tool_used (required), session_id (required), plagiarism_score (required), +2 more. Returns: object

regenerate_sectionRegenerate SectionC

Regenerate specific section with user feedback

Inputs: feedback (required), session_id (required), section_name (required). Returns: object

request_more_researchRequest More ResearchA

Request additional focused research

Inputs: session_id (required), specific_queries (required). Returns: object

research_topicResearch TopicB

Research topic from multiple sources + fetch relevant images

Sources:

  • Wikipedia API

  • arXiv API (for AI/ML papers)

  • DuckDuckGo web search

  • Image search for charts/benchmarks/diagrams

Inputs: session_id (required), depth, specific_queries. Returns: object

run_quality_analysisRun Quality AnalysisB

Run automatic quality checks on final draft

Checks:

  1. Readability scores (Flesch-Kincaid)

  2. Citation tracking

  3. Image placement validation

  4. Structure analysis

  5. SEO basics

Inputs: session_id (required). Returns: object

save_draftSave DraftB

Save the generated blog draft to database

Inputs: content (required), session_id (required). Returns: object

save_outlineSave OutlineC

Save the generated outline to database

Inputs: session_id (required), outline_data (required). Returns: object

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    B3.1/5.0

    Scored across 23 tools

    Disambiguation4/5

    Most tools map to distinct workflow stages (research, outline, draft, plagiarism, QA, export), but a few could be confused: generate_outline/generate_full_content are agent instructions that overlap conceptually with save_outline/save_draft, and the multiple get_*_summary tools require reading descriptions to distinguish.

    Naming Consistency5/5

    Every tool follows a consistent verb_noun snake_case pattern (create_*, get_*, list_*, approve_*, save_*, export_*). The verbs are predictable and the workflow stage is clear from the name.

    Tool Count3/5

    At 23 tools, the surface feels heavy and falls in the borderline 16-25 range, though the multi-stage workflow gives most tools a purpose. Several session and file getters could potentially be consolidated.

    Completeness3/5

    The end-to-end pipeline is covered (research → outline → draft → plagiarism → QA → export), but there are notable gaps: sessions can be created/listed but not updated/deleted, saved outlines cannot be retrieved directly, and the server exports markdown rather than publishing to Medium.

    Maintenance

    ActivityInactive
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers