overseerr-mcp 1.0.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. overseerr_mcp-1.0.1/.agents/plugins/marketplace.json +20 -0
  2. overseerr_mcp-1.0.1/.app.json +1 -0
  3. overseerr_mcp-1.0.1/.claude-plugin/plugin.json +45 -0
  4. overseerr_mcp-1.0.1/.codex-plugin/plugin.json +43 -0
  5. overseerr_mcp-1.0.1/.dockerignore +49 -0
  6. overseerr_mcp-1.0.1/.env.example +47 -0
  7. overseerr_mcp-1.0.1/.github/workflows/ci.yml +44 -0
  8. overseerr_mcp-1.0.1/.github/workflows/docker-publish.yml +75 -0
  9. overseerr_mcp-1.0.1/.github/workflows/publish-pypi.yml +63 -0
  10. overseerr_mcp-1.0.1/.gitignore +86 -0
  11. overseerr_mcp-1.0.1/.mcp.json +8 -0
  12. overseerr_mcp-1.0.1/.pre-commit-config.yaml +23 -0
  13. overseerr_mcp-1.0.1/AGENTS.md +1 -0
  14. overseerr_mcp-1.0.1/CHANGELOG.md +26 -0
  15. overseerr_mcp-1.0.1/CLAUDE.md +41 -0
  16. overseerr_mcp-1.0.1/Dockerfile +56 -0
  17. overseerr_mcp-1.0.1/GEMINI.md +1 -0
  18. overseerr_mcp-1.0.1/Justfile +76 -0
  19. overseerr_mcp-1.0.1/LICENSE +21 -0
  20. overseerr_mcp-1.0.1/PKG-INFO +434 -0
  21. overseerr_mcp-1.0.1/README.md +423 -0
  22. overseerr_mcp-1.0.1/assets/icon.png +0 -0
  23. overseerr_mcp-1.0.1/assets/logo.svg +4 -0
  24. overseerr_mcp-1.0.1/assets/screenshots/.gitkeep +0 -0
  25. overseerr_mcp-1.0.1/docker-compose.yml +34 -0
  26. overseerr_mcp-1.0.1/docs/overseerr-api.yaml +6571 -0
  27. overseerr_mcp-1.0.1/docs/overseerr.subdomain.conf +11 -0
  28. overseerr_mcp-1.0.1/entrypoint.sh +14 -0
  29. overseerr_mcp-1.0.1/gemini-extension.json +29 -0
  30. overseerr_mcp-1.0.1/hooks/hooks.json +22 -0
  31. overseerr_mcp-1.0.1/hooks/scripts/ensure-gitignore.sh +22 -0
  32. overseerr_mcp-1.0.1/hooks/scripts/ensure-ignore-files.sh +111 -0
  33. overseerr_mcp-1.0.1/hooks/scripts/fix-env-perms.sh +30 -0
  34. overseerr_mcp-1.0.1/hooks/scripts/sync-env.sh +46 -0
  35. overseerr_mcp-1.0.1/overseerr_mcp/__init__.py +1 -0
  36. overseerr_mcp-1.0.1/overseerr_mcp/client.py +98 -0
  37. overseerr_mcp-1.0.1/overseerr_mcp/server.py +495 -0
  38. overseerr_mcp-1.0.1/pyproject.toml +32 -0
  39. overseerr_mcp-1.0.1/scripts/check-docker-security.sh +145 -0
  40. overseerr_mcp-1.0.1/scripts/check-no-baked-env.sh +138 -0
  41. overseerr_mcp-1.0.1/scripts/check-outdated-deps.sh +181 -0
  42. overseerr_mcp-1.0.1/scripts/ensure-ignore-files.sh +271 -0
  43. overseerr_mcp-1.0.1/scripts/lint-plugin.sh +459 -0
  44. overseerr_mcp-1.0.1/scripts/setup-data-dirs.sh +22 -0
  45. overseerr_mcp-1.0.1/scripts/smoke-test.sh +235 -0
  46. overseerr_mcp-1.0.1/server.json +37 -0
  47. overseerr_mcp-1.0.1/skills/overseerr/SKILL.md +113 -0
  48. overseerr_mcp-1.0.1/tests/test_live.sh +17 -0
  49. overseerr_mcp-1.0.1/uv.lock +1658 -0
