Dve MCP sluzby: obecna podle specifikace a MCP EasyWeb, strankovani nastroju

MCP je standard, ale prihlaseni k nemu ne. Oficialni specifikace stoji na
OAuth 2.1 a objevovani autorizacniho serveru pres .well-known. EasyWeb
(Centaur) ma prihlaseni vlastni: POST /login s HTTP Basic vrati trojici tokenu
a obnovuje se vlastnimi endpointy. Zadny OAuth, zadne .well-known, jina verze
protokolu, zadne SSE ani hlavicka sezeni.

Proto dve sluzby, ne jedna s prepinacem: firma pri zakladani konektoru
vyplnuje neco jineho. U obecne ID a tajemstvi aplikace nebo hotovy token,
u EasyWebu jmeno, heslo a nazev zarizeni. Slucovat to by znamenalo formular,
kde je pulka poli vzdycky k nicemu, a hadani, ktera pulka to prave je.

Obecna sluzba zustava plnohodnotna. Vlastni server je duvod pridat sluzbu, ne
duvod zavrit dvere ostatnim.

Pribylo:
- src/mcp/dialect.ts - rozdily obou serveru na jednom miste: prihlaseni, verze
  protokolu, jestli se prijima SSE a jestli se posila Mcp-Session-Id. Rozesete
  po klientovi by u kazdeho dalsiho serveru pribyl dalsi if na jinem miste
- sluzba MCP EasyWeb: adresa, jmeno, heslo, nazev a otisk zarizeni.
  Prihlasovaci adresy si portal odvodi sam, otisk doplni z ID konektoru
- hotovy token u obecne sluzby. Rada verejnych serveru nic jineho nenabizi
- objevovani pres WWW-Authenticate, coz specifikace ma jako povinnou cestu.
  Pouziva se az kdyz obvykla mista selzou, stoji to volani navic
- zivotnost z tela tokenu: kdyz server expires_in ani datum neposle, cte se
  exp z JWT. Presne pripad EasyWebu
- strankovani nastroju: nastroj s parametrem cursor dostane v builderu prepinac
  Nacist vsechny stranky. Kurzor je hodnota z odpovedi, takze v dobe stavby
  stromu ho nikdo nezna a nejde ho vyplnit dopredu. Krok pak vraci navic items,
  pages, pageCount a truncated. Strop je 20 stranek

