Alayman MCP Server - Article Retrieval and Search
A Model Context Protocol (MCP) server that provides tools and prompts to retrieve and search blog articles from the Alayman blog (A Layman on Medium) by Jen-Hsuan Hsieh (Sean).
Overview
This MCP server provides tools and prompts to interact with Alayman blog articles, allowing you to:
- Fetch paginated article lists (currently 285+ articles available)
- Search and filter articles by topic, title, or content
- Generate contextual prompts for article discovery
- Access article metadata including author, publication time, read time, and engagement metrics
Features
- Article Retrieval Tool: Fetches paginated articles with customizable limit and offset
- Article List Prompt: Generates intelligent prompts for article discovery with optional filters
- Structured Output: Returns validated data using Pydantic models
- Pagination Support: Efficient handling of large article collections
- Async HTTP: Uses httpx for efficient async API calls
- Error Handling: Comprehensive exception handling for network and HTTP errors
- SSE Transport: Server-Sent Events support for HTTP-based MCP connections
- Dual Transport: Supports both stdio (for Claude Desktop/Code) and SSE (for HTTP clients)
Topics Covered in the Blog
The Alayman blog covers a wide range of software engineering topics, including:
- Frontend Development: React, Angular, Next.js, Vue.js, TypeScript, JavaScript
- Backend Development: Django, Node.js, NestJS, Python, GraphQL, RESTful APIs
- Data Visualization: D3.js, Cytoscape.js, Highcharts, ECharts
- Cloud & DevOps: AWS, Docker, Kubernetes, CI/CD, GitLab, GitHub Actions
- Architecture & Patterns: Micro Frontends, Design Patterns, System Design
- Testing: Unit Testing, Integration Testing, Karma, Jasmine
- AI & Tools: Claude CLI, GitHub Copilot, RAG, LangChain.js
- Web Performance: SEO, Optimization, Caching, SSR/SSG
- Career & Soft Skills: Team Management, Digital Nomad Life, Conference Insights
Requirements
- Python 3.11 or higher
- uv (package manager)
Installation
- Clone this repository
- Install dependencies:
uv sync
- Create a
.envfile in the project root with the required configuration:
# Required: API endpoint URL
ALAYMAN_API_URL=your_api_url_here
# Optional: Port for SSE server (default: 8000)
# PORT=8000
Usage
Running the Server
The server supports two transport modes: stdio and SSE (Server-Sent Events).
SSE Transport (Default)
Start the MCP server with SSE transport over HTTP:
uv run server.py
By default, the server will start on http://127.0.0.1:8000 with the SSE endpoint available at:
- SSE endpoint:
http://127.0.0.1:8000/sse - Messages endpoint:
http://127.0.0.1:8000/messages
You can specify a custom port using the PORT environment variable:
PORT=3000 uv run server.py
Stdio Transport
For stdio transport (used by Claude Desktop and some MCP clients), the server will automatically use stdio when invoked by those clients through their configuration files.
Testing with MCP Inspector
The MCP Inspector is a web-based tool for testing MCP servers.
Testing with SSE Transport
To test the SSE server with MCP Inspector:
- Start the server in SSE mode:
uv run server.py
- In a separate terminal, start the MCP Inspector and connect to the SSE endpoint:
npx @modelcontextprotocol/inspector http://127.0.0.1:8000/sse
The inspector will connect to your running SSE server and allow you to test tools and prompts interactively.
Testing with Stdio Transport
For stdio transport testing:
npx @modelcontextprotocol/inspector uv run server.py
This will start the inspector and connect it to your server automatically using stdio.
Integration with Claude Desktop
To use this server with Claude Desktop, add it to your Claude Desktop configuration:
- macOS:
~/Library/Application Support/Claude/claude_desktop_config.json - Windows:
%APPDATA%/Claude/claude_desktop_config.json
{
"mcpServers": {
"shellserver": {
"command": "uv",
"args": ["run", "/absolute/path/to/server.py"],
"cwd": "/absolute/path/to/shellserver"
}
}
}
Restart Claude Desktop after updating the configuration.
Integration with Claude Code
Claude Code supports both stdio and SSE transport for MCP servers. Choose the method that best fits your needs.
Option 1: SSE Transport (Recommended for Remote/Network Access)
First, start the MCP server with SSE transport:
uv run server.py
Then add the SSE server to Claude Code using the claude mcp add command:
claude mcp add --scope user --transport sse alayman http://127.0.0.1:8000/sse
This will add the SSE server with the name "alayman" to your user-level MCP configuration.
Alternatively, you can manually add it to your Claude Code MCP configuration:
- macOS/Linux:
~/.claude/mcp.json - Windows:
%USERPROFILE%\.claude\mcp.json
{
"mcpServers": {
"alayman": {
"url": "http://127.0.0.1:8000/sse"
}
}
}
For remote SSE servers:
{
"mcpServers": {
"alayman": {
"url": "https://your-server.com/mcp/alayman/sse"
}
}
}
Option 2: Stdio Transport (Default)
Add the server to Claude Code using the claude mcp add command. From the project directory, run:
claude mcp add --scope user alayman uv run $(pwd)/server.py
This will add the server with the name "alayman" to your user-level MCP configuration, making it available across all your Claude Code sessions.
Alternatively, you can manually add it to your Claude Code MCP configuration:
{
"mcpServers": {
"alayman": {
"command": "uv",
"args": ["run", "/absolute/path/to/server.py"],
"cwd": "/absolute/path/to/alayman-mcp"
}
}
}
Reloading Configuration
After updating the configuration, restart Claude Code or reload the MCP servers for the changes to take effect.
Integration with Docker and Claude Code
Build the Docker image
docker build -t alayman .
Option 1: Docker with SSE Transport
Run the Docker container with SSE transport:
docker run -d -p 8000:8000 \
-e ALAYMAN_API_URL=your_api_url \
--name alayman-mcp \
alayman
Then add the SSE endpoint to Claude Code:
claude mcp add --scope user --transport sse alayman http://127.0.0.1:8000/sse
Or manually configure:
{
"mcpServers": {
"alayman": {
"url": "http://127.0.0.1:8000/sse"
}
}
}
Option 2: Docker with Stdio Transport
Add the Docker container as the MCP server with stdio:
claude mcp add-json --scope user alayman '{"type":"stdio","command":"docker","args":["run","-i","--rm","--init","-e","DOCKER_CONTAINER=true","alayman"]}'
Or manually configure:
{
"mcpServers": {
"alayman": {
"command": "docker",
"args": ["run", "-i", "--rm", "--init", "-e", "DOCKER_CONTAINER=true", "alayman"]
}
}
}
Using SSE Transport with MCP Clients
When running the server with SSE transport, you can connect to it from any MCP client that supports SSE/HTTP connections.
Connection Details
- Base URL:
http://127.0.0.1:8000 - SSE Endpoint:
http://127.0.0.1:8000/sse - Messages Endpoint:
http://127.0.0.1:8000/messages - Transport Type:
sse
Example: Connecting with MCP Client SDK
If you're building a custom MCP client using the MCP SDK, you can connect to the SSE server like this:
Python:
from mcp.client import Client
from mcp.client.sse import sse_client
async with sse_client("http://127.0.0.1:8000/sse") as (read, write):
async with Client(read, write) as client:
# Use the client to call tools
result = await client.call_tool("get_articles", {"limit": 10})
print(result)
TypeScript/JavaScript:
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { SSEClientTransport } from "@modelcontextprotocol/sdk/client/sse.js";
const transport = new SSEClientTransport(
new URL("http://127.0.0.1:8000/sse")
);
const client = new Client({
name: "example-client",
version: "1.0.0",
}, {
capabilities: {}
});
await client.connect(transport);
// Call tools
const result = await client.callTool({
name: "get_articles",
arguments: { limit: 10 }
});
Benefits of SSE Transport
- HTTP-based: Works through standard HTTP infrastructure
- Firewall-friendly: Easier to deploy in corporate environments
- Debugging: Can use standard HTTP tools (curl, Postman, etc.)
- Scalability: Can be load-balanced and proxied
- No stdio: Doesn't require process spawning
Deploying SSE Server
For production deployments, you can run the SSE server as a service:
Using systemd (Linux):
[Unit]
Description=Alayman MCP Server
After=network.target
[Service]
Type=simple
User=www-data
WorkingDirectory=/path/to/alayman-mcp
Environment="ALAYMAN_API_URL=your_api_url"
Environment="PORT=8000"
ExecStart=/usr/local/bin/uv run server.py
Restart=always
[Install]
WantedBy=multi-user.target
Using Docker for SSE:
# Run with SSE transport exposed on port 8000
docker run -d \
-p 8000:8000 \
-e ALAYMAN_API_URL=your_api_url \
-e PORT=8000 \
--name alayman-mcp \
alayman
Behind a reverse proxy (nginx):
location /mcp/alayman/ {
proxy_pass http://127.0.0.1:8000/;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Host $host;
proxy_buffering off;
proxy_cache off;
}
Quick Start Examples
Once integrated with Claude Desktop or Claude Code, you can use the server in various ways:
Direct tool usage:
Show me the first 10 articles from the Alayman blog
Get articles 20-30 from the blog
Retrieve 5 articles starting from position 10
Using the prompt command (Claude Code):
/alayman:list_articles 10 "the title contains 'React'"
/alayman:list_articles 5 "articles about Django"
/alayman:list_articles 15 "published in the last year"
Natural language queries:
Find all articles about Angular
Show me articles related to AWS
List articles about data visualization with D3.js
Available Tools and Prompts
Tool: get_articles
Retrieves a paginated list of blog articles from the API.
Parameters:
limit(int, optional): Number of articles to return (default: 20, min: 1, max: 100)offset(int, optional): Number of articles to skip (default: 0, min: 0)
Returns: An ArticlesResponse object containing:
articles(list[Article]): List of article objectstotal(int): Total number of articles availableoffset(int): Current offset valuelimit(int): Current limit valuehas_more(bool): Whether more articles are available
Article Object Fields:
id(int): Unique article identifiertitle(str): Article titlesubtitle(str): Article subtitleimage(str): URL to article imageurl(str): URL to article pageauthor(str): Article author nametime(str): Publication timestamp (ISO 8601)readtime(str): Estimated reading timecategory(int): Article category IDdescription(str): Article descriptionshareCount(int): Number of sharescheckCount(int): Number of views/checks
Example usage in Claude:
Can you retrieve the first 10 articles?
Can you get articles 20-40?
Fetch the latest 5 articles from the blog.
Prompt: list_articles
Generates an intelligent prompt to list and filter Alayman's articles. This prompt will instruct the LLM to use the get_articles tool and apply specific filters.
Parameters:
number(int, optional): Number of articles to list (default: 10)condition(str, optional): Condition or filter criteria for articles (default: "")
Example usage in Claude Code:
/alayman:list_articles 5 "the title contains 'React'"
/alayman:list_articles 10 "published in 2024"
/alayman:list_articles 15 "related to Python"
When you run this prompt, it generates instructions for Claude to fetch articles and apply your specified conditions when presenting the results.
Project Structure
alayman-mcp/
├── server.py # Main MCP server implementation
├── pyproject.toml # Project dependencies and metadata
├── uv.lock # Dependency lock file
├── README.md # This file
├── CLAUDE.md # Claude Code project instructions
├── reference.md # Additional reference documentation
├── Dockerfile # Docker container configuration
├── .dockerignore # Docker build exclusions
├── .env.example # Example environment variables
├── .env # Environment variables (not in git)
├── .python-version # Python version specification (3.11)
├── .gitignore # Git exclusions
├── .venv/ # Virtual environment (created by uv)
└── rules/ # Development rules and guidelines
└── python.md # Python coding standards
Dependencies
mcp[cli]>=1.22.0- Model Context Protocol SDK with CLI supporthttpx>=0.28.0- Modern async HTTP clientpython-dotenv- Environment variable management from .env files
Development
Architecture
The server uses the FastMCP framework from the MCP Python SDK, which provides:
- Simple decorator-based tool and prompt registration
- Automatic JSON schema generation from type hints
- Built-in validation using Pydantic models
- Support for async operations
Code Structure
- Pydantic Models:
Article: Defines the article schema for type-safe data validationArticlesResponse: Defines the paginated response structure
- Tool Function: The
get_articles()async function fetches and validates article data with pagination support - Prompt Function: The
list_articles()function generates contextual prompts for article discovery - Server Instance: FastMCP server configured with stdio transport
Error Handling
The server includes comprehensive error handling for:
- HTTP errors (4xx, 5xx responses)
- Network connectivity issues
- JSON parsing errors
- Data validation failures
All errors are caught and returned as descriptive exception messages.
License
This project is provided as-is for educational and development purposes.
