Přeskočit na obsah

Tato stránka byla automaticky přeložena z angličtiny, jediného jazyka, ve kterém se tento web píše. Číst originál.

MCP neříká nic, co neříká jeho schopnost

MCP neříká nic, co neříká jeho schopnost

majordomus://adr/adr-0110navrženo architekturamcpprojectionscapabilitiesbezpečnost

odkazuje na

  • put_in_force apps/majordomus-cli/src/capability/builtin/mcp.rs (soubor)
  • put_in_force apps/majordomus-cli/src/capability/model.rs (soubor)
  • put_in_force apps/majordomus-cli/src/cockpit/mcp.rs (soubor)
  • put_in_force apps/majordomus-cli/src/mcp/protocol.rs (soubor)
  • put_in_force adr-0004
  • put_in_force adr-0040
  • put_in_force docs/MCP.md (dokument)
  • put_in_force project.interfaces-are-projections@1
  • put_in_force project.operation-transport-parity@1
  • put_in_force apps/majordomus-cli/tests/mcp_prose.rs (test)

odkazuje na něj

Nic ve vrstvě to nejmenuje. Zpětné odkazy se odvozují, takže prázdný seznam je odpověď, ne opomenutí.

110. MCP neříká nic, co neříká jeho schopnost

Kontext

ADR 0004 udělalo z každého rozhraní projekci jednoho registru a u dvou věcí, které klient MCP vypisuje, to drželo z konstrukce: tools/list a resources/list se staví procházením registru, takže nástroj nemůže existovat bez schopnosti a schopnost, která nástroj deklaruje, ho nemůže nemít. tools/call, trasa HTTP a příkazová řádka dosahují jednoho executoru a jednoho handleru; neexistuje větev, kterou by šlo jen MCP.

To, co projekce o nástroji říkala, byla jiná věc. Změřeno na stromu, vůči kterému bylo toto rozhodnutí psáno (v0.14.0, 166 nástrojů):

  • Tři ze čtyř anotací nástroje byly v kódu protokolu konstanty: destructiveHint: false, idempotentHint: true, openWorldHint: false. V den, kdy vznikly, platily pro každý nástroj. Od ADR 0040 tři nástroje zapisují do repozitáře — jeden z nich maže soubory — a přesto byl každý klientovi stále oznamován jako neschopný cokoli zničit a bezpečný k opakování. Instrukce initialize se podařilo přimět, aby svou větu o zapisovatelích odvozovaly; anotace vedle nich ne.
  • Odmítnutí dorazilo ke klientovi MCP jako věta. HTTP projekce téhož handleru odpověděla invalid_input, not_found nebo refused jako slovem; klient MCP musel text parsovat, aby zjistil, které z nich.
  • Příručka, komentář modulu, dokumentační komentář k typu nástroje a šablona webu každá stále uváděly, že žádný nástroj do repozitáře nezapisuje.
  • Nic neodpovídalo na „jaká je tady projekce MCP“ jako jedna hodnota. Verze protokolu byly v initialize, efekt každého nástroje v anotaci, deklarovaní klienti v share/providers.yaml a zda konfigurace klienta spouští server tohoto repozitáře v shellové funkci. Cockpit pro nic z toho neměl stránku.

Rozhodnutí

Bezpečnost nástroje je bezpečností jeho schopnosti. ExecutionPolicy::hints klasifikuje, co smí volající předpokládat, z efektu, který schopnost již nese, a anotace MCP jsou touto hodnotou: čtení je jen pro čtení a idempotentní; změna paměti tohoto procesu není ani jedno a nic neničí; zápis do repozitáře je destruktivní a není idempotentní. Klasifikace je konzervativní ve směru, který volající přežije — žádný handler nedeklaroval, že druhé volání nic nezmění, takže žádný není jako takový ohlášen. Z handleru nic nesahá za stroj, takže openWorldHint je false, a to stejnou klasifikací, nikoli konstantou. Samotný efekt cestuje v _meta.majordomus.effect.

Kategorie odmítnutí je kategorie chyby. CapabilityError::code je jedno slovo na variantu a čtou ho oba transporty: pole error.code v HTTP a _meta.majordomus.error.code ve výsledku nástroje s isError: true. Odmítnutý výsledek nenese structuredContent, protože schéma výstupu popisuje úspěch.

Servírované metody jsou seznam, který čte dispečer. protocol::METHODS se konzultuje dříve, než se požadavek vůbec prohlédne, takže seznam je to, co se servíruje, a ne jeho popis.

Projekce je popsána schopností. mcp.projection odpovídá jako jedna typovaná hodnota: kdo odpovídá na initialize, verze protokolu, přenosy a relace připojené přes každý, obsluhované metody a ty, které ne, každý nástroj s jeho efektem a nápovědami, nástroje, které zapisují do repozitáře, zdroje a kde stojí konfigurace každého deklarovaného klienta v tomto repozitáři. Stránka MCP v Cockpitu, trasa HTTP, nástroj, zdroj a majordomus mcp --inspect ji vykreslují. Nevypisuje nic svého.

Název nástroje zůstává deklarovaný. Deklaruje se jednou, na schopnosti, a registr odmítne duplicitu nebo špatně utvořený název. Neodvozuje se z id schopnosti: 89 ze 166 názvů se liší od toho, co by dalo odvození (capabilities.list je majordomus_capabilities), každý z nich drží klienti i měřená plocha release a odvození by bylo zásadním přejmenováním poloviny plochy bez užitku pro jakéhokoli volajícího. Kontroluje se místo toho jediné místo, kde se název píše podruhé: próza. tests/mcp_prose.rs čte autorské dokumenty, bootstrapové soubory, šablony poskytovatelů a šablony webu a selže na názvu tvaru nástroje, který registr neprojektuje.

Prompty zůstávají neservírované a popis to říká. Promptové assety repozitáře vykreslují kontext lokální pro checkout, který vlastní shellový nástroj; servírované bez vykreslení by se četly jako hotové. Zůstávají zdroji. mcp.projection uvádí prompts: false, místo aby klient musel zjistit z -32601.

Konfigurace klientů zůstávají bootstrap soubory. .mcp.json, .codex/config.toml a soubor nastavení Gemini jsou každý jedna položka jmenující launcher, ve třech formátech vlastněných třemi klienty, a klient je čte dříve, než existuje jakýkoli server, který by je generoval. Negenerují se. Jejich postavení se měří — wired, foreign nebo absent, čteno ze souboru — a konfigurace, která existuje a nejmenuje launcher, je nález s nápravou.

Co se tímto nemění

Nepřidává se žádný nástroj, který zapisuje, ani žádná cesta zápisu do MCP. Schopnost zapisuje do repozitáře, jen když deklaruje .writes_repository(); handler je ten, který dosáhne každý transport, takže co odmítne přes HTTP, odmítne přes MCP týmiž slovy. MCP nedostává vlastní autorizační vrstvu: server je jen na loopbacku, požadavek měnící stav z cizího původu prohlížeče se odmítne před jakýmkoli handlerem a rozhodnutí, zda zavolat něco, co něco mění, zůstává na klientovi, což je přesně to, o čem mají anotace informovat.

Zamítnuté alternativy

  • Deklarace idempotent a destructive na schopnost. Bylo by přesnější pro obslužnou funkci, která jen připisuje, a je to druhé místo, kde si deklarace může odporovat. Efekt je již deklarován; nápovědy ho následují. Deklaraci na úrovni obslužné funkce lze přidat, až se ukáže, že volající potřebuje rozlišení.
  • Odvozování jmen nástrojů z id schopností. Zamítnuto výše: přejmenování 89 nástrojů.
  • Servírování dovedností nebo workflow jako MCP promptů. Už jsou zdroji se stabilními URI. Druhý protokolový povrch pro týž text by potřeboval pravidlo, který z nich má klient preferovat, a nikdo o něj nepožádal.
  • Generování klientských konfigurací. Soubor, který klient čte, aby našel server, nelze dlužit serveru.

Co důkaz našel a co po sobě nechal

Sada testů shody psaná vedle tohoto rozhodnutí (tests/mcp_conformance.rs) prošla každý zdroj a každý nástroj čtení na tajemství podstrčené do prostředí a repozitáře. Jedno se dostalo ke klientovi: přihlašovací údaj vložený do URL remote origin vrátil session_domain.identity doslova, přes MCP i HTTP, a shellový nástroj zapsal týž řetězec jako identitu repozitáře do sdílených záznamů, které se sledují a pushují. To je opraveno tam, kde to vzniklo, a ne tady: na vlastní větvi (fix/a-remote-url-is-published-without-its-credential, test/cases/941), před tímto rozhodnutím, protože přihlašovací údaj nečeká na architekturu. Dokud ta větev není v historii, se kterou se tato mergne, test no_secret_in_the_environment_or_the_repository_reaches_a_client sady zde selhává a je ponechán selhávat, ne ignorován.

Změřilo také mezeru, kterou toto rozhodnutí nezavírá. Registr neumí říct, že odpověď schopnosti je funkcí jejího vstupu a samotného repozitáře: properties.rs jmenuje tři výjimky podle id a test parity mezi procesy musel vylučovat podle tagu a měření (environment.preflight, mesh.doctor, executions.list, health.report, server.status a dashboard.overview odpovídají v každém procesu jinak). Deklarovaná klasifikace by umožnila vymezit paritu modelem místo seznamem; dotýká se každé deklarace a je ponechána jako dluh, pojmenovaný zde, aby nebyl znovuobjevován.

Důsledky

  • Tři nástroje jsou nyní ohlašovány jako destruktivní a ne idempotentní a každý příkazový nástroj jako ne idempotentní. Klient, který se před destruktivním voláním ptá člověka, se nyní zeptá i před těmito třemi. To je zamýšlená změna.
  • capabilities.projections nese effect na každém řádku a registr získává mcp.projection. Veřejný povrch se rozšířil, což release engine měří jako minor verzi.
  • Klient se může větvit podle _meta.majordomus.error.code. Text se nemění.
  • Přidání schopnosti, která deklaruje nástroj, ji dostane na stránku MCP v Cockpitu, do generované reference schopností, do dokumentu OpenAPI a do tools/list s anotacemi, které o ní platí, bez úpravy jiného souboru než její deklarace.

Odkud to pochází

kanonický soubor
.ai/repo/adrs/0110-mcp-says-nothing-its-capability-does-not.md
identity
adr-0110
dostupné také jako
Zdroj MCP majordomus://adr/adr-0110 · majordomus entity show adr/adr-0110 · GET /api/v1/entity?uri=majordomus://adr/adr-0110
v Cockpitu
/cockpit/objects/adr/adr-0110

Tato stránka je generována z výše uvedeného souboru pomocí scripts/generate-site-data; úprava stránky nic nemění, úprava souboru změní všechna rozhraní. Výše uvedené vztahy jsou hrany docs/generated/graph.json, které spustitelný program zapisuje ze stejného indexu.

Prohledává názvy a popisy všech stránek, které tento web publikuje.