{
 "$schema": "../../schema.json",
 "schema": "fundus/1",
 "id": "agentenformular-webmcp",
 "name": "Agentenformular mit WebMCP",
 "name_en": "Agent-ready form with WebMCP (declarative and imperative tools, optional llms.txt)",
 "kurz": "Termin- und Angebotsformular eines Heizungsbauers, das Menschen normal bedienen und KI-Agenten als WebMCP-Werkzeug lesen; eine umschaltbare Agenten-Sicht zeigt Schema, Lese-Werkzeug und eine optionale llms.txt.",
 "kategorie": "Sektionen & Funktionen",
 "kategorie_slug": "sektionen",
 "kategorie_nr": 16,
 "bau_chat": "D",
 "prioritaet": "F",
 "trendstatus": "aufsteigend",
 "belegstatus": "quellenbelegt",
 "website_belege": 0,
 "stimmung": [
  "präzise",
  "experimentell"
 ],
 "stimmung_roh": [
  "funktional",
  "vertrauenswürdig",
  "zeitgeistig"
 ],
 "technik": [
  "form",
  "vanilla-js",
  "webmcp",
  "markdown"
 ],
 "technik_gruppen": [
  "css",
  "js"
 ],
 "leistungskosten": "niedrig",
 "steckbrief": {
  "beschreibung": "Ein Anfrage- oder Terminformular, das für Menschen ganz normal funktioniert und für KI-Agenten zusätzlich als Werkzeug beschrieben ist. Deklarativ über HTML-Attribute: toolname und tooldescription am <form>, toolparamdescription an den Feldern. Der Browser leitet daraus ein JSON-Schema ab. Imperativ registriert die Seite weitere Werkzeuge per document.modelContext.registerTool(), etwa eine Abfrage freier Termine. Beides nur mit Feature-Erkennung. Optional dazu eine llms.txt im Wurzelverzeichnis, die Agenten erklärt, was die Seite anbietet; ihre Wirkung ist nicht belegt, Google braucht sie für AI Overviews und AI Mode nicht.",
  "warum_es_wirkt": "Assistenten buchen zunehmend im Auftrag ihrer Nutzer. Ein beschriebenes Formular erspart ihnen das Raten über Bildschirmfotos und Klickpfade. Der Betrieb bekommt saubere Anfragen, der Mensch behält die Kontrolle: Ohne toolautosubmit füllt der Agent nur aus, abgeschickt wird erst nach Klick. Wer es heute einbaut, verliert nichts, denn ohne Unterstützung bleiben die Attribute wirkungslos.",
  "wann_einsetzen": "Termin- und Anfrageformulare mit klaren Feldern: Wartungstermin, Rückruf, Reservierung, Probestunde, Kostenvoranschlag. Seiten, deren Kundschaft schon mit Assistenten plant (Handwerk, Praxis, Fahrschule, Gastronomie, Kurse).",
  "wann_nicht": "Für Zahlungen, Verträge und sensible Daten (Gesundheit, Ausweise) kein automatisches Absenden und keine Werkzeuge ohne Bestätigung. Nicht als Ersatz für ein gutes Formular für Menschen. Wenn Spam ein Problem ist: Agenten-Anfragen brauchen dieselben Schutzmaßnahmen wie alle anderen.",
  "varianten": [
   "Terminformular nur deklarativ (toolname, tooldescription, toolparamdescription), Mensch bestätigt den Versand",
   "Deklaratives Formular plus imperatives Lese-Werkzeug (freie Termine, Einzugsgebiet prüfen) mit annotations.readOnlyHint",
   "Suchformular mit toolautosubmit: Agent darf selbst absenden, weil nichts Folgenreiches passiert",
   "Antwort an den Agenten über SubmitEvent.respondWith(): Bestätigung mit Vorgangsnummer oder Liste der Feldfehler",
   "llms.txt mit Verweis auf Formular, Leistungen und Einzugsgebiet, kombinierbar mit einer Maschinenansicht (optional, ohne belegte Wirkung bei Google)"
  ],
  "umsetzung": "Formular wie immer bauen (label, name, required, autocomplete), dann ergänzen: <form toolname=\"termin_anfragen\" tooldescription=\"Was das Werkzeug tut, was danach passiert\">, an jedem Feld toolparamdescription mit Format und Beispiel. Auswahlen als <select>. Kein toolautosubmit, wenn der Versand Folgen hat. Keine Honigtopf- oder versteckten Felder mit name im Werkzeug-Formular: Sie landen vermutlich im Schema; Spamschutz serverseitig. Im submit-Handler: e.preventDefault(); if (e.agentInvoked) e.respondWith(Promise.resolve('Anfrage KH-… eingegangen')); bei Fehlern die Feldmeldungen zurückgeben. Imperativ nur mit Feature-Erkennung: const mc = document.modelContext || navigator.modelContext; if (mc && typeof mc.registerTool === 'function') mc.registerTool({…, annotations: { readOnlyHint: true }}, { signal }). CSS für :tool-form-active nur in @supports selector(:tool-form-active). Wechselt das Formular (Variante, Schritt), toolname entfernen bzw. controller.abort(). Optional: llms.txt als statische Datei unter /llms.txt, ohne belegte Wirkung bei Google. Google nennt für AI Overviews und AI Mode ausdrücklich keine neuen maschinenlesbaren Dateien oder KI-Textdateien als nötig (developers.google.com/search/docs/appearance/ai-features, Stand 10.12.2025); für Sichtbarkeit zählen strukturierte Daten passend zum sichtbaren Text und ein aktuelles Unternehmensprofil. Dem Kunden nicht als Sichtbarkeits-Maßnahme verkaufen. Die Agenten-Sicht der Demo ist ein Erklärwerkzeug; auf Kundenseiten dafür mensch-maschine-umschalter nehmen oder weglassen.",
  "mobil": "Identisch. Felder mit autocomplete und inputmode, Ziele mindestens 48 px (Touch 52 px), Schrift 17 px gegen Zoom. Die Agenten-Sicht steht in der Demo auf dem Telefon über dem Formular.",
  "reduzierte_bewegung": "Ansichtswechsel und Ausfüllen ohne Bewegung, Zustände wechseln sofort.",
  "barrierefreiheit": "Die Attribute ändern nichts für Screenreader; Grundlage bleibt ein zugängliches Formular mit <label>, Fehlertexten über aria-describedby und Fokus auf das erste fehlerhafte Feld (WCAG 3.3.1, 3.3.2). Gute Labels helfen doppelt, denn Chrome nimmt sie als Beschreibung, wenn toolparamdescription fehlt. Füllt ein Agent aus, kündigt eine Statusmeldung (role=\"status\") das an, und der Mensch prüft vor dem Senden."
 },
 "messwerte": {
  "easing": "cubic-bezier(0.4, 0, 0.2, 1)",
  "dauer_ms": "150 Farbe, 240 Ansichtswechsel, 400 Einblendung",
  "stagger_ms": "",
  "distanz": "8px",
  "sonstiges": "Chrome-Standard für :tool-form-active: outline 1px dashed, outline-offset -1px",
  "herkunft": "eigene Festlegung",
  "quelle": "Rezept handwerk-werkstatt-klartext (Holzrausch .15s cubic-bezier(.4,0,.2,1)); Umriss aus Chrome-Doku Declarative API"
 },
 "kurve": {
  "bezier": [
   0.4,
   0.0,
   0.2,
   1.0
  ],
  "css": "cubic-bezier(0.4, 0, 0.2, 1)",
  "name": "Material Standard",
  "dauer_ms": 150
 },
 "gesehen_bei": [
  {
   "seite": "Chrome for Developers: WebMCP Declarative API",
   "url": "https://developer.chrome.com/docs/ai/webmcp/declarative-api",
   "auszeichnung": "",
   "beobachtung": "Abgerufen 01.11.2026 (Stand der Seite 25.09.2026). Attribute toolname, tooldescription und toolautosubmit am <form>, toolparamdescription an Feldern. Schema: Textfelder werden \"string\", <select> wird anyOf mit const und title plus enum, required landet in required. Beschreibung fällt ohne toolparamdescription auf das <label>, dann auf aria-description zurück. Ereignisse toolactivated und toolcancel an document.modelContext, SubmitEvent.agentInvoked und respondWith() (vorher preventDefault()). Pseudoklassen :tool-form-active und :tool-submit-active; Chrome zeichnet standardmäßig einen gestrichelten 1-px-Umriss. Origin Trial.",
   "art": "artikel"
  },
  {
   "seite": "Chrome for Developers: WebMCP Imperative API",
   "url": "https://developer.chrome.com/docs/ai/webmcp/imperative-api",
   "auszeichnung": "",
   "beobachtung": "Abgerufen 01.11.2026 (Stand der Seite 16.10.2026). document.modelContext.registerTool({ name, description, inputSchema, execute, annotations }, { signal }); Abmelden über AbortController.abort(). annotations: readOnlyHint, untrustedContentHint, consequentialHint (Standard false). Dazu getTools(), executeTool() und das Ereignis toolchange. Chrome 153: Abmelden bricht laufende Aufrufe nicht mehr ab. Chrome 155: JSON-Strings als Argumente veraltet.",
   "art": "artikel"
  },
  {
   "seite": "Search Engine Journal: ChatGPT adds WebMCP support",
   "url": "https://searchenginejournal.com/chatgpt-adds-webmcp-support/587237",
   "auszeichnung": "",
   "beobachtung": "27.08.2026: WebMCP im eingebauten Browser der ChatGPT-Desktop-App, nur für freigeschaltete Konten. OpenAI fragt vor dem Zugriff auf eine Seite und bestätigt heikle Aktionen. Der Entwurf stammt aus der W3C Web Machine Learning Community Group und ist kein Standard.",
   "art": "artikel"
  },
  {
   "seite": "MCP Playground: WebMCP in 2026, The API Moved",
   "url": "https://mcpplaygroundonline.com/blog/what-is-webmcp.md",
   "auszeichnung": "",
   "beobachtung": "27.08.2026: Die API liegt seit dem Entwurf vom Juli 2026 an document.modelContext statt navigator.modelContext; Chrome 150 hat den alten Ort als veraltet markiert, der Origin Trial (Chrome 149 bis 156) liefert beide. provideContext() und clearContext() sind seit März 2026 gestrichen. Der Spezifikationstext für die deklarative API ist noch offen.",
   "art": "artikel"
  },
  {
   "seite": "llms.txt (Vorschlag von Jeremy Howard)",
   "url": "https://llmstxt.org/index.md",
   "auszeichnung": "",
   "beobachtung": "Format: H1 mit dem Namen (einzige Pflicht), Blockzitat mit Kurzfassung, freie Absätze, H2-Abschnitte als Linklisten \"- [Name](URL): Hinweis\", ein H2 \"Optional\" für Verzichtbares. Datei unter /llms.txt.",
   "art": "artikel"
  }
 ],
 "tutorials": [
  {
   "titel": "Chrome: WebMCP Declarative API",
   "url": "https://developer.chrome.com/docs/ai/webmcp/declarative-api"
  },
  {
   "titel": "Chrome: WebMCP Imperative API",
   "url": "https://developer.chrome.com/docs/ai/webmcp/imperative-api"
  },
  {
   "titel": "The /llms.txt file",
   "url": "https://llmstxt.org/index.md"
  }
 ],
 "kombinierbar_mit": [
  "mensch-maschine-umschalter",
  "kontakt-anfrage-formular",
  "validierung-nach-interaktion"
 ],
 "urls": {
  "detail": "https://cecodesign.de/lab/fundus/sektionen/agentenformular-webmcp/",
  "meta": "https://cecodesign.de/lab/fundus/sektionen/agentenformular-webmcp/meta.json",
  "demo": "https://cecodesign.de/lab/fundus/sektionen/agentenformular-webmcp/demo"
 },
 "herkunft": {
  "quelldateien": [
   "DEF-Recherche 01.11.2026"
  ],
  "pruefnotizen": [
   "01.11.2026: Attributnamen und API aus den Chrome-Dokuseiten (Declarative 25.09.2026, Imperative 16.10.2026) übernommen. Die Spezifikation (webmachinelearning.github.io/webmcp) war aus der Arbeitsumgebung nicht abrufbar.",
   "Keine Produktions-Website mit WebMCP gefunden; Belege sind Doku und Fachartikel. Die Recherche-Quellen semrush.com/blog/webmcp und seoinc.com waren nicht abrufbar.",
   "Nicht dokumentiert und in der Demo als Annahme gekennzeichnet: wie Radiogruppen, Datums- und Dateifelder ins Schema eingehen. Die Demo nutzt deshalb <select> für Auswahlen.",
   "Der Spezifikationstext der deklarativen API ist laut mcpplaygroundonline.com (27.08.2026) noch offen; Namen können sich ändern. Vor Kundeneinsatz neu prüfen.",
   "02.11.2026 erneut per WebFetch geprüft: Attribute, Schema-Ableitung, Ereignisse, respondWith() nach preventDefault(), Pseudoklassen und annotations stimmen mit den Chrome-Seiten überein (Declarative 25.09.2026, Imperative 16.10.2026; dazu: window.ontoolactivated/ontoolcancel ab Chrome 156 nicht mehr unterstützt, Annotation debugging ab 156). Origin-Trial-Spanne 149 bis 156 und die Veraltung von navigator.modelContext in Chrome 150 nur über mcpplaygroundonline.com belegt."
  ]
 },
 "bau": {
  "status": "fertig",
  "kurz": "Termin- und Angebotsformular eines Heizungsbauers, das Menschen normal bedienen und KI-Agenten als WebMCP-Werkzeug lesen; eine umschaltbare Agenten-Sicht zeigt Schema, Lese-Werkzeug und eine optionale llms.txt.",
  "demo": true,
  "abhaengigkeiten": [],
  "werte": {
   "easing": "cubic-bezier(0.4, 0, 0.2, 1) für alles Sichtbare · Ausblenden cubic-bezier(0.4, 0, 1, 1)",
   "dauer_ms": "150 Farbe, Druck und Hover · 240 Wechsel Mensch/Agent (Schalter-Daumen, Ausblenden 160) · 400 Einblenden Agenten-Sicht, Anmerkungen, Fehlermeldung, Protokollzeile · 900 simulierter Versand",
   "distanz": "8px translateY bei allen Einblendungen",
   "druck": "scale 0.97 auf Absende- und Anruf-Knopf",
   "deklarativ": "<form toolname=\"termin_anfragen\" tooldescription=\"…\"> und toolparamdescription an jedem Feld; kein toolautosubmit; Auswahlen als <select> (Schema: anyOf mit const/title plus enum); required → required",
   "imperativ": "const mc = document.modelContext || navigator.modelContext; if (mc && typeof mc.registerTool === 'function') await mc.registerTool({ name, description, inputSchema, annotations: { readOnlyHint: true }, execute }, { signal }); Abmelden per AbortController.abort() beim Variantenwechsel",
   "antwort_an_agent": "submit-Handler: preventDefault(); bei e.agentInvoked e.respondWith(Promise) mit Vorgangsnummer oder mit den Feldfehlern als Text",
   "ereignisse": "document.modelContext: toolactivated → Hinweis „Ein Assistent hat das Formular ausgefüllt“ (role=status), toolcancel → Hinweis weg",
   "aktiv_zustand": "@supports selector(:tool-form-active) { form:tool-form-active .zettel { outline: 1px dashed } .absenden:tool-submit-active { outline: 2px dashed } }; nachgestellt über .werkzeug-aktiv",
   "erkennung": "CSS.supports('selector(:tool-form-active)') für deklarativ, document.modelContext bzw. navigator.modelContext für imperativ; Anzeige im Kopf der Sektion",
   "felder": "Wartungstermin: 9 Felder, 6 Pflicht (anliegen, plz, woche, zeitfenster, name, telefon); Wunschwochen aus dem heutigen Datum als JJJJ-Www",
   "pruefen": "Fehler erst nach dem Verlassen eines Feldes, danach live; PLZ fünfstellig und im Einzugsgebiet",
   "ziele": "Zellen mindestens 48 px, Touch 52 px",
   "farben": "Grund #EFEDEA, Zellen #F8F7F4, Linien und Text #1A1A1A, Signal #FB6100 nur für Anrufen und Absenden, Fehler #B3261E; Agenten-Schicht als Blaupause #10265A mit Raster 24 px, Anmerkungen #1F45B5",
   "schrift": "Special Gothic 700 (h1 clamp(2.25rem, 1.5rem + 3vw, 3.5rem), Zeilenhöhe 1.05, -0.01em), Labels Special Gothic wdth 75 versal 0.8125rem +0.04em, Text Atkinson Hyperlegible Next 1.0625rem/1.55, JSON Geist Mono 12.5px/1.6",
   "vorfuehrung_runde_ms": "etwa 15000: Mensch → Zeiger auf „Agent“ → llms.txt → Lese-Werkzeug → toolactivated → Felder füllen (22 ms je 2 Zeichen) → Mensch klickt Absenden → respondWith → Bestätigung"
  },
  "ausloeser": "klick",
  "touch": "Gleiches Verhalten per Antippen. Unter 860 px eine Spalte: Agenten-Sicht steht statt der Einleitung über dem Formular (höchstens 560 px hoch, scrollt innen). Unter 560 px Zellen einspaltig, Absenden volle Breite. Felder 17 px gegen iOS-Zoom, Ziele 52 px.",
  "reduziert": "Alle Übergänge und Animationen aus: Ansicht wechselt sofort, Felder werden in der Vorführung ohne Tippen gesetzt, Wartezeiten auf höchstens 60 ms gekürzt, kein Lade-Kreisel.",
  "korrekturen": {
   "umsetzung": "Formular wie immer bauen (label, name, required, autocomplete), dann ergänzen: <form toolname=\"termin_anfragen\" tooldescription=\"Was das Werkzeug tut, was danach passiert\">, an jedem Feld toolparamdescription mit Format und Beispiel. Auswahlen als <select>. Kein toolautosubmit, wenn der Versand Folgen hat. Keine Honigtopf- oder versteckten Felder mit name im Werkzeug-Formular: Sie landen vermutlich im Schema; Spamschutz serverseitig. Im submit-Handler: e.preventDefault(); if (e.agentInvoked) e.respondWith(Promise.resolve('Anfrage KH-… eingegangen')); bei Fehlern die Feldmeldungen zurückgeben. Imperativ nur mit Feature-Erkennung: const mc = document.modelContext || navigator.modelContext; if (mc && typeof mc.registerTool === 'function') mc.registerTool({…, annotations: { readOnlyHint: true }}, { signal }). CSS für :tool-form-active nur in @supports selector(:tool-form-active). Wechselt das Formular (Variante, Schritt), toolname entfernen bzw. controller.abort(). Optional: llms.txt als statische Datei unter /llms.txt, ohne belegte Wirkung bei Google. Google nennt für AI Overviews und AI Mode ausdrücklich keine neuen maschinenlesbaren Dateien oder KI-Textdateien als nötig (developers.google.com/search/docs/appearance/ai-features, Stand 10.12.2025); für Sichtbarkeit zählen strukturierte Daten passend zum sichtbaren Text und ein aktuelles Unternehmensprofil. Dem Kunden nicht als Sichtbarkeits-Maßnahme verkaufen. Die Agenten-Sicht der Demo ist ein Erklärwerkzeug; auf Kundenseiten dafür mensch-maschine-umschalter nehmen oder weglassen.",
   "mobil": "Identisch. Felder mit autocomplete und inputmode, Ziele mindestens 48 px (Touch 52 px), Schrift 17 px gegen Zoom. Die Agenten-Sicht steht in der Demo auf dem Telefon über dem Formular."
  },
  "geprueft": "02.11.2026",
  "notiz": "Welt: Rezept handwerk-werkstatt-klartext, erfundener Heizungs- und Sanitärbetrieb Klütmann Haustechnik aus Hameln (Notdienst, Einzugsgebiet Landkreis Hameln-Pyrmont). Formular als Auftragszettel mit 1-px-Kastenraster (Prinzip der Kasten-Navigation von holzrausch.de), Orange nur für Anrufen und Absenden, eigene SVG-Anlagenskizze statt Foto. Agenten-Sicht als Blaupause: JSON-Schema live aus dem DOM nach den Regeln der Chrome-Doku abgeleitet, imperatives Lese-Werkzeug, llms.txt nach llmstxt.org; Anmerkungen an jeder Zelle zeigen Parametername, Typ und Beschreibung. Echte Registrierung nur mit Feature-Erkennung; ohne Unterstützung steht „nachgestellt“ im Kopf. Vorführung: Agent liest llms.txt, ruft das Lese-Werkzeug, füllt aus, der Mensch schickt ab, respondWith liefert die Vorgangsnummer. Stand der API: developer.chrome.com (Declarative 25.09.2026, Imperative 16.10.2026). Nicht in einem Browser mit WebMCP geprüft (Headless-Chromium ohne Origin Trial). AD-Review 02.11.2026: Note 5. Tastatur, Leer-, Fehler- und Erfolgszustand per Playwright geprüft; Steckbrief gegen die Chrome-Doku (Declarative 25.09.2026, Imperative 16.10.2026) abgeglichen. Zugang 02.11.2026: Varianten-Leiste und Gruppe mit flex-wrap (320 px ohne Querscrollen); im Kontrastmodus Rahmen für Knöpfe und für die nur unterstrichenen Formularfelder. Korrektur 02.11.2026: llms.txt als „optional, ohne belegte Wirkung bei Google“ gekennzeichnet (Reiter /llms.txt der Agenten-Sicht, umsetzung, Quelle neu/…json: beschreibung, varianten, umsetzung); Google-Doku zu AI-Funktionen per Abruf geprüft.",
  "varianten": [
   {
    "id": "termin",
    "name": "Wartungstermin",
    "wann": "Handwerk, Praxis, Fahrschule, Werkstatt: kurze Terminanfrage mit Rückruf; Agent prüft vorher freie Zeitfenster.",
    "werte": {
     "toolname": "termin_anfragen",
     "felder": "9, davon 6 Pflicht",
     "lese_werkzeug": "freie_termine_abfragen {plz, woche?}",
     "pflicht_kontakt": "telefon"
    }
   },
   {
    "id": "projekt",
    "name": "Projektanfrage",
    "wann": "Größere Vorhaben mit Angebot (Heizungstausch, Bad, Kostenvoranschlag); Agent prüft vorher das Einzugsgebiet.",
    "werte": {
     "toolname": "angebot_anfragen",
     "felder": "9, davon 5 Pflicht; Fotos als Dateifeld nicht im Schema (Annahme)",
     "lese_werkzeug": "einzugsgebiet_pruefen {plz}",
     "pflicht_kontakt": "email"
    }
   }
  ]
 }
}
