Pandoc Bridge
A document format conversion service using Pandoc, supporting both REST (OpenAPI 3.1) and MCP (Model Context Protocol) interfaces.
Features
- 40+ Format Support: Convert between Markdown, HTML, LaTeX, DOCX, PDF, and many more formats
- Dual Protocol: REST API with OpenAPI documentation and MCP server for AI assistants
- Bearer Token Auth: Shared JWT authentication across both protocols
- Streaming Support: Server-Sent Events for progress tracking
- Rate Limiting: Built-in protection against abuse
- Docker Ready: Production-ready containerization with multi-arch support
Documentation
- API Reference - Detailed REST API documentation
- MCP Integration - Model Context Protocol guide
- Container Registry Guide - Docker deployment guide
- OpenAPI Spec - Interactive Swagger UI (when running)
Quick Start
Using Docker Compose
# Start the service
docker-compose up -d
# Check health
curl http://localhost:8000/health
Local Development
# Install dependencies
pip install -e ".[dev]"
# Run the server
uvicorn src.main:app --reload
# Or use the CLI
pandoc-bridge
API Endpoints
Public Endpoints
| Endpoint | Description |
|---|---|
GET / | Service information |
GET /health | Health check with Pandoc version |
GET /api/v1/formats | List supported formats |
GET /docs | Swagger UI documentation |
Protected Endpoints (Require Bearer Token)
| Endpoint | Description |
|---|---|
POST /api/v1/convert/text | Convert text content |
POST /api/v1/convert/file | Convert uploaded file |
POST /api/v1/convert/stream | Stream conversion with SSE |
MCP Endpoint
| Endpoint | Description |
|---|---|
POST /mcp | MCP Streamable HTTP transport |
Usage Examples
Convert Text (REST)
# Get a token (for development, tokens are pre-configured)
TOKEN="your-jwt-token"
# Convert Markdown to HTML
curl -X POST http://localhost:8000/api/v1/convert/text \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"content": "# Hello World\n\nThis is **bold** text.",
"from_format": "markdown",
"to_format": "html"
}'
Convert File (REST)
curl -X POST http://localhost:8000/api/v1/convert/file \
-H "Authorization: Bearer $TOKEN" \
-F "file=@document.md" \
-F "to_format=docx" \
-o converted.docx
Using with Claude Desktop (MCP)
Add to your Claude Desktop configuration:
{
"mcpServers": {
"pandoc-bridge": {
"command": "npx",
"args": ["-y", "mcp-remote", "http://localhost:8000/mcp"]
}
}
}
Or with authentication:
{
"mcpServers": {
"pandoc-bridge": {
"command": "npx",
"args": [
"-y", "mcp-remote",
"--header", "Authorization: Bearer ${PANDOC_TOKEN}",
"http://localhost:8000/mcp"
]
}
}
}
MCP Tools
| Tool | Description |
|---|---|
convert_text | Convert text between formats |
convert_file_base64 | Convert base64-encoded files |
list_formats | Get supported formats |
get_service_info | Get version information |
MCP Resources
| Resource | Description |
|---|---|
formats://list | JSON list of supported formats |
formats://matrix | Format conversion compatibility matrix |
Authentication
Scopes
| Scope | Description |
|---|---|
formats:read | Query formats (public) |
convert:text | Text conversion |
convert:file | File conversion |
admin | Full access |
Token Format
{
"sub": "client-id",
"scopes": ["formats:read", "convert:text", "convert:file"],
"exp": 1735600000,
"iat": 1735513600
}
Configuration
Environment variables (see .env.example):
| Variable | Default | Description |
|---|---|---|
HOST | 0.0.0.0 | Server host |
PORT | 8000 | Server port |
LOG_LEVEL | INFO | Logging level |
ENVIRONMENT | development | Environment (development/production) |
JWT_SECRET_KEY | (required in prod) | JWT signing key (min 32 chars) |
JWT_EXPIRE_HOURS | 24 | Token expiration time |
MAX_FILE_SIZE_MB | 50 | Maximum file size |
CONVERSION_TIMEOUT | 60 | Conversion timeout in seconds |
⚠️ Security Note: Always set
JWT_SECRET_KEYin production. Generate one with:python -c "import secrets; print(secrets.token_urlsafe(32))"
Development
Run Tests
# Install dev dependencies
pip install -e ".[dev]"
# Run tests
pytest
# Run with coverage
pytest --cov=src --cov-report=html
Lint Code
# Run ruff
ruff check src tests
ruff format src tests
Type Check
mypy src
Security Scan
# Install security tools
pip install bandit safety
# Run security scan
bandit -r src -ll
# Check dependencies
safety check
CI/CD
The project uses GitHub Actions for continuous integration and deployment:
-
CI Pipeline (
pipeline.yml):- Runs on Python 3.12 and 3.13
- Linting with ruff
- Type checking with mypy
- Tests with pytest and coverage
- Security scanning with bandit
- Deploys documentation to GitHub Pages
-
Container Publishing (
publish-container.yml):- Triggered on version tags (
v*.*.*) - Multi-arch builds (amd64, arm64)
- Publishes to GitHub Container Registry
- Triggered on version tags (
Running Locally
# Copy environment template
cp .env.example .env
# Edit .env with your settings
vim .env
# Start with Docker
docker-compose up --build
Architecture
┌─────────────────────────────────────────────────────┐
│ FastAPI App │
│ (Port 8000) │
├─────────────────────┬───────────────────────────────┤
│ REST API │ MCP Server │
│ /api/v1/* │ /mcp │
│ (OpenAPI 3.1) │ (Streamable HTTP) │
├─────────────────────┴───────────────────────────────┤
│ Shared Auth (Bearer Token) │
├─────────────────────────────────────────────────────┤
│ ConversionService (Core) │
├─────────────────────────────────────────────────────┤
│ Pandoc CLI │
└─────────────────────────────────────────────────────┘
License
MIT License - see LICENSE for details.