Skip to content

build: pin mcp SDK to the stable v1 line and document Android TV wireless debugging requirements - #23

Merged
netixc merged 3 commits into
mainfrom
fm/stremio-mcp-modernization-audit
Jul 21, 2026
Merged

build: pin mcp SDK to the stable v1 line and document Android TV wireless debugging requirements#23
netixc merged 3 commits into
mainfrom
fm/stremio-mcp-modernization-audit

Conversation

@netixc

@netixc netixc commented Jul 21, 2026

Copy link
Copy Markdown
Owner

Intent

Ship the captain-approved safe modernization for netixc/stremio-mcp: pin the official Python MCP SDK to the stable v1 line with an explicit upper bound (mcp>=1.28.1,<2), refresh uv.lock while keeping resolved mcp 1.28.1, and document current Android TV Wireless Debugging requirements (Android 13+ for TV, Platform Tools wireless-era minimum with preference for current stable, separate pairing vs connection ports, and that native Platform Tools adb remains intentional because pure-Python ADB clients lack modern TLS/STLS plus shell diagnostics).

Deliberate constraints from the modernization audit and captain decisions: keep native adb, stdio, low-level MCP Server, httpx, and setuptools unchanged; do not add Android TV Remote, Cast, Appium, FastMCP, MCP v2, or any new runtime dependency (Android TV Remote experiment was declined); do not include the separate ANDROID_TV_PORT fix, version bump to 0.1.1, changelog release conversion, tag, PyPI publish, or MCP Registry publish in this PR. Include independently checkable proof via a unit test that parses pyproject.toml and proves the MCP requirement accepts 1.28.1 and rejects 2.0.0, with genuine fail-before/pass-after against the bound.

What Changed

  • Tightened the mcp dependency in pyproject.toml from >=1.28.1 to >=1.28.1,<2 and refreshed uv.lock accordingly, so installs stay on the stable v1 SDK line until a deliberate v2 migration; the resolved version is unchanged at 1.28.1 and no new runtime dependency was added. Recorded under Changed in CHANGELOG.md (no release conversion or version bump).
  • Added ReleaseMetadataTests in tests/test_stremio_mcp.py that parse the [project] dependency list and assert the requirement accepts 1.28.1 and rejects 2.0.0. The parsing is regex/text-based rather than tomllib so the module still imports on Python 3.10, which is in the CI matrix.
  • Expanded the Android TV wireless debugging docs in README.md and AGENTS.md: Android 13+ for official TV wireless debugging, a Platform Tools floor of 30.0.0+ with a preference for the latest stable, the separate (often ephemeral) pairing vs connection ports, and the rationale for keeping native Platform Tools adb — pure-Python ADB clients lack modern TLS (STLS) and shell diagnostics.

The transport, MCP server style, httpx usage, and build backend are unchanged. Pipeline checks pass, including uv sync --locked, the 100-test unit suite, compileall, and uv build; testing also covered a fail-before/pass-after run of the new pin test against a temporarily reverted bound.

Risk Assessment

✅ Low: The change is a bounded dependency upper bound plus documentation and one self-contained metadata test, all matching the stated intent, with the previously reported Python 3.10 import break now fixed and no runtime code touched.

Testing

Ran the full CI-equivalent chain (locked sync, 100 unit tests, compileall, build) plus targeted evidence work: I evaluated the built wheel's Requires-Dist with packaging to show the pin accepts mcp 1.28.1 and rejects 2.0.0 exactly as an installer would, confirmed uv.lock still resolves 1.28.1, demonstrated genuine fail-before/pass-after for the new pyproject-parsing test by reverting and restoring the upper bound, drove a real MCP stdio session against the installed console script to show the pinned SDK still serves initialize/tools/list/tools/call, and captured a rendered screenshot of the updated README Android TV Wireless Debugging documentation. Everything passed and the diff stays inside the declared scope; build/cache artifacts were cleaned from the worktree.

Evidence: Installer-level proof the MCP pin accepts 1.28.1 and rejects 2.0.0