@@ -0,0 +1,20 @@
1
+ {
2
+ "name": "overseerr-mcp",
3
+ "interface": {
4
+ "displayName": "Overseerr MCP"
5
+ },
6
+ "plugins": [
7
+ {
8
+ "name": "overseerr-mcp",
9
+ "source": {
10
+ "source": "local",
11
+ "path": "./"
12
+ },
13
+ "policy": {
14
+ "installation": "AVAILABLE",
15
+ "authentication": "ON_INSTALL"
16
+ },
17
+ "category": "Media"
18
+ }
19
+ ]
20
+ }
@@ -0,0 +1 @@
1
+ {"name": "overseerr-mcp", "version": "1.0.0", "description": "Overseerr media request management via MCP"}
@@ -0,0 +1,45 @@
1
+ {
2
+ "name": "overseerr-mcp",
3
+ "version": "1.0.1",
4
+ "description": "Overseerr media requests via MCP tools with HTTP fallback. Search movies and TV shows, submit requests, and monitor failed requests.",
5
+ "author": {
6
+ "name": "Jacob Magar"
7
+ },
8
+ "homepage": "https://github.com/jmagar/overseerr-mcp",
9
+ "repository": "https://github.com/jmagar/overseerr-mcp",
10
+ "license": "MIT",
11
+ "keywords": [
12
+ "overseerr",
13
+ "media",
14
+ "requests",
15
+ "plex",
16
+ "mcp"
17
+ ],
18
+ "userConfig": {
19
+ "overseerr_mcp_url": {
20
+ "type": "string",
21
+ "title": "Overseerr MCP Server URL",
22
+ "description": "URL of the overseerr-mcp MCP server (e.g. http://overseerr-mcp:9151).",
23
+ "default": "https://overseerr.tootie.tv/mcp",
24
+ "sensitive": false
25
+ },
26
+ "overseerr_mcp_token": {
27
+ "type": "string",
28
+ "title": "MCP Server Bearer Token",
29
+ "description": "Bearer token for authenticating with the MCP server. Must match OVERSEERR_MCP_TOKEN in the server's .env. Generate with: openssl rand -hex 32",
30
+ "sensitive": true
31
+ },
32
+ "overseerr_url": {
33
+ "type": "string",
34
+ "title": "Overseerr Server URL",
35
+ "description": "Base URL of your Overseerr server, e.g. https://overseerr.example.com. No trailing slash.",
36
+ "sensitive": true
37
+ },
38
+ "overseerr_api_key": {
39
+ "type": "string",
40
+ "title": "Overseerr API Key",
41
+ "description": "Overseerr API key. Found in Overseerr Settings → General → API Key.",
42
+ "sensitive": true
43
+ }
44
+ }
45
+ }
@@ -0,0 +1,43 @@
1
+ {
2
+ "name": "overseerr-mcp",
3
+ "version": "1.0.1",
4
+ "description": "Overseerr media requests via MCP.",
5
+ "homepage": "https://github.com/jmagar/overseerr-mcp",
6
+ "repository": "https://github.com/jmagar/overseerr-mcp",
7
+ "license": "MIT",
8
+ "keywords": [
9
+ "overseerr",
10
+ "media",
11
+ "requests",
12
+ "plex",
13
+ "mcp"
14
+ ],
15
+ "skills": "./skills/",
16
+ "mcpServers": "./.mcp.json",
17
+ "apps": "./.app.json",
18
+ "interface": {
19
+ "displayName": "Overseerr MCP",
20
+ "shortDescription": "Search media and submit Overseerr requests",
21
+ "longDescription": "Search movies and TV shows, inspect details, and submit or review Overseerr media requests through MCP tools and bundled skills.",
22
+ "developerName": "Jacob Magar",
23
+ "category": "Media",
24
+ "capabilities": [
25
+ "Read",
26
+ "Write"
27
+ ],
28
+ "websiteURL": "https://github.com/jmagar/overseerr-mcp",
29
+ "defaultPrompt": [
30
+ "Search Overseerr for a movie.",
31
+ "Request a TV show in Overseerr.",
32
+ "Check failed Overseerr requests."
33
+ ],
34
+ "brandColor": "#F59E0B",
35
+ "composerIcon": "./assets/icon.png",
36
+ "logo": "./assets/logo.svg"
37
+ },
38
+ "author": {
39
+ "name": "Jacob Magar",
40
+ "email": "jmagar@users.noreply.github.com",
41
+ "url": "https://github.com/jmagar"
42
+ }
43
+ }
@@ -0,0 +1,49 @@
1
+ .git
2
+ .github
3
+ .claude-plugin
4
+ .codex-plugin
5
+ .agents
6
+ .beads
7
+ .dolt
8
+ .omc
9
+ .lavra
10
+ .serena
11
+ .cache
12
+ .worktrees
13
+ .full-review
14
+ .full-review-archive-*
15
+ .vscode
16
+ .cursor
17
+ .windsurf
18
+ .1code
19
+ .idea
20
+ .env
21
+ .env.*
22
+ !.env.example
23
+ *.log
24
+ logs/
25
+ backups/
26
+ docs/
27
+ specs/
28
+ *.md
29
+ !README.md
30
+ __pycache__
31
+ *.pyc
32
+ .pytest_cache
33
+ .ruff_cache
34
+ .mypy_cache
35
+ .coverage
36
+ htmlcov
37
+ .hypothesis
38
+ node_modules
39
+ dist
40
+ coverage
41
+ *.tsbuildinfo
42
+ target
43
+ Justfile
44
+ biome.json
45
+ .pre-commit-config.yaml
46
+ .prettierrc
47
+ .prettierignore
48
+ tests/
49
+
@@ -0,0 +1,47 @@
1
+ # Overseerr MCP Server Environment Configuration
2
+
3
+ # =============================================================================
4
+ # OVERSEERR CONNECTION
5
+ # =============================================================================
6
+ OVERSEERR_URL=https://your-overseerr-instance.example.com
7
+ OVERSEERR_API_KEY=your_overseerr_api_key
8
+
9
+ # =============================================================================
10
+ # MCP SERVER SETTINGS
11
+ # =============================================================================
12
+
13
+ # Bearer token for MCP server authentication (required unless OVERSEERR_MCP_NO_AUTH=true)
14
+ # Generate with: openssl rand -hex 32
15
+ OVERSEERR_MCP_TOKEN=
16
+
17
+ # Set to true to disable bearer auth (only if secured at network/proxy level)
18
+ OVERSEERR_MCP_NO_AUTH=false
19
+
20
+ # Transport mode: 'http' for HTTP server
21
+ OVERSEERR_MCP_TRANSPORT=http
22
+
23
+ # Host interface (0.0.0.0 for Docker/external access)
24
+ OVERSEERR_MCP_HOST=0.0.0.0
25
+
26
+ # Port the MCP server binds to (update compose port mappings if changed)
27
+ OVERSEERR_MCP_PORT=9151
28
+
29
+ # =============================================================================
30
+ # DESTRUCTIVE OPERATION GATES
31
+ # =============================================================================
32
+ OVERSEERR_MCP_ALLOW_DESTRUCTIVE=false
33
+ OVERSEERR_MCP_ALLOW_YOLO=false
34
+
35
+ # =============================================================================
36
+ # DOCKER / COMPOSE
37
+ # =============================================================================
38
+ PUID=1000
39
+ PGID=1000
40
+ DOCKER_NETWORK=mcp-net
41
+ APPDATA_PATH=/mnt/appdata
42
+
43
+ # =============================================================================
44
+ # LOGGING
45
+ # =============================================================================
46
+ OVERSEERR_LOG_LEVEL=INFO
47
+ LOG_LEVEL=INFO
@@ -0,0 +1,44 @@
1
+ name: CI
2
+ on:
3
+ push:
4
+ branches: [main]
5
+ pull_request:
6
+ jobs:
7
+ lint:
8
+ runs-on: ubuntu-latest
9
+ steps:
10
+ - uses: actions/checkout@v4
11
+ - uses: astral-sh/setup-uv@v5
12
+ - name: Install dependencies
13
+ run: uv sync --group dev
14
+ - name: Ruff check
15
+ run: uv run ruff check .
16
+ - name: Ruff format
17
+ run: uv run ruff format --check .
18
+ typecheck:
19
+ runs-on: ubuntu-latest
20
+ steps:
21
+ - uses: actions/checkout@v4
22
+ - uses: astral-sh/setup-uv@v5
23
+ - name: Install dependencies
24
+ run: uv sync --group dev
25
+ - run: uv run ty check
26
+ test:
27
+ runs-on: ubuntu-latest
28
+ steps:
29
+ - uses: actions/checkout@v4
30
+ - uses: astral-sh/setup-uv@v5
31
+ - name: Install dependencies
32
+ run: uv sync --group dev
33
+ - run: uv run pytest
34
+ version-sync:
35
+ runs-on: ubuntu-latest
36
+ steps:
37
+ - uses: actions/checkout@v4
38
+ - run: bash scripts/check-outdated-deps.sh || true
39
+ contract-drift:
40
+ runs-on: ubuntu-latest
41
+ steps:
42
+ - uses: actions/checkout@v4
43
+ - uses: astral-sh/setup-uv@v5
44
+ - run: bash scripts/lint-plugin.sh
@@ -0,0 +1,75 @@
1
+ name: Build and Push Docker Image
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - main
7
+ tags:
8
+ - 'v*'
9
+ pull_request:
10
+ branches:
11
+ - main
12
+ workflow_dispatch:
13
+
14
+ env:
15
+ REGISTRY: ghcr.io
16
+ IMAGE_NAME: ${{ github.repository }}
17
+
18
+ jobs:
19
+ build-and-push:
20
+ runs-on: ubuntu-latest
21
+ permissions:
22
+ contents: read
23
+ packages: write
24
+
25
+ steps:
26
+ - name: Checkout repository
27
+ uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
28
+
29
+ - name: Set up Docker Buildx
30
+ uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3
31
+
32
+ - name: Log in to GitHub Container Registry
33
+ if: github.event_name != 'pull_request'
34
+ uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3
35
+ with:
36
+ registry: ${{ env.REGISTRY }}
37
+ username: ${{ github.actor }}
38
+ password: ${{ secrets.GITHUB_TOKEN }}
39
+
40
+ - name: Extract metadata
41
+ id: meta
42
+ uses: docker/metadata-action@c299e40c65443455700f0fdfc63efafe5b349051 # v5
43
+ with:
44
+ images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
45
+ tags: |
46
+ type=ref,event=branch
47
+ type=ref,event=pr
48
+ type=semver,pattern={{version}}
49
+ type=semver,pattern={{major}}.{{minor}}
50
+ type=semver,pattern={{major}}
51
+ type=raw,value=latest,enable={{is_default_branch}}
52
+ type=sha
53
+
54
+ - name: Build and push Docker image
55
+ uses: docker/build-push-action@ca052bb54ab0790a636c9b5f226502c73d547a25 # v5
56
+ with:
57
+ context: .
58
+ platforms: linux/amd64,linux/arm64
59
+ push: ${{ github.event_name != 'pull_request' }}
60
+ tags: ${{ steps.meta.outputs.tags }}
61
+ labels: ${{ steps.meta.outputs.labels }}
62
+ cache-from: type=gha
63
+ cache-to: type=gha,mode=max
64
+ sbom: true
65
+ provenance: mode=max
66
+
67
+ - name: Scan image for vulnerabilities
68
+ if: github.event_name != 'pull_request'
69
+ uses: aquasecurity/trivy-action@915b19bbe73b92a6cf82a1bc12b087c9a19a5fe2 # v0.28.0
70
+ with:
71
+ image-ref: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}
72
+ format: 'sarif'
73
+ output: 'trivy-results.sarif'
74
+ severity: 'CRITICAL,HIGH'
75
+
@@ -0,0 +1,63 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*.*.*"
7
+
8
+ permissions:
9
+ contents: write
10
+ id-token: write
11
+
12
+ jobs:
13
+ publish:
14
+ runs-on: ubuntu-latest
15
+ environment: release
16
+ steps:
17
+ - uses: actions/checkout@v4
18
+
19
+ - uses: astral-sh/setup-uv@v5
20
+
21
+ - name: Verify tag matches pyproject.toml version
22
+ run: |
23
+ PKG_VERSION=$(grep -m1 '^version' pyproject.toml | sed 's/.*"\(.*\)".*/\1/')
24
+ TAG_VERSION="${GITHUB_REF_NAME#v}"
25
+ if [ "$PKG_VERSION" != "$TAG_VERSION" ]; then
26
+ echo "Version mismatch: pyproject.toml=$PKG_VERSION tag=$TAG_VERSION"
27
+ exit 1
28
+ fi
29
+
30
+ - name: Build package
31
+ run: uv build
32
+
33
+ - name: Publish to PyPI
34
+ uses: pypa/gh-action-pypi-publish@release/v1
35
+ with:
36
+ attestations: true
37
+
38
+ - name: Create GitHub Release
39
+ env:
40
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
41
+ run: |
42
+ gh release create "$GITHUB_REF_NAME" \
43
+ --title "Release $GITHUB_REF_NAME" \
44
+ --generate-notes \
45
+ dist/*
46
+
47
+ - name: Install mcp-publisher
48
+ run: |
49
+ curl -fsSL "https://github.com/modelcontextprotocol/registry/releases/latest/download/mcp-publisher_$(uname -s | tr '[:upper:]' '[:lower:]')_$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/').tar.gz" | tar xz mcp-publisher
50
+
51
+ - name: Set version in server.json
52
+ run: |
53
+ VERSION="${GITHUB_REF_NAME#v}"
54
+ jq --arg v "$VERSION" '
55
+ .version = $v |
56
+ .packages = [.packages[] | if .registryType == "pypi" then .version = $v else . end]
57
+ ' server.json > server.tmp && mv server.tmp server.json
58
+
59
+ - name: Authenticate to MCP Registry
60
+ run: ./mcp-publisher login dns --domain tootie.tv --private-key ${{ secrets.MCP_PRIVATE_KEY }}
61
+
62
+ - name: Publish to MCP Registry
63
+ run: ./mcp-publisher publish
@@ -0,0 +1,86 @@
1
+ # ── Secrets ──────────────────────────────────────────────────────────────────
2
+ .env
3
+ .env.*
4
+ !.env.example
5
+
6
+ # ── Runtime artifacts ────────────────────────────────────────────────────────
7
+ logs/
8
+ backups/
9
+ *.log
10
+ *.pid
11
+ *.bak
12
+ *.bak-*
13
+
14
+ # ── Claude Code / AI tooling ────────────────────────────────────────────────
15
+ .claude/settings.local.json
16
+ .claude/worktrees/
17
+ .omc/
18
+ .lavra/
19
+ .beads/
20
+ .dolt/
21
+ *.db
22
+ *.db-shm
23
+ *.db-wal
24
+ .beads-credential-key
25
+ .serena/
26
+ .worktrees/
27
+ .full-review/
28
+ .full-review-archive-*
29
+ .bivvy
30
+
31
+ # ── IDE / editor ─────────────────────────────────────────────────────────────
32
+ .vscode/
33
+ .cursor/
34
+ .windsurf/
35
+ .1code/
36
+ .idea/
37
+ .zed/
38
+ *.iml
39
+ *.swp
40
+ *.swo
41
+ *~
42
+ .emdash.json
43
+
44
+ # ── OS generated ─────────────────────────────────────────────────────────────
45
+ .DS_Store
46
+ Thumbs.db
47
+
48
+ # ── Caches (ALL tool caches go here) ─────────────────────────────────────────
49
+ .cache/
50
+
51
+ # ── Documentation artifacts (session/plan docs, not reference) ───────────────
52
+ .docs/
53
+ docs/plans/
54
+ docs/sessions/
55
+ docs/reports/
56
+ docs/research/
57
+ docs/superpowers/
58
+ specs/
59
+
60
+ # ── Python ───────────────────────────────────────────────────────────────────
61
+ .venv/
62
+ __pycache__/
63
+ *.py[oc]
64
+ *.egg-info/
65
+ *.egg
66
+ build/
67
+ dist/
68
+ sdist/
69
+ wheels/
70
+ pip-wheel-metadata/
71
+ *.whl
72
+ .hypothesis/
73
+ .pytest_cache/
74
+ .ruff_cache/
75
+ .ty_cache/
76
+ .mypy_cache/
77
+ .pytype/
78
+ .pyre/
79
+ .pyright/
80
+ htmlcov/
81
+ .coverage
82
+ .coverage.*
83
+ coverage.xml
84
+ .tox/
85
+ .nox/
86
+ pip-log.txt
@@ -0,0 +1,8 @@
1
+ {
2
+ "mcpServers": {
3
+ "overseerr-mcp": {
4
+ "type": "http",
5
+ "url": "${OVERSEERR_MCP_URL}"
6
+ }
7
+ }
8
+ }
@@ -0,0 +1,23 @@
1
+ repos:
2
+ - repo: local
3
+ hooks:
4
+ - id: skills-validate
5
+ name: Validate skills
6
+ entry: just validate-skills
7
+ language: system
8
+ pass_filenames: false
9
+ - id: docker-security
10
+ name: Docker security check
11
+ entry: bash scripts/check-docker-security.sh
12
+ language: system
13
+ pass_filenames: false
14
+ - id: no-baked-env
15
+ name: No baked env vars
16
+ entry: bash scripts/check-no-baked-env.sh
17
+ language: system
18
+ pass_filenames: false
19
+ - id: ensure-ignore-files
20
+ name: Ensure ignore files
21
+ entry: bash scripts/ensure-ignore-files.sh --check
22
+ language: system
23
+ pass_filenames: false
@@ -0,0 +1 @@
1
+ CLAUDE.md
@@ -0,0 +1,26 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ ## [1.0.1] - 2026-04-03
11
+
12
+ ### Fixed
13
+ - **OAuth discovery 401 cascade**: BearerAuthMiddleware was blocking GET /.well-known/oauth-protected-resource, causing MCP clients to surface generic "unknown error". Added WellKnownMiddleware (RFC 9728) to return resource metadata.
14
+
15
+ ### Added
16
+ - **docs/AUTHENTICATION.md**: New setup guide covering token generation and client config.
17
+ - **README Authentication section**: Added quick-start examples and link to full guide.
18
+
19
+
20
+
21
+ ### Added
22
+ - FastMCP server with `overseerr` and `overseerr_help` tools
23
+ - Planned: BearerAuthMiddleware with startup token validation (not yet implemented in this release)
24
+ - Dual transport (http/stdio via OVERSEERR_MCP_TRANSPORT)
25
+ - Pagination for all list actions
26
+ - Destructive ops confirmation gate
@@ -0,0 +1,41 @@
1
+ # overseerr-mcp
2
+
3
+ MCP server for Overseerr media request management.
4
+
5
+ ## Development
6
+
7
+ - Language: Python (FastMCP + uv)
8
+ - Port: 9151 (OVERSEERR_MCP_PORT)
9
+ - Auth: Bearer token (OVERSEERR_MCP_TOKEN) + Overseerr API key (OVERSEERR_API_KEY)
10
+
11
+ ## Commands
12
+
13
+ ```bash
14
+ just dev # run locally
15
+ just test # run tests
16
+ just lint # ruff check
17
+ just build # docker build
18
+ ```
19
+
20
+
21
+ ## Version Bumping
22
+
23
+ **Every feature branch push MUST bump the version in ALL version-bearing files.**
24
+
25
+ Bump type is determined by the commit message prefix:
26
+ - `feat!:` or `BREAKING CHANGE` → **major** (X+1.0.0)
27
+ - `feat` or `feat(...)` → **minor** (X.Y+1.0)
28
+ - Everything else (`fix`, `chore`, `refactor`, `test`, `docs`, etc.) → **patch** (X.Y.Z+1)
29
+
30
+ **Files to update (if they exist in this repo):**
31
+ - `Cargo.toml` — `version = "X.Y.Z"` in `[package]`
32
+ - `package.json` — `"version": "X.Y.Z"`
33
+ - `pyproject.toml` — `version = "X.Y.Z"` in `[project]`
34
+ - `.claude-plugin/plugin.json` — `"version": "X.Y.Z"`
35
+ - `.codex-plugin/plugin.json` — `"version": "X.Y.Z"`
36
+ - `gemini-extension.json` — `"version": "X.Y.Z"`
37
+ - `README.md` — version badge or header
38
+ - `CHANGELOG.md` — new entry under the bumped version
39
+
40
+ All files MUST have the same version. Never bump only one file.
41
+ CHANGELOG.md must have an entry for every version bump.
@@ -0,0 +1,56 @@
1
+ # syntax=docker/dockerfile:1
2
+
3
+ # ── builder ──────────────────────────────────────────────────────────────────
4
+ FROM python:3.11-slim AS builder
5
+
6
+ COPY --from=ghcr.io/astral-sh/uv:0.10.10 /uv /uvx /bin/
7
+
8
+ WORKDIR /app
9
+
10
+ # Install dependencies first (layer cache)
11
+ COPY pyproject.toml uv.lock* ./
12
+ RUN touch README.md
13
+ RUN --mount=type=cache,target=/root/.cache/uv \
14
+ uv sync --frozen --no-dev --no-install-project
15
+
16
+ # Copy source and install project
17
+ COPY overseerr_mcp/ ./overseerr_mcp/
18
+ RUN --mount=type=cache,target=/root/.cache/uv \
19
+ uv sync --frozen --no-dev
20
+
21
+ # ── runtime ──────────────────────────────────────────────────────────────────
22
+ FROM python:3.11-slim AS runtime
23
+
24
+ RUN groupadd --gid 1000 mcpuser && \
25
+ useradd --uid 1000 --gid mcpuser --shell /bin/bash --create-home mcpuser && \
26
+ apt-get update && apt-get install -y --no-install-recommends wget && \
27
+ rm -rf /var/lib/apt/lists/*
28
+
29
+ WORKDIR /app
30
+
31
+ # Copy the built venv and source from builder
32
+ COPY --from=builder /app/.venv /app/.venv
33
+ COPY --from=builder /app/overseerr_mcp /app/overseerr_mcp
34
+ COPY --from=builder /app/pyproject.toml /app/pyproject.toml
35
+
36
+ # Copy entrypoint
37
+ COPY entrypoint.sh ./
38
+ RUN chmod +x entrypoint.sh && \
39
+ mkdir -p /app/logs && \
40
+ chown -R mcpuser:mcpuser /app
41
+
42
+ USER mcpuser
43
+
44
+ EXPOSE 9151
45
+
46
+ ENV PATH="/app/.venv/bin:$PATH" \
47
+ PYTHONUNBUFFERED=1 \
48
+ PYTHONDONTWRITEBYTECODE=1 \
49
+ OVERSEERR_MCP_HOST=0.0.0.0 \
50
+ OVERSEERR_MCP_PORT=9151 \
51
+ OVERSEERR_MCP_TRANSPORT=http
52
+
53
+ HEALTHCHECK --interval=30s --timeout=10s --start-period=30s --retries=3 \
54
+ CMD wget -qO- http://localhost:9151/health || exit 1
55
+
56
+ CMD ["./entrypoint.sh"]
@@ -0,0 +1 @@
1
+ CLAUDE.md