Add spec
This commit is contained in:
commit
3c5b0da801
1 changed files with 314 additions and 0 deletions
314
SPEC.md
Normal file
314
SPEC.md
Normal file
|
|
@ -0,0 +1,314 @@
|
||||||
|
# Ghost MCP
|
||||||
|
|
||||||
|
This is the spec for the Ghost Blog platform MCP server.
|
||||||
|
|
||||||
|
## Goal
|
||||||
|
|
||||||
|
- The main goal is to implement the MCP tools for all https://docs.ghost.org/content-api REST actions
|
||||||
|
- Provide a comprehensive MCP server that allows Claude to interact with Ghost blog content
|
||||||
|
- Support all major Ghost Content API endpoints for reading published content
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
### Infrastructure
|
||||||
|
- Deploy a local Ghost instance using `docker compose` and figure out a way to create an API key
|
||||||
|
- Set up proper authentication using Ghost Content API keys
|
||||||
|
- Configure the MCP server to connect to the Ghost instance
|
||||||
|
|
||||||
|
### Development
|
||||||
|
- Implement MCP server using Node.js/TypeScript
|
||||||
|
- Follow MCP protocol specifications
|
||||||
|
- Include comprehensive error handling and validation
|
||||||
|
- Support proper filtering, pagination, and query parameters
|
||||||
|
|
||||||
|
## Ghost Content API Endpoints
|
||||||
|
|
||||||
|
The Ghost Content API provides read-only access to published content. All endpoints support the following:
|
||||||
|
- Content API key authentication (query parameter)
|
||||||
|
- JSON response format with consistent structure
|
||||||
|
- Filtering, pagination, and field selection
|
||||||
|
- Full caching support
|
||||||
|
|
||||||
|
### Posts
|
||||||
|
- `GET /posts/` - List all published posts
|
||||||
|
- `GET /posts/{id}/` - Get a specific post by ID
|
||||||
|
- `GET /posts/slug/{slug}/` - Get a specific post by slug
|
||||||
|
|
||||||
|
### Pages
|
||||||
|
- `GET /pages/` - List all published pages
|
||||||
|
- `GET /pages/{id}/` - Get a specific page by ID
|
||||||
|
- `GET /pages/slug/{slug}/` - Get a specific page by slug
|
||||||
|
|
||||||
|
### Tags
|
||||||
|
- `GET /tags/` - List all tags
|
||||||
|
- `GET /tags/{id}/` - Get a specific tag by ID
|
||||||
|
- `GET /tags/slug/{slug}/` - Get a specific tag by slug
|
||||||
|
|
||||||
|
### Authors
|
||||||
|
- `GET /authors/` - List all authors
|
||||||
|
- `GET /authors/{id}/` - Get a specific author by ID
|
||||||
|
- `GET /authors/slug/{slug}/` - Get a specific author by slug
|
||||||
|
|
||||||
|
### Tiers
|
||||||
|
- `GET /tiers/` - List all membership tiers
|
||||||
|
|
||||||
|
### Settings
|
||||||
|
- `GET /settings/` - Get public settings
|
||||||
|
|
||||||
|
## API Response Format
|
||||||
|
|
||||||
|
All Ghost Content API responses follow this structure:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"resource_type": [{ ... }],
|
||||||
|
"meta": {
|
||||||
|
"pagination": {
|
||||||
|
"page": 1,
|
||||||
|
"limit": 15,
|
||||||
|
"pages": 1,
|
||||||
|
"total": 1,
|
||||||
|
"next": null,
|
||||||
|
"prev": null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## MCP Tools Specification
|
||||||
|
|
||||||
|
The following MCP tools should be implemented to provide comprehensive access to the Ghost Content API:
|
||||||
|
|
||||||
|
### Posts Tools
|
||||||
|
- **`ghost_list_posts`** - List all published posts
|
||||||
|
- Parameters: `limit?` (number), `page?` (number), `filter?` (string), `include?` (string), `fields?` (string)
|
||||||
|
- Returns: Array of post objects with pagination metadata
|
||||||
|
|
||||||
|
- **`ghost_get_post_by_id`** - Get a specific post by ID
|
||||||
|
- Parameters: `id` (required string), `include?` (string), `fields?` (string)
|
||||||
|
- Returns: Single post object
|
||||||
|
|
||||||
|
- **`ghost_get_post_by_slug`** - Get a specific post by slug
|
||||||
|
- Parameters: `slug` (required string), `include?` (string), `fields?` (string)
|
||||||
|
- Returns: Single post object
|
||||||
|
|
||||||
|
### Pages Tools
|
||||||
|
- **`ghost_list_pages`** - List all published pages
|
||||||
|
- Parameters: `limit?` (number), `page?` (number), `filter?` (string), `include?` (string), `fields?` (string)
|
||||||
|
- Returns: Array of page objects with pagination metadata
|
||||||
|
|
||||||
|
- **`ghost_get_page_by_id`** - Get a specific page by ID
|
||||||
|
- Parameters: `id` (required string), `include?` (string), `fields?` (string)
|
||||||
|
- Returns: Single page object
|
||||||
|
|
||||||
|
- **`ghost_get_page_by_slug`** - Get a specific page by slug
|
||||||
|
- Parameters: `slug` (required string), `include?` (string), `fields?` (string)
|
||||||
|
- Returns: Single page object
|
||||||
|
|
||||||
|
### Tags Tools
|
||||||
|
- **`ghost_list_tags`** - List all tags
|
||||||
|
- Parameters: `limit?` (number), `page?` (number), `filter?` (string), `include?` (string), `fields?` (string)
|
||||||
|
- Returns: Array of tag objects with pagination metadata
|
||||||
|
|
||||||
|
- **`ghost_get_tag_by_id`** - Get a specific tag by ID
|
||||||
|
- Parameters: `id` (required string), `include?` (string), `fields?` (string)
|
||||||
|
- Returns: Single tag object
|
||||||
|
|
||||||
|
- **`ghost_get_tag_by_slug`** - Get a specific tag by slug
|
||||||
|
- Parameters: `slug` (required string), `include?` (string), `fields?` (string)
|
||||||
|
- Returns: Single tag object
|
||||||
|
|
||||||
|
### Authors Tools
|
||||||
|
- **`ghost_list_authors`** - List all authors
|
||||||
|
- Parameters: `limit?` (number), `page?` (number), `filter?` (string), `include?` (string), `fields?` (string)
|
||||||
|
- Returns: Array of author objects with pagination metadata
|
||||||
|
|
||||||
|
- **`ghost_get_author_by_id`** - Get a specific author by ID
|
||||||
|
- Parameters: `id` (required string), `include?` (string), `fields?` (string)
|
||||||
|
- Returns: Single author object
|
||||||
|
|
||||||
|
- **`ghost_get_author_by_slug`** - Get a specific author by slug
|
||||||
|
- Parameters: `slug` (required string), `include?` (string), `fields?` (string)
|
||||||
|
- Returns: Single author object
|
||||||
|
|
||||||
|
### Other Tools
|
||||||
|
- **`ghost_list_tiers`** - List all membership tiers
|
||||||
|
- Parameters: `limit?` (number), `page?` (number), `include?` (string), `fields?` (string)
|
||||||
|
- Returns: Array of tier objects
|
||||||
|
|
||||||
|
- **`ghost_get_settings`** - Get public settings
|
||||||
|
- Parameters: None
|
||||||
|
- Returns: Settings object
|
||||||
|
|
||||||
|
### Common Parameters
|
||||||
|
- `limit`: Number of resources to return (default: 15, max: 50)
|
||||||
|
- `page`: Page number for pagination (default: 1)
|
||||||
|
- `filter`: Filter string using Ghost's filtering syntax
|
||||||
|
- `include`: Comma-separated list of related resources to include
|
||||||
|
- `fields`: Comma-separated list of fields to return
|
||||||
|
|
||||||
|
## Docker Compose Setup
|
||||||
|
|
||||||
|
Create a `docker-compose.yml` file to run Ghost locally:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
version: '3.8'
|
||||||
|
services:
|
||||||
|
ghost:
|
||||||
|
image: ghost:5-alpine
|
||||||
|
restart: always
|
||||||
|
ports:
|
||||||
|
- "2368:2368"
|
||||||
|
environment:
|
||||||
|
database__client: mysql
|
||||||
|
database__connection__host: db
|
||||||
|
database__connection__user: root
|
||||||
|
database__connection__password: yourpassword
|
||||||
|
database__connection__database: ghost
|
||||||
|
url: http://localhost:2368
|
||||||
|
volumes:
|
||||||
|
- ghost_content:/var/lib/ghost/content
|
||||||
|
depends_on:
|
||||||
|
- db
|
||||||
|
|
||||||
|
db:
|
||||||
|
image: mysql:8.0
|
||||||
|
restart: always
|
||||||
|
environment:
|
||||||
|
MYSQL_ROOT_PASSWORD: yourpassword
|
||||||
|
MYSQL_DATABASE: ghost
|
||||||
|
volumes:
|
||||||
|
- mysql_data:/var/lib/mysql
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
ghost_content:
|
||||||
|
mysql_data:
|
||||||
|
```
|
||||||
|
|
||||||
|
### API Key Creation Process
|
||||||
|
|
||||||
|
1. Start the Ghost instance: `docker compose up -d`
|
||||||
|
2. Visit `http://localhost:2368/ghost` to set up your admin account
|
||||||
|
3. Navigate to Settings → Integrations → Custom Integrations
|
||||||
|
4. Create a new integration to get your Content API key
|
||||||
|
5. Save the Content API key for MCP server configuration
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
The MCP server should support configuration via:
|
||||||
|
|
||||||
|
### Environment Variables
|
||||||
|
- `GHOST_URL`: Ghost instance URL (default: http://localhost:2368)
|
||||||
|
- `GHOST_CONTENT_API_KEY`: Content API key (required)
|
||||||
|
- `GHOST_VERSION`: API version (default: v5.0)
|
||||||
|
|
||||||
|
### Configuration File
|
||||||
|
Alternative JSON configuration file:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"ghost": {
|
||||||
|
"url": "http://localhost:2368",
|
||||||
|
"contentApiKey": "your-content-api-key",
|
||||||
|
"version": "v5.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Implementation Details
|
||||||
|
|
||||||
|
### Project Structure
|
||||||
|
```
|
||||||
|
ghost-mcp/
|
||||||
|
├── src/
|
||||||
|
│ ├── index.ts # MCP server entry point
|
||||||
|
│ ├── ghost-client.ts # Ghost API client
|
||||||
|
│ ├── tools/
|
||||||
|
│ │ ├── posts.ts # Post-related tools
|
||||||
|
│ │ ├── pages.ts # Page-related tools
|
||||||
|
│ │ ├── tags.ts # Tag-related tools
|
||||||
|
│ │ ├── authors.ts # Author-related tools
|
||||||
|
│ │ └── settings.ts # Settings and tiers tools
|
||||||
|
│ ├── types/
|
||||||
|
│ │ ├── ghost.ts # Ghost API response types
|
||||||
|
│ │ └── mcp.ts # MCP-specific types
|
||||||
|
│ └── utils/
|
||||||
|
│ ├── validation.ts # Parameter validation
|
||||||
|
│ └── errors.ts # Error handling utilities
|
||||||
|
├── package.json
|
||||||
|
├── tsconfig.json
|
||||||
|
├── docker-compose.yml
|
||||||
|
└── README.md
|
||||||
|
```
|
||||||
|
|
||||||
|
### Technology Stack
|
||||||
|
- **Node.js** (v18+) with **TypeScript**
|
||||||
|
- **@modelcontextprotocol/sdk** for MCP implementation
|
||||||
|
- **axios** or **fetch** for HTTP requests
|
||||||
|
- **zod** for runtime type validation
|
||||||
|
- **dotenv** for environment variable management
|
||||||
|
|
||||||
|
### Error Handling
|
||||||
|
- Validate all input parameters using Zod schemas
|
||||||
|
- Handle Ghost API errors gracefully with meaningful messages
|
||||||
|
- Implement retry logic for transient network errors
|
||||||
|
- Return proper MCP error responses with error codes
|
||||||
|
|
||||||
|
### Testing Strategy
|
||||||
|
- Unit tests for individual tools and utilities
|
||||||
|
- Integration tests with local Ghost instance
|
||||||
|
- Mock Ghost API responses for reliable testing
|
||||||
|
- Test parameter validation and error scenarios
|
||||||
|
|
||||||
|
### Performance Considerations
|
||||||
|
- Implement request caching where appropriate
|
||||||
|
- Use connection pooling for HTTP requests
|
||||||
|
- Support streaming responses for large datasets
|
||||||
|
- Add request rate limiting to respect Ghost API limits
|
||||||
|
|
||||||
|
## Questions for Clarification
|
||||||
|
|
||||||
|
Before proceeding with implementation, please clarify the following:
|
||||||
|
|
||||||
|
### 1. API Scope
|
||||||
|
- **Question**: Should this MCP server be read-only (Content API) or also include write operations (Admin API)?
|
||||||
|
- **Impact**: Admin API would require different authentication and additional tools for creating/updating content
|
||||||
|
- **Recommendation**: Start with read-only Content API for initial implementation
|
||||||
|
|
||||||
|
### 2. Authentication Strategy
|
||||||
|
- **Question**: Do you want to support both Content API keys and Admin API keys?
|
||||||
|
- **Impact**: Different authentication methods have different capabilities and security considerations
|
||||||
|
- **Recommendation**: Begin with Content API keys only
|
||||||
|
|
||||||
|
### 3. Filtering and Pagination
|
||||||
|
- **Question**: Should all Ghost API filtering/pagination options be exposed as tool parameters?
|
||||||
|
- **Impact**: More parameters provide flexibility but increase complexity
|
||||||
|
- **Options**:
|
||||||
|
- Full parameter exposure (complete flexibility)
|
||||||
|
- Simplified parameter set (easier to use)
|
||||||
|
- Progressive enhancement (start simple, add more later)
|
||||||
|
|
||||||
|
### 4. Error Handling Strategy
|
||||||
|
- **Question**: Any specific error handling or retry logic requirements?
|
||||||
|
- **Impact**: Affects reliability and user experience
|
||||||
|
- **Considerations**: Network timeouts, rate limits, API downtime
|
||||||
|
|
||||||
|
### 5. Configuration Management
|
||||||
|
- **Question**: How should the Ghost instance URL and API keys be configured?
|
||||||
|
- **Options**:
|
||||||
|
- Environment variables only
|
||||||
|
- Configuration file only
|
||||||
|
- Both (with precedence order)
|
||||||
|
- Runtime configuration via MCP parameters
|
||||||
|
|
||||||
|
### 6. Additional Features
|
||||||
|
- **Question**: Are there any additional features beyond basic CRUD operations?
|
||||||
|
- **Examples**:
|
||||||
|
- Content search across posts/pages
|
||||||
|
- Bulk operations
|
||||||
|
- Content analytics/statistics
|
||||||
|
- Webhook support for real-time updates
|
||||||
|
|
||||||
|
### 7. Development Environment
|
||||||
|
- **Question**: Should the development setup include sample Ghost content for testing?
|
||||||
|
- **Impact**: Makes testing and development easier but increases setup complexity
|
||||||
|
|
||||||
|
Please provide guidance on these questions to ensure the implementation meets your specific needs and use cases.
|
||||||
Loading…
Add table
Reference in a new issue