Skip to main content
Glama
README.md
# BlogPublisher

Multi-platform blog publishing system that integrates with ResearchAgent for automated content distribution.

## Overview

BlogPublisher receives SEO-optimized articles from ResearchAgent and publishes them to multiple platforms:

- Personal website blog
- LinkedIn
- Twitter/X (as threads)
- Substack (email newsletter)
- Facebook (planned)
- Instagram (planned)

## Architecture

```
ResearchAgent (SEO writing) → BlogPublisher (distribution) → Multiple Platforms
```

### Features

✅ **Article Management**
- Save articles with SEO metadata
- Draft/scheduled/published status tracking
- PostgreSQL storage

✅ **Multi-Platform Publishing**
- Publish to 4+ platforms simultaneously
- Platform-specific content formatting
- Publication tracking and analytics

✅ **Scheduling**
- Schedule posts for future publication
- Automated cron-based publishing
- Retry logic for failures

✅ **MCP Integration**
- 7 MCP tools for Claude Desktop
- Seamless integration with ResearchAgent
- Single conversation workflow

## Quick Start

### 1. Prerequisites

- Python 3.10+
- PostgreSQL 14+
- Platform API credentials (see API Setup below)

### 2. Installation

```bash
cd ~/1_REPOS/BlogPublisher

# Create virtual environment
python -m venv venv
source venv/bin/activate  # On Windows: venv\Scripts\activate

# Install dependencies
pip install -r requirements.txt

# Setup environment
cp .env.example .env
# Edit .env with your credentials
```

### 3. Database Setup

```bash
# Create PostgreSQL database
createdb blogpublisher

# Update DATABASE_URL in .env
DATABASE_URL=postgresql://user:password@localhost:5432/blogpublisher

# Initialize database (tables auto-created on first run)
python backend/app.py  # Runs migrations
```

### 4. Claude Desktop Configuration

Add to `~/Library/Application Support/Claude/claude_desktop_config.json`:

```json
{
  "mcpServers": {
    "research-agent": {
      "command": "python",
      "args": ["/Users/tmac/1_REPOS/ResearchAgent/backend/mcp_server.py"]
    },
    "blogpublisher": {
      "command": "python",
      "args": ["/Users/tmac/1_REPOS/BlogPublisher/backend/mcp_server.py"],
      "env": {
        "DATABASE_URL": "postgresql://localhost:5432/blogpublisher"
      }
    }
  }
}
```

Restart Claude Desktop.

## Usage

### Daily Blogging Workflow

In Claude Desktop:

```
1. "Write SEO article about [topic]"
   → ResearchAgent creates optimized article

2. "Save this article to BlogPublisher"
   → Returns article_id

3. "Publish to website and LinkedIn immediately"
   → Publishes to both platforms

4. "Schedule Twitter thread for tomorrow at 10 AM"
   → Queues Twitter publication
```

### MCP Tools

**save_article**
```json
{
  "title": "Article Title",
  "content": "Markdown content...",
  "summary": "Brief summary",
  "keywords": ["seo", "keywords"],
  "seo_score": {"score": 85}
}
```
Returns: `article_id`

**publish_article**
```json
{
  "article_id": "uuid",
  "platforms": ["website", "linkedin", "twitter", "substack"]
}
```
Returns: Publication results per platform

**schedule_article**
```json
{
  "article_id": "uuid",
  "platforms": ["linkedin", "twitter"],
  "publish_time": "tomorrow at 6 AM"
}
```
Returns: Schedule confirmation

**get_article**
```json
{
  "article_id": "uuid"
}
```
Returns: Full article with publication status

**list_articles**
```json
{
  "status": "published",
  "limit": 10
}
```
Returns: List of articles

**format_for_platform**
```json
{
  "article_id": "uuid",
  "platform": "twitter"
}
```
Returns: Platform-optimized content

**generate_social_posts**
```json
{
  "article_id": "uuid"
}
```
Returns: Social media variants for all platforms

## API Setup

### Required Credentials

#### Website Blog
- `WEBSITE_API_URL`: Your blog API endpoint
- `WEBSITE_API_KEY`: API authentication key

#### LinkedIn
1. Create LinkedIn App: https://www.linkedin.com/developers/apps
2. Get OAuth 2.0 access token
3. Set `LINKEDIN_ACCESS_TOKEN`

#### Twitter/X
1. Create Twitter Developer account: https://developer.twitter.com
2. Create App and get API keys
3. Set:
   - `TWITTER_API_KEY`
   - `TWITTER_API_SECRET`
   - `TWITTER_ACCESS_TOKEN`
   - `TWITTER_ACCESS_SECRET`

