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:
co-authored by
Claude Opus 5
parent
d881dab30d
commit
4d156d2837
@@ -67,6 +67,10 @@ do stromu. Validace pri ukladani se pta katalogu, ne klienta.
|
||||
takze i cislo je text. Prevod na skutecny typ se dela az pred volanim, u toho,
|
||||
kdo vi, jaky typ to ma byt.
|
||||
|
||||
**Nektera pole konektoru vyplnuje portal, ne clovek.** Maji priznak `managed`,
|
||||
ve formulari se nezobrazuji a zapisuji se zvlast, aby zapis neshodil vysledek
|
||||
overeni. Dnes je to klic zarizeni u MCP EasyWebu.
|
||||
|
||||
**Prava se nedovozuji na klientovi.** Server vraci `GET /api/dashboard/access`
|
||||
s tim, co uzivatel smi. Dvoji vypocet se jednou rozejde.
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ React aplikaci ze slozky `dist/public`.
|
||||
| Odesilani souboru ze skriptu | hotovo | `ctx.http.postForm`, obsah jako Base64 |
|
||||
| OpenAI pod vlastnim klicem | hotovo | dotaz, soubor, prepis zvuku, seznam modelu |
|
||||
| Konektory za firmu | hotovo | pristupove udaje v konektoru, overeni napojeni |
|
||||
| MCP servery firmy | hotovo | dve sluzby: obecna podle specifikace a MCP EasyWebu |
|
||||
| MCP servery firmy | hotovo | obecna sluzba a MCP EasyWebu vcetne klice zarizeni |
|
||||
| Transformace dat | hotovo | pravidla i sablona JSON, kroky si predavaji struktury |
|
||||
| Prace nad celym modelem | hotovo | ukazka tela, cesty v sablonach, smycka nad seznamem |
|
||||
| Vlastni skripty firmy | hotovo | prevod dat v JS, v logu vstup i vystup |
|
||||
|
||||
@@ -37,12 +37,12 @@ sluzbu, ne duvod zavrit dvere ostatnim.
|
||||
|
||||
Rozdily jsou na jednom miste v `src/mcp/dialect.ts`:
|
||||
|
||||
| Vlastnost | MCP server | MCP EasyWeb |
|
||||
| ------------------------- | ------------ | ------------ |
|
||||
| prihlaseni | OAuth 2.1 | vlastni |
|
||||
| verze protokolu | `2025-06-18` | `2025-11-25` |
|
||||
| odpoved jako SSE stream | ano | ne |
|
||||
| hlavicka `Mcp-Session-Id` | ano | ne |
|
||||
| Vlastnost | MCP server | MCP EasyWeb |
|
||||
| ------------------------- | ------------ | ---------------------- |
|
||||
| prihlaseni | OAuth 2.1 | klic zarizeni, podpisy |
|
||||
| verze protokolu | `2025-06-18` | `2025-11-25` |
|
||||
| odpoved jako SSE stream | ano | ano, i na bezne volani |
|
||||
| hlavicka `Mcp-Session-Id` | ano | ne, sezeni je u tokenu |
|
||||
|
||||
Verze protokolu neni kosmetika: EasyWeb si po handshaku kontroluje, ze hlavicka
|
||||
`MCP-Protocol-Version` sedi na jeho konstantu, a jinou odmitne.
|
||||
@@ -85,23 +85,10 @@ OAuth. Kdyby slo jen jedno, cast serveru by nesla napojit vubec.
|
||||
| ------------------ | ---------------------------------------------------- |
|
||||
| Adresa MCP serveru | endpoint, napr. `https://web.firmy.cz/centaur/mcp` |
|
||||
| Jmeno | uzivatel, pod kterym se portal hlasi |
|
||||
| Heslo | portal si za nej sam vyzvedne pristup |
|
||||
| Heslo | pouzije se **jednou**, na registraci zarizeni |
|
||||
| Nazev zarizeni | pod timhle nazvem je prihlaseni videt v logu serveru |
|
||||
| Otisk zarizeni | podle nej server pozna totez zarizeni |
|
||||
|
||||
Token se nezadava a zadavat nejde. **Zakaznik dostane adresu, jmeno a heslo**,
|
||||
token vydava az server a ma omezenou zivotnost.
|
||||
|
||||
Prihlasovaci adresy si portal odvodi z adresy serveru sam:
|
||||
|
||||
| Endpoint | K cemu |
|
||||
| ----------------------------- | -------------------------------- |
|
||||
| `{server}/login` | HTTP Basic, vrati trojici tokenu |
|
||||
| `{server}/renew-access-token` | obnova pristupoveho tokenu |
|
||||
|
||||
Otisk zarizeni se doplnuje z ID konektoru (`worknuke-con_abc123`), aby server
|
||||
poznal, ze jde porad o totez zarizeni, a aby si dve napojeni tehoz portalu
|
||||
nesahala do sezeni.
|
||||
Token se nezadava a zadavat nejde. Zakaznik dostane adresu, jmeno a heslo.
|
||||
|
||||
### Adresa se u EasyWebu srovnava
|
||||
|
||||
@@ -110,51 +97,124 @@ Vlepena prihlasovaci cesta se odrizne a chybejici `/mcp` se doplni, takze
|
||||
cestu prisny - i `/mcp/login/` s lomitkem na konci vraci 404.
|
||||
|
||||
**U obecne sluzby se adresa nemeni.** Cizi server muze mit endpoint kdekoliv
|
||||
a "opravit" mu adresu podle naseho odhadu znamena rozbit napojeni, ktere by
|
||||
jinak fungovalo.
|
||||
a opravovat mu ji podle naseho odhadu znamena rozbit napojeni, ktere by jinak
|
||||
fungovalo.
|
||||
|
||||
### Kdyz server odpovi 400
|
||||
## Prihlaseni k EasyWebu
|
||||
|
||||
`400 Bad Request` z `/login` **neni chyba pozadavku u nas**. Server ho ma jako
|
||||
"malformed authorization request" a odpovida jim i na udaje, ktere neuzna.
|
||||
Overeno proti bezicimu serveru: spatne heslo, prazdne heslo i neznamy ucet
|
||||
vraceji tutez odpoved jako udaje spravne, telo je vzdycky jen `Bad Request`
|
||||
v HTML. Rozlisit se to zvenku neda, takze to hlaska rika narovinu misto toho,
|
||||
aby posilala cloveka hledat chybu v adrese.
|
||||
Nejspecifictejsi cast celeho napojeni. Stoji za to ji precist celou, protoze
|
||||
**chybny postup umi zablokovat ucet**.
|
||||
|
||||
Rozdil oproti chybejicimu prihlaseni je videt: `/login` **bez** hlavicky
|
||||
`Authorization` vraci 401, s ni uz 400.
|
||||
### Token patri zarizeni, ne uctu
|
||||
|
||||
## Prihlaseni a zivotnost tokenu
|
||||
Server nevydava token proti jmenu a heslu, ale proti **zarizeni**. Zarizeni je
|
||||
pár klicu ECDSA P-256. Jmeno a heslo se pouziji jedinkrat, kdyz se klic
|
||||
registruje. Od te chvile je identitou klic a kazde volani, ktere s tokeny hybe,
|
||||
se jim podepisuje.
|
||||
|
||||
Cely zivotni cyklus resi `src/mcp/auth.ts`. **Token je kratkodoby, jeho
|
||||
zivotnost urcuje server a hlidat ji je prace portalu.**
|
||||
| Co | Kde zije | Prezije restart |
|
||||
| --------------------- | --------------------------------- | --------------- |
|
||||
| klic zarizeni a otisk | mezi udaji konektoru, zasifrovane | ano |
|
||||
| pristupovy token | pamet procesu | ne |
|
||||
| obnovovaci token | pamet procesu | ne |
|
||||
| token zarizeni | pamet procesu | ne |
|
||||
|
||||
| Situace | Co portal udela |
|
||||
| -------------------------------- | ---------------------------------------------- |
|
||||
| token plati | pouzije ho |
|
||||
| do vyprseni zbyva min nez minuta | vymeni ho driv, nez vyprsi behem volani |
|
||||
| server vydal obnovovaci token | obnovi jim, je to levnejsi nez cele prihlaseni |
|
||||
| obnova neprojde | prihlasi se cele znovu |
|
||||
| server token odmitne pres 401 | zahodi ho a zkusi to **jednou** znovu |
|
||||
Klic **musi** prezit restart, jinak by se pri kazdem startu registrovalo nove
|
||||
zarizeni. Tokeny naopak prezit **nesmi**: po restartu uz neplati a jejich
|
||||
pouziti vypada jako pokus o zneuziti.
|
||||
|
||||
Kdy token vyprsi, se zjistuje ze tri zdroju v tomhle poradi: `expires_in`
|
||||
v sekundach, datum v odpovedi, a nakonec **`exp` z tela samotneho tokenu**.
|
||||
To posledni je pro servery, ktere zivotnost nikam nepisou, ale vydavaji JWT -
|
||||
a je to presne pripad EasyWebu. Kdyz neni ani jedno, pocita se s peti minutami,
|
||||
tedy odhaduje se dolu.
|
||||
Klic se uklada mezi udaje konektoru, protoze ty uz se ukladaji zasifrovane
|
||||
a tohle je privatni klic. Pole ma priznak `managed`, takze ho ve formulari
|
||||
nikdo nevidi ani nevyplnuje - portal si ho vyrobi sam pri prvnim prihlaseni.
|
||||
|
||||
### Podpisy
|
||||
|
||||
| Kde | Radky podpisu, spojene novym radkem |
|
||||
| --------------- | ------------------------------------------------------------------------ |
|
||||
| registrace | `CELEBRUM-MCP-KEY-REGISTRATION-V1`, jmeno, otisk, otisk klice, nonce |
|
||||
| obnova pristupu | `CELEBRUM-MCP-POP-V1`, `renew-access`, hash tokenu, nonce, ID pozadavku |
|
||||
| obnova zarizeni | `CELEBRUM-MCP-POP-V1`, `renew-refresh`, hash tokenu, nonce, ID pozadavku |
|
||||
|
||||
Podpis musi byt v tvaru **P1363**, tedy holé `r || s`, 64 bajtu. Node podepisuje
|
||||
ve vychozim nastaveni do DER a ten by protistrana neuznala. Vsechno kolem toho
|
||||
je v `src/mcp/easyweb/crypto.ts`.
|
||||
|
||||
### Retez s ustupy
|
||||
|
||||
`ensureAccess` jde odshora dolu, kazdy dalsi clanek je drazsi:
|
||||
|
||||
1. pristupovy token jeste plati (rezerva 90 sekund) - pouzije se
|
||||
2. obnova obnovovacim tokenem
|
||||
3. obnova tokenem zarizeni
|
||||
4. cele prihlaseni jmenem a heslem
|
||||
|
||||
Na 401 a 409 se pokracuje dalsim clankem, jina chyba probublá ven. **409 znamena,
|
||||
ze token uz nekdo spotreboval** - tokeny jsou jednorazove a po kazde obnove ten
|
||||
predchozi neplati. Obnovovaci token se pri kazde obnove pristupu meni, takze se
|
||||
musi ulozit oba.
|
||||
|
||||
Proto plati **jedno prihlaseni naraz na konektor**. Dve soubezne automatizace
|
||||
nad tymz napojenim by jinak spustily dve obnovy, druha by pracovala se
|
||||
spotrebovanym tokenem a server by zarizeni zablokoval. Resi to jedna sdilena
|
||||
rozdelana operace: druhy volajici pocka na vysledek prvniho.
|
||||
|
||||
### Kdyz server odpovi 400 nebo 401
|
||||
|
||||
| Kod | Co to znamena |
|
||||
| --- | ----------------------------------------------------------- |
|
||||
| 400 | telo neni v poradku, typicky chybi podpis nebo verejny klic |
|
||||
| 401 | telo je v poradku, ale server neuznal jmeno a heslo |
|
||||
|
||||
Overeno proti bezicimu serveru: **bez podpisu vraci 400 na cokoliv**, i na
|
||||
spravne jmeno a heslo, a telo odpovedi je jen `Bad Request` v HTML. Se spravnym
|
||||
telem a neplatnym uctem vraci 401. Rozdil mezi tim je to jedine, podle ceho jde
|
||||
zvenku poznat, jestli je chyba v napojeni, nebo v uctu.
|
||||
|
||||
## Zivotnost tokenu
|
||||
|
||||
U obecne sluzby resi tokeny `src/mcp/auth.ts`, u EasyWebu
|
||||
`src/mcp/easyweb/session.ts`. Spolecne plati, ze **token je kratkodoby, jeho
|
||||
zivotnost urcuje server a hlidat ji je prace portalu**.
|
||||
|
||||
| Situace | Co portal udela |
|
||||
| --------------------------------- | ------------------------------------------ |
|
||||
| token plati | pouzije ho |
|
||||
| do vyprseni zbyva min nez rezerva | vymeni ho driv, nez vyprsi behem volani |
|
||||
| server vydal obnovovaci token | obnovi jim, je to levnejsi nez prihlaseni |
|
||||
| obnova neprojde | jde o clanek niz, nakonec cele prihlaseni |
|
||||
| server odmitne token nebo sezeni | prihlasi se znovu a **jednou** to zopakuje |
|
||||
|
||||
Kdy token vyprsi, se cte z `exp` v tele JWT. EasyWeb zivotnost jinam nepise
|
||||
a pristupovy token plati zhruba pul hodiny. U obecne sluzby se driv zkusi
|
||||
`expires_in` a datum v odpovedi.
|
||||
|
||||
Odmitnuty token je na odebrana opravneni: jeste neexpiroval, ale uz neplati.
|
||||
Druhy pokus uz se nedela, to uz nejsou udaje, ktere by sedely.
|
||||
|
||||
**Token se drzi jen v pameti.** Po restartu se o novy rekne znovu. Do souboru
|
||||
ani do tabulky nepatri: ulozit kratkodoby token je vsechna rizika ulozeni bez
|
||||
jakekoliv vyhody. Kes drzi otisk udaju, takze zmena hesla ulozeny token
|
||||
zneplatni.
|
||||
Server to rekne bud kodem 401, nebo chybou `-32008` **uvnitr uspesne odpovedi**.
|
||||
To druhe by bez zvlastniho osetreni vypadalo jako chyba volani a krok by skoncil
|
||||
misto toho, aby se prihlasil znovu.
|
||||
|
||||
Zpusob prihlaseni se pise do hlasky u konektoru. Uzivatel vyplnil udaje a ma
|
||||
vedet, jak s nimi portal nalozil, nez zacne hledat chybu jinde.
|
||||
|
||||
## Handshake plati na token
|
||||
|
||||
`initialize` a po nem `notifications/initialized` se posilaji **jednou na
|
||||
token**, ne pred kazdym volanim. Server drzi sezeni u tokenu, takze po jeho
|
||||
vymene se to musi zopakovat, jinak odpovi, ze relace neni inicializovana.
|
||||
|
||||
## Odpoved muze byt stream
|
||||
|
||||
Server si sam vybira, jestli odpovi JSON telem, nebo SSE streamem, a **streamem
|
||||
odpovida i na obycejna volani**. Klient proto nabizi obojí a umi obojí precist.
|
||||
|
||||
Cte se **po kouscich a konci se u prvni skutecne odpovedi**. Server stream
|
||||
u dlouhych uloh sam nezavira a posila do nej tlukot srdce, takze cekani na
|
||||
konec by skoncilo az timeoutem. Konce radku prichazi jako CRLF a bloky se
|
||||
poznaji podle dvou novych radku, takze se to nejdriv srovna.
|
||||
|
||||
Stream, ktery skonci bez odpovedi, **neni chyba**. Server to obcas udela
|
||||
a pro krok je to prazdny vysledek.
|
||||
|
||||
## Nacteni nastroju
|
||||
|
||||
`POST /api/dashboard/connectors/{id}/mcp/tools`
|
||||
@@ -220,43 +280,80 @@ nastroj s parametrem `cursorColor` by jinak zacal delat neco jineho, nez co ma.
|
||||
V odpovedi se prijima `nextCursor`, `next_cursor` i `cursor`, bez ohledu na
|
||||
velikost pismen.
|
||||
|
||||
Strop je **20 stranek na krok**. Rozbity server muze vracet porad tentyz kurzor
|
||||
Strop je **20 stranek na krok**. Seznamy samotne (nastroje, zdroje, prompty)
|
||||
se strankuji taky a skladaji se vzdycky - bez toho je videt jen prvni stranka,
|
||||
tedy asi dvacet polozek, a vypada to jako uplny seznam. Rozbity server muze vracet porad tentyz kurzor
|
||||
a bez stropu by krok bezel, dokud ho nezastavi timeout. Kdyz se strop vycerpa
|
||||
a server porad nabizi dalsi, rekne se to v souhrnu kroku - tichy vysledek by
|
||||
vypadal jako uplny.
|
||||
|
||||
## Co krok vraci
|
||||
|
||||
Vzdy tri hodnoty, at uz nastroj deklaruje cokoliv:
|
||||
Vzdy ctyri hodnoty, at uz nastroj deklaruje cokoliv:
|
||||
|
||||
| Vystup | Co je to |
|
||||
| ------------ | ----------------------------------------------------- |
|
||||
| `text` | textova cast odpovedi |
|
||||
| `data` | rozbaleny obsah, at uz je to objekt, seznam nebo text |
|
||||
| `structured` | strukturovana cast, kdyz ji odpoved ma |
|
||||
| `isError` | nastroj rekl, ze se nepovedlo (neni to chyba spojeni) |
|
||||
| `structured` | strukturovana cast, kdyz ji nastroj ma |
|
||||
|
||||
Kdyz nastroj deklaruje `outputSchema`, jsou k tomu jeho vlastni pole rozbalena
|
||||
do vystupu, takze na ne jde postavit podminka bez psani cesty. Pri kolizi jmen
|
||||
vyhravaji ty tri spolecne: `text` znamena text odpovedi vzdycky, at uz si
|
||||
nastroj rika co chce. Vlastni pole toho jmena je porad v `structured`.
|
||||
vyhravaji ty spolecne: `text` znamena text odpovedi vzdycky, at uz si nastroj
|
||||
rika co chce. Vlastni pole toho jmena je porad v `structured`.
|
||||
|
||||
`outputSchema` je v MCP nepovinne a vetsina serveru ho nema. Pak je znamy jen
|
||||
text odpovedi. Neni to nedodelek u nas.
|
||||
### Rozbaleni
|
||||
|
||||
MCP vraci obsah zabaleny na vic zpusobu a nekdy vic vrstev pres sebe:
|
||||
|
||||
```
|
||||
{ "content": [ { "type": "text", "text": "{\"records\": [...]}" } ] }
|
||||
{ "structuredContent": { "records": [...] } }
|
||||
{ "contents": [ ... ] }
|
||||
```
|
||||
|
||||
Bez rozbaleni by v kroku skoncil JSON zapsany jako text a v podmince by se s nim
|
||||
nedalo nic delat. Rozbaluje se proto rekurzivne, prednost ma `structuredContent`
|
||||
- to je cast, kterou sam server oznacil za strukturovanou.
|
||||
|
||||
## Nastroje, ktere bezi dlouho
|
||||
|
||||
Nektere nastroje se nedaji zavolat rovnou. Server u nich obycejne volani odmitne
|
||||
a ceka, ze se spusti jako **uloha**: krok si o ni rekne, dostane jeji ID a pak
|
||||
ceka na vysledek.
|
||||
|
||||
Cekame **dotazovanim** (`tasks/list`, pak `tasks/get`), protoze stav odtud je to
|
||||
jedine, co je vzdycky pravda. Notifikace o prubehu chodi nejvys jednou a mohou
|
||||
se minout.
|
||||
|
||||
Dve veci, ktere se snadno prehlednou:
|
||||
|
||||
- **Dokoncena uloha ze seznamu mizi.** "Neni v seznamu" tedy neznamena "bezi".
|
||||
Po nekolika marnych kolech se prejde na primy dotaz, ktery zna i ulohy, ktere
|
||||
uz ze seznamu vypadly.
|
||||
- **Limit kroku se posouva.** Bezne volani ma na odpoved patnact sekund, uloha
|
||||
deset minut. Kdyby platil ten kratky, kazda uloha by skoncila timeoutem.
|
||||
|
||||
Kdyz uloha nedobehne ani do deseti minut, **neni to chyba**: na serveru bezi dal
|
||||
a krok to rekne misto toho, aby predstiral selhani.
|
||||
|
||||
## Bezpecnost a limity
|
||||
|
||||
- **Adresa nesmi mirit do vnitrni site.** Tataz kontrola jako u HTTP a SMTP,
|
||||
vyplnuje ji firma.
|
||||
- **Heslo ani token neopousti server.** Heslo se z API nevraci vubec, token
|
||||
nikde nevznika jinde nez v pameti procesu. V logu jsou zredigovane oboje.
|
||||
- **Heslo ani token neopousti server.** Heslo se z API nevraci vubec, tokeny
|
||||
nikde nevznikaji jinde nez v pameti procesu. V logu jsou zredigovane oboje.
|
||||
- **Klic zarizeni je ulozeny zasifrovane** mezi udaji konektoru, stejne jako
|
||||
ostatni tajne hodnoty.
|
||||
- **Cizi napojeni se chova jako neexistujici.** Krok si konektor nacita pres
|
||||
filtr na firmu, takze strom s cizim ID konektoru selze.
|
||||
- **Krok se neopakuje.** MCP nema idempotencni klic, takze druhy pokus po
|
||||
timeoutu by nastroj provedl podruhe - a jestli to znamena druhou objednavku,
|
||||
vi jen server, ktery neni nas.
|
||||
- Plati stejny timeout a strop na velikost odpovedi jako u skriptu
|
||||
(`SCRIPT_TIMEOUT_MS`, `SCRIPT_MAX_RESPONSE_BYTES`).
|
||||
- `tools/list` se strankuje nejvys dvacetkrat, stejne jako volani nastroje.
|
||||
- Plati stejny strop na velikost odpovedi jako u skriptu
|
||||
(`SCRIPT_MAX_RESPONSE_BYTES`), a to i u streamu, kde se pocita prubezne.
|
||||
- Seznamy se strankuji nejvys stokrat, volani nastroje dvacetkrat.
|
||||
|
||||
## Co se **nedela**
|
||||
|
||||
@@ -271,42 +368,48 @@ text odpovedi. Neni to nedodelek u nas.
|
||||
|
||||
## Kde to je
|
||||
|
||||
| Cast | Soubor |
|
||||
| ------------------- | ------------------------------------------- |
|
||||
| Rozdily serveru | `src/mcp/dialect.ts` |
|
||||
| Protokol | `src/mcp/client.ts` |
|
||||
| Prihlaseni a tokeny | `src/mcp/auth.ts` |
|
||||
| Prevod schemat | `src/mcp/schema.ts` |
|
||||
| Nastroje v katalogu | `src/data/mcpTools.ts` |
|
||||
| Obe sluzby | `src/data/services.ts` |
|
||||
| Nacteni nastroju | `src/routes/connectors.ts` |
|
||||
| Vykonna cast kroku | `src/runtime/builtinSteps.ts`, `runMcpTool` |
|
||||
| Ulozeni u konektoru | `src/data/connectors/*`, migrace `004` |
|
||||
| Portal | `web/src/pages/dashboard/Connectors.tsx` |
|
||||
| Cast | Soubor |
|
||||
| -------------------- | ------------------------------------------- |
|
||||
| Rozdily serveru | `src/mcp/dialect.ts` |
|
||||
| Protokol | `src/mcp/client.ts` |
|
||||
| Prihlaseni obecne | `src/mcp/auth.ts` |
|
||||
| Klice EasyWebu | `src/mcp/easyweb/crypto.ts` |
|
||||
| Zarizeni u konektoru | `src/mcp/easyweb/device.ts` |
|
||||
| Tokeny EasyWebu | `src/mcp/easyweb/session.ts` |
|
||||
| Prevod schemat | `src/mcp/schema.ts` |
|
||||
| Nastroje v katalogu | `src/data/mcpTools.ts` |
|
||||
| Obe sluzby | `src/data/services.ts` |
|
||||
| Nacteni nastroju | `src/routes/connectors.ts` |
|
||||
| Vykonna cast kroku | `src/runtime/builtinSteps.ts`, `runMcpTool` |
|
||||
| Ulozeni u konektoru | `src/data/connectors/*`, migrace `004` |
|
||||
| Portal | `web/src/pages/dashboard/Connectors.tsx` |
|
||||
|
||||
## Co jeste chybi
|
||||
|
||||
| Chybi | Poznamka |
|
||||
| -------------------------- | ----------------------------------------------------------------------- |
|
||||
| Zdroje a prompty | server je umi vedle nastroju, viz nize |
|
||||
| Nastroje pro model | dnes vybira nastroj clovek |
|
||||
| stdio transport | umi se jen HTTP, tedy to, co delaji servery dostupne po siti |
|
||||
| Prihlaseni s presmerovanim | authorization code vyzaduje cloveka v prohlizeci, napojeni bezi bez nej |
|
||||
| Chybi | Poznamka |
|
||||
| ---------------------------- | ----------------------------------------------------------------------- |
|
||||
| Zdroje a prompty | server je umi vedle nastroju, viz nize |
|
||||
| Trvaly kanal notifikaci | GET SSE. Prubeh uloh se zatim zjistuje dotazovanim |
|
||||
| Nahravani souboru po castech | `POST {server}/upload`, potreba u nastroju, ktere berou obrazky |
|
||||
| Hlidani zmen na serveru | verze serveru a diff seznamu, tedy upozorneni, ze se kontrakty zmenily |
|
||||
| Nastroje pro model | dnes vybira nastroj clovek |
|
||||
| stdio transport | umi se jen HTTP, tedy to, co delaji servery dostupne po siti |
|
||||
| Prihlaseni s presmerovanim | authorization code vyzaduje cloveka v prohlizeci, napojeni bezi bez nej |
|
||||
|
||||
### Zdroje a prompty
|
||||
|
||||
MCP server vedle nastroju vystavuje **zdroje** (`resources/list`,
|
||||
`resources/read`) a **prompty** (`prompts/list`, `prompts/get`). U EasyWebu to
|
||||
neni okrajova vec: cislaky jako seznam entit, metadata entity nebo seznam
|
||||
chybovych kodu jsou prave zdroje, ne nastroje.
|
||||
neni okrajova vec: seznam entit, schema entity, chybove kody i samotne
|
||||
objednavky se ctou jako zdroje, ne jako nastroje.
|
||||
|
||||
Do kroku automatizace se to hodi - "precti zdroj a pouzij hodnotu" je totez co
|
||||
ciselnik. Neni to udelane, protoze zdroje maji URI sablonu misto schematu
|
||||
argumentu, takze prevod na pole kroku je jina uloha nez u nastroju. Zdroje umi
|
||||
navic vlastni strankovani po cislech stranek, ne kurzorem.
|
||||
ciselnik. Neni to udelane, protoze zdroj ma URI sablonu misto schematu
|
||||
argumentu, takze prevod na pole kroku je jina uloha nez u nastroju. Navic se
|
||||
u nich query sklada rucne: datumy jsou ISO s dvojteckami a bezne kodovani by je
|
||||
prepsalo tak, ze by filtr tise nefungoval.
|
||||
|
||||
### Nastroje pro model
|
||||
|
||||
Az bude krok "nechat model splnit ukol", muze dostat nastroje serveru jako sve
|
||||
schopnosti a vybirat si sam. Cely klient uz na to je, chybi to napojeni na
|
||||
model.
|
||||
schopnosti a vybirat si sam. Cely klient uz na to je, chybi napojeni na model.
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user