# Built wheel: dist/stremio_mcp_server-0.1.0-py3-none-any.whl # Requires-Dist as an installer (pip/uv) sees it: Requires-Dist: httpx>=0.28.1 Requires-Dist: mcp<2,>=1.28.1 # Evaluating specifier '<2,>=1.28.1' for package 'mcp': mcp 1.28.1 -> ACCEPTED mcp 1.99.0 -> ACCEPTED mcp 2.0.0 -> REJECTED mcp 2.1.0 -> REJECTED # Locked resolution still pins the v1 baseline: uv.lock resolved mcp == 1.28.1 OK: v1 accepted, 2.x rejected, lock pinned at 1.28.1

# Built wheel: dist/stremio_mcp_server-0.1.0-py3-none-any.whl
# Requires-Dist as an installer (pip/uv) sees it:
    Requires-Dist: httpx>=0.28.1
    Requires-Dist: mcp<2,>=1.28.1

# Evaluating specifier '<2,>=1.28.1' for package 'mcp':
    mcp 1.28.1   -> ACCEPTED
    mcp 1.99.0   -> ACCEPTED
    mcp 2.0.0    -> REJECTED
    mcp 2.1.0    -> REJECTED

# Locked resolution still pins the v1 baseline:
    uv.lock resolved mcp == 1.28.1

OK: v1 accepted, 2.x rejected, lock pinned at 1.28.1
Evidence: Fail-before / pass-after for the new MCP pin test

=== FAIL-BEFORE: revert the bound to the pre-change 'mcp>=1.28.1' === AssertionError: 'mcp>=1.28.1' != 'mcp>=1.28.1,<2' FAILED (failures=1) === PASS-AFTER: restore 'mcp>=1.28.1,<2' === Ran 1 test in 0.001s OK

=== FAIL-BEFORE: revert the bound to the pre-change 'mcp>=1.28.1' ===
6:name = "stremio-mcp-server"
12:keywords = ["mcp", "stremio", "android-tv", "adb", "remote-control"]
31:    "mcp>=1.28.1",
35:stremio-mcp = "stremio_mcp:cli"
36:stremio-mcp-server = "stremio_mcp:cli"
39:Homepage = "https://github.com/netixc/stremio-mcp"
40:Documentation = "https://github.com/netixc/stremio-mcp#readme"
41:Repository = "https://github.com/netixc/stremio-mcp"
42:Issues = "https://github.com/netixc/stremio-mcp/issues"
43:Changelog = "https://github.com/netixc/stremio-mcp/blob/main/CHANGELOG.md"
Pin the official SDK to v1 until a deliberate v2 migration.
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/control/.no-mistakes/worktrees/19a627fa957c/01KY31C3FBD9A7CJTQ89T5YSPG/tests/test_stremio_mcp.py", line 847, in test_mcp_dependency_stays_on_stable_v1
    self.assertEqual(requirement, "mcp>=1.28.1,<2")
AssertionError: 'mcp>=1.28.1' != 'mcp>=1.28.1,<2'
- mcp>=1.28.1
+ mcp>=1.28.1,<2
?            +++


----------------------------------------------------------------------
Ran 1 test in 0.001s

FAILED (failures=1)

=== PASS-AFTER: restore 'mcp>=1.28.1,<2' ===
6:name = "stremio-mcp-server"
12:keywords = ["mcp", "stremio", "android-tv", "adb", "remote-control"]
31:    "mcp>=1.28.1,<2",
35:stremio-mcp = "stremio_mcp:cli"
36:stremio-mcp-server = "stremio_mcp:cli"
39:Homepage = "https://github.com/netixc/stremio-mcp"
40:Documentation = "https://github.com/netixc/stremio-mcp#readme"
41:Repository = "https://github.com/netixc/stremio-mcp"
42:Issues = "https://github.com/netixc/stremio-mcp/issues"
43:Changelog = "https://github.com/netixc/stremio-mcp/blob/main/CHANGELOG.md"
.
----------------------------------------------------------------------
Ran 1 test in 0.001s

OK
Evidence: Live MCP stdio session against the shipped server with the pinned SDK

