Dev.to Blog Publisher MCP Server
by Dineshv0311
README.md
# Dev.to Blog Publisher MCP Server
A custom [Model Context Protocol (MCP)](https://modelcontextprotocol.io) server that lets Claude publish markdown blog posts directly to [Dev.to](https://dev.to) — no copy-pasting into the Dev.to editor required.
Built with [FastMCP](https://github.com/jlowin/fastmcp) and the [Dev.to API](https://developers.forem.com/api).
## Overview
This server exposes a single MCP tool, `publish_blog_to_devto`, which any MCP-compatible client (like Claude Desktop) can call to create an article on your Dev.to account. Pair it with the official [filesystem MCP server](https://github.com/modelcontextprotocol/servers/tree/main/src/filesystem) and you can ask Claude to:
> "Read `blog.txt` from my drafts folder, refine the content, and publish it to Dev.to as a draft with relevant tags."
Claude reads the file, cleans up the writing, and calls this server to publish it — all in one conversation, no manual formatting.
## Features
- Publish articles as **drafts** or **live**
- Set title, tags, series, canonical URL, and cover image
- Uses your personal Dev.to API key — the key never leaves your machine except to call Dev.to's own API
## Requirements
- Python 3.10+
- [`uv`](https://docs.astral.sh/uv/) for package management
- A [Dev.to API key](https://dev.to/settings/extensions) (Settings → Extensions → DEV Community API Keys)
- [Claude Desktop](https://claude.ai/download) or another MCP-compatible client
## Setup
### 1. Clone and install dependencies
```bash
git clone https://github.com/Dineshv0311/devto-mcp-server.git
cd devto-mcp-server
uv sync
```
### 2. Configure your API key
Copy the template and fill in your key:
```bash
cp .env.template .env
```
Then edit `.env`:
```
DEVTO_API_KEY=your_devto_api_key_here
```
> ⚠️ `.env` is listed in `.gitignore` — never commit your real API key.
### 3. Test the server standalone (recommended)
Before wiring it into Claude Desktop, verify the server works using the MCP Inspector:
```bash
uv run mcp dev dev-server.py
```
This opens a local web UI where you can call `publish_blog_to_devto` directly and inspect the raw request/response — useful for catching issues before debugging through a chat interface.
### 4. Connect it to Claude Desktop
Open your Claude Desktop config file:
- **Windows:** `%APPDATA%\Claude\claude_desktop_config.json`
- **macOS:** `~/Library/Application Support/Claude/claude_desktop_config.json`
Add this server **inside** the top-level `mcpServers` key:
```json
{
"mcpServers": {
"devto": {
"command": "C:\\path\\to\\uv.exe",
"args": ["--directory", "C:\\path\\to\\devto-mcp-server", "run", "dev-server.py"]
}
}
}
```
> 💡 On Windows, use the full path to `uv.exe` (find it with `where.exe uv`) — Claude Desktop doesn't always inherit your shell's PATH.
Fully quit and reopen Claude Desktop (check it's not lingering in the system tray) and confirm the server shows as **running** under Settings → Developer → Local MCP servers.
## Usage
Once connected, talk to Claude normally:
> "I have a file `blog.txt` in my drafts folder — refine its content and publish it to Dev.to as a draft with tags: mcp, ai, python."
### Tool: `publish_blog_to_devto`
| Parameter | Required | Description |
|-------------------|:--------:|----------------------------------------------------------|
| `title` | ✅ | Article title |
| `body_markdown` | ✅ | Full article content in markdown |
| `tags` | ❌ | List of tags (e.g. `["mcp", "ai", "python"]`) |
| `published` | ❌ | `true` for live, `false` for draft (default: `false`) |
| `series` | ❌ | Name of the series this article belongs to |
| `canonical_url` | ❌ | Canonical URL if cross-posted |
| `cover_image` | ❌ | URL of a cover image |
Tip: publish with `published: false` first to review the draft on Dev.to before making it live.
## Project Structure
```
devto-mcp-server/
├── dev-server.py # MCP server + publish_blog_to_devto tool
├── devto-test.py # Standalone test script for the Dev.to API call
├── example-config.json # Example Claude Desktop config snippet
├── .env.template # Template for required environment variables
├── pyproject.toml # Project dependencies (managed by uv)
└── README.md
```
## Troubleshooting
**`ModuleNotFoundError: No module named 'mcp.server.fastmcp'`**
There's an unrelated package squatting the `mcp` name on PyPI. Pin the real SDK explicitly:
```bash
uv remove mcp
uv add "mcp[cli]>=1.2.0,<2.0.0"
```
**Server doesn't show up in Claude Desktop**
Double-check `devto` is nested *inside* `mcpServers` in the config, not a sibling key. Fully restart Claude Desktop.
**`uv` not found after installing**
Close and reopen your terminal so it picks up the updated PATH.
**Dev.to API returns 422 Unprocessable Entity**
Usually means a duplicate title/slug already exists on your account. Try a slightly different title.
## License
MIT — see [LICENSE](./LICENSE)TDQS
A4/5.0
Scored across 1 tool
Disambiguation5/5
Only one tool exists, so there is no possibility of confusing it with others. The tool's purpose is clear from its name and description.
Naming Consistency5/5
The single tool uses a clear verb_noun pattern (publish_blog_to_devto), consistent with common MCP naming conventions, though there is no other tool to compare.
Tool Count3/5
Having exactly one tool for a blogging platform is very thin; a typical integration would need at least listing, updating, and deleting articles. This falls on the borderline of being too few.
Completeness2/5
The server only supports publishing posts; there are no operations for reading, updating, deleting, or listing existing articles. This is a significant gap that would prevent an agent from managing a blog lifecycle.
Maintenance
ActivitySlowing
ResponsivenessNo issues