Opraveno: prihlaseni driv zkousela password grant a HTTP Basic proti hlavnimu
endpointu. Prvni OAuth 2.1 zrusil, druhe neni nikde ve specifikaci a u EasyWebu
by stejne neproslo - ten chce Basic na /login, ne na /mcp.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
JiriUhlir
2026-08-28 10:13:33 +02:00
co-authored by Claude Opus 5
parent 92fecca70c
commit 81e4348ad8
14 changed files with 1006 additions and 352 deletions
+3
View File
@@ -109,6 +109,9 @@ jedne firme**, protoze ho vystavuje jeji server. Proto s sebou nese `tenantId`
a `serviceCatalog(tenantId)` bez firmy nevrati zadny. Zapomenuty argument tak
znamena "nic", ne "vsechno" - stejne pravidlo jako u filtru na firmu.
Sluzby s nastroji jsou dve (obecna a EasyWeb), takze se filtruje i podle
sluzby. Nastroje jednoho serveru nemaji co delat v katalogu toho druheho.
U MCP navic **ID operace nese ID konektoru** (`tool:con_a1b2:create_order`).
Firma muze mit dva servery a na obou nastroj `search`; kdyby ID bylo jen
`search`, krok by nemel jak rict, ktery z nich. U ostatnich sluzeb to nehrozi,
+1 -1
View File
@@ -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 | nacte nastroje ze serveru, kazdy je krok automatizace |
| MCP servery firmy | hotovo | dve sluzby: obecna podle specifikace a MCP EasyWebu |
| 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 |
+10 -6
View File
@@ -57,13 +57,17 @@ Nazev promenne vznikne z ID sluzby velkymi pismeny, pomlcka je podtrzitko:
Treti pripad jsou sluzby, ktere **nejdou pres HTTP tak jako zbytek**. Rika to
pole `transport`:
| `transport` | Sluzba | Cim se lisi |
| ----------- | ---------- | -------------------------------------------------------------- |
| `http` | vetsina | vychozi, skript rekne cestu a runtime doplni adresu a hlavicky |
| `smtp` | E-mail | neni to HTTP, operaci vykona vnitrni krok |
| `mcp` | MCP server | JSON-RPC se sezenim, a hlavne **zadne operace v katalogu** |
| `transport` | Sluzba | Cim se lisi |
| ----------- | ----------------------- | -------------------------------------------------------------- |
| `http` | vetsina | vychozi, skript rekne cestu a runtime doplni adresu a hlavicky |
| `smtp` | E-mail | neni to HTTP, operaci vykona vnitrni krok |
| `mcp` | MCP server, MCP EasyWeb | JSON-RPC se sezenim, a hlavne **zadne operace v katalogu** |
U obou nevychozich nese adresu serveru **konektor mezi udaji**, ne pole "vlastni
Sluzby s `transport: 'mcp'` jsou dve, protoze prihlaseni k MCP standardizovane
neni: obecna podle specifikace a EasyWeb s vlastnim prihlasenim. Podrobnosti
v [24-mcp-konektory.md](24-mcp-konektory.md).
U vsech nevychozich nese adresu serveru **konektor mezi udaji**, ne pole "vlastni
adresa sluzby": sluzba zadnou vlastni adresu nema, protoze kazda firma ma svuj
server. Podrobnosti v [21-realne-sluzby.md](21-realne-sluzby.md)
a [24-mcp-konektory.md](24-mcp-konektory.md).
+156 -74
View File
@@ -1,6 +1,6 @@
# 24 - MCP konektory
Hotovo. Firma si zalozi napojeni na svuj MCP server, stiskne **Nacist nastroje**
Hotovo. Firma si zalozi napojeni na MCP server, stiskne **Nacist nastroje**
a jeho nastroje se objevi v builderu jako kroky automatizace.
## Co MCP je
@@ -11,14 +11,46 @@ toho, co prijima a co vraci. Klient si o ne rekne (`tools/list`) a pak je vola
(`tools/call`).
Bezne je klientem model - dostane nastroje jako sve schopnosti a sam si vybira,
ktery zavolat. **My jsme klientem taky, jen si nastroj vybira clovek v
builderu.** Prinos je tentyz: napojeni na cizi system vznikne bez radky kodu
ktery zavolat. **My jsme klientem taky, jen si nastroj vybira clovek
v builderu.** Prinos je tentyz: napojeni na cizi system vznikne bez radky kodu
u nas.
## Dve sluzby, ne jedna
| Sluzba | Pro co |
| --------------- | -------------------------------------------- |
| **MCP server** | libovolny server podle oficialni specifikace |
| **MCP EasyWeb** | server EasyWebu, tedy Centaur |
MCP je standard, ale **prihlaseni k nemu ne**. Oficialni specifikace stoji na
OAuth 2.1 vcetne objevovani autorizacniho serveru pres `.well-known`. EasyWeb
ma prihlaseni vlastni: `POST /login` s HTTP Basic vrati trojici tokenu a ty se
obnovuji vlastnimi endpointy. Zadny OAuth, zadne `.well-known`.
Proc dve sluzby a ne jedna s prepinacem: **firma vyplnuje neco jineho**.
U oficialni ID a tajemstvi aplikace nebo hotovy token, u EasyWebu jmeno, heslo
a nazev zarizeni. Hadat to z adresy nejde a nabidnout obojí najednou by
znamenalo formular, kde je pulka poli vzdycky k nicemu.
Obecna sluzba pritom **zustava plnohodnotna**. Vlastni server je duvod pridat
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 |
Verze protokolu neni kosmetika: EasyWeb si po handshaku kontroluje, ze hlavicka
`MCP-Protocol-Version` sedi na jeho konstantu, a jinou odmitne.
## Jak to vypada
1. Konektory, Novy konektor, sluzba **MCP server**.
2. Vyplni se adresa serveru, jmeno a heslo.
1. Konektory, Novy konektor, sluzba **MCP server** nebo **MCP EasyWeb**.
2. Vyplni se adresa a prihlasovaci udaje.
3. Tlacitko **Nacist nastroje**. Portal se serveru zepta, co nabizi.
4. V builderu jsou nastroje jako kroky, s vlastnimi poli a vystupy.
@@ -27,64 +59,87 @@ popis, jake parametry prijima (povinne s hvezdickou) a jake hodnoty vraci.
## Co si firma vyplni
Zakaznik dostane ke svemu serveru **adresu, jmeno a heslo**. Token nedostane
a nema jak ho ziskat - vyda ho az autorizacni server a ma omezenou zivotnost.
Obstarat ho, hlidat platnost a vcas ho obnovit je proto prace portalu.
| Pole | K cemu |
| --------------------- | -------------------------------------------------------- |
| Adresa MCP serveru | cely endpoint, napr. `https://mcp.firma.cz/mcp` |
| Jmeno | jmeno nebo ID aplikace, prazdne u serveru bez prihlaseni |
| Heslo | heslo nebo tajny klic k tomu jmenu |
| Adresa pro prihlaseni | jen kdyz ji portal sam nenajde |
| Rozsah opravneni | jen kdyz ji provozovatel serveru rekl |
Adresa je **mezi udaji**, ne v poli "vlastni adresa sluzby". U ostatnich sluzeb
je adresa vlastnost sluzby a konektor ji smi jen prepsat, tady je to naopak:
sluzba zadnou adresu nema, protoze kazda firma ma svuj server. Stejne to ma
Adresa je u obou **mezi udaji**, ne v poli "vlastni adresa sluzby". U ostatnich
sluzeb je adresa vlastnost sluzby a konektor ji smi jen prepsat, tady je to
naopak: sluzba zadnou adresu nema, kazda firma ma svuj server. Stejne to ma
SMTP.
### MCP server
| Pole | K cemu |
| --------------------- | ----------------------------------------------- |
| Adresa MCP serveru | cely endpoint, napr. `https://mcp.firma.cz/mcp` |
| Token | kdyz jste dostali hotovy token |
| ID aplikace | druha moznost: server ma OAuth |
| Tajemstvi aplikace | patri k ID aplikace |
| Adresa pro prihlaseni | jen kdyz ji portal sam nenajde |
| Rozsah opravneni | jen kdyz ji provozovatel rekl |
Ctyri pole na prihlaseni vypadaji jako moc, ale kazde je jina realna situace.
Verejne servery vydavaji hotovy token a nic jineho neumi, firemni jedou na
OAuth. Kdyby slo jen jedno, cast serveru by nesla napojit vubec.
### MCP EasyWeb
| Pole | K cemu |
| ------------------ | ---------------------------------------------------- |
| 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 |
| 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.
## Prihlaseni a zivotnost tokenu
Cely zivotni cyklus tokenu resi `src/mcp/auth.ts`. Postup je vzdy stejny:
1. **Kde se prihlasit.** Bud je adresa vyplnena u konektoru, nebo se zjisti od
serveru: `/.well-known/oauth-protected-resource` rekne, ktery autorizacni
server za nim stoji, a jeho metadata rikaji token endpoint.
2. **Cim se prihlasit.** Nejdriv `client_credentials`, tedy jmeno a heslo jako
identita aplikace. Kdyz to server odmitne, zkusi se `password`, tedy jmeno
a heslo jako uzivatel. Ktere z toho firma dostala, se z udaju samych poznat
neda a nutit ji to vybirat by znamenalo ptat se na neco, co nevi.
3. **Kdyz autorizacni server neni**, posle se HTTP Basic. Mensi servery zadny
OAuth nemaji a jmeno s heslem je u nich presne tohle.
Ktera z cest to byla, se pise do hlasky u konektoru: uzivatel vyplnil jmeno
a heslo a ma vedet, jak s nimi portal nalozil, nez zacne hledat chybu jinde.
Zivotnost urcuje server:
Cely zivotni cyklus resi `src/mcp/auth.ts`. **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 minuta | vymeni ho driv, nez vyprsi behem volani |
| server poslal `refresh_token` | obnovi jim, je to levnejsi nez cele prihlaseni |
| `expires_in` server neuvedl | pocita s peti minutami, tedy odhaduje dolu |
| 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 |
To posledni je na odebrana opravneni: token jeste neexpiroval, ale uz neplati.
Druhy pokus uz se nedela - to uz nejsou udaje, ktere by sedely.
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.
**Token se drzi jen v pameti.** Je kratkodoby, takze po restartu se o novy rekne
znovu. Do souboru ani do tabulky nepatri: ulozit kratkodoby token je vsechna
rizika ulozeni bez jakekoliv vyhody.
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.
Zpusob prihlaseni se pise do hlasky u konektoru. Uzivatel vyplnil udaje a ma
vedet, jak s nimi portal nalozil, nez zacne hledat chybu jinde.
## Nacteni nastroju
`POST /api/dashboard/connectors/{id}/mcp/tools`
Je to zaroven **overeni konektoru**, proto se zapisuje do historie: kdyz server
odpovi seznamem, adresa i prihlaseni sedi. Nic to nemeni, da se to spustit kdykoliv.
Tlacitko "Overit" u MCP konektoru neni - delalo by presne tohle.
odpovi seznamem, adresa i prihlaseni sedi. Nic to nemeni, da se to spustit
kdykoliv. Tlacitko "Overit" u MCP konektoru neni, delalo by presne tohle.
Dve pravidla, ktera nejsou zrejma:
@@ -117,6 +172,37 @@ spadne az uvnitr nastroje, kde uz neni poznat, co se stalo.
Nepovinne pole, ktere zustane prazdne, **se serveru vubec neposle**. Prazdny
retezec neni totez jako nevyplneno - pretisknul by vychozi hodnotu serveru.
## Strankovani nastroju
Nastroj muze vracet data po strankach: v odpovedi je kurzor na dalsi a ten se
posle zpatky v argumentu. Vzorem je `db/search` v EasyWebu, ktery ma `limit`
a `cursor` a vraci `NextCursor`.
Kurzor je hodnota z odpovedi, takze **v dobe stavby stromu ho nikdo nezna**
a nejde ho vyplnit dopredu. Nastroj, ktery ma parametr `cursor`, proto dostane
v builderu prepinac **Nacist vsechny stranky** navic. Zapnuty projde stranky za
sebou a vysledky spoji.
K obvyklym vystupum pak pribydou:
| Vystup | Co je to |
| ----------- | -------------------------------------------- |
| `items` | polozky ze vsech stranek za sebou |
| `pages` | jednotlive stranky tak, jak prisly |
| `pageCount` | kolik stranek se nacetlo |
| `truncated` | true = strop vycerpan a server nabizel dalsi |
Pozna se to podle jmena, protoze JSON Schema nema jak rict "tohle je kurzor".
Je to dohoda, ne standard, takze se hleda **presne `cursor`** a nic jineho -
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
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:
@@ -140,10 +226,7 @@ text odpovedi. Neni to nedodelek u nas.
- **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,
vcetne tvaru bez slova `Bearer`.
- **Zmena hesla zneplatni ulozeny token.** Kes si drzi otisk udaju, takze po
uprave konektoru se portal prihlasi znovu.
nikde nevznika jinde nez v pameti procesu. V logu jsou zredigovane oboje.
- **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
@@ -151,8 +234,7 @@ text odpovedi. Neni to nedodelek u nas.
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. Server, ktery vraci porad tentyz
kurzor, by jinak cyklil donekonecna.
- `tools/list` se strankuje nejvys dvacetkrat, stejne jako volani nastroje.
## Co se **nedela**
@@ -162,8 +244,6 @@ text odpovedi. Neni to nedodelek u nas.
- **Zmena udaju nastroje nemaze.** Jina adresa muze vratit jiny seznam, ale
dokud ho nekdo nenacte, jsou ty stare porad to jedine, co v ulozenych
automatizacich drzi kroky nazivu.
- **`resources` a `prompts` se nectou.** Server je umi vedle nastroju, ale krok
stromu ma neco udelat, ne cist dokumenty.
- **Nejsme MCP server.** Je to opacny smer a jine rozhodnuti: pustit cizi
modely na nase tickety.
@@ -171,11 +251,12 @@ text odpovedi. Neni to nedodelek u nas.
| 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` |
| Sluzba `mcp` | `src/data/services.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` |
@@ -183,26 +264,27 @@ text odpovedi. Neni to nedodelek u nas.
## Co jeste chybi
| Chybi | Poznamka |
| ---------------------------- | ----------------------------------------------------------------------- |
| Nastroje pro model | dnes vybira nastroj clovek. Predat je modelu je dalsi krok, viz nize |
| stdio a starsi SSE transport | umi se jen Streamable HTTP, tedy to, co delaji verejne servery |
| Schvalovani volani | server ho umi vyzadovat, my na to zatim neumime cekat |
| 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 |
| 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.
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.
### Nastroje pro model
Az bude krok "nechat model splnit ukol", muze dostat nastroje MCP serveru jako
sve schopnosti a vybirat si sam. Dve cesty, lisi se tim, kudy tece token:
- **Server preda modelu OpenAI.** Malo prace (`{"type": "mcp", ...}` v Responses
API), ale token jde do OpenAI, ta vola server firmy primo, server musi byt
dostupny z jeji site a volani nejdou pres nas log.
- **Klientem zustaneme my.** Nastroje se modelu predaji jako obycejne funkce
a volame je my. Token zustava u nas, plati nase stropy a redakce, funguje to
s jakymkoliv modelem - a hlavne uz je to postavene, tenhle dokument je presne
o tom.
Druha cesta je uz z devadesati procent hotova. Prvni by znamenala poslat
zakaznikuv token treti strane, coz je proti tomu, jak je postaveny zbytek
systemu.
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.
+42
View File
@@ -2,6 +2,48 @@
Nejnovejsi nahore.
## 2026-08-28 - dve MCP sluzby: obecna a EasyWeb, strankovani nastroju
MCP je standard, ale **prihlaseni k nemu ne**. Oficialni specifikace stoji na
OAuth 2.1 a objevovani autorizacniho serveru pres `.well-known`. EasyWeb
(Centaur) ma prihlaseni vlastni: `POST /login` s HTTP Basic vrati trojici tokenu
a obnovuje se vlastnimi endpointy. Zadny OAuth, zadne `.well-known`, jina verze
protokolu, zadne SSE ani hlavicka sezeni.
Proto jsou v katalogu **dve sluzby**, ne jedna s prepinacem: firma pri zakladani
konektoru vyplnuje neco jineho. U obecne ID a tajemstvi aplikace nebo hotovy
token, u EasyWebu jmeno, heslo a nazev zarizeni. Slucovat to by znamenalo
formular, kde je pulka poli vzdycky k nicemu, a hadani, ktera pulka to je.
Obecna sluzba pritom **zustava plnohodnotna**. Vlastni server je duvod pridat
sluzbu, ne duvod zavrit dvere ostatnim.
### Pribylo
- `src/mcp/dialect.ts` - rozdily obou serveru na jednom miste: prihlaseni,
verze protokolu, jestli se prijima SSE a jestli se posila `Mcp-Session-Id`.
Rozesete po klientovi by u kazdeho dalsiho serveru pribyl dalsi `if` jinde.
- **Sluzba MCP EasyWeb.** Adresa, jmeno, heslo, nazev a otisk zarizeni.
Prihlasovaci adresy si portal odvodi z adresy serveru sam. Otisk se doplnuje
z ID konektoru, aby server poznal totez zarizeni.
- **Hotovy token u obecne sluzby.** Rada verejnych serveru nic jineho nenabizi
a bez toho by na ne neslo zalozit konektor.
- **Objevovani pres `WWW-Authenticate`.** Specifikace to ma jako povinnou cestu:
server u odpovedi 401 rekne, kde jsou jeho metadata. Pouziva se az kdyz obvykla
mista selzou, protoze to stoji volani navic.
- **Zivotnost z tela tokenu.** Kdyz server `expires_in` ani datum neposle, cte se
`exp` z JWT. To je presne pripad EasyWebu.
- **Strankovani nastroju.** Nastroj s parametrem `cursor` dostane v builderu
prepinac Nacist vsechny stranky. Kurzor je hodnota z odpovedi, takze v dobe
stavby stromu ho nikdo nezna a nejde ho vyplnit dopredu. Krok pak vraci navic
`items`, `pages`, `pageCount` a `truncated`. Strop je 20 stranek.
### Opraveno
Prihlaseni driv zkousela `password` grant a HTTP Basic proti hlavnimu endpointu.
Prvni OAuth 2.1 zrusil, druhe neni nikde ve specifikaci a u EasyWebu by stejne
neproslo - ten chce Basic na `/login`, ne na `/mcp`.
## 2026-08-28 - MCP: prihlaseni jmenem a heslem, tokeny si resi portal
Predchozi verze chtela po uzivateli token. To bylo spatne zadani: zakaznik