vmaf-mcp 1.0.0rc1__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.
- vmaf_mcp-1.0.0rc1/.gitignore +233 -0
- vmaf_mcp-1.0.0rc1/Dockerfile +58 -0
- vmaf_mcp-1.0.0rc1/PKG-INFO +116 -0
- vmaf_mcp-1.0.0rc1/README.md +78 -0
- vmaf_mcp-1.0.0rc1/claude-desktop-config-example.json +21 -0
- vmaf_mcp-1.0.0rc1/pyproject.toml +95 -0
- vmaf_mcp-1.0.0rc1/requirements-dev-lock.txt +1597 -0
- vmaf_mcp-1.0.0rc1/requirements-production-lock.txt +1538 -0
- vmaf_mcp-1.0.0rc1/requirements-runtime-lock.txt +521 -0
- vmaf_mcp-1.0.0rc1/src/vmaf_mcp/__init__.py +18 -0
- vmaf_mcp-1.0.0rc1/src/vmaf_mcp/http_scoring.py +66 -0
- vmaf_mcp-1.0.0rc1/src/vmaf_mcp/http_transport.py +873 -0
- vmaf_mcp-1.0.0rc1/src/vmaf_mcp/server.py +4572 -0
- vmaf_mcp-1.0.0rc1/tests/test_backend_dispatch.py +123 -0
- vmaf_mcp-1.0.0rc1/tests/test_backend_probe_and_allowlist_0511.py +268 -0
- vmaf_mcp-1.0.0rc1/tests/test_coverage_round2.py +1393 -0
- vmaf_mcp-1.0.0rc1/tests/test_coverage_round3.py +1264 -0
- vmaf_mcp-1.0.0rc1/tests/test_coverage_round4.py +1295 -0
- vmaf_mcp-1.0.0rc1/tests/test_coverage_round6.py +762 -0
- vmaf_mcp-1.0.0rc1/tests/test_http_transport.py +584 -0
- vmaf_mcp-1.0.0rc1/tests/test_http_transport_round5.py +655 -0
- vmaf_mcp-1.0.0rc1/tests/test_import_graph.py +144 -0
- vmaf_mcp-1.0.0rc1/tests/test_iserror_invariant.py +680 -0
- vmaf_mcp-1.0.0rc1/tests/test_mcp2_registration.py +99 -0
- vmaf_mcp-1.0.0rc1/tests/test_mcp_hardening_wave1.py +433 -0
- vmaf_mcp-1.0.0rc1/tests/test_mcp_http_edge_cases_adr1075.py +328 -0
- vmaf_mcp-1.0.0rc1/tests/test_mcp_p0_adr0608.py +339 -0
- vmaf_mcp-1.0.0rc1/tests/test_p1_tools.py +559 -0
- vmaf_mcp-1.0.0rc1/tests/test_parity_argv.py +201 -0
- vmaf_mcp-1.0.0rc1/tests/test_path_and_bench_env.py +237 -0
- vmaf_mcp-1.0.0rc1/tests/test_probe_backend_pr850.py +106 -0
- vmaf_mcp-1.0.0rc1/tests/test_probe_findings_2026_05_17.py +318 -0
- vmaf_mcp-1.0.0rc1/tests/test_pytest_pythonpath.py +81 -0
- vmaf_mcp-1.0.0rc1/tests/test_python_surfaces_bug_audit.py +183 -0
- vmaf_mcp-1.0.0rc1/tests/test_score_extras_adr1117.py +448 -0
- vmaf_mcp-1.0.0rc1/tests/test_server.py +586 -0
- vmaf_mcp-1.0.0rc1/tests/test_sidecar_tools_1240.py +406 -0
- vmaf_mcp-1.0.0rc1/tests/test_smoke_e2e.py +220 -0
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
# Caches, build artifacts
|
|
2
|
+
.DS_Store
|
|
3
|
+
.cache/
|
|
4
|
+
# Rust build artifacts
|
|
5
|
+
target/
|
|
6
|
+
# Editor / refactor scratch backups — never in tree (ADR-0546 audit cleanup
|
|
7
|
+
# bundle surfaced a 142 KB `tools/vmaf-tune/src/vmaftune/cli.py.bak` that
|
|
8
|
+
# had been polluting greps for weeks).
|
|
9
|
+
*.bak
|
|
10
|
+
*.orig
|
|
11
|
+
*.egg*
|
|
12
|
+
.idea/
|
|
13
|
+
*.py[cod]
|
|
14
|
+
.tox/
|
|
15
|
+
.*version
|
|
16
|
+
# Virtual environments. No trailing slash on the second pattern: `.venv*/`
|
|
17
|
+
# matches only DIRECTORIES, so a symlink named `.venv` sailed past it and was
|
|
18
|
+
# committed by #1231. That symlink pointed at the maintainer's own absolute
|
|
19
|
+
# venv path, so every fresh checkout materialised a self-referential loop and
|
|
20
|
+
# `git pull` replaced anyone's real (ignored, hence disposable) venv with it.
|
|
21
|
+
.venv*/
|
|
22
|
+
.venv*
|
|
23
|
+
__pycache__/
|
|
24
|
+
build/
|
|
25
|
+
build-golden/
|
|
26
|
+
core/build-golden/
|
|
27
|
+
dist/
|
|
28
|
+
vmaf_output.xml
|
|
29
|
+
compile_commands.json
|
|
30
|
+
|
|
31
|
+
# tiny-AI training artifacts (re-generated by ai/scripts/train_konvid.py).
|
|
32
|
+
# The contents of ai/data/ are gitignored EXCEPT the ADR-0203 Python
|
|
33
|
+
# modules. We use the "ignore everything inside the dir, then re-allow
|
|
34
|
+
# .py" pattern so the dir itself stays tracked for the modules below.
|
|
35
|
+
ai/data/*
|
|
36
|
+
!ai/data/__init__.py
|
|
37
|
+
!ai/data/netflix_loader.py
|
|
38
|
+
!ai/data/feature_extractor.py
|
|
39
|
+
!ai/data/scores.py
|
|
40
|
+
# Phase F.5 calibrated recipe overrides (ADR-0325).
|
|
41
|
+
# Tracked as a tiny JSON snapshot — regenerated by
|
|
42
|
+
# ai/scripts/calibrate_phase_f_recipes.py against a real corpus.
|
|
43
|
+
!ai/data/phase_f_recipes_calibrated.json
|
|
44
|
+
# ADR-0335 — hardware-capability prior table is small, hand-curated,
|
|
45
|
+
# and committed in-tree (not a generated artifact).
|
|
46
|
+
!ai/data/hardware_caps.csv
|
|
47
|
+
runs/
|
|
48
|
+
|
|
49
|
+
# Large test data (generated via testdata/generate.sh)
|
|
50
|
+
testdata/*_1280x720_*.yuv
|
|
51
|
+
testdata/*_1920x1080_*.yuv
|
|
52
|
+
testdata/*_3840x2160_*.yuv
|
|
53
|
+
testdata/bbb/*.yuv
|
|
54
|
+
|
|
55
|
+
# Large binary files
|
|
56
|
+
*.mp4
|
|
57
|
+
*.mkv
|
|
58
|
+
|
|
59
|
+
# Upstream MATLAB MEX compiled artefacts (platform-specific binaries).
|
|
60
|
+
# Rebuild locally via `mex file.c` if you need the MATLAB reference path.
|
|
61
|
+
# Paths follow ADR-0700 rename (python/vmaf/ → compat/python-vmaf/).
|
|
62
|
+
# See Scorecard Binary-Artifacts / D38.
|
|
63
|
+
compat/python-vmaf/matlab/**/*.mex
|
|
64
|
+
compat/python-vmaf/matlab/**/*.mex[0-9]*
|
|
65
|
+
compat/python-vmaf/matlab/**/*.mexa64
|
|
66
|
+
compat/python-vmaf/matlab/**/*.mexglx
|
|
67
|
+
compat/python-vmaf/matlab/**/*.mexlx
|
|
68
|
+
compat/python-vmaf/matlab/**/*.mexmac
|
|
69
|
+
compat/python-vmaf/matlab/**/*.mexmaci64
|
|
70
|
+
compat/python-vmaf/matlab/**/*.mexsol
|
|
71
|
+
compat/python-vmaf/matlab/**/*.mexw32
|
|
72
|
+
compat/python-vmaf/matlab/**/*.mexw64
|
|
73
|
+
compat/python-vmaf/matlab/**/*.dll
|
|
74
|
+
compat/python-vmaf/matlab/**/*.exp
|
|
75
|
+
compat/python-vmaf/matlab/**/*.lib
|
|
76
|
+
compat/python-vmaf/matlab/**/*.o
|
|
77
|
+
|
|
78
|
+
# Cython-generated C from compat/python-vmaf/core/adm_dwt2_cy.pyx
|
|
79
|
+
# (produced by `python setup.py build_ext`; never tracked).
|
|
80
|
+
compat/python-vmaf/core/adm_dwt2_cy.c
|
|
81
|
+
compat/python-vmaf/core/adm_dwt2_cy.cpp
|
|
82
|
+
|
|
83
|
+
# Local corpus data — large YUV/MP4 fixtures, never committed.
|
|
84
|
+
# Was only in .git/info/exclude; now visible to all contributors.
|
|
85
|
+
.corpus/
|
|
86
|
+
|
|
87
|
+
# Working/scratch directories
|
|
88
|
+
.workingdir/
|
|
89
|
+
# Also match it as a symlink. A trailing slash only matches a real
|
|
90
|
+
# directory, so an agent worktree that symlinks this shared state dir
|
|
91
|
+
# in (the praetor flavor audit wants them present) leaves an untracked
|
|
92
|
+
# entry that `git add -A` happily commits -- an absolute path to one
|
|
93
|
+
# machine, landing in a PR. Caught exactly that way; see bug ledger L-78.
|
|
94
|
+
.workingdir
|
|
95
|
+
|
|
96
|
+
# vmaf-tune Phase A scratch outputs (ADR-0237)
|
|
97
|
+
corpus.jsonl
|
|
98
|
+
# ...but never a committed test fixture. The bare pattern above matches at any
|
|
99
|
+
# depth, which silently excluded pkg/benchmark/testdata/corpus.jsonl from its
|
|
100
|
+
# own PR and left the package's tests failing on a missing file.
|
|
101
|
+
!**/testdata/corpus.jsonl
|
|
102
|
+
tools/vmaf-tune/build/
|
|
103
|
+
tools/vmaf-tune/dist/
|
|
104
|
+
tools/vmaf-tune/*.egg-info/
|
|
105
|
+
|
|
106
|
+
# external-bench harness scratch / binary downloads (ADR-0332)
|
|
107
|
+
tools/external-bench/**/build/
|
|
108
|
+
tools/external-bench/**/dist/
|
|
109
|
+
tools/external-bench/**/*.bin
|
|
110
|
+
tools/external-bench/**/output*.json
|
|
111
|
+
tools/external-bench/**/__pycache__/
|
|
112
|
+
|
|
113
|
+
# Zed per-user local settings (auth tokens, window state — machine-specific).
|
|
114
|
+
# .zed/ itself IS tracked (shared project config); only the local/ subdir is not.
|
|
115
|
+
.zed/local/
|
|
116
|
+
|
|
117
|
+
# Claude Code local (machine-specific) settings
|
|
118
|
+
.claude/settings.local.json
|
|
119
|
+
.claude/scheduled_tasks.lock
|
|
120
|
+
# Agent isolation worktrees (created by parallel-agent harness; machine-local).
|
|
121
|
+
.claude/worktrees/
|
|
122
|
+
# Local merge-train nudger + its log (machine-local operator tooling).
|
|
123
|
+
.claude/mergetrain/
|
|
124
|
+
|
|
125
|
+
# Generated benchmark results
|
|
126
|
+
testdata/bbb/results/
|
|
127
|
+
build-docs/
|
|
128
|
+
preprints202604.0035.v1.pdf
|
|
129
|
+
|
|
130
|
+
# Meson wrap-fetched subprojects (downloaded at meson setup time).
|
|
131
|
+
# Only the .wrap files + packagefiles/ are tracked; the unpacked
|
|
132
|
+
# upstream trees are gitignored.
|
|
133
|
+
core/subprojects/*/
|
|
134
|
+
!core/subprojects/packagefiles/
|
|
135
|
+
core/subprojects/packagecache/
|
|
136
|
+
core/subprojects/.wraplock
|
|
137
|
+
|
|
138
|
+
# Per-run training output (per-epoch ONNX checkpoints)
|
|
139
|
+
model/tiny/training_runs/
|
|
140
|
+
|
|
141
|
+
# u2netp fork-local mirror (ADR-0325). Binary lives only in GitHub
|
|
142
|
+
# Releases; the scaffold (license, model card, operator doc, release
|
|
143
|
+
# workflow guard) is tracked, the binary itself is not.
|
|
144
|
+
model/u2netp_mirror.onnx
|
|
145
|
+
model/u2netp_mirror.pth
|
|
146
|
+
|
|
147
|
+
# Go build artifacts (ADR-0702)
|
|
148
|
+
# Compiled binaries at the repo root (from `go build ./cmd/...`).
|
|
149
|
+
# Anchored with a leading "/" so the patterns match only files at the repo
|
|
150
|
+
# root, not directories named "vmafx-tune" anywhere in the tree (e.g.
|
|
151
|
+
# cmd/vmafx-tune/). Leading slash also prevents hiding new test files.
|
|
152
|
+
/vmafx-server
|
|
153
|
+
/vmafx-mcp
|
|
154
|
+
/vmafx-tune
|
|
155
|
+
/vmafx-controller
|
|
156
|
+
/vmafx-node
|
|
157
|
+
/vmafx-operator
|
|
158
|
+
/vmafx-ort-runner
|
|
159
|
+
# Per-package test binaries
|
|
160
|
+
*.test
|
|
161
|
+
# Go build cache is stored in $GOPATH/pkg, not the repo; go.sum is tracked.
|
|
162
|
+
# Dist directories from per-cmd Makefile targets
|
|
163
|
+
/cmd/*/dist/
|
|
164
|
+
|
|
165
|
+
# Rust build artifacts (ADR-0702)
|
|
166
|
+
# Workspace target directory (cargo output)
|
|
167
|
+
/target/
|
|
168
|
+
# Rust source backup files (rustfmt temp)
|
|
169
|
+
**/*.rs.bk
|
|
170
|
+
# Cargo.lock: kept for workspace binaries (this workspace's root Cargo.lock
|
|
171
|
+
# is tracked); per-crate library Cargo.lock files are gitignored below.
|
|
172
|
+
# Library crates inside bindings/ produce their own Cargo.lock which we
|
|
173
|
+
# do NOT track (libraries let consumers pin).
|
|
174
|
+
bindings/rust/**/Cargo.lock
|
|
175
|
+
|
|
176
|
+
# Nsight Compute profiling artifacts
|
|
177
|
+
*.ncu-rep
|
|
178
|
+
|
|
179
|
+
# Generated upscaled perf benchmark fixtures (reproducible from 576x324 native)
|
|
180
|
+
testdata/ref_1920x1080_48f.yuv
|
|
181
|
+
testdata/dis_1920x1080_48f.yuv
|
|
182
|
+
testdata/ref_2560x1440_48f.yuv
|
|
183
|
+
testdata/dis_2560x1440_48f.yuv
|
|
184
|
+
testdata/bbb/ref_3840x2160_30f.yuv
|
|
185
|
+
testdata/bbb/dis_3840x2160_30f.yuv
|
|
186
|
+
|
|
187
|
+
# Geometry-bearing wrappers generated from committed Kubernetes E2E raw clips.
|
|
188
|
+
test/e2e/fixtures/ref.y4m
|
|
189
|
+
test/e2e/fixtures/dist.y4m
|
|
190
|
+
# kuttl may materialize a credential-bearing kubeconfig in its working
|
|
191
|
+
# directory; the harness uses only the dedicated file below RUNNER_TEMP.
|
|
192
|
+
/kubeconfig
|
|
193
|
+
|
|
194
|
+
# Pyright strict-audit config (ADR-0888). Intentionally local-only —
|
|
195
|
+
# shipping it would surface ~1,600 stub-cascade errors as a CI gate
|
|
196
|
+
# before the long-tail cleanup is done. Operators re-run with
|
|
197
|
+
# `pyright -p pyrightconfig.audit.json --outputjson <pkg>/`.
|
|
198
|
+
pyrightconfig.audit.json
|
|
199
|
+
|
|
200
|
+
# Fuzzer-generated corpus growth (seed entries are not tracked)
|
|
201
|
+
core/test/fuzz/*_corpus/
|
|
202
|
+
|
|
203
|
+
# Netflix golden-data YUV fixtures (CLAUDE.md section 8). Downloaded by
|
|
204
|
+
# scripts/test/fetch-test-yuvs.sh, deliberately untracked because of their size
|
|
205
|
+
# -- but they are the numerical ground truth, so they must never be reachable by
|
|
206
|
+
# `git clean -xfd`. Ignoring them makes clean skip them and keeps them out of
|
|
207
|
+
# `git status` noise.
|
|
208
|
+
python/test/resource/yuv/
|
|
209
|
+
python/test/resource/test_image_yuv/
|
|
210
|
+
|
|
211
|
+
# Cython extension built in-place by compat/python-vmaf (setup.py build_ext).
|
|
212
|
+
compat/python-vmaf/core/*.so
|
|
213
|
+
|
|
214
|
+
# Per-host sidecar identity cache, written at runtime by vmafx-tune sidecar.
|
|
215
|
+
# Machine-local state, never a build input (ADR-0237-style scratch).
|
|
216
|
+
relcache/
|
|
217
|
+
|
|
218
|
+
# Test artifact: vmaftune.encode probes ffmpeg with `[ffmpeg_bin, "-version"]`,
|
|
219
|
+
# and a stubbed binary in the test suite leaves a file literally named
|
|
220
|
+
# `-version` behind. A leading dash also makes `pre-commit run --files` parse
|
|
221
|
+
# the path as an option, so the large-file hook never sees it.
|
|
222
|
+
/tools/vmaf-tune/-version
|
|
223
|
+
build-upstream-ab/
|
|
224
|
+
|
|
225
|
+
# local-only agent scratch (bench fixtures, fan-out logs, tmp scratch)
|
|
226
|
+
.claude/bench-data/
|
|
227
|
+
.claude/fanout/
|
|
228
|
+
.claude/tmpsp/
|
|
229
|
+
|
|
230
|
+
# Vendor skill mirrors. `.claude/skills/` is canonical and tracked; the
|
|
231
|
+
# per-vendor copies drift and are regenerated from it.
|
|
232
|
+
.agents/skills/
|
|
233
|
+
/.standards/worktrees/
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# syntax=docker/dockerfile:1.27@sha256:bde3983e9c939224420ddaf6b784cc30e09b035a4dea01f581230c50809f372e
|
|
2
|
+
#
|
|
3
|
+
# Sandboxed vmaf-mcp server — MCP over stdio + pre-built libvmaf binary.
|
|
4
|
+
#
|
|
5
|
+
# Build from the repo root so the build context has libvmaf and mcp-server/:
|
|
6
|
+
# docker build -f mcp-server/vmaf-mcp/Dockerfile -t vmaf-mcp .
|
|
7
|
+
#
|
|
8
|
+
# Run (mount your YUV corpus read-only, keep stdio open for MCP):
|
|
9
|
+
# docker run --rm -i \
|
|
10
|
+
# -v /path/to/yuv-corpus:/data:ro \
|
|
11
|
+
# -e VMAF_MCP_ALLOW=/data \
|
|
12
|
+
# vmaf-mcp
|
|
13
|
+
|
|
14
|
+
FROM ubuntu:26.04@sha256:61ebaa5cc23ca45450db85eac015435199ec569e28ec222ea13f2aed2110b8a6 AS build
|
|
15
|
+
|
|
16
|
+
ENV DEBIAN_FRONTEND=noninteractive
|
|
17
|
+
# hadolint ignore=DL3008
|
|
18
|
+
RUN apt-get update && apt-get install -y --no-install-recommends \
|
|
19
|
+
build-essential meson ninja-build pkg-config nasm \
|
|
20
|
+
python3 python3-pip python3-venv \
|
|
21
|
+
ca-certificates git \
|
|
22
|
+
&& rm -rf /var/lib/apt/lists/*
|
|
23
|
+
|
|
24
|
+
WORKDIR /src
|
|
25
|
+
COPY . /src
|
|
26
|
+
WORKDIR /src/libvmaf
|
|
27
|
+
RUN meson setup ../build -Denable_cuda=false -Denable_sycl=false --buildtype=release \
|
|
28
|
+
&& ninja -C ../build
|
|
29
|
+
WORKDIR /src
|
|
30
|
+
RUN python3 -m pip install --no-cache-dir --break-system-packages --require-hashes \
|
|
31
|
+
-r requirements/locks/package-build.txt \
|
|
32
|
+
&& python3 -m build --no-isolation --wheel --outdir /wheels mcp-server/vmaf-mcp
|
|
33
|
+
|
|
34
|
+
FROM ubuntu:26.04@sha256:61ebaa5cc23ca45450db85eac015435199ec569e28ec222ea13f2aed2110b8a6
|
|
35
|
+
|
|
36
|
+
ENV DEBIAN_FRONTEND=noninteractive \
|
|
37
|
+
VMAF_BIN=/opt/vmaf/vmaf \
|
|
38
|
+
PATH=/opt/vmaf:$PATH
|
|
39
|
+
|
|
40
|
+
# hadolint ignore=DL3008
|
|
41
|
+
RUN apt-get update && apt-get install -y --no-install-recommends \
|
|
42
|
+
python3 python3-pip python3-venv \
|
|
43
|
+
ca-certificates \
|
|
44
|
+
&& rm -rf /var/lib/apt/lists/*
|
|
45
|
+
|
|
46
|
+
COPY --from=build /src/build/tools/vmaf /opt/vmaf/vmaf
|
|
47
|
+
COPY --from=build /wheels/vmaf_mcp-*.whl /tmp/
|
|
48
|
+
COPY --from=build /src/mcp-server/vmaf-mcp/requirements-runtime-lock.txt /tmp/
|
|
49
|
+
COPY --from=build /src/model /opt/vmaf/model
|
|
50
|
+
COPY --from=build /src/testdata /opt/vmaf/testdata
|
|
51
|
+
|
|
52
|
+
RUN pip install --no-cache-dir --break-system-packages --require-hashes \
|
|
53
|
+
-r /tmp/requirements-runtime-lock.txt \
|
|
54
|
+
&& pip install --no-cache-dir --break-system-packages --no-deps \
|
|
55
|
+
/tmp/vmaf_mcp-*.whl
|
|
56
|
+
|
|
57
|
+
WORKDIR /opt/vmaf
|
|
58
|
+
ENTRYPOINT ["vmaf-mcp"]
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: vmaf-mcp
|
|
3
|
+
Version: 1.0.0-rc.1
|
|
4
|
+
Summary: MCP server exposing VMAF scoring, model listing, and benchmark runs via JSON-RPC.
|
|
5
|
+
Project-URL: Homepage, https://github.com/VMAFx/vmafx
|
|
6
|
+
Project-URL: Repository, https://github.com/VMAFx/vmafx
|
|
7
|
+
Project-URL: Documentation, https://vmafx.github.io/vmafx/mcp/
|
|
8
|
+
Project-URL: Issues, https://github.com/VMAFx/vmafx/issues
|
|
9
|
+
Project-URL: Changelog, https://github.com/VMAFx/vmafx/blob/master/CHANGELOG.md
|
|
10
|
+
Author-email: Lusoris <lusoris@pm.me>
|
|
11
|
+
License-Expression: BSD-2-Clause-Patent
|
|
12
|
+
Requires-Python: >=3.10
|
|
13
|
+
Requires-Dist: anyio>=4.15.1
|
|
14
|
+
Requires-Dist: mcp>=2.2.0
|
|
15
|
+
Requires-Dist: pydantic>=2.13.5
|
|
16
|
+
Provides-Extra: dev
|
|
17
|
+
Requires-Dist: mypy>=2.3.1; extra == 'dev'
|
|
18
|
+
Requires-Dist: prometheus-client>=0.26.0; extra == 'dev'
|
|
19
|
+
Requires-Dist: pytest-aiohttp>=1.1.1; extra == 'dev'
|
|
20
|
+
Requires-Dist: pytest-asyncio>=1.4.0; extra == 'dev'
|
|
21
|
+
Requires-Dist: pytest>=9.1.1; extra == 'dev'
|
|
22
|
+
Requires-Dist: ruff>=0.16.8; extra == 'dev'
|
|
23
|
+
Provides-Extra: eval
|
|
24
|
+
Requires-Dist: numpy>=2.5.3; extra == 'eval'
|
|
25
|
+
Requires-Dist: onnxruntime>=1.30.0; extra == 'eval'
|
|
26
|
+
Requires-Dist: pandas>=3.0.6; extra == 'eval'
|
|
27
|
+
Requires-Dist: pyarrow>=25.0.1; extra == 'eval'
|
|
28
|
+
Requires-Dist: scipy>=1.18.1; extra == 'eval'
|
|
29
|
+
Provides-Extra: http
|
|
30
|
+
Requires-Dist: aiohttp>=3.14.3; extra == 'http'
|
|
31
|
+
Requires-Dist: prometheus-client>=0.26.0; extra == 'http'
|
|
32
|
+
Provides-Extra: vlm
|
|
33
|
+
Requires-Dist: accelerate>=1.15.0; extra == 'vlm'
|
|
34
|
+
Requires-Dist: pillow>=12.3.0; extra == 'vlm'
|
|
35
|
+
Requires-Dist: torch>=2.14.0; extra == 'vlm'
|
|
36
|
+
Requires-Dist: transformers>=5.17.0; extra == 'vlm'
|
|
37
|
+
Description-Content-Type: text/markdown
|
|
38
|
+
|
|
39
|
+
<!-- markdownlint-disable MD060 -->
|
|
40
|
+
# vmaf-mcp
|
|
41
|
+
|
|
42
|
+
> **DEPRECATED (ADR-1229).** The MCP server is now the Go binary `vmafx-mcp`
|
|
43
|
+
> (`cmd/vmafx-mcp/`), installed at `/usr/local/bin/vmafx-mcp` in every container
|
|
44
|
+
> image. Attach with `docker exec -i vmaf-dev-mcp vmafx-mcp`. This Python package
|
|
45
|
+
> implements the same fifteen tools and is retained for one release as a
|
|
46
|
+
> reference implementation; it is no longer installed by `dev/Containerfile` and
|
|
47
|
+
> a follow-up removes it. Do not add tools here — add them to `cmd/vmafx-mcp/`.
|
|
48
|
+
|
|
49
|
+
MCP (Model Context Protocol) server that exposes the VMAFx fork's
|
|
50
|
+
scoring CLI to LLM tooling via JSON-RPC over stdio.
|
|
51
|
+
|
|
52
|
+
## Tools
|
|
53
|
+
|
|
54
|
+
| Tool | Description |
|
|
55
|
+
| ----------------------- | ---------------------------------------------------------------------------------- |
|
|
56
|
+
| `vmaf_score` | Score a (ref, dis) raw YUV pair. Returns the full JSON report. |
|
|
57
|
+
| `vmaf_score_encoded` | Score encoded video (MP4/MKV/Y4M/…) — decodes via ffmpeg, then scores. (ADR-0608) |
|
|
58
|
+
| `list_models` | Enumerate models under `model/` (`.json`, `.pkl`, `.onnx`). |
|
|
59
|
+
| `list_backends` | Report which backends (`cpu`/`cuda`/`sycl`/`hip`/`metal`) are compiled in. |
|
|
60
|
+
| `probe_backend` | Runtime health check: compiled-in vs driver-functional distinction. (ADR-0608) |
|
|
61
|
+
| `vmaf_version` | Return binary path, version string, and build flags. (ADR-0608) |
|
|
62
|
+
| `run_benchmark` | Run `testdata/bench_all.sh` on the built-in fixture pairs. |
|
|
63
|
+
| `eval_model_on_split` | Evaluate an ONNX tiny-AI model on a parquet feature split. |
|
|
64
|
+
| `compare_models` | Rank ONNX models on the same split by PLCC. |
|
|
65
|
+
| Tool | Description |
|
|
66
|
+
| --------------- | ------------------------------------------------------------ |
|
|
67
|
+
| `vmaf_score` | Score a (ref, dis) YUV pair. Returns the full JSON report. |
|
|
68
|
+
| `list_models` | Enumerate models under `model/` (`.json`, `.pkl`, `.onnx`). |
|
|
69
|
+
| `list_backends` | Report which backends (`cpu`/`cuda`/`sycl`/`hip`) are live. |
|
|
70
|
+
| `run_benchmark` | Run `testdata/bench_all.sh` on a pair. |
|
|
71
|
+
| `eval_model_on_split` | Evaluate an ONNX tiny-AI model on a parquet feature split. |
|
|
72
|
+
| `compare_models` | Rank ONNX models on the same split by PLCC. |
|
|
73
|
+
| `describe_worst_frames` | Extract the lowest-VMAF frames and describe visible artefacts with local VLM extras. |
|
|
74
|
+
|
|
75
|
+
## Install
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
cd mcp-server/vmaf-mcp
|
|
79
|
+
pip install -e .
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Requires a built `libvmaf` binary at `build/tools/vmaf` (override via
|
|
83
|
+
`VMAF_BIN=/abs/path/to/vmaf`).
|
|
84
|
+
|
|
85
|
+
## Run
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
# Stdio transport (default for Claude Desktop, Cursor, etc.)
|
|
89
|
+
vmaf-mcp
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## Path allowlisting
|
|
93
|
+
|
|
94
|
+
For safety, the server only reads files under `testdata/`,
|
|
95
|
+
`python/test/resource/`, and `model/`. Extend via colon-separated
|
|
96
|
+
`VMAF_MCP_ALLOW`:
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
VMAF_MCP_ALLOW=/data/my-corpus:/mnt/yuv vmaf-mcp
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## Claude Desktop config
|
|
103
|
+
|
|
104
|
+
```json
|
|
105
|
+
{
|
|
106
|
+
"mcpServers": {
|
|
107
|
+
"vmaf": {
|
|
108
|
+
"command": "vmaf-mcp",
|
|
109
|
+
"env": {
|
|
110
|
+
"VMAF_BIN": "/home/you/dev/vmaf/build/tools/vmaf",
|
|
111
|
+
"VMAF_MCP_ALLOW": "/data/yuv-corpus"
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
```
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
<!-- markdownlint-disable MD060 -->
|
|
2
|
+
# vmaf-mcp
|
|
3
|
+
|
|
4
|
+
> **DEPRECATED (ADR-1229).** The MCP server is now the Go binary `vmafx-mcp`
|
|
5
|
+
> (`cmd/vmafx-mcp/`), installed at `/usr/local/bin/vmafx-mcp` in every container
|
|
6
|
+
> image. Attach with `docker exec -i vmaf-dev-mcp vmafx-mcp`. This Python package
|
|
7
|
+
> implements the same fifteen tools and is retained for one release as a
|
|
8
|
+
> reference implementation; it is no longer installed by `dev/Containerfile` and
|
|
9
|
+
> a follow-up removes it. Do not add tools here — add them to `cmd/vmafx-mcp/`.
|
|
10
|
+
|
|
11
|
+
MCP (Model Context Protocol) server that exposes the VMAFx fork's
|
|
12
|
+
scoring CLI to LLM tooling via JSON-RPC over stdio.
|
|
13
|
+
|
|
14
|
+
## Tools
|
|
15
|
+
|
|
16
|
+
| Tool | Description |
|
|
17
|
+
| ----------------------- | ---------------------------------------------------------------------------------- |
|
|
18
|
+
| `vmaf_score` | Score a (ref, dis) raw YUV pair. Returns the full JSON report. |
|
|
19
|
+
| `vmaf_score_encoded` | Score encoded video (MP4/MKV/Y4M/…) — decodes via ffmpeg, then scores. (ADR-0608) |
|
|
20
|
+
| `list_models` | Enumerate models under `model/` (`.json`, `.pkl`, `.onnx`). |
|
|
21
|
+
| `list_backends` | Report which backends (`cpu`/`cuda`/`sycl`/`hip`/`metal`) are compiled in. |
|
|
22
|
+
| `probe_backend` | Runtime health check: compiled-in vs driver-functional distinction. (ADR-0608) |
|
|
23
|
+
| `vmaf_version` | Return binary path, version string, and build flags. (ADR-0608) |
|
|
24
|
+
| `run_benchmark` | Run `testdata/bench_all.sh` on the built-in fixture pairs. |
|
|
25
|
+
| `eval_model_on_split` | Evaluate an ONNX tiny-AI model on a parquet feature split. |
|
|
26
|
+
| `compare_models` | Rank ONNX models on the same split by PLCC. |
|
|
27
|
+
| Tool | Description |
|
|
28
|
+
| --------------- | ------------------------------------------------------------ |
|
|
29
|
+
| `vmaf_score` | Score a (ref, dis) YUV pair. Returns the full JSON report. |
|
|
30
|
+
| `list_models` | Enumerate models under `model/` (`.json`, `.pkl`, `.onnx`). |
|
|
31
|
+
| `list_backends` | Report which backends (`cpu`/`cuda`/`sycl`/`hip`) are live. |
|
|
32
|
+
| `run_benchmark` | Run `testdata/bench_all.sh` on a pair. |
|
|
33
|
+
| `eval_model_on_split` | Evaluate an ONNX tiny-AI model on a parquet feature split. |
|
|
34
|
+
| `compare_models` | Rank ONNX models on the same split by PLCC. |
|
|
35
|
+
| `describe_worst_frames` | Extract the lowest-VMAF frames and describe visible artefacts with local VLM extras. |
|
|
36
|
+
|
|
37
|
+
## Install
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
cd mcp-server/vmaf-mcp
|
|
41
|
+
pip install -e .
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Requires a built `libvmaf` binary at `build/tools/vmaf` (override via
|
|
45
|
+
`VMAF_BIN=/abs/path/to/vmaf`).
|
|
46
|
+
|
|
47
|
+
## Run
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
# Stdio transport (default for Claude Desktop, Cursor, etc.)
|
|
51
|
+
vmaf-mcp
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Path allowlisting
|
|
55
|
+
|
|
56
|
+
For safety, the server only reads files under `testdata/`,
|
|
57
|
+
`python/test/resource/`, and `model/`. Extend via colon-separated
|
|
58
|
+
`VMAF_MCP_ALLOW`:
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
VMAF_MCP_ALLOW=/data/my-corpus:/mnt/yuv vmaf-mcp
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Claude Desktop config
|
|
65
|
+
|
|
66
|
+
```json
|
|
67
|
+
{
|
|
68
|
+
"mcpServers": {
|
|
69
|
+
"vmaf": {
|
|
70
|
+
"command": "vmaf-mcp",
|
|
71
|
+
"env": {
|
|
72
|
+
"VMAF_BIN": "/home/you/dev/vmaf/build/tools/vmaf",
|
|
73
|
+
"VMAF_MCP_ALLOW": "/data/yuv-corpus"
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
```
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"//": "Drop this into Claude Desktop's mcpServers config (~/Library/Application Support/Claude/claude_desktop_config.json on macOS, %APPDATA%/Claude/claude_desktop_config.json on Windows). Adjust paths for your machine.",
|
|
3
|
+
"mcpServers": {
|
|
4
|
+
"vmaf-local": {
|
|
5
|
+
"command": "vmaf-mcp",
|
|
6
|
+
"env": {
|
|
7
|
+
"VMAF_BIN": "/home/you/dev/vmaf/build/tools/vmaf",
|
|
8
|
+
"VMAF_MCP_ALLOW": "/home/you/yuv-corpus:/home/you/renders"
|
|
9
|
+
}
|
|
10
|
+
},
|
|
11
|
+
"vmaf-docker": {
|
|
12
|
+
"command": "docker",
|
|
13
|
+
"args": [
|
|
14
|
+
"run", "--rm", "-i",
|
|
15
|
+
"-v", "/home/you/yuv-corpus:/data:ro",
|
|
16
|
+
"-e", "VMAF_MCP_ALLOW=/data",
|
|
17
|
+
"ghcr.io/VMAFx/vmafx-mcp:latest"
|
|
18
|
+
]
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "vmaf-mcp"
|
|
3
|
+
version = "1.0.0-rc.1" # x-release-please-version
|
|
4
|
+
description = "MCP server exposing VMAF scoring, model listing, and benchmark runs via JSON-RPC."
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.10"
|
|
7
|
+
license = "BSD-2-Clause-Patent"
|
|
8
|
+
authors = [
|
|
9
|
+
{ name = "Lusoris", email = "lusoris@pm.me" },
|
|
10
|
+
]
|
|
11
|
+
dependencies = [
|
|
12
|
+
"mcp>=2.2.0",
|
|
13
|
+
"pydantic>=2.13.5",
|
|
14
|
+
"anyio>=4.15.1",
|
|
15
|
+
]
|
|
16
|
+
|
|
17
|
+
[project.optional-dependencies]
|
|
18
|
+
dev = [
|
|
19
|
+
"pytest>=9.1.1",
|
|
20
|
+
"pytest-asyncio>=1.4.0",
|
|
21
|
+
"pytest-aiohttp>=1.1.1",
|
|
22
|
+
"prometheus-client>=0.26.0",
|
|
23
|
+
"ruff>=0.16.8",
|
|
24
|
+
"mypy>=2.3.1",
|
|
25
|
+
]
|
|
26
|
+
# Optional HTTP operator surface (--transport http). Kept separate so stdio
|
|
27
|
+
# clients do not need aiohttp or Prometheus at runtime (ADR-0701).
|
|
28
|
+
http = [
|
|
29
|
+
"aiohttp>=3.14.3",
|
|
30
|
+
"prometheus-client>=0.26.0",
|
|
31
|
+
]
|
|
32
|
+
# Optional: enables `eval_model_on_split` + `compare_models`. Pulls in the
|
|
33
|
+
# ONNX / pandas / scipy stack, so it's off by default to keep the base MCP
|
|
34
|
+
# install light for callers that only want `vmaf_score`.
|
|
35
|
+
eval = [
|
|
36
|
+
"numpy>=2.5.3",
|
|
37
|
+
"pandas>=3.0.6",
|
|
38
|
+
"pyarrow>=25.0.1",
|
|
39
|
+
"onnxruntime>=1.30.0",
|
|
40
|
+
"scipy>=1.18.1",
|
|
41
|
+
]
|
|
42
|
+
# Optional: enables `describe_worst_frames` with vision-language fallback
|
|
43
|
+
# (SmolVLM → Moondream2 → metadata-only). Pulls in transformers + torch.
|
|
44
|
+
# Heavy install; off by default so the base MCP keeps a light footprint
|
|
45
|
+
# (ADR-0172 / T6-6).
|
|
46
|
+
vlm = [
|
|
47
|
+
"transformers>=5.17.0",
|
|
48
|
+
"torch>=2.14.0",
|
|
49
|
+
"Pillow>=12.3.0",
|
|
50
|
+
"accelerate>=1.15.0",
|
|
51
|
+
]
|
|
52
|
+
|
|
53
|
+
[project.scripts]
|
|
54
|
+
vmaf-mcp = "vmaf_mcp.server:main"
|
|
55
|
+
vmafx-mcp = "vmaf_mcp.server:main"
|
|
56
|
+
|
|
57
|
+
[project.urls]
|
|
58
|
+
Homepage = "https://github.com/VMAFx/vmafx"
|
|
59
|
+
Repository = "https://github.com/VMAFx/vmafx"
|
|
60
|
+
Documentation = "https://vmafx.github.io/vmafx/mcp/"
|
|
61
|
+
Issues = "https://github.com/VMAFx/vmafx/issues"
|
|
62
|
+
Changelog = "https://github.com/VMAFx/vmafx/blob/master/CHANGELOG.md"
|
|
63
|
+
|
|
64
|
+
[build-system]
|
|
65
|
+
requires = ["hatchling>=1.32.0"]
|
|
66
|
+
build-backend = "hatchling.build"
|
|
67
|
+
|
|
68
|
+
[tool.hatch.build.targets.wheel]
|
|
69
|
+
packages = ["src/vmaf_mcp"]
|
|
70
|
+
|
|
71
|
+
[tool.pytest.ini_options]
|
|
72
|
+
pythonpath = ["src"]
|
|
73
|
+
testpaths = ["tests"]
|
|
74
|
+
filterwarnings = ["error"]
|
|
75
|
+
asyncio_default_fixture_loop_scope = "function"
|
|
76
|
+
markers = [
|
|
77
|
+
# Tests >30 s wall (or that exercise real GPUs / containers and may grow
|
|
78
|
+
# past 30 s). Exclude with `pytest -m 'not slow'` for fast iteration.
|
|
79
|
+
# See docs/adr/0908-slow-test-audit-2026-05-30.md.
|
|
80
|
+
"slow: marks tests as slow (deselect with -m 'not slow')",
|
|
81
|
+
]
|
|
82
|
+
|
|
83
|
+
[tool.ruff]
|
|
84
|
+
line-length = 100
|
|
85
|
+
target-version = "py310"
|
|
86
|
+
|
|
87
|
+
[tool.ruff.lint]
|
|
88
|
+
select = ["E", "F", "W", "I", "B", "SIM", "RUF"]
|
|
89
|
+
ignore = [
|
|
90
|
+
"E501", # line length handled by black
|
|
91
|
+
"B008", # typer.Option / FastAPI Depends pattern — idiomatic
|
|
92
|
+
"RUF001", # ambiguous unicode — em-dashes in strings are intentional
|
|
93
|
+
"RUF002", # ambiguous unicode in docstrings
|
|
94
|
+
"RUF003", # ambiguous unicode in comments
|
|
95
|
+
]
|