$ .venv/bin/stremio-mcp (installed mcp SDK == 1.28.1) <- initialize: {"name": "stremio-mcp", "version": "1.28.1"} protocolVersion=2025-06-18 <- tools/list: 5 tools - search: Search for movies or TV shows. Returns results with IMDb IDs. - play: Play movies or TV episodes. Use 'query' to search by title, or 'imdb_id' - library: Read or mutate the Stremio library. Add/remove require an explicit IMDb - tv_control: Control Android TV. volume: up/down/mute/set. playback: play/pause/toggl - playback_status: Get current playback status. Returns app, title, state (playing/paused/s -> tools/call search (no TMDB key configured) <- Error: TMDB_API_KEY not configured.

$ .venv/bin/stremio-mcp   (installed mcp SDK == 1.28.1)

<- initialize: {"name": "stremio-mcp", "version": "1.28.1"} protocolVersion=2025-06-18
<- tools/list: 5 tools
     - search: Search for movies or TV shows. Returns results with IMDb IDs.
     - play: Play movies or TV episodes. Use 'query' to search by title, or 'imdb_id'
     - library: Read or mutate the Stremio library. Add/remove require an explicit IMDb 
     - tv_control: Control Android TV. volume: up/down/mute/set. playback: play/pause/toggl
     - playback_status: Get current playback status. Returns app, title, state (playing/paused/s

-> tools/call search (no TMDB key configured)
<- Error: TMDB_API_KEY not configured.
- Evidence: Screenshot: rendered README Android TV Wireless Debugging requirements (local file: /tmp/no-mistakes-evidence/01KY31C3FBD9A7CJTQ89T5YSPG/readme-android-tv-requirements.png)
Evidence: Rendered README sections (GFM HTML source for the screenshot)
<!doctype html><meta charset=utf-8>
<link rel=stylesheet href="https://cdn.jsdelivr.net/npm/github-markdown-css@5/github-markdown.min.css">
<style>body{margin:0;background:#f6f8fa}.markdown-body{max-width:900px;margin:24px auto;padding:32px;background:#fff;border:1px solid #d0d7de;border-radius:8px}</style>
<article class="markdown-body"><h2>Requirements</h2>
<ul>
<li>Android TV with <a href="https://www.stremio.com/" rel="nofollow">Stremio</a> installed and configured with working addons</li>
<li>For modern Wireless Debugging on TV: <strong>Android TV / Google TV running Android 13 (API 33) or higher</strong>, per Google's <a href="https://developer.android.com/tools/adb#wireless-android-11" rel="nofollow">wireless adb requirements</a></li>
<li><a href="https://www.python.org/downloads/" rel="nofollow">Python 3.10+</a></li>
<li><a href="https://docs.astral.sh/uv/getting-started/installation/" rel="nofollow">uv</a></li>
<li><a href="https://developer.android.com/tools/releases/platform-tools" rel="nofollow">Android SDK Platform Tools</a> (<code class="notranslate">adb</code>) — install a <strong>current release</strong> and keep it updated; use at least the wireless-debugging era of Platform Tools (<strong>30.0.0+</strong>, when <code class="notranslate">adb pair</code> landed). Prefer the latest stable from the Platform Tools page for mDNS and TLS fixes</li>
<li>A free <a href="https://www.themoviedb.org/settings/api" rel="nofollow">TMDB API key</a> for title search</li>
<li>Optional: a <a href="https://github.com/netixc/stremio-mcp/blob/main/docs/stremio-auth-key.md">Stremio auth key</a> for library access</li>
</ul>
<h2>Installation</h2>
<h3>PyPI package (recommended)</h3>
<p>Run the latest published release without cloning the repository:</p>
<div class="highlight highlight-source-shell"><pre class="notranslate">uvx stremio-mcp-server</pre></div>
<p>To run the current release explicitly:</p>
<div class="highlight highlight-source-shell"><pre class="notranslate">uvx --from stremio-mcp-server==0.1.0 stremio-mcp-server</pre></div>
<h3>Source checkout</h3>
<p>Use a source checkout for development or local modifications:</p>
<div class="highlight highlight-source-shell"><pre class="notranslate">git clone https://github.com/netixc/stremio-mcp.git
<span class="pl-c1">cd</span> stremio-mcp
uv sync --locked
cp .env.example .env</pre></div>
<p>Edit <code class="notranslate">.env</code> with your TV endpoint and API keys. The file is ignored by Git; never commit it.</p>
<div class="highlight highlight-source-dotenv"><pre class="notranslate"><span class="pl-v">TMDB_API_KEY</span><span class="pl-k">=</span><span class="pl-s">your_tmdb_api_key</span>
<span class="pl-v">ANDROID_TV_HOST</span><span class="pl-k">=</span><span class="pl-s">192.168.1.100</span>
<span class="pl-v">ANDROID_TV_PORT</span><span class="pl-k">=</span><span class="pl-s">37139</span>
<span class="pl-v">STREMIO_AUTH_KEY</span><span class="pl-k">=</span>
<span class="pl-c"><span class="pl-c">#</span> ADB_PATH=/absolute/path/to/adb</span></pre></div>
<h2>Pair and connect the TV</h2>
<p>This server talks to the TV through the <strong>native Platform Tools <code class="notranslate">adb</code> client</strong>, not a pure-Python ADB library. That is intentional: modern Wireless Debugging negotiates TLS (<code class="notranslate">STLS</code>) and this project needs a full shell for intents, key events, and media-session diagnostics. Pure-Python clients that only speak legacy ADB-over-TCP do not cover that path.</p>
<p>On the TV, enable <strong>Developer options</strong> and <strong>Wireless debugging</strong>. Menu names vary by manufacturer. Official wireless debugging for TV requires <strong>Android 13+</strong>; see Google's <a href="https://developer.android.com/tools/adb#wireless-android-11" rel="nofollow">Connect to a device over Wi-Fi</a> guide.</p>
<p>Modern Wireless Debugging displays <strong>separate pairing and connection ports</strong> (often ephemeral). Pair once, then connect with the current connection port:</p>
<div class="highlight highlight-source-shell"><pre class="notranslate">adb pair TV_IP:PAIRING_PORT
<span class="pl-c"><span class="pl-c">#</span> Enter the temporary pairing code shown on the TV.</span>

adb connect TV_IP:CONNECTION_PORT
adb devices -l</pre></div>
<p>Set <code class="notranslate">ANDROID_TV_PORT</code> to the <strong>connection port</strong>, not the temporary pairing port. The device must appear as <code class="notranslate">device</code>, not <code class="notranslate">offline</code> or <code class="notranslate">unauthorized</code>. Wireless Debugging ports may change after a reboot or after debugging is toggled. On newer Platform Tools and Android versions, a previously paired device may also reconnect via mDNS when it returns to a trusted network; still configure the explicit connection port when the UI shows one.</p>
<p>Legacy network debugging may use port <code class="notranslate">5555</code> (<code class="notranslate">adb tcpip</code> after USB); only use that workflow when your TV explicitly documents it. Prefer Wireless Debugging on supported TVs.</p></article>

Pipeline

Updates from git push no-mistakes

✅ **intent** - passed

✅ No issues found.

✅ **Rebase** - passed

✅ No issues found.

⚠️ **Review** - 1 info
  • 🚨 tests/test_stremio_mcp.py:9 - import tomllib is unconditional at module scope, but tomllib was added in Python 3.11 while requires-python = &#34;&gt;=3.10&#34; and the CI matrix includes 3.10 (.github/workflows/ci.yml:22). On Python 3.10 the import raises ModuleNotFoundError before any test class is collected, so the ENTIRE tests/test_stremio_mcp.py module fails to load — not just the new MCP-pin test. tomli is not a declared dependency and is absent from uv.lock, so no fallback exists. Fix by parsing the dependency without tomllib (the file is read as text anyway) or by guarding the import with a version check plus a text-based fallback; adding tomli for <3.11 would require a dev dependency and lock refresh.
  • ℹ️ tests/test_stremio_mcp.py:783 - _version_tuple/_cmp_version/_requirement_contains hand-roll ~50 lines of partial PEP 440 semantics that are only exercised by one assertion set, and they diverge from real resolver behaviour (pre-release suffixes are truncated, so &gt;=1.28.1 would be reported as accepting 1.28.1rc1; _requirement_contains silently returns True when no version clause is found at all). Since test_mcp_dependency_stays_on_stable_v1 already asserts the exact requirement string, the semantic bound checks can be expressed far more simply (e.g. assert the parsed clause set is {(&#39;&gt;=&#39;, &#39;1.28.1&#39;), (&#39;&lt;&#39;, &#39;2&#39;)}) without a bespoke comparator.
  • ℹ️ tests/test_stremio_mcp.py:859 - self.assertEqual(requirement, &#34;mcp&gt;=1.28.1,&lt;2&#34;) makes the test fail on semantically identical rewrites such as mcp&gt;=1.28.1,&lt;2.0 or mcp &gt;= 1.28.1, &lt; 2. That strictness is defensible as a deliberate pin, but it means the bound-evaluation assertions below it can never independently fail; flagging so the tradeoff is a conscious choice.
  • ℹ️ README.md:33 - The requirements list hardcodes "37.x at the time of writing" as the current Platform Tools stable release. This is an unverifiable-offline, fast-ageing claim that will silently become wrong; consider dropping the specific version and keeping only the 30.0.0+ floor plus "prefer the latest stable from the Platform Tools page", which is the durable guidance the intent asks for.

🔧 Fix: Make MCP pin test 3.10-safe and drop stale adb version claim
1 info still open:

  • ℹ️ tests/test_stremio_mcp.py:769 - _project_dependencies scans the [project] table with regexes instead of a TOML parser — a reasonable tradeoff given the 3.10 floor and the no-new-dependency constraint. Worth knowing the one edge it has: re.findall(r&#34;[\&#34;&#39;]([^\&#34;&#39;]+)[\&#34;&#39;]&#34;, ...) also picks up quoted strings on commented-out lines inside the dependencies array, so a # &#34;mcp&gt;=1.0&#34;, line would produce a second mcp match and trip the expected one &#39;mcp&#39; dependency AssertionError. It fails loudly rather than silently, so no action is needed unless the array grows comments.
✅ **Test** - passed

✅ No issues found.

  • uv sync --locked — lockfile consistent with pyproject (34 packages resolved, no drift)
  • uv run --locked python -m unittest discover -s tests -v — 100 tests, all pass
  • uv run --locked python -m compileall -q src tests
  • uv build — sdist + wheel built
  • Manual resolver-level proof: parsed Requires-Dist from the built wheel METADATA and evaluated it with packaging → mcp 1.28.1/1.99.0 ACCEPTED, 2.0.0/2.1.0 REJECTED; asserted uv.lock still resolves mcp == 1.28.1
  • Fail-before/pass-after: temporarily reverted pyproject to mcp&gt;=1.28.1, ran tests.test_stremio_mcp.ReleaseMetadataTests.test_mcp_dependency_stays_on_stable_v1 (FAILED), restored the bound and re-ran (OK); worktree restored clean
  • End-to-end MCP stdio session against the installed .venv/bin/stremio-mcp console script: initialize handshake, notifications/initialized, tools/list, and tools/call search with the pinned SDK (mcp 1.28.1)
  • Rendered the changed README ## Requirements## Pair and connect the TV sections via the GitHub markdown API and captured a full-page screenshot to verify the Android 13+, Platform Tools 30.0.0+/latest-stable, pairing-vs-connection-port, and native-adb TLS/STLS rationale copy
  • Scope audit of the diff: 5 files touched, no new runtime dependency, no FastMCP/Appium/Android TV Remote/Cast, transport/backend unchanged, version still 0.1.0, no changelog release conversion, tag, or publish
✅ **Document** - passed

✅ No issues found.

✅ **Lint** - passed

✅ No issues found.

✅ **Push** - passed

✅ No issues found.

netixc added 3 commits July 21, 2026 21:09
Bound the official mcp dependency to >=1.28.1,<2 so a future v2 stable
release cannot be selected accidentally. Keep the lock on mcp 1.28.1.
Document Android 13+ Wireless Debugging for TV, a durable Platform Tools
floor with a preference for current releases, separate pair/connect ports,
and why native adb remains the intentional transport.
@netixc
netixc merged commit 16d0934 into main Jul 21, 2026
6 checks passed
@netixc
netixc deleted the fm/stremio-mcp-modernization-audit branch July 25, 2026 14:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant