Medium MCP API Server
by jignesh88
A Model Context Protocol (MCP) server that integrates with Medium's API to enable seamless content publishing and user account management from external applications. It serves as a bridge between AI assistants and the Medium publishing platform.
Last updated: N/A
Medium MCP API Server
A Model Context Protocol (MCP) server that integrates with Medium's API to enable seamless content publishing and user account management from external applications. The Model Context Protocol provides a standardized way for AI models to interact with external services and APIs, allowing this server to serve as a bridge between AI assistants and the Medium publishing platform.
🚀 Features
-
Authentication & User Management
- Secure Medium OAuth integration
- JWT-based authentication
- User profile management
-
Content Publishing
- Support for Markdown and HTML content formats
- Draft creation and management
- Post scheduling
- Publication integration
- Tag and category support
-
Media Management
- Image upload and storage
- Content formatting utilities
-
Reliability & Performance
- Redis-based caching
- Job scheduling for post publication
- Comprehensive error handling
- Rate limiting
📋 Requirements
- Node.js 16+
- MongoDB
- Redis (optional, but recommended for scheduling)
- Medium API credentials
🛠️ Installation
Using Docker (Recommended)
-
Clone the repository:
git clone https://github.com/jignesh88/medium-mcp-api.git cd medium-mcp-api
-
Create a
.env
file based on the example:cp .env.example .env
-
Update the
.env
file with your credentials:MEDIUM_CLIENT_ID=your_medium_client_id MEDIUM_CLIENT_SECRET=your_medium_client_secret MEDIUM_REDIRECT_URI=http://your-domain.com/api/auth/medium/callback JWT_SECRET=your_strong_secret_key
-
Start the services using Docker Compose:
docker-compose up -d
Manual Installation
-
Clone the repository:
git clone https://github.com/jignesh88/medium-mcp-api.git cd medium-mcp-api
-
Install dependencies:
npm install
-
Create and configure your
.env
file -
Start MongoDB and Redis servers
-
Start the application:
npm start
🔐 Medium API Setup
- Create a Medium developer application at https://medium.com/me/applications
- Set the callback URL to
http://your-domain.com/api/auth/medium/callback
- Copy your Client ID and Client Secret to your
.env
file
📚 API Documentation
Authentication Endpoints
Register a new user
POST /api/auth/register
Request Body:
{
"email": "[email protected]",
"name": "John Doe"
}
Response:
{
"message": "User registered successfully",
"token": "jwt_token_here",
"user": {
"userId": "user_id",
"email": "[email protected]",
"name": "John Doe"
}
}
Login
POST /api/auth/login
Request Body:
{
"email": "[email protected]"
}
Response:
{
"message": "Login successful",
"token": "jwt_token_here",
"user": {
"userId": "user_id",
"email": "[email protected]",
"name": "John Doe",
"mediumConnected": true
}
}
Connect Medium Account
GET /api/auth/medium
Headers:
Authorization: Bearer jwt_token_here
Response:
{
"authUrl": "https://medium.com/m/oauth/authorize?client_id=..."
}
Content Management Endpoints
Create a Post
POST /api/posts
Headers:
Authorization: Bearer jwt_token_here
Request Body:
{
"title": "My New Post",
"content": "# Markdown Content\n\nThis is my post content.",
"contentFormat": "markdown",
"tags": ["programming", "tutorial"],
"publishStatus": "draft",
"publicationId": "optional_publication_id"
}
Response:
{
"_id": "post_id",
"userId": "user_id",
"title": "My New Post",
"content": "# Markdown Content\n\nThis is my post content.",
"contentFormat": "markdown",
"tags": ["programming", "tutorial"],
"publishStatus": "draft",
"createdAt": "2025-03-16T07:00:00.000Z",
"updatedAt": "2025-03-16T07:00:00.000Z"
}
Publish a Post to Medium
POST /api/posts/:postId/publish
Headers:
Authorization: Bearer jwt_token_here
Response:
{
"message": "Post published successfully",
"post": {
"_id": "post_id",
"mediumPostId": "medium_post_id",
"title": "My New Post",
"published": true,
...
}
}
Get User's Posts
GET /api/posts?status=draft&page=1&limit=10
Headers:
Authorization: Bearer jwt_token_here
Response:
{
"posts": [
{
"_id": "post_id",
"title": "My New Post",
...
}
],
"total": 15,
"page": 1,
"pages": 2
}
Media Management
Upload an Image
POST /api/media/upload
Headers:
Authorization: Bearer jwt_token_here
Content-Type: multipart/form-data
Form Data:
image: [file]
Response:
{
"message": "File uploaded successfully",
"filePath": "/uploads/filename.jpg",
"fileName": "filename.jpg",
"originalName": "my-image.jpg",
"mimeType": "image/jpeg",
"size": 12345
}
🔄 Integrating with the MCP Server
Example: Publishing a post with Node.js
const axios = require('axios');
const API_URL = 'http://your-domain.com';
const TOKEN = 'your_jwt_token';
async function publishPost() {
try {
// Create a draft post
const post = await axios.post(`${API_URL}/api/posts`, {
title: 'My Awesome Article',
content: '# Hello Medium\n\nThis is my first post published via the MCP API.',
contentFormat: 'markdown',
tags: ['api', 'medium', 'tutorial'],
publishStatus: 'draft'
}, {
headers: {
'Authorization': `Bearer ${TOKEN}`
}
});
// Publish the post to Medium
const published = await axios.post(`${API_URL}/api/posts/${post.data._id}/publish`, {}, {
headers: {
'Authorization': `Bearer ${TOKEN}`
}
});
console.log('Post published successfully!', published.data);
} catch (error) {
console.error('Error publishing post:', error.response?.data || error.message);
}
}
publishPost();
📅 Scheduled Publishing
The server supports scheduling posts for future publication. When creating or updating a post, include a scheduledAt
field with an ISO timestamp:
{
"title": "Scheduled Post",
"content": "This will be published automatically.",
"scheduledAt": "2025-03-20T12:00:00.000Z"
}
The server will automatically publish the post at the specified time if Redis is configured.
🛡️ Security Considerations
- Always use HTTPS in production
- Rotate your JWT secret regularly
- Set up proper monitoring and logging
- Store sensitive data in environment variables or a secure vault
- Implement proper CORS policies
🔧 Configuration
All configuration is done through environment variables:
| Variable | Description | Required | |----------|-------------|----------| | PORT | Server port (default: 3000) | No | | MONGODB_URI | MongoDB connection string | Yes | | REDIS_URL | Redis connection string | No | | JWT_SECRET | Secret for JWT tokens | Yes | | MEDIUM_CLIENT_ID | Medium API client ID | Yes | | MEDIUM_CLIENT_SECRET | Medium API client secret | Yes | | MEDIUM_REDIRECT_URI | OAuth callback URL | Yes | | FRONTEND_URL | URL for frontend redirects | Yes |
📜 License
MIT
🤝 Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature
) - Commit your changes (
git commit -m 'Add some amazing feature'
) - Push to the branch (
git push origin feature/amazing-feature
) - Open a Pull Request