MCP EasyWeb podle skutecne specifikace: auth v2 s klicem zarizeni

Predchozi verze posilala na /login jen jmeno, heslo a nazev zarizeni. Server na
to odpovidal 400 Bad Request na cokoliv, i na spravne udaje, protoze cekal neco
uplne jineho.

EasyWeb ma auth v2: token se nevydava proti uctu, ale proti zarizeni, a to je
par klicu ECDSA P-256. Jmeno a heslo se pouziji jedinkrat, pri registraci klice,
a soucasti registrace je podpis, kterym zarizeni dokazuje, ze privatni klic
k poslanemu verejnemu opravdu ma. Od te chvile se podepisuje kazde volani, ktere
s tokeny hybe.

Overeno proti bezicimu serveru: se spravnym telem uz /login nevraci 400, ale 401
s neplatnymi udaji. Ucty z jejich testovaciho settings.json na verejnych
instancich neplati, takze dal se bez skutecnych udaju nedostanu.

Prihlaseni:
- src/mcp/easyweb/crypto.ts - klice, podpisy, otisky. Podpis musi byt P1363,
  tedy hole r||s, 64 bajtu. Node podepisuje ve vychozim nastaveni do DER a ten
  by protistrana neuznala
- src/mcp/easyweb/device.ts - klic se vyrobi jednou a prezije restart, uklada se
  mezi udaje konektoru, ktere uz jsou zasifrovane. Novy priznak `managed` na
  poli sluzby znamena, ze ho vyplnuje portal a ve formulari se nezobrazuje
- src/mcp/easyweb/session.ts - tri tokeny, retez s ustupy (platny pristupovy,
  obnova obnovovacim, obnova zarizenim, cele prihlaseni), jedno prihlaseni
  naraz na konektor, tokeny jen v pameti

Ta posledni pravidla nejsou opatrnost navic: tokeny jsou jednorazove, druhe
pouziti server odmita kodem 409 a umi zarizeni zablokovat.

Transport:
- server si sam vybira, jestli odpovi JSON telem nebo SSE streamem, a streamem
  odpovida i na obycejna volani. Klient nabizi obojí a cte stream po kouscich -
  u dlouhych uloh ho server sam nezavira
- handshake plati na token, ne na volani
- odmitnute sezeni prijde jako chyba -32008 uvnitr uspesne odpovedi
- seznamy se skladaji pres vsechny stranky, bez toho je videt jen prvni
- odpoved se rozbaluje rekurzivne (structuredContent, contents, content, JSON
  zapsany jako text)

Dlouho bezici nastroje se spousti jako uloha a ceka se na ni dotazovanim. Limit
kroku se pri tom posouva z patnacti sekund na deset minut.

Nedodelane: trvaly kanal notifikaci (GET SSE), nahravani souboru po castech
a hlidani zmen kontraktu podle verze serveru.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
JiriUhlir
2026-08-28 10:58:24 +02:00
co-authored by Claude Opus 5
parent d881dab30d
commit 4d156d2837
18 changed files with 1514 additions and 404 deletions
+65
View File
@@ -2,6 +2,71 @@
Nejnovejsi nahore.
## 2026-08-28 - MCP EasyWeb podle skutecne specifikace (auth v2)
Predchozi verze posilala na `/login` jen jmeno, heslo a nazev zarizeni. Server
na to odpovidal `400 Bad Request` na cokoliv, i na spravne udaje, protoze
**cekal neco uplne jineho**.
EasyWeb ma auth v2: token se nevydava proti uctu, ale proti **zarizeni**, a to
je pár klicu ECDSA P-256. Jmeno a heslo se pouziji jedinkrat, kdyz se klic
registruje, a soucasti registrace je podpis, kterym zarizeni dokazuje, ze
privatni klic k poslanemu verejnemu opravdu ma. Od te chvile se podepisuje
kazde volani, ktere s tokeny hybe.
Overeno proti bezicimu serveru: se spravnym telem uz `/login` nevraci 400, ale
401 s neplatnymi udaji. Ucty z jejich testovaciho `settings.json` na verejnych
instancich neplati, takze dal se bez skutecnych udaju nedostanu.
### Prihlaseni
- `src/mcp/easyweb/crypto.ts` - klice, podpisy, otisky. Podpis musi byt
**P1363**, tedy holé `r || s`, 64 bajtu. Node podepisuje ve vychozim
nastaveni do DER a ten by protistrana neuznala.
- `src/mcp/easyweb/device.ts` - klic zarizeni se vyrobi jednou a **prezije
restart**: uklada se mezi udaje konektoru, ktere uz jsou zasifrovane.
Pole ma novy priznak `managed`, takze ho ve formulari nikdo nevidi.
- `src/mcp/easyweb/session.ts` - tri tokeny, retez s ustupy
(platny pristupovy, obnova obnovovacim, obnova zarizenim, cele prihlaseni),
**jedno prihlaseni naraz na konektor**, tokeny **jen v pameti**.
Ta posledni tri pravidla nejsou opatrnost navic: tokeny jsou jednorazove, druhe
pouziti server odmita kodem 409 a **umi zarizeni zablokovat**. Dve soubezne
automatizace nad tymz napojenim by bez jedne sdilene rozdelane operace spustily
dve obnovy a druha by pracovala se spotrebovanym tokenem.
### Transport
- **Server si sam vybira, jestli odpovi JSON telem, nebo SSE streamem**, a
streamem odpovida i na obycejna volani. Klient proto nabizi obojí a cte
stream **po kouscich** - u dlouhych uloh ho server sam nezavira a posila do
nej tlukot srdce, takze cekani na konec by skoncilo az timeoutem.
- Handshake plati **na token**, ne na volani. Server drzi sezeni u tokenu.
- Odmitnute sezeni prijde jako chyba `-32008` **uvnitr uspesne odpovedi**. Bez
zvlastniho osetreni by to vypadalo jako chyba volani a krok by skoncil misto
toho, aby se prihlasil znovu.
- Seznamy se skladaji pres vsechny stranky. Bez toho je videt jen prvni, tedy
asi dvacet nastroju, a vypada to jako uplny seznam.
- Odpoved se rozbaluje rekurzivne (`structuredContent`, `contents`, `content`,
JSON zapsany jako text). Jinak by v kroku skoncil JSON jako retezec, se
kterym uz se v podmince nic nesvede.
### Dlouho bezici nastroje
Nastroj, ktery server odmitne spustit rovnou, se spusti jako **uloha** a ceka se
na ni dotazovanim. Stav z `tasks/list` a `tasks/get` je to jedine, co je vzdycky
pravda - notifikace o prubehu chodi nejvys jednou. Dokoncena uloha ze seznamu
mizi, takze po nekolika marnych kolech se prejde na primy dotaz.
Limit kroku se pri tom posouva z patnacti sekund na deset minut. Kdyz uloha
nedobehne ani tak, neni to chyba: na serveru bezi dal a krok to rekne.
### Co z toho zbylo nedodelane
Trvaly kanal notifikaci (GET SSE), nahravani souboru po castech a hlidani zmen
kontraktu podle verze serveru. Vsechno je v
[24-mcp-konektory.md](24-mcp-konektory.md) v seznamu toho, co chybi.
## 2026-08-28 - dve MCP sluzby: obecna a EasyWeb, strankovani nastroju
MCP je standard, ale **prihlaseni k nemu ne**. Oficialni specifikace stoji na