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.
- overseerr_mcp-1.0.1/.agents/plugins/marketplace.json +20 -0
- overseerr_mcp-1.0.1/.app.json +1 -0
- overseerr_mcp-1.0.1/.claude-plugin/plugin.json +45 -0
- overseerr_mcp-1.0.1/.codex-plugin/plugin.json +43 -0
- overseerr_mcp-1.0.1/.dockerignore +49 -0
- overseerr_mcp-1.0.1/.env.example +47 -0
- overseerr_mcp-1.0.1/.github/workflows/ci.yml +44 -0
- overseerr_mcp-1.0.1/.github/workflows/docker-publish.yml +75 -0
- overseerr_mcp-1.0.1/.github/workflows/publish-pypi.yml +63 -0
- overseerr_mcp-1.0.1/.gitignore +86 -0
- overseerr_mcp-1.0.1/.mcp.json +8 -0
- overseerr_mcp-1.0.1/.pre-commit-config.yaml +23 -0
- overseerr_mcp-1.0.1/AGENTS.md +1 -0
- overseerr_mcp-1.0.1/CHANGELOG.md +26 -0
- overseerr_mcp-1.0.1/CLAUDE.md +41 -0
- overseerr_mcp-1.0.1/Dockerfile +56 -0
- overseerr_mcp-1.0.1/GEMINI.md +1 -0
- overseerr_mcp-1.0.1/Justfile +76 -0
- overseerr_mcp-1.0.1/LICENSE +21 -0
- overseerr_mcp-1.0.1/PKG-INFO +434 -0
- overseerr_mcp-1.0.1/README.md +423 -0
- overseerr_mcp-1.0.1/assets/icon.png +0 -0
- overseerr_mcp-1.0.1/assets/logo.svg +4 -0
- overseerr_mcp-1.0.1/assets/screenshots/.gitkeep +0 -0
- overseerr_mcp-1.0.1/docker-compose.yml +34 -0
- overseerr_mcp-1.0.1/docs/overseerr-api.yaml +6571 -0
- overseerr_mcp-1.0.1/docs/overseerr.subdomain.conf +11 -0
- overseerr_mcp-1.0.1/entrypoint.sh +14 -0
- overseerr_mcp-1.0.1/gemini-extension.json +29 -0
- overseerr_mcp-1.0.1/hooks/hooks.json +22 -0
- overseerr_mcp-1.0.1/hooks/scripts/ensure-gitignore.sh +22 -0
- overseerr_mcp-1.0.1/hooks/scripts/ensure-ignore-files.sh +111 -0
- overseerr_mcp-1.0.1/hooks/scripts/fix-env-perms.sh +30 -0
- overseerr_mcp-1.0.1/hooks/scripts/sync-env.sh +46 -0
- overseerr_mcp-1.0.1/overseerr_mcp/__init__.py +1 -0
- overseerr_mcp-1.0.1/overseerr_mcp/client.py +98 -0
- overseerr_mcp-1.0.1/overseerr_mcp/server.py +495 -0
- overseerr_mcp-1.0.1/pyproject.toml +32 -0
- overseerr_mcp-1.0.1/scripts/check-docker-security.sh +145 -0
- overseerr_mcp-1.0.1/scripts/check-no-baked-env.sh +138 -0
- overseerr_mcp-1.0.1/scripts/check-outdated-deps.sh +181 -0
- overseerr_mcp-1.0.1/scripts/ensure-ignore-files.sh +271 -0
- overseerr_mcp-1.0.1/scripts/lint-plugin.sh +459 -0
- overseerr_mcp-1.0.1/scripts/setup-data-dirs.sh +22 -0
- overseerr_mcp-1.0.1/scripts/smoke-test.sh +235 -0
- overseerr_mcp-1.0.1/server.json +37 -0
- overseerr_mcp-1.0.1/skills/overseerr/SKILL.md +113 -0
- overseerr_mcp-1.0.1/tests/test_live.sh +17 -0
- 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,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
|