v1.1.0
[1.1.0] – 2026-07-30
Fixed
-
API-Basispfade und EPG-Endpunkt korrigiert (Basis: PR #46 von @aburossi).
/video/v3und/audio/v3sind bei Apigee nicht mehr als Basepath
registriert — sie antworten mit 302 aufdeveloper.srgssr.ch, exakt wie
ein frei erfundener Pfad. Weil 302 kein 4xx ist, greiftraise_for_status()
nicht:resp.json()lief auf HTML und der User sah nur «Unerwarteter
Fehler». Neu/videometadata/v2und/audiometadata/v2.Das EPG adressiert einen Tag über
/{bu}/{tv|radio}/stations/{station}—
Unternehmenseinheit und Sendertyp sind Pfadsegmente, nicht Query-Parameter.
Dafür kommtbroadcast_type(tv/radio, Defaulttv) als neues Feld an
srgssr_epg_get_programs. Die Antwort heisstprograms(nicht
programList) und trägt die Zeit indateTimes.startTime, den Text in
shortDescription/longDescription; die alten Feldnamen bleiben als
Fallback erhalten.Die
epg://{bu}/{channel_id}/{date}-Resource hing am selben alten Pfad und
wird mitgezogen. URL-Bau und Programm-Extraktion liegen jetzt in
_epg_station_url()/_extract_raw_programs()intools/epg.py, die sich
Tool und Resource teilen — die beiden Oberflächen können nicht mehr auf
verschiedene Endpunkte auseinanderlaufen. Die Resource-URI hat kein Feld für
den Sendertyp und ist damit TV-only; für Radio das Tool verwenden. Das steht
jetzt auch in der Resource-Beschreibung.Sender-IDs folgen der Stations-Schreibweise (
srf-1stattsrf1);
Tool-Beispiele, Prompt-Default, READMEs,EXAMPLES.mdund der Live-Test sind
nachgezogen.Die EPG-Mocks in
tests/test_unit.pymatchen exakte URLs statt eines
Präfix-Patterns — ein Mock, der jeden Pfad unterEPG_BASEakzeptiert, wäre
über den nicht migrierten Resource-Aufruf grün durchgelaufen. Drei neue
Tests decken die Station-Response-Form, denradio-Pfadsegment-Fall und den
Endpunkt der Resource ab.
Removed
-
fastmcpals Abhängigkeit entfernt — nichts importierte es. Es war ein
Rest aus der Zeit, in der dieser Servermcptransitiv darüber bezog; mit
der direktenmcp-Deklaration wurde es überflüssig und blieb trotzdem
stehen. Nichts schlug fehl, deshalb fiel es nicht auf.Gemessen in frischen venvs, nur Runtime-Abhängigkeiten: 84 → 44 Pakete,
also 40 weniger, und keines kommt hinzu. Was mit verschwindet, ist der Punkt:
redisundburner-redis,py-key-value-aio,pydocket,
prometheus_client,keyring/SecretStorage/jeepney,Authlib,
joserfc,websockets,cronsim,jsonschema-path. Ein Redis-Client, ein
Keyring-Stack und eine OAuth-Bibliothek wurden in einen read-only Server über
öffentliche Daten installiert, wegen einer ungenutzten Zeile.tests/test_dependencies.pyhält das offen in beide Richtungen: der Test
prüft Gleichheit von „deklariert" und „importiert", nicht bloss Abwesenheit.
Ein legitimer Wiedereinzug vonfastmcpverlangt also die Deklaration zurück,
statt den Test zu löschen. Ein zweiter Test prüft den Scanner selbst gegen
mcp, damit ein kaputter Import-Scan nicht jede Gleichheit trivial erfüllt.
Beide Richtungen sind mutationsgetestet.Die Dependabot-Gruppen nennen
fastmcpnicht mehr — das Pattern wäre mit der
Abhängigkeit toter Code geworden.Geprüft: 162 passed / 14 deselected (156 plus die sechs neuen Tests),
Coverage 96.7 % gegen das 80-%-Gate,ruff check src/clean, und ein Install
in einem frischen venv startet den Server mit allen 15 Tools. Kein
yaml-Import im Projekt, obwohlPyYAMLmit wegfällt.
Changed
-
Migration auf die
mcp2.x Server-API. Pin von>=1.28.1,<2auf
>=2.0.0,<3. Die Untergrenze ist hart: 2.0.0 hatmcp.server.fastmcpohne
Kompatibilitätsschicht entfernt, dieser Code läuft also gar nicht mehr auf
1.x — ein>=1.x-Bereich würde einen Resolver eine Version wählen lassen,
die beim Import scheitert.FastMCP→MCPServer.Bestehende Clients sehen keinen Unterschied: der Legacy-
initialize-Handshake
deckelt weiterhin bei 2025-11-25 — nachgemessen, nicht aus einem
Konstantennamen geschlossen; wer2026-07-28anfragt, bekommt2025-11-25
zurück. mcp 2.x bedient über denselben Server aber eine zweite, „moderne"
Ära (Per-Request-Envelope; die erste Anfrage des Clients entscheidet), die
2026-07-28 erreicht. Ein 2.x-Client verhandelt also die neuere Revision. Kein
Bruch, aber auch kein Protokoll-No-op.PROTOCOL_VERSIONbleibt bei2025-06-18— der Guard gegen
SUPPORTED_PROTOCOL_VERSIONS(jetztmcp.types.versionstatt
mcp.shared.version) hält, der Wert ist also weiter gültig. -
_build_mcp()→_transport_kwargs().MCPServer.settingsträgt
host/port/mount_pathnicht mehr; sie sindrun()-Argumente. Die alte
Zuweisung ist kein stiller No-op, sondern wirftValueError— ein Test hält
beides fest, damit der Grund für die Indirektion nicht verloren geht.mount_pathhat in 2.x keine Entsprechung. In 1.x schrieb es nur den
angekündigten Message-Endpoint um, während die Route unpräfixiert blieb —
korrekt allein dann, wenn eine äussere ASGI-App den Server unter diesem
Präfix einhängt. 2.x nutzt einen Wert für beides, also bildet
SRGSSR_MCP_MOUNT_PATHaufmessage_pathab, wodurch die Route mitwandert.
Fürstreamable-httpwurde die Einstellung bereits in 1.x ignoriert
(run()gab sie nie anrun_streamable_http_asyncweiter); sie bleibt
ignoriert, denn ein Durchreichen wäre jetzt einTypeErrorstatt eines
stillen No-ops.Geprüft: 156 passed / 14 deselected gegen die 1.x-Baseline von 152 — die
Differenz sind genau die fünf neuen Tests minus dem einen ersetzten.
ruff check src/, Coverage-Gate (96.7 % gegen 80 %) und ein Install in
einem frischen venv sind grün.
Fixed
-
Declared
mcpexplicitly and capped it at<2. This server imports
mcp.server.fastmcp, but never declaredmcp— it arrived transitively via
fastmcp.mcp2.0.0, published 2026-07-28, removed that module, and the
only reason installs still work today is an upper bound insidefastmcp-slim,
a package this project never names. The dependency that is actually imported
is now declared and bounded here rather than left to someone else's resolver. -
User-Agent no longer reports a stale version. Three numbers had drifted
apart:pyproject.tomlsaid1.0.3,__init__.__version__said0.1.0, and
the hard-codedUSER_AGENTin_http.pysaid1.0.0. Every request to the
SRG SSR APIs carried the stale value.__version__now comes from the
installed distribution metadata (importlib.metadata, generated from
pyproject.toml) and the User-Agent is derived from it. Guarded by
tests/test_version.py.