main tooling
This commit is contained in:
parent
004d5614e2
commit
a160d00082
7 changed files with 2239 additions and 32 deletions
109
Makefile
109
Makefile
|
|
@ -1,24 +1,19 @@
|
||||||
# Ghost MCP Development Makefile
|
# Ghost MCP Development Makefile
|
||||||
|
|
||||||
.PHONY: help install install-uv start-ghost stop-ghost setup-tokens test test-connection run dev clean logs status check-deps
|
.PHONY: help install install-local deps-install-python deps-install-dev deps-deps-install-uv install-pip venv start-ghost stop-ghost restart-ghost setup-tokens test test-unit test-integration test-coverage test-fast test-parallel test-connection clean-test run dev format lint clean logs status check-deps setup docs
|
||||||
|
|
||||||
# Default target
|
.PHONY: help
|
||||||
help: ## Show this help message
|
help: ## Show this help message
|
||||||
@echo "Ghost MCP Development Commands"
|
@echo "Available targets:"
|
||||||
@echo "============================="
|
|
||||||
@echo ""
|
|
||||||
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-20s\033[0m %s\n", $$1, $$2}'
|
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-20s\033[0m %s\n", $$1, $$2}'
|
||||||
@echo ""
|
|
||||||
@echo "Quick start:"
|
|
||||||
@echo " make install-uv # Install uv package manager (if not installed)"
|
|
||||||
@echo " make install # Install Python dependencies"
|
|
||||||
@echo " make start-ghost # Start Ghost and database containers"
|
|
||||||
@echo " make setup-tokens # Extract API keys and create .env file"
|
|
||||||
@echo " make test # Test the implementation"
|
|
||||||
@echo " make run # Run the MCP server"
|
|
||||||
|
|
||||||
# Python environment setup
|
# Python environment setup
|
||||||
install-uv: ## Install uv package manager
|
venv: ## Create a virtual environment
|
||||||
|
python3 -m venv venv
|
||||||
|
./venv/bin/pip install -U pip setuptools
|
||||||
|
./venv/bin/pip install -e ".[dev]"
|
||||||
|
|
||||||
|
deps-deps-install-uv: ## Install uv package manager
|
||||||
@echo "📦 Installing uv package manager..."
|
@echo "📦 Installing uv package manager..."
|
||||||
@if command -v uv >/dev/null 2>&1; then \
|
@if command -v uv >/dev/null 2>&1; then \
|
||||||
echo "✅ uv is already installed"; \
|
echo "✅ uv is already installed"; \
|
||||||
|
|
@ -29,18 +24,34 @@ install-uv: ## Install uv package manager
|
||||||
echo "✅ uv installed successfully"; \
|
echo "✅ uv installed successfully"; \
|
||||||
fi
|
fi
|
||||||
|
|
||||||
install: ## Install Python dependencies using uv
|
# Install the MCP server system-wide
|
||||||
|
install: ## Install the MCP server system-wide
|
||||||
|
claude mcp remove ghost-mcp -s user || true
|
||||||
|
claude mcp add ghost-mcp -s user -- \
|
||||||
|
bash -c "cd $(PWD) && uv run python -m ghost_mcp.server"
|
||||||
|
|
||||||
|
# Install the MCP server in the project scope only
|
||||||
|
install-local: ## Install the MCP server in the project scope only
|
||||||
|
claude mcp remove ghost-mcp || true
|
||||||
|
claude mcp add ghost-mcp -- \
|
||||||
|
bash -c "cd $(PWD) && uv run python -m ghost_mcp.server"
|
||||||
|
|
||||||
|
deps-install-python: ## Install Python dependencies using uv
|
||||||
@echo "📦 Installing Python dependencies with uv..."
|
@echo "📦 Installing Python dependencies with uv..."
|
||||||
@if ! command -v uv >/dev/null 2>&1; then \
|
@if ! command -v uv >/dev/null 2>&1; then \
|
||||||
echo "❌ uv not found. Run 'make install-uv' first"; \
|
echo "❌ uv not found. Run 'make deps-deps-install-uv' first"; \
|
||||||
exit 1; \
|
exit 1; \
|
||||||
fi
|
fi
|
||||||
uv sync
|
uv sync
|
||||||
@echo "✅ Dependencies installed successfully"
|
@echo "✅ Dependencies installed successfully"
|
||||||
|
|
||||||
|
# Install dev dependencies
|
||||||
|
deps-install-dev: ## Install development dependencies
|
||||||
|
uv sync --extra dev
|
||||||
|
|
||||||
install-pip: ## Install Python dependencies using pip (fallback)
|
install-pip: ## Install Python dependencies using pip (fallback)
|
||||||
@echo "📦 Installing Python dependencies with pip..."
|
@echo "📦 Installing Python dependencies with pip..."
|
||||||
python -m pip install -e .
|
python -m pip install -e ".[dev]"
|
||||||
@echo "✅ Dependencies installed successfully"
|
@echo "✅ Dependencies installed successfully"
|
||||||
|
|
||||||
# Docker environment
|
# Docker environment
|
||||||
|
|
@ -84,7 +95,25 @@ setup-tokens: ## Extract API keys from Ghost database and create .env file
|
||||||
@echo "🔑 Setting up API tokens..."
|
@echo "🔑 Setting up API tokens..."
|
||||||
./scripts/setup-tokens.sh
|
./scripts/setup-tokens.sh
|
||||||
|
|
||||||
# Testing
|
# Testing targets
|
||||||
|
test: ## Run all tests
|
||||||
|
uv run pytest tests/ -v
|
||||||
|
|
||||||
|
test-unit: ## Run unit tests only
|
||||||
|
uv run pytest tests/test_models.py tests/test_client.py -v
|
||||||
|
|
||||||
|
test-integration: ## Run integration tests
|
||||||
|
uv run pytest tests/test_mcp_tools.py tests/test_server.py -v
|
||||||
|
|
||||||
|
test-coverage: ## Run tests with coverage report
|
||||||
|
uv run pytest tests/ --cov=. --cov-report=html --cov-report=term
|
||||||
|
|
||||||
|
test-fast: ## Run tests with fail-fast and short traceback
|
||||||
|
uv run pytest tests/ -x --tb=short
|
||||||
|
|
||||||
|
test-parallel: ## Run tests in parallel
|
||||||
|
uv run pytest tests/ -n auto
|
||||||
|
|
||||||
test-connection: ## Test Ghost API connectivity
|
test-connection: ## Test Ghost API connectivity
|
||||||
@if [ ! -f .env ]; then \
|
@if [ ! -f .env ]; then \
|
||||||
echo "❌ .env file not found. Run 'make setup-tokens' first"; \
|
echo "❌ .env file not found. Run 'make setup-tokens' first"; \
|
||||||
|
|
@ -92,16 +121,9 @@ test-connection: ## Test Ghost API connectivity
|
||||||
fi
|
fi
|
||||||
@python scripts/test-connection.py
|
@python scripts/test-connection.py
|
||||||
|
|
||||||
test: check-deps test-connection ## Run all tests
|
# Clean up test artifacts
|
||||||
@echo "🧪 Running comprehensive tests..."
|
clean-test: ## Clean up test artifacts
|
||||||
@echo "Testing MCP tools registration..."
|
rm -rf .coverage htmlcov/ .pytest_cache/ tests/__pycache__/ __pycache__/
|
||||||
@python -c "\
|
|
||||||
import sys; \
|
|
||||||
sys.path.insert(0, 'src'); \
|
|
||||||
from ghost_mcp.server import mcp; \
|
|
||||||
print(f'✅ FastMCP server initialized'); \
|
|
||||||
print(f' Tools registered: {len([attr for attr in dir(mcp) if not attr.startswith(\"_\")])}+')"
|
|
||||||
@echo "✅ All tests passed!"
|
|
||||||
|
|
||||||
# Running the server
|
# Running the server
|
||||||
run: check-deps ## Run the Ghost MCP server
|
run: check-deps ## Run the Ghost MCP server
|
||||||
|
|
@ -165,17 +187,40 @@ check-deps: ## Check if all dependencies are available
|
||||||
exit 1; \
|
exit 1; \
|
||||||
fi
|
fi
|
||||||
|
|
||||||
clean: ## Clean up development environment
|
# Code quality
|
||||||
|
.PHONY: format
|
||||||
|
format: ## Format code with ruff and black
|
||||||
|
@echo "🎨 Formatting code..."
|
||||||
|
uv run ruff format .
|
||||||
|
uv run black .
|
||||||
|
@echo "✅ Code formatting completed"
|
||||||
|
|
||||||
|
.PHONY: lint
|
||||||
|
lint: ## Run linting with ruff and mypy
|
||||||
|
@echo "🔍 Running linters..."
|
||||||
|
uv run ruff check .
|
||||||
|
uv run mypy src/
|
||||||
|
@echo "✅ Linting completed"
|
||||||
|
|
||||||
|
clean: ## Clean up temporary files and development environment
|
||||||
@echo "🧹 Cleaning up development environment..."
|
@echo "🧹 Cleaning up development environment..."
|
||||||
docker-compose down -v
|
find . -type f -name "*.pyc" -delete || true
|
||||||
rm -f .env
|
find . -type d -name "__pycache__" -delete || true
|
||||||
|
find . -type d -name ".pytest_cache" -delete || true
|
||||||
|
rm -rf .ruff_cache/ || true
|
||||||
|
rm -rf venv/ || true
|
||||||
|
rm -rf .pytest_cache/ || true
|
||||||
|
rm -rf htmlcov/ || true
|
||||||
|
rm -f .coverage* coverage.xml || true
|
||||||
|
docker-compose down -v || true
|
||||||
|
rm -f .env || true
|
||||||
@if command -v uv >/dev/null 2>&1; then \
|
@if command -v uv >/dev/null 2>&1; then \
|
||||||
uv clean; \
|
uv clean; \
|
||||||
fi
|
fi
|
||||||
@echo "✅ Cleanup complete"
|
@echo "✅ Cleanup complete"
|
||||||
|
|
||||||
# Development workflow
|
# Development workflow
|
||||||
setup: install-uv install start-ghost setup-tokens ## Complete setup from scratch
|
setup: deps-deps-install-uv deps-install-python start-ghost setup-tokens ## Complete setup from scratch
|
||||||
@echo ""
|
@echo ""
|
||||||
@echo "🎉 Ghost MCP setup complete!"
|
@echo "🎉 Ghost MCP setup complete!"
|
||||||
@echo ""
|
@echo ""
|
||||||
|
|
|
||||||
259
README.md
Normal file
259
README.md
Normal file
|
|
@ -0,0 +1,259 @@
|
||||||
|
# Ghost MCP Server
|
||||||
|
|
||||||
|
A comprehensive Model Context Protocol (MCP) server for Ghost CMS, providing both read-only Content API and read/write Admin API access through FastMCP.
|
||||||
|
|
||||||
|
## 🎯 Features
|
||||||
|
|
||||||
|
- **Complete Ghost API Coverage**: Both Content API (read-only) and Admin API (read/write)
|
||||||
|
- **15+ MCP Tools**: Posts, pages, tags, authors, settings, and more
|
||||||
|
- **Modern Python Implementation**: FastMCP 2.12.3 with async/await
|
||||||
|
- **JWT Authentication**: Secure Admin API access with token caching
|
||||||
|
- **Robust Error Handling**: 5 error categories with comprehensive logging
|
||||||
|
- **Configuration Management**: Environment variables with precedence
|
||||||
|
- **Development Tools**: Complete Docker setup and automation scripts
|
||||||
|
|
||||||
|
## 🚀 Quick Start
|
||||||
|
|
||||||
|
### Prerequisites
|
||||||
|
|
||||||
|
- Docker and Docker Compose
|
||||||
|
- Python 3.10+ (with uv recommended)
|
||||||
|
|
||||||
|
### Setup
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Clone the repository
|
||||||
|
git clone <repository-url>
|
||||||
|
cd ghost-mcp
|
||||||
|
|
||||||
|
# Complete setup from scratch
|
||||||
|
make setup
|
||||||
|
|
||||||
|
# Or step by step:
|
||||||
|
make install-uv # Install uv package manager
|
||||||
|
make install # Install Python dependencies
|
||||||
|
make start-ghost # Start Ghost and database
|
||||||
|
make setup-tokens # Extract API keys and create .env
|
||||||
|
make test # Test the implementation
|
||||||
|
```
|
||||||
|
|
||||||
|
### Usage
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Run the MCP server
|
||||||
|
make run
|
||||||
|
|
||||||
|
# Development mode with auto-reload
|
||||||
|
make dev
|
||||||
|
|
||||||
|
# Check system status
|
||||||
|
make status
|
||||||
|
|
||||||
|
# View container logs
|
||||||
|
make logs
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📋 Available MCP Tools
|
||||||
|
|
||||||
|
### Content API Tools (Read-only)
|
||||||
|
|
||||||
|
- `get_posts` - Get published posts with filtering/pagination
|
||||||
|
- `get_post_by_id` - Get single post by ID
|
||||||
|
- `get_post_by_slug` - Get single post by slug
|
||||||
|
- `search_posts` - Search posts by title/content
|
||||||
|
- `get_pages` - Get published pages
|
||||||
|
- `get_page_by_id` - Get single page by ID
|
||||||
|
- `get_page_by_slug` - Get single page by slug
|
||||||
|
- `get_tags` - Get tags with filtering
|
||||||
|
- `get_tag_by_id` - Get single tag by ID
|
||||||
|
- `get_tag_by_slug` - Get single tag by slug
|
||||||
|
- `get_authors` - Get authors
|
||||||
|
- `get_author_by_id` - Get single author by ID
|
||||||
|
- `get_author_by_slug` - Get single author by slug
|
||||||
|
- `get_settings` - Get public settings
|
||||||
|
- `get_site_info` - Get basic site information
|
||||||
|
|
||||||
|
### Admin API Tools (Read/Write)
|
||||||
|
|
||||||
|
- `create_post` - Create new posts with full options
|
||||||
|
- `update_post` - Update existing posts
|
||||||
|
- `delete_post` - Delete posts
|
||||||
|
- `get_admin_posts` - Get posts including drafts
|
||||||
|
- `create_page` - Create new pages
|
||||||
|
- `create_tag` - Create new tags
|
||||||
|
|
||||||
|
### Utility Tools
|
||||||
|
|
||||||
|
- `check_ghost_connection` - Test connectivity and configuration
|
||||||
|
|
||||||
|
## 🔧 Configuration
|
||||||
|
|
||||||
|
Configuration is managed through environment variables with precedence:
|
||||||
|
|
||||||
|
1. Environment variables
|
||||||
|
2. `.env` file
|
||||||
|
3. Default values
|
||||||
|
|
||||||
|
### Required Variables
|
||||||
|
|
||||||
|
```bash
|
||||||
|
GHOST_URL=http://localhost:2368
|
||||||
|
GHOST_CONTENT_API_KEY=your_content_api_key_here
|
||||||
|
GHOST_ADMIN_API_KEY=your_admin_api_key_here
|
||||||
|
```
|
||||||
|
|
||||||
|
### Optional Variables
|
||||||
|
|
||||||
|
```bash
|
||||||
|
GHOST_VERSION=v5.0
|
||||||
|
GHOST_MODE=auto # auto, readonly, readwrite
|
||||||
|
GHOST_TIMEOUT=30
|
||||||
|
GHOST_MAX_RETRIES=3
|
||||||
|
GHOST_RETRY_BACKOFF_FACTOR=2.0
|
||||||
|
|
||||||
|
LOG_LEVEL=info # debug, info, warning, error
|
||||||
|
LOG_STRUCTURED=true
|
||||||
|
LOG_REQUEST_ID=true
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🛠️ Development
|
||||||
|
|
||||||
|
### Project Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
ghost-mcp/
|
||||||
|
├── src/ghost_mcp/
|
||||||
|
│ ├── server.py # FastMCP server entry point
|
||||||
|
│ ├── client.py # Ghost API client
|
||||||
|
│ ├── config.py # Configuration management
|
||||||
|
│ ├── auth/ # Authentication modules
|
||||||
|
│ ├── tools/
|
||||||
|
│ │ ├── content/ # Content API tools
|
||||||
|
│ │ └── admin/ # Admin API tools
|
||||||
|
│ ├── types/ # Type definitions
|
||||||
|
│ └── utils/ # Utilities
|
||||||
|
├── scripts/ # Setup and test scripts
|
||||||
|
├── contracts/ # API documentation
|
||||||
|
├── docker-compose.yml # Ghost + MySQL setup
|
||||||
|
├── Makefile # Development commands
|
||||||
|
└── pyproject.toml # Python project config
|
||||||
|
```
|
||||||
|
|
||||||
|
### Available Commands
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make help # Show all commands
|
||||||
|
make setup # Complete setup from scratch
|
||||||
|
make install # Install dependencies with uv
|
||||||
|
make start-ghost # Start Ghost containers
|
||||||
|
make setup-tokens # Generate API keys
|
||||||
|
make test # Run tests
|
||||||
|
make test-connection # Test API connectivity
|
||||||
|
make run # Run MCP server
|
||||||
|
make status # Check system status
|
||||||
|
make clean # Clean up everything
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🐳 Docker Environment
|
||||||
|
|
||||||
|
The project includes a complete Docker Compose setup:
|
||||||
|
|
||||||
|
- **Ghost**: Latest Ghost 5.x with Alpine Linux
|
||||||
|
- **MySQL 8.0**: Database with health checks
|
||||||
|
- **Development optimized**: Logging, auto-restart, volume persistence
|
||||||
|
|
||||||
|
### URLs
|
||||||
|
|
||||||
|
- **Ghost Admin**: http://localhost:2368/ghost/
|
||||||
|
- **Ghost Site**: http://localhost:2368/
|
||||||
|
- **Database**: localhost:3306
|
||||||
|
|
||||||
|
## 🔐 API Authentication
|
||||||
|
|
||||||
|
### Content API
|
||||||
|
- Uses query parameter authentication
|
||||||
|
- 26-character hex API key
|
||||||
|
- Read-only access to published content
|
||||||
|
|
||||||
|
### Admin API
|
||||||
|
- Uses JWT token authentication
|
||||||
|
- Format: `id:secret` (24-char + 64-char hex)
|
||||||
|
- 5-minute token expiration with automatic renewal
|
||||||
|
- Full read/write access
|
||||||
|
|
||||||
|
## 📊 Error Handling
|
||||||
|
|
||||||
|
Comprehensive error handling with 5 categories:
|
||||||
|
|
||||||
|
1. **Network Errors**: Connection timeouts, DNS failures
|
||||||
|
2. **Authentication Errors**: Invalid keys, expired tokens
|
||||||
|
3. **Ghost API Errors**: Ghost-specific errors with codes
|
||||||
|
4. **Validation Errors**: Invalid parameters, malformed data
|
||||||
|
5. **File Upload Errors**: Media upload failures
|
||||||
|
|
||||||
|
All errors include:
|
||||||
|
- Unique error ID
|
||||||
|
- Category classification
|
||||||
|
- Context information
|
||||||
|
- Request ID for tracing
|
||||||
|
|
||||||
|
## 🧪 Testing
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Test Ghost API connectivity
|
||||||
|
make test-connection
|
||||||
|
|
||||||
|
# Run all tests
|
||||||
|
make test
|
||||||
|
|
||||||
|
# Test specific functionality
|
||||||
|
python scripts/test-connection.py
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📝 Logging
|
||||||
|
|
||||||
|
Structured logging with configurable levels:
|
||||||
|
|
||||||
|
- **Request IDs**: Track requests across components
|
||||||
|
- **Structured format**: JSON output for production
|
||||||
|
- **Context preservation**: Error context and debugging info
|
||||||
|
- **Performance metrics**: Request timing and retry information
|
||||||
|
|
||||||
|
## 🔄 Retry Logic
|
||||||
|
|
||||||
|
Robust retry mechanism:
|
||||||
|
|
||||||
|
- **Exponential backoff**: Configurable base delay and multiplier
|
||||||
|
- **Jitter**: Prevents thundering herd problems
|
||||||
|
- **Max retries**: Configurable retry limits
|
||||||
|
- **Circuit breaker**: Fail fast after repeated failures
|
||||||
|
|
||||||
|
## 📚 Documentation
|
||||||
|
|
||||||
|
- **API Contracts**: Complete Ghost API documentation in `contracts/`
|
||||||
|
- **Type Definitions**: Full type coverage with Pydantic models
|
||||||
|
- **Examples**: Working examples for all tools
|
||||||
|
- **Development Guide**: Step-by-step setup and usage
|
||||||
|
|
||||||
|
## 🤝 Contributing
|
||||||
|
|
||||||
|
1. Fork the repository
|
||||||
|
2. Create a feature branch
|
||||||
|
3. Make changes with tests
|
||||||
|
4. Run `make test` to verify
|
||||||
|
5. Submit a pull request
|
||||||
|
|
||||||
|
## 📄 License
|
||||||
|
|
||||||
|
MIT License - see LICENSE file for details
|
||||||
|
|
||||||
|
## 🆘 Support
|
||||||
|
|
||||||
|
- **Issues**: GitHub issues for bugs and features
|
||||||
|
- **Documentation**: Check `contracts/` for API details
|
||||||
|
- **Logs**: Use `make logs` for troubleshooting
|
||||||
|
- **Status**: Use `make status` for system health
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Built with FastMCP 2.12.3 and Ghost 5.x** 🚀
|
||||||
|
|
@ -27,6 +27,7 @@ dev = [
|
||||||
"pytest>=7.4.0",
|
"pytest>=7.4.0",
|
||||||
"pytest-asyncio>=0.21.0",
|
"pytest-asyncio>=0.21.0",
|
||||||
"pytest-cov>=4.1.0",
|
"pytest-cov>=4.1.0",
|
||||||
|
"pytest-xdist>=3.3.0",
|
||||||
"black>=23.0.0",
|
"black>=23.0.0",
|
||||||
"ruff>=0.1.0",
|
"ruff>=0.1.0",
|
||||||
"mypy>=1.7.0",
|
"mypy>=1.7.0",
|
||||||
|
|
|
||||||
1
tests/__init__.py
Normal file
1
tests/__init__.py
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
"""Tests for Ghost MCP server."""
|
||||||
29
tests/test_client.py
Normal file
29
tests/test_client.py
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
"""Tests for Ghost API client."""
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
from unittest.mock import AsyncMock, patch
|
||||||
|
|
||||||
|
from ghost_mcp.client import GhostClient
|
||||||
|
from ghost_mcp.config import config
|
||||||
|
|
||||||
|
|
||||||
|
class TestGhostClient:
|
||||||
|
"""Test Ghost API client."""
|
||||||
|
|
||||||
|
def test_client_initialization(self):
|
||||||
|
"""Test client initialization."""
|
||||||
|
client = GhostClient()
|
||||||
|
assert client.base_url.endswith("/")
|
||||||
|
assert client.timeout == config.ghost.timeout
|
||||||
|
|
||||||
|
def test_build_url(self):
|
||||||
|
"""Test URL building."""
|
||||||
|
client = GhostClient()
|
||||||
|
url = client._build_url("posts/", "content")
|
||||||
|
assert url.endswith("ghost/api/content/posts/")
|
||||||
|
|
||||||
|
def test_build_admin_url(self):
|
||||||
|
"""Test Admin API URL building."""
|
||||||
|
client = GhostClient()
|
||||||
|
url = client._build_url("posts/", "admin")
|
||||||
|
assert url.endswith("ghost/api/admin/posts/")
|
||||||
59
tests/test_models.py
Normal file
59
tests/test_models.py
Normal file
|
|
@ -0,0 +1,59 @@
|
||||||
|
"""Tests for Ghost MCP models and types."""
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
from pydantic import ValidationError
|
||||||
|
|
||||||
|
from ghost_mcp.types.ghost import GhostPost, PostStatus, VisibilityType
|
||||||
|
from ghost_mcp.types.errors import GhostMCPError, ErrorCategory
|
||||||
|
from ghost_mcp.config import GhostConfig, LogLevel
|
||||||
|
|
||||||
|
|
||||||
|
class TestGhostModels:
|
||||||
|
"""Test Ghost data models."""
|
||||||
|
|
||||||
|
def test_post_status_enum(self):
|
||||||
|
"""Test post status enumeration."""
|
||||||
|
assert PostStatus.DRAFT == "draft"
|
||||||
|
assert PostStatus.PUBLISHED == "published"
|
||||||
|
assert PostStatus.SCHEDULED == "scheduled"
|
||||||
|
|
||||||
|
def test_visibility_enum(self):
|
||||||
|
"""Test visibility enumeration."""
|
||||||
|
assert VisibilityType.PUBLIC == "public"
|
||||||
|
assert VisibilityType.MEMBERS == "members"
|
||||||
|
|
||||||
|
|
||||||
|
class TestErrorModels:
|
||||||
|
"""Test error models."""
|
||||||
|
|
||||||
|
def test_ghost_mcp_error(self):
|
||||||
|
"""Test base error class."""
|
||||||
|
error = GhostMCPError("Test error", ErrorCategory.NETWORK)
|
||||||
|
assert error.category == ErrorCategory.NETWORK
|
||||||
|
assert str(error) == "Test error"
|
||||||
|
assert error.id is not None
|
||||||
|
|
||||||
|
def test_error_to_dict(self):
|
||||||
|
"""Test error serialization."""
|
||||||
|
error = GhostMCPError("Test error", ErrorCategory.VALIDATION, code="TEST_001")
|
||||||
|
error_dict = error.to_dict()
|
||||||
|
assert error_dict["message"] == "Test error"
|
||||||
|
assert error_dict["category"] == "VALIDATION"
|
||||||
|
assert error_dict["code"] == "TEST_001"
|
||||||
|
|
||||||
|
|
||||||
|
class TestConfig:
|
||||||
|
"""Test configuration models."""
|
||||||
|
|
||||||
|
def test_ghost_config_defaults(self):
|
||||||
|
"""Test Ghost configuration defaults."""
|
||||||
|
config = GhostConfig()
|
||||||
|
assert str(config.url) == "http://localhost:2368"
|
||||||
|
assert config.version == "v5.0"
|
||||||
|
assert config.timeout == 30
|
||||||
|
|
||||||
|
def test_log_level_enum(self):
|
||||||
|
"""Test log level enumeration."""
|
||||||
|
assert LogLevel.INFO == "info"
|
||||||
|
assert LogLevel.DEBUG == "debug"
|
||||||
|
assert LogLevel.ERROR == "error"
|
||||||
Loading…
Add table
Reference in a new issue