#### Substack
1. Get Substack API credentials from your publication settings
2. Set:
   - `SUBSTACK_API_KEY`
   - `SUBSTACK_PUBLICATION_ID`

### Optional: Facebook & Instagram
- `FACEBOOK_ACCESS_TOKEN`
- `FACEBOOK_PAGE_ID`
- `INSTAGRAM_USERNAME`
- `INSTAGRAM_PASSWORD`

## Platform-Specific Formatting

### LinkedIn
- First 3 sentences as hook
- Professional tone
- 1-3 hashtags
- Link at end

### Twitter/X
- Converts to thread (280 chars/tweet)
- Numbered tweets (1/N)
- Link in last tweet
- Key points extracted

### Substack
- Full article as HTML email
- Subject line from title
- Preview text from summary
- Created as draft (manual publish)

### Website
- Markdown to HTML conversion
- SEO frontmatter
- Categories/tags
- Featured image support

## Automation

### Scheduler (Cron Jobs)

Start the scheduler:

```bash
python backend/scheduler/cron.py
```

Or run as background service:

```bash
# Using systemd (Linux)
sudo systemctl enable blogpublisher-scheduler
sudo systemctl start blogpublisher-scheduler

# Using launchd (macOS)
# See docs/deployment/macos-launchd.md
```

The scheduler runs every minute and publishes any pending scheduled posts.

## REST API

Optional REST API for programmatic access:

```bash
# Start API server
python backend/app.py
# Runs on http://localhost:8001

# API docs
open http://localhost:8001/docs
```

### Endpoints

- `POST /articles` - Create article
- `GET /articles` - List articles
- `GET /articles/{id}` - Get article
- `GET /health` - Health check

## Development

### Project Structure

```
BlogPublisher/
├── backend/
│   ├── database/
│   │   ├── models.py      # SQLAlchemy models
│   │   └── db.py          # Database connection
│   ├── publishers/
│   │   ├── base.py        # Abstract publisher
│   │   ├── website.py     # Website publisher
│   │   ├── linkedin.py    # LinkedIn publisher
│   │   ├── twitter.py     # Twitter publisher
│   │   └── substack.py    # Substack publisher
│   ├── scheduler/
│   │   └── cron.py        # Automated publishing
│   ├── mcp_server.py      # MCP integration
│   └── app.py             # FastAPI server
├── data/
│   ├── articles/          # Article storage
│   └── media/             # Images
├── requirements.txt
├── .env.example
└── README.md
```

### Adding New Platforms

1. Create publisher class in `backend/publishers/yourplatform.py`
2. Inherit from `BasePublisher`
3. Implement required methods:
   - `validate_config()`
   - `format_content()`
   - `publish()`
4. Add to `Platform` enum in `models.py`
5. Update `get_publisher()` in `mcp_server.py` and `cron.py`

Example:

```python
from .base import BasePublisher

class NewPlatformPublisher(BasePublisher):
    def validate_config(self):
        if "api_key" not in self.config:
            raise ValueError("Missing api_key")

    def format_content(self, content, metadata=None):
        # Platform-specific formatting
        return formatted_content

    def publish(self, title, content, metadata=None):
        # API call to publish
        return {
            "success": True,
            "post_id": "...",
            "url": "..."
        }
```

## Troubleshooting

### Database Connection Issues

```bash
# Check PostgreSQL is running
pg_isready

# Test connection
psql -U user -d blogpublisher
```

### MCP Tools Not Showing

1. Check Claude Desktop config file location
2. Verify Python path in config
3. Restart Claude Desktop
4. Check logs: `~/Library/Logs/Claude/mcp.log`

### Publishing Failures

Check platform API credentials:

```bash
# Test LinkedIn token
curl -H "Authorization: Bearer $LINKEDIN_ACCESS_TOKEN" \
  https://api.linkedin.com/v2/me

# Test Twitter credentials
# Use backend/publishers/test_publisher.py
```

## Testing

```bash
# Test database
python backend/database/db.py

# Test publishers
python backend/publishers/test_publisher.py

# Test MCP tools (requires running server)
python backend/mcp_server.py
```

## Roadmap

- [x] Core article storage
- [x] Website/LinkedIn/Twitter/Substack publishers
- [x] MCP integration
- [x] Scheduling system
- [ ] Facebook & Instagram publishers
- [ ] Analytics dashboard
- [ ] Content calendar UI
- [ ] Image optimization
- [ ] Link shortening
- [ ] A/B testing
- [ ] Performance metrics

## License

MIT

## Support

For issues or questions:
- Create GitHub issue
- Check documentation in `/docs`
- See ResearchAgent integration guide