samdaw13/plex-mcp-server
If you are the rightful owner of plex-mcp-server and would like to certify it and/or have it hosted online, please leave a comment on the right or send an email to dayong@mcphub.com.
Plex MCP Server is a Model Context Protocol server designed to provide a standardized interface for AI assistants, automation tools, and custom integrations to interact with Plex Media Server.
Plex MCP Server
A Model Context Protocol (MCP) server for Plex Media Server, providing a standardized interface for AI assistants, automation tools, and custom integrations to interact with your Plex server.
Overview
Plex MCP Server creates a unified MCP-compliant API layer on top of the Plex Media Server API, offering:
- MCP Protocol Compliance - Works seamlessly with Claude Desktop, Cline, and other MCP clients
- Standardized JSON responses for compatibility with automation tools, AI systems, and other integrations
- Multiple transport methods (stdio and SSE) for flexible integration options
- Rich tool set - 60+ tools for managing libraries, collections, playlists, media, users, playback, and more
- Error handling with consistent response formats
- Docker support for easy deployment
- Connection pooling with automatic reconnection for reliability
Requirements
- Python 3.13+
- Plex Media Server with valid authentication token
- Access to the Plex server (locally or remotely)
Installation
Option 1: Using uv (Recommended)
uv is a fast Python package installer and resolver.
# Install uv if you haven't already
curl -LsSf https://astral.sh/uv/install.sh | sh
# Clone this repository
git clone https://github.com/yourusername/plex-mcp-server.git
cd plex-mcp-server
# Install dependencies
uv sync
# Create .env file
cp .env.example .env
# Edit .env with your Plex server details
Option 2: Using pip
# Clone this repository
git clone https://github.com/yourusername/plex-mcp-server.git
cd plex-mcp-server
# Install dependencies
pip install -r requirements.txt
# Create .env file
cp .env.example .env
# Edit .env with your Plex server details
Option 3: Using Docker
# Clone this repository
git clone https://github.com/yourusername/plex-mcp-server.git
cd plex-mcp-server
# Create .env file
cp .env.example .env
# Edit .env with your Plex server details
# Start the server with Docker Compose
docker-compose up -d
Environment Variables
Configure your .env file with the following variables:
# Plex Configuration
PLEX_URL=http://your-plex-server:32400
PLEX_TOKEN=your-plex-token
PLEX_USERNAME=your-username # Optional, used for some user-specific queries
# FastMCP Server Configuration (for SSE mode)
FASTMCP_HOST=0.0.0.0
FASTMCP_PORT=3001
Finding Your Plex Token: See Plex's official guide for instructions on obtaining your authentication token.
Usage
The server can be run in two transport modes: stdio (Standard Input/Output) or SSE (Server-Sent Events). Each mode is suitable for different integration scenarios.
Running with stdio Transport
The stdio transport is ideal for direct integration with MCP clients like Claude Desktop, Cline, or other AI assistants.
Using Python Module (Recommended)
python -m plex_mcp_server
Using Legacy Script (Still supported)
python plex_mcp_server.py --transport stdio
Configuration for Claude Desktop
Add this to your Claude Desktop configuration file:
macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
Windows: %APPDATA%\Claude\claude_desktop_config.json
{
"mcpServers": {
"plex": {
"command": "python",
"args": [
"-m",
"plex_mcp_server"
],
"env": {
"PLEX_URL": "http://localhost:32400",
"PLEX_TOKEN": "your-plex-token",
"PLEX_USERNAME": "your-username"
}
}
}
}
Note: If using uv, you can also use:
{
"mcpServers": {
"plex": {
"command": "uv",
"args": [
"--directory",
"/path/to/plex-mcp-server",
"run",
"plex-mcp-server"
],
"env": {
"PLEX_URL": "http://localhost:32400",
"PLEX_TOKEN": "your-plex-token",
"PLEX_USERNAME": "your-username"
}
}
}
}
Running with SSE Transport
The Server-Sent Events (SSE) transport provides a web-based interface for integration with web applications, automation platforms, and remote MCP clients.
Using Python Module (Default)
python -m plex_mcp_server
This starts the SSE server on http://0.0.0.0:3001 by default.
Using Legacy Script with Custom Options
python plex_mcp_server.py --transport sse --host 0.0.0.0 --port 3001
Using Docker
docker-compose up -d
The server will be available at:
- SSE endpoint:
http://localhost:3001/sse - Message endpoint:
http://localhost:3001/messages/ - Tools endpoint:
http://localhost:3001/tools- List all available MCP tools
Configuration for MCP Clients (SSE Mode)
{
"mcpServers": {
"plex": {
"url": "http://localhost:3001/sse"
}
}
}
Tools Endpoint
When running in SSE mode, the server exposes a /tools endpoint that returns a JSON list of all available MCP tools. Note: This endpoint does not change how MCP clients connect to the server. MCP clients still connect via the /sse endpoint or stdio transport as configured. The /tools endpoint is a separate HTTP endpoint designed for tooling, type safety, and development purposes.
This endpoint is particularly useful for:
- Type Safety: Generate TypeScript interfaces or other type definitions from tool schemas
- Discovery: Programmatically discover what tools are available
- Documentation: Generate documentation from tool metadata
- Integration: Build custom UIs or automation that need to know available operations
- Debugging: Verify which tools are registered and their configurations
Endpoint: GET http://localhost:3001/tools
Response Format:
Each tool in the response includes:
name- The tool's unique identifierdescription- Human-readable description of what the tool doesparameters- JSON schema defining the tool's input parametersoutput_schema- JSON schema defining the tool's output formatannotations- Tool metadata (readOnlyHint, destructiveHint, etc.)access- Access level extracted from tool tags (read, write, delete)
Example Response:
[
{
"name": "library_list",
"description": "List all libraries on the server",
"parameters": {
"type": "object",
"properties": {},
"required": []
},
"output_schema": {
"type": "object",
"properties": {
"result": {
"anyOf": [
{"$ref": "#/$defs/LibraryListResponse"},
{"$ref": "#/$defs/ErrorResponse"}
]
}
}
},
"annotations": {
"title": null,
"readOnlyHint": true,
"destructiveHint": null,
"idempotentHint": null,
"openWorldHint": null
},
"access": "read"
},
{
"name": "media_search",
"description": "Search for media across all libraries",
"parameters": {
"type": "object",
"properties": {
"query": {
"type": "string"
},
"content_type": {
"type": "string",
"default": null
}
},
"required": ["query"]
},
"output_schema": {...},
"annotations": {...},
"access": "read"
}
]
Usage Examples:
# Get all tools
curl http://localhost:3001/tools
# Filter tools by access level (using jq)
curl http://localhost:3001/tools | jq '.[] | select(.access == "write")'
# Get tool names only
curl http://localhost:3001/tools | jq '.[].name'
# Find tools that can delete
curl http://localhost:3001/tools | jq '.[] | select(.access == "delete")'
Using in MCP Server Context:
The tools endpoint is particularly useful when building integrations that need to:
- Type Safety & Code Generation: Generate TypeScript interfaces, Python types, or other language bindings from tool schemas
- Dynamic Tool Discovery: Instead of hardcoding tool names, query the endpoint to discover available tools at runtime
- Permission Management: Use the
accessfield to filter tools based on user permissions - UI Generation: Build dynamic forms and interfaces based on tool parameter schemas
- Documentation: Automatically generate API documentation from tool metadata
TypeScript Type Generation Example:
You can use the /tools endpoint to generate TypeScript interfaces for type-safe tool calls:
// Fetch tools and generate types
async function generateToolTypes() {
const response = await fetch('http://localhost:3001/tools');
const tools = await response.json();
// Generate TypeScript interfaces
const typeDefinitions = tools.map(tool => {
const paramsType = generateTypeFromSchema(tool.parameters);
const returnType = generateTypeFromSchema(tool.output_schema);
return `
export interface ${tool.name}Params ${paramsType}
export type ${tool.name}Result = ${returnType};
export async function ${tool.name}(params: ${tool.name}Params): Promise<${tool.name}Result> {
// Type-safe tool call implementation
}
`;
}).join('\n\n');
return typeDefinitions;
}
// Example generated interface:
// export interface media_searchParams {
// query: string;
// content_type?: string | null;
// }
// export type media_searchResult = MediaSearchResponse | ErrorResponse;
Using with JSON Schema to TypeScript Tools:
You can use tools like json-schema-to-typescript to automatically generate types:
# Fetch tools and generate TypeScript definitions
curl http://localhost:3001/tools | \
jq -r '.[] | "\(.name): \(.parameters | tostring)"' | \
json2ts --input - --output plex-tools.d.ts
Dynamic UI Generation Example:
A web dashboard could fetch the tools list and dynamically generate a control panel:
// Fetch available tools
const response = await fetch('http://localhost:3001/tools');
const tools = await response.json();
// Filter read-only tools for a "View" panel
const readOnlyTools = tools.filter(t => t.access === 'read');
// Filter write tools for an "Edit" panel
const writeTools = tools.filter(t => t.access === 'write');
// Generate form fields from parameter schemas
function generateFormFields(tool) {
const fields = [];
const props = tool.parameters.properties || {};
for (const [name, schema] of Object.entries(props)) {
fields.push({
name,
type: schema.type,
required: tool.parameters.required?.includes(name),
description: schema.description
});
}
return fields;
}
Available Tools (60+ MCP Tools)
The server exposes all functionality as MCP tools that can be called by any MCP client. Here's an overview organized by module:
Library Module (7 tools)
library_list- List all libraries on the serverlibrary_get_stats- Get statistics for a specific librarylibrary_refresh- Refresh a library or all librarieslibrary_scan- Scan a library for new contentlibrary_get_details- Get detailed information about a librarylibrary_get_recently_added- Get recently added medialibrary_get_contents- Get full contents of a library
Media Module (7 tools)
media_search- Search for media across all librariesmedia_get_details- Get detailed information about a specific media itemmedia_edit_metadata- Edit metadata for media itemsmedia_delete- Delete media from the librarymedia_get_artwork- Get artwork/images for mediamedia_set_artwork- Set custom artwork for mediamedia_list_available_artwork- List all available artwork options
Playlist Module (9 tools)
playlist_list- List all playlistsplaylist_get_contents- Get contents of a specific playlistplaylist_create- Create a new playlistplaylist_delete- Delete a playlistplaylist_add_to- Add items to a playlistplaylist_remove_from- Remove items from a playlistplaylist_edit- Edit playlist details (title, summary)playlist_upload_poster- Upload custom poster for a playlistplaylist_copy_to_user- Copy a playlist to another user's account
Collection Module (6 tools)
collection_list- List all collectionscollection_create- Create a new collectioncollection_add_to- Add items to a collectioncollection_remove_from- Remove items from a collectioncollection_delete- Delete a collectioncollection_edit- Comprehensively edit collection attributes (title, summary, artwork, labels, advanced settings)
User Module (5 tools)
user_search_users- Search for users or list all usersuser_get_info- Get detailed information about a useruser_get_on_deck- Get on deck (in progress) media for a useruser_get_watch_history- Get recent watch history for a useruser_get_statistics- Get watch statistics for users over different time periods
Sessions Module (2 tools)
sessions_get_active- Get current playback sessions with IP addressessessions_get_media_playback_history- Get playback history for a specific media item
Server Module (7 tools)
server_get_plex_logs- Get Plex server logsserver_get_info- Get detailed server informationserver_get_bandwidth- Get bandwidth statisticsserver_get_current_resources- Get resource usage informationserver_get_butler_tasks- Get information about scheduled butler tasksserver_run_butler_task- Manually run a specific butler taskserver_get_alerts- Get real-time server alerts via websocket
Client Module (8 tools)
client_list- List all available Plex clientsclient_get_details- Get detailed information about a clientclient_get_timelines- Get current timeline information for a clientclient_get_active- Get all clients currently playing mediaclient_start_playback- Start playback of media on a clientclient_control_playback- Control playback (play, pause, stop, seek, volume)client_navigate- Navigate a client interface (up, down, select, back, home)client_set_streams- Set audio, subtitle, or video streams
Note: Client module functionality depends on having active Plex clients connected to your server. Some features may have limitations depending on the client type and capabilities.
Response Format
All commands return standardized JSON responses for maximum compatibility with various tools, automation platforms, and AI systems. This consistent structure makes it easy to process responses programmatically.
For successful operations, the response typically includes:
{
"success_field": true,
"relevant_data": "value",
"additional_info": {}
}
For errors, the response format is:
{
"error": "Error message describing what went wrong"
}
For multiple matches (when searching by title), results are returned as an array of objects with identifying information:
[
{
"title": "Item Title",
"id": 12345,
"type": "movie",
"year": 2023
},
{
"title": "Another Item",
"id": 67890,
"type": "show",
"year": 2022
}
]
Development & Debugging
Using the Watcher Script
For development and debugging, you can use the included watcher.py script which monitors for file changes and automatically restarts the server:
python watcher.py
This is useful during development to see changes immediately without manually restarting the server.
Running Tests
If you have pytest installed (included in dev dependencies):
# Install dev dependencies with uv
uv sync --group dev
# Or with pip
pip install pytest pytest-asyncio
# Run tests
pytest
Debug Mode
Enable debug mode for more verbose logging:
python plex_mcp_server.py --transport sse --debug
Architecture
The server is built using:
- FastMCP - A high-performance MCP server framework
- PlexAPI - Official Python bindings for the Plex API
- Starlette/Uvicorn - ASGI web framework for SSE transport
- Python 3.13+ - Latest Python features and performance
Project Structure
plex-mcp-server/
├── src/plex_mcp_server/
│ ├── __init__.py
│ ├── __main__.py # Main entry point
│ ├── server.py # Server setup and routing
│ └── modules/
│ ├── __init__.py # MCP instance and connection management
│ ├── library.py # Library tools
│ ├── media.py # Media tools
│ ├── playlist.py # Playlist tools
│ ├── collection.py # Collection tools
│ ├── user.py # User tools
│ ├── sessions.py # Session tools
│ ├── server.py # Server tools
│ └── client.py # Client tools
├── plex_mcp_server.py # Legacy entry point
├── docker-compose.yml # Docker setup
├── Dockerfile # Container definition
├── pyproject.toml # Project metadata and dependencies
├── requirements.txt # Pip requirements
└── README.md # This file
Use Cases
- AI Assistant Integration - Let Claude or other AI assistants manage your Plex library
- Home Automation - Integrate with Home Assistant, n8n, or other automation platforms
- Custom Dashboards - Build custom monitoring and control interfaces
- Batch Operations - Automate bulk metadata updates, organization, and cleanup
- Content Management - Programmatically manage collections, playlists, and media
- Analytics - Track viewing habits and generate custom reports
- Remote Control - Control playback on Plex clients from anywhere
Troubleshooting
Connection Issues
If you're having trouble connecting to your Plex server:
- Verify your
PLEX_URLis correct and accessible - Ensure your
PLEX_TOKENis valid (tokens can expire) - Check network connectivity between the MCP server and Plex server
- Review logs for specific error messages
MCP Client Integration
If your MCP client can't see the server:
- For stdio mode: Ensure the command path is correct in your client config
- For SSE mode: Verify the server is running and accessible at the configured URL
- Check environment variables are properly set
- Restart your MCP client after configuration changes
Common Errors
- "Failed to connect to Plex" - Check PLEX_URL and PLEX_TOKEN
- "Library not found" - Verify the library name exactly matches what's in Plex
- "Module not found" - Ensure dependencies are installed (
uv syncorpip install -r requirements.txt)
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
License
MIT License - See LICENSE file for details
Acknowledgments
- Built with FastMCP by @jlowin
- Uses PlexAPI for Plex integration
- Follows the Model Context Protocol specification