Navrh MCP konektoru

Neni to naprogramovane, je to navrh: documentation/24-mcp-konektory.md.

Podstata problemu: MCP server je katalog operaci, ktery se zepta az za behu,
kdezto nas katalog je znamy pri prekladu. Retezec service.actions ->
findOperation -> scriptIdFor se dnes cely pta statickeho katalogu, takze by
slo pouzit jen nastroj, ktery uz nekdo predem zapsal do kodu - presny opak
toho, o co jde.

Navrh: jedna sluzba mcp a kazdy server jako konektor pod ni. Nastroje se
doplni do katalogu pres withRuntimeOptions, tedy tim samym zpusobem, jakym uz
se doplnuji resitele, skupiny a typy ticketu. Schema vstupu se prevede
z JSON Schema na OperationField, co se neprevede skonci jako json.

Jen Streamable HTTP, ne stdio: stdio by znamenalo pustit zakaznikuv program
uvnitr naseho containeru. Adresa projde stejnou kontrolou vnitrni site jako
HTTP a SMTP. Idempotence u MCP nefunguje, proto by se krok neopakoval sam.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
JiriUhlir
2026-08-28 09:09:28 +02:00
co-authored by Claude Opus 5
parent e1c52e3da3
commit 2d38ac1350
2 changed files with 186 additions and 0 deletions
+172
View File
@@ -0,0 +1,172 @@
# 24 - MCP konektory
Navrh, neni naprogramovane.
Cil: firma si vyplni udaje sveho MCP serveru a jeho nastroje se objevi
v builderu jako kterakoliv jina operace.
## Co je MCP z pohledu tohohle systemu
MCP server je **katalog operaci, ktery se zepta az za behu**. Rekne "umim
`create_invoice`, `search_customer`, `send_report`", ke kazde da popis a schema
vstupu, a pak je umi vykonat.
To je presne to, co u nas dela `src/data/services.ts` plus slozka `scripts/`.
Rozdil je v jedine veci, a ta rozhoduje o celem navrhu:
| Dnes | MCP |
| ----------------------------------- | ----------------------------------------- |
| Operace jsou zname pri prekladu | Operace se zjisti az od serveru |
| Katalog je stejny pro vsechny firmy | Kazda firma ma jiny server, jine nastroje |
| Skript je nas, prosel code review | Nastroj je zakaznikuv, nevidime do nej |
## Kde to narazi
Retezec od builderu k behu je dnes tenhle:
```
StepPicker -> service.actions (co nabidnout)
ulozeni -> findOperation(...) (existuje ta operace?)
beh -> scriptIdFor(...) (kdo to vykona)
```
Vsechny tri se ptaji **statickeho katalogu**. U MCP zadny staticky katalog
neni: seznam operaci patri konektoru, ne sluzbe. Bez zmeny by slo ulozit jen
krok, ktery uz nekdo predem zapsal do kodu, coz je presny opak toho, o co jde.
## Navrh: jedna sluzba, operace z konektoru
**Ne sluzba na kazdy MCP server.** Sluzby jsou kod a zakaznik si je nezalozi.
Misto toho jedna sluzba `mcp` a kazdy server je **konektor** pod ni:
```
Sluzba "MCP server" definujeme my, jednou
| credentials: adresa, token, nazev
|
+-- Konektor "Interni sklad" zaklada si firma
| tools: create_order, get_stock, ... zjisteno od serveru
|
+-- Konektor "Firemni wiki" jiny server, jine nastroje
```
Krok stromu pak nese `serviceId: 'mcp'`, `operationId: '<nazev nastroje>'`
a `connectorId`. Ten treti udaj je u MCP **povinny**, na rozdil od ostatnich
sluzeb: bez nej neni jasne, ktery server se pta, a dva konektory mohou mit
nastroj stejneho jmena.
### Kudy se nastroje dostanou do builderu
Katalog uz umi doplnit nabidku az za behu. `withRuntimeOptions` presne tohle
dela pro resitele, skupiny a typy ticketu - hodnoty, ktere v dobe prekladu
neexistuji. Nastroje MCP jsou tentyz pripad, jen misto polozek vyberu doplni
cele operace.
Schema vstupu prijde jako JSON Schema a prevede se na `OperationField`, tedy
tvar, ktery builder uz umi vykreslit. Prevod je primocary u toho, co se
v praxi pouziva:
| JSON Schema | `OperationField` |
| ----------------------- | -------------------- |
| `string` | `text` |
| `string` s `enum` | `choice` s `options` |
| `string` a dlouhy popis | `longtext` |
| `number`, `integer` | `text` s kontrolou |
| `boolean` | `choice` ano/ne |
| `object`, `array` | `json` |
Co se neprevede, skonci jako `json`. Radsi pole, do ktereho clovek napise
strukturu rucne, nez pole, ktere tvari, ze rozumi necemu, cemu nerozumi.
### Kdo to vykona
Jeden skript `mcp.call-tool` pro vsechny nastroje. Nazev nastroje je vstup,
ne soubor. Psat skript na kazdy nastroj nejde - nevznikaji u nas.
## Co si firma vyplni
| Pole | K cemu |
| ----------------- | -------------------------------------------------- |
| Nazev | co clovek uvidi v builderu, napr. "Interni sklad" |
| Adresa serveru | HTTPS adresa MCP endpointu |
| Token | tajny, posila se jako `Authorization: Bearer` |
| Vlastni hlavicka | pro servery, ktere chteji neco jineho nez Bearer |
| Povolene nastroje | prazdne = vsechny. Jinak vycet, ktery se smi volat |
Posledni radek neni ozdoba. MCP server muze zpristupnit i nastroje, ktere do
automatizace nepatri (mazani, sprava uctu). Vycet je jednodussi nez vysvetlovat
lidem, ktere nastroje nepouzivat.
## Jen HTTP, ne stdio
MCP zna dva prenosy. `stdio` spousti server jako lokalni proces - to u nas
nepripada v uvahu: znamenalo by to pustit zakaznikuv program uvnitr naseho
containeru, a to je jina trida rizika nez zavolat cizi API.
Zustava **Streamable HTTP**, tedy JSON-RPC pres POST. To `ctx.http` umi uz ted,
takze skript nepotrebuje zadny novy pristup k siti.
Adresa serveru projde stejnou kontrolou jako u HTTP a SMTP: **nesmi mirit do
vnitrni site** (`isPrivateHost`). Vyplnuje ji firma, takze je to jedina zabrana
proti tomu, aby si nechala zavolat na neco uvnitr.
## Overeni konektoru
`tools/list`. Je to cteci volani, vyzaduje autorizaci a jeho vysledek se stejne
potrebuje - takze overeni a zjisteni nastroju je jedno volani, ne dve.
Vysledek se ulozi ke konektoru a **necte se pri kazdem otevreni builderu**.
Seznam nastroju se meni radove pri nasazeni serveru, ne mezi dvema kliknutimi.
Obnovi se pri overeni konektoru a tlacitkem "Nacist nastroje znovu".
## Co se stane, kdyz nastroj zmizi
Ulozeny strom odkazuje na nastroj jmenem. Server se nasadi znovu, nastroj se
prejmenuje a krok ukazuje do prazdna.
Nesmi to byt chyba ulozeni. Strom uz ulozeny je a firma za to nemuze:
| Situace | Vysledek |
| ---------------------------------------- | ----------------------------------------- |
| Nastroj v ulozenem seznamu neni | **nedodelek**, jako chybejici konektor |
| Server je nedostupny pri ukladani stromu | ulozit, validovat proti ulozenemu seznamu |
| Nastroj chybi az pri behu | koncova chyba, neopakovat |
Rozdil proti dnesku: u naseho skriptu je chybejici operace nase chyba, tady je
to bezna zmena na cizi strane.
## Bezpecnost
- **Do logu jde odpoved nastroje.** Prochazi stejnou redakci jako vsechno
ostatni, ale token do ni patri jen ten nas - co si server pise do odpovedi,
neovlivnime. Stoji za to pri prvnim nasazeni kouknout, co vraci.
- **Strop na velikost odpovedi** uz existuje (`SCRIPT_MAX_RESPONSE_BYTES`).
U MCP je potreba: nastroj muze vratit cely dokument.
- **Idempotence nefunguje.** Nas `Idempotency-Key` je hlavicka, ktere MCP
nerozumi. Druhy pokus po timeoutu tedy nastroj zavola podruhe. U ctecich
nastroju to nevadi, u zapisovych ano - proto se u kroku s MCP **neopakuje
automaticky**, dokud nebude jak rict, ze je nastroj bezpecny opakovat.
- **Nastroj je zakaznikuv.** Nevidime do nej a neruceme za to, co udela. To je
rozdil proti nasim skriptum a musi to byt videt i v portalu.
## Postup
| Faze | Co |
| ---- | -------------------------------------------------------------------------- |
| 1 | Sluzba `mcp`, pole konektoru, overeni pres `tools/list`, ulozeni seznamu |
| 2 | Nastroje do katalogu pres `withRuntimeOptions`, prevod JSON Schema na pole |
| 3 | Skript `mcp.call-tool` a vykonani ve strome |
| 4 | Vycet povolenych nastroju, tlacitko na obnoveni seznamu |
Prvni faze je uzitecna sama o sobe: firma si napojeni zalozi a overi, i kdyz
se jeste neda pouzit v kroku.
## Co bych nedelal
- **Nezpristupnoval bych MCP zdroje a prompty.** Server umi vedle nastroju
i `resources` a `prompts`. Do stromu kroku patri akce, ne cteni dokumentu -
a bez toho je model o polovinu jednodussi.
- **Nedelal bych z nas MCP server.** Zajimava vec, ale je to opacny smer:
pustit cizi modely na nase tickety je jine rozhodnuti nez zavolat cizi
nastroj.
- **Nespoustel bych nastroje bez konektoru.** Zadny "rychly test adresou" -
napojeni je vlastnost firmy a ma jednu cestu.
+14
View File
@@ -2,6 +2,20 @@
Nejnovejsi nahore.
## 2026-08-28 - navrh MCP konektoru
Novy dokument [24-mcp-konektory.md](24-mcp-konektory.md). Neni to
naprogramovane, je to navrh.
Podstata: MCP server je katalog operaci, ktery se zepta az za behu, kdezto nas
katalog je znamy pri prekladu. Retezec `service.actions` -> `findOperation`
-> `scriptIdFor` se dnes cely pta statickeho katalogu, takze by slo pouzit jen
nastroj, ktery uz nekdo predem zapsal do kodu - presny opak toho, o co jde.
Navrh je **jedna sluzba `mcp` a kazdy server jako konektor pod ni**, s nastroji
doplnenymi do katalogu pres `withRuntimeOptions`, tedy tim samym zpusobem, jakym
uz se doplnuji resitele a typy ticketu. Jen HTTP, ne stdio.
## 2026-08-28 - transformace maji svou kategorii, pribylo XML
### Odstraneno