Hier verbindest du fremde KI-Dienste (Ryze, Higgsfield, eigene Server …), damit der Assistent
deren Werkzeuge mitbenutzen kann. Nötig: die MCP-Adresse des Dienstes (https…, meist endet
sie auf /mcp) und — falls der Dienst einen Schlüssel verlangt — ein Secret-Name.
Den Schlüssel selbst hinterlegst nur du am Rechner: npx wrangler pages secret put MCP_RYZE --project-name=mocfor-ki
Dienste, die nur eine Browser-Anmeldung anbieten (ohne Schlüssel), können hier nicht angebunden werden.
Womit klemmt es?
/* ---------- Mikrofon: Transkript ins Eingabefeld (korrigierbar) ----------
* Gleiche Engine wie der Sprach-Knopf im Fußmenü, aber hier landet das
* Verstandene IM FELD — die Person liest, korrigiert bei Bedarf und sendet
* selbst. Live-Zwischenstand wird direkt ins Feld geschrieben. */
(function(){
const knopf = document.getElementById("mikrofrage");
const feld = document.getElementById("frage");
if (!knopf || !feld) return;
const SR = window.SpeechRecognition || window.webkitSpeechRecognition;
if (!SR) { knopf.style.display = "none"; return; } /* ohne Dienst: kein toter Knopf */
let rec = null, vorher = "";
function stopUi(){ knopf.classList.remove("hoert"); knopf.textContent = "🎙"; }
knopf.addEventListener("click", () => {
if (rec) { try { rec.stop(); } catch(e){} rec = null; stopUi(); return; }
vorher = feld.value ? feld.value.replace(/\s+$/, "") + " " : "";
rec = new SR(); rec.lang = "de-DE"; rec.interimResults = true; rec.maxAlternatives = 3;
knopf.classList.add("hoert"); knopf.textContent = "⏹";
rec.onresult = ev => {
let fest = "", live = "";
for (let i = 0; i < ev.results.length; i++) {
if (ev.results[i].isFinal) {
let beste = "";
for (let k = 0; k < ev.results[i].length; k++) {
const t = (ev.results[i][k].transcript || "").trim();
if (t.length > beste.length) beste = t;
}
fest += beste + " ";
} else live += (ev.results[i][0] && ev.results[i][0].transcript) || "";
}
feld.value = (vorher + fest + live).trimStart();
};
rec.onerror = ev => {
stopUi(); rec = null;
const g = ev && ev.error;
feld.placeholder = g === "not-allowed" ? "Mikrofon nicht erlaubt — bitte im Browser freigeben"
: g === "no-speech" ? "Nichts verstanden — nochmal aufs Mikrofon tippen"
: "Spracheingabe abgebrochen";
};
rec.onend = () => { stopUi(); rec = null; feld.focus(); };
try { rec.start(); } catch(e){ stopUi(); rec = null; }
});
})();