A production-ready Model Context Protocol (MCP) server that provides AI assistants with seamless access to the Trakt.tv API, enabling intelligent TV show tracking, watchlist management, and personalized viewing recommendations.
- Watch History Tracking: Complete viewing history with episode counts, timestamps, and progress tracking
- Smart Watchlist Management: Add, remove, and organize shows across all your devices
- Advanced Show Discovery: Powerful search with Trakt's extensive database and trending shows
- Dual Transport Support: Production-ready HTTP (Streamable) and development-friendly stdio modes
- Async Architecture: Built with FastMCP and httpx for high-performance async operations
- Lifecycle Management: Automatic resource initialization and cleanup with async context managers
- Comprehensive Error Handling: Detailed exception hierarchy for authentication, network, and API errors
- Structured Logging: Configurable logging system for monitoring and debugging
trakt-mcp-server/
├── main.py # Application entry point with transport selection
├── src/
│ ├── server.py # FastMCP server with lifespan management
│ ├── api/
│ │ └── __init__.py # TraktAPIClient with async HTTP operations
│ ├── config/
│ │ └── __init__.py # Configuration management and validation
│ ├── exceptions/
│ │ └── __init__.py # Custom exception hierarchy
│ ├── formatters/
│ │ └── __init__.py # Output formatters for tool responses
│ ├── tools/
│ │ ├── __init__.py # Tool registration system
│ │ ├── history.py # Watch history tools
│ │ ├── watchlist.py # Watchlist management tools
│ │ └── discovery.py # Search and trending tools
│ └── utils/
│ └── logger.py # Structured logging configuration
├── requirements.txt # Python dependencies
├── .env.example # Environment configuration template
└── README.md # This file
- FastMCP Server: Leverages FastMCP for declarative tool registration and automatic type validation
- Async API Client: httpx-based client with connection pooling and automatic retries
- Lifespan Context: Ensures proper resource initialization and cleanup across server lifecycle
- Tool Categories: Organized into history, watchlist, and discovery modules for maintainability
Retrieves complete watch history with detailed viewing statistics.
Returns:
- All watched TV shows with episode counts
- Last watched timestamps and total plays
- Viewing progress for each series
- Formatted JSON response
Use Cases:
- "What shows have I watched recently?"
- "Have I already seen Breaking Bad?"
- Recommendation filtering (avoid suggesting watched content)
Fetches the user's curated watchlist - the primary source for personalized recommendations.
Returns:
- All bookmarked shows with metadata
- Title, year, rating, genres
- Timestamp when added to watchlist
Use Cases:
- "What should I watch tonight?"
- "Show me my saved shows"
- Priority recommendations from user's own list
Adds a TV show to the user's watchlist with cross-device sync.
Parameters:
show_id(string, required): Trakt numeric ID fromsearch_shows- Pattern:
^[0-9]+$(validated)
- Pattern:
Returns: Confirmation with number of shows added
Workflow:
- Call
search_showsto find the show - Extract Trakt ID from results
- Call
add_to_watchlistwith that ID
Requirements: OAuth access token with watchlist permissions
Removes a show from the watchlist without affecting watch history.
Parameters:
show_id(string, required): Trakt numeric ID
Returns: Confirmation with number of shows removed
Search Trakt's extensive database by title or keywords.
Parameters:
query(string, required): Search term (min length: 1)
Returns:
- Top 10 matching shows
- Trakt IDs, titles, years, ratings
- Score-sorted results
Use Cases:
- "Search for The Office"
- Finding show IDs for watchlist operations
- "Is there a show called Dark?"
Get real-time trending shows based on community activity.
Parameters:
limit(integer, optional): Number of results (1-20, default: 10)
Returns:
- Currently popular shows
- Viewer counts and ratings
- Real-time community engagement data
Use Cases:
- "What's trending right now?"
- "What are people watching?"
- Zeitgeist recommendations
- Python 3.8+ (recommended: 3.11+ for optimal async performance)
- Trakt.tv account (free registration at trakt.tv)
- Trakt API credentials (Client ID and OAuth Access Token)
git clone <repository-url>
cd trakt-mcp-serverpython -m venv venv
# Windows
venv\Scripts\activate
# macOS/Linux
source venv/bin/activatepip install -r requirements.txtDependencies:
mcp- FastMCP framework for MCP server implementationhttpx- High-performance async HTTP client for Trakt APIpython-dotenv- Environment variable managementpydantic- Data validation (dependency of FastMCP)
cp .env.example .envEdit .env with your credentials:
# Required: Trakt API Credentials
TRAKT_CLIENT_ID=your_trakt_client_id_here
TRAKT_ACCESS_TOKEN=your_oauth_access_token_here
TRAKT_API_VERSION=2
# Optional: Logging Configuration
LOG_LEVEL=INFO # Options: DEBUG, INFO, WARNING, ERROR, CRITICAL-
Create Application
- Navigate to Trakt.tv Applications
- Click "New Application"
- Fill in application details (name, description, redirect URI)
-
Get Client ID
- Copy the Client ID from your application page
- Add to
.envasTRAKT_CLIENT_ID
-
Generate Access Token
- In your application settings, generate an OAuth token
- Required permissions:
public,read,write(for watchlist management) - Copy the generated token
- Add to
.envasTRAKT_ACCESS_TOKEN
-
Verify Configuration
python -c "from src.config import AppConfig; print('✓ Configuration valid')"
The server supports two transport protocols optimized for different use cases:
Best for local development and MCP client integrations (Claude Desktop, etc.)
python main.pyCharacteristics:
- Each client gets dedicated process
- Input/output via standard streams
- Ideal for single-user local development
- Default mode when no flags specified
Recommended for production deployments and network access
python main.py --httpCharacteristics:
- Full bidirectional communication via HTTP
- Multiple concurrent client support
- Server runs on
0.0.0.0:8000 - Supports streaming responses
- Production-grade scalability
Connection:
HTTP Endpoint: http://localhost:8000
Protocol: Streamable HTTP (MCP standard)
# stdio mode
python -m trakt_mcp_server
# HTTP mode
python -m trakt_mcp_server --http| Variable | Required | Default | Description |
|---|---|---|---|
TRAKT_CLIENT_ID |
Yes | - | Trakt API Client ID |
TRAKT_ACCESS_TOKEN |
Yes | - | OAuth Access Token |
TRAKT_API_VERSION |
Yes | 2 |
Trakt API version |
LOG_LEVEL |
No | INFO |
Logging verbosity |
The TraktAPIClient is configured in src/api/init.py:
httpx.AsyncClient(
timeout=30.0, # Request timeout
follow_redirects=True, # Auto-follow redirects
headers={
"Content-Type": "application/json",
"User-Agent": "TraktMCPServer/1.0.0",
"trakt-api-version": "2",
"trakt-api-key": TRAKT_CLIENT_ID,
"Authorization": f"Bearer {TRAKT_ACCESS_TOKEN}"
}
)This server implements the Model Context Protocol and works with any compatible client:
- Custom MCP Clients - Any client implementing MCP specification
- Development Tools - MCP Inspector, testing frameworks
1. Start the Server
# For local MCP clients
python main.py
# For network-accessible deployment
python main.py --http2. Configure Client
For stdio transport (Claude Desktop example):
{
"mcpServers": {
"trakt": {
"command": "python",
"args": ["main.py"],
"cwd": "/path/to/trakt-mcp-server",
"env": {
"TRAKT_CLIENT_ID": "your_client_id",
"TRAKT_ACCESS_TOKEN": "your_token"
}
}
}
}For HTTP transport:
{
"mcpServers": {
"trakt": {
"url": "http://localhost:8000",
"transport": "streamable-http"
}
}
}3. Available Tools
Once connected, the client has access to all 6 tools:
get_watched_showsget_watchlistadd_to_watchlistremove_from_watchlistsearch_showsget_trending_shows
Set logging level via environment variable:
LOG_LEVEL=DEBUG # Maximum verbosity
LOG_LEVEL=INFO # Standard operations (default)
LOG_LEVEL=WARNING # Warnings and errors only
LOG_LEVEL=ERROR # Errors only
LOG_LEVEL=CRITICAL # Critical failures onlyThe logger (src/utils/logger.py) provides structured output:
2025-01-15 14:30:22 [INFO] src.server: Initializing Trakt API client...
2025-01-15 14:30:22 [INFO] src.api: TraktAPIClient initialized successfully
2025-01-15 14:30:23 [INFO] main: Starting stdio server...
For troubleshooting, enable debug logging:
LOG_LEVEL=DEBUG python main.pyProvides detailed information:
- HTTP request/response details
- API endpoint calls
- Tool invocation parameters
- Exception stack traces
The server implements a comprehensive error handling system (src/exceptions/init.py):
TraktAPIError # Base exception
├── AuthenticationError # 401 - Invalid credentials
├── ResourceNotFoundError # 404 - Show/resource not found
└── NetworkError # Connection/timeout errorsAll errors are:
- Logged with full context and stack traces
- Formatted as user-friendly messages
- Returned through MCP protocol to client
Example:
# Invalid credentials
AuthenticationError: "Invalid Trakt credentials. Check TRAKT_ACCESS_TOKEN."
# Network timeout
NetworkError: "Failed to connect to Trakt API. Check network connection."
# Show not found
ResourceNotFoundError: "Show ID 99999999 not found in Trakt database."The httpx client automatically handles:
- Connection pooling
- Redirect following
- Timeout management (30s default)
src/
├── server.py # FastMCP server + lifespan management
├── api/ # API client layer
├── config/ # Configuration + validation
├── exceptions/ # Custom exception types
├── formatters/ # Response formatting logic
├── tools/ # MCP tool definitions (modular)
│ ├── history.py # Watch history tools
│ ├── watchlist.py # Watchlist management
│ └── discovery.py # Search + trending
└── utils/ # Logging utilities
Tools are registered using FastMCP decorators:
@mcp.tool()
async def my_new_tool(
ctx: Context[ServerSession, AppContext],
param: Annotated[str, Field(description="Parameter description")]
) -> str:
"""
Tool description for AI assistant.
Detailed explanation of what the tool does.
"""
api = ctx.request_context.lifespan_context.api_client
result = await api.my_api_method(param)
return format_result(result)Register in src/tools/init.py:
def register_all_tools(mcp: FastMCP) -> None:
register_watchlist_tools(mcp)
register_history_tools(mcp)
register_discovery_tools(mcp)
register_my_new_tools(mcp) # Add thisContributions welcome! Please:
- Fork the repository
- Create a feature branch
- Follow existing code style and patterns
- Add tests for new functionality
- Submit a pull request