Entwickler
MCP ist der offene Standard für die Verbindung von KI mit Ihren Systemen: Registrieren Sie Ihren Server, wählen Sie aus, wer welche Tools nutzen darf, veröffentlichen Sie. Starten Sie den Assistenten im Web, auf iOS, Android und dem Desktop — und verwalten Sie jeden Workspace aus jedem MCP-Client.
claude mcp add --transport http busymate-ai https://busymate.ai/mcpEinstiege
Ein Script-Tag auf jeder Seite, die Sie freigeben — Launcher und Gast-Chat funktionieren sofort.
Installiere das versionierte Swift-Paket für Kontoidentität, Chat und eine beim Antippen angeforderte Mikrofonberechtigung.
Installiere die versionierte Android-Bibliothek für Kontoidentität, Chat und eine beim Antippen angeforderte Mikrofonberechtigung.
Ihr eigener MCP-Server wird zu den Aktionen des Assistenten, im Auftrag jedes einzelnen Kunden.
Steuere die Plattform aus Claude, Claude Code, Cursor oder jedem MCP-Client über OAuth.
WebMCP: Ihre Seiten listen ihre eigenen Aktionen als Tools auf — buchen, bestellen, einen Status prüfen — mit integrierter Bestätigung.
01Schnellstart
Ihre App bleibt die Quelle der Wahrheit. Der Assistent erhält ein kurzlebiges signiertes Token, das sagt, wer anwesend ist, und ruft Ihre Tools als eigener, eingegrenzter Actor auf.
01
Hält Identität und Kontodaten; signiert ein Zwei-Minuten-Token, das sagt, wer angemeldet ist.
02
Wendet die Einstellungen Ihres Workspace an: Inhalte, Modelle, Zugriffsstufen der Tools, Bestätigungsschritte, Übergabe.
03
Beantwortet Tools für genau einen Nutzer und nimmt den Nutzer aus dem angemeldeten Bearer-Token — nie aus den Tool-Argumenten.
7 Wege zur Anbindung, ein Assistent: Web-Embed · Angemeldete Kunden · iOS · Android · Desktop · REST-API · Ihr MCP-Server
02Angemeldete Kunden
Damit der Assistent weiß, wer fragt, signiert ein authentifizierter Endpunkt in Ihrem Backend ein kurzlebiges Token (ein ES256-JWT) mit Ihrer stabilen Kunden-ID und wenigen unbedenklichen Anzeigefeldern.
Das Token lebt maximal 120 Sekunden, trägt eine einmalige Nonce und jti und benennt Ihren Workspace. Der private Schlüssel und Ihre Produktsitzung erreichen niemals den Browser oder den Chat.
import { SignJWT, importJWK } from "jose";
// POST https://YOUR-PRODUCT-DOMAIN/api/bmai/identity — requires YOUR OWN logged-in product session.
app.post("/api/bmai/identity", requireSession, async (req, res) => {
// Fresh on EVERY mint. Never persist the launch token/nonce in localStorage,
// sessionStorage, cookies, React state, or module state: every assistant
// launch consumes this pair exactly once.
const nonce = typeof req.body?.nonce === "string" ? req.body.nonce : "";
if (!/^[A-Za-z0-9_-]{32,200}$/.test(nonce)) return res.status(400).json({ error: "invalid_nonce" });
const key = await importJWK(JSON.parse(process.env.AI_LAUNCH_PRIVATE_JWK), "ES256");
const token = await new SignJWT({
tenant_id: process.env.BMAI_TENANT_ID, // the tenant id shown in Console → Identity
nonce, // equals the sibling field below
name: req.user.displayName, // optional low-sensitivity display claim
})
.setProtectedHeader({ alg: "ES256", kid: process.env.AI_LAUNCH_KEY_ID })
.setIssuer(process.env.BMAI_ISSUER) // the Issuer you registered in Console → Identity
.setAudience("busymate-ai")
.setSubject(req.user.id) // IMMUTABLE internal account id; never email/phone/session id
.setJti(crypto.randomUUID()) // one-time (replay-protected)
.setIssuedAt()
.setExpirationTime("120s") // <= registered max age (120s)
.sign(key);
res.set("Cache-Control", "no-store");
res.status(201).json({ token, nonce, expiresIn: 120 });
});Das Token sagt, wer da ist — nicht, was diese Person darf. Halten Sie Guthaben, Geräte, Einstellungen und jede Änderung hinter Tools, die nur für einen Nutzer antworten.
03Web und Vollbild
Das SDK fragt Ihr Backend nach einer Identität, wenn es eine braucht, funktioniert für Gäste, aktualisiert sich nach Login und Logout, öffnet externe Links außerhalb des Frames und braucht keine Drittanbieter-Cookies.
<!-- Floating "mate" launcher for Your product.
Anonymous chat works immediately on the allowed origins. -->
<script>
function newLaunchNonce() {
const bytes = new Uint8Array(32);
crypto.getRandomValues(bytes);
return btoa(String.fromCharCode(...bytes))
.replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, "");
}
window.BusymateAI = {
getIdentity: async () => {
const accessToken = await getProductAccessToken(); // YOUR existing auth helper
if (!accessToken) return null;
const nonce = newLaunchNonce();
const returnTo = new URL(location.href); returnTo.search = ""; returnTo.hash = "";
const r = await fetch("https://YOUR-PRODUCT-DOMAIN/api/bmai/identity", {
method: "POST", credentials: "include", cache: "no-store",
headers: { "content-type": "application/json", authorization: "Bearer " + accessToken },
body: JSON.stringify({ nonce, returnTo: returnTo.href }),
});
if (r.status === 401) return null; // signed out -> anonymous chat
if (!r.ok) throw new Error("AI identity mint failed (" + r.status + ")");
// MUST be a newly minted { token, nonce } pair on every call. Never
// persist either value in localStorage, sessionStorage, cookies, React
// state, or module state.
const identity = await r.json();
if (identity.nonce !== nonce) throw new Error("AI identity nonce mismatch");
return { token: identity.token, nonce: identity.nonce };
},
};
// Call after YOUR product completes login, an access-token/session
// rotation, or an account switch — upgrades the live conversation in
// place, same thread. Do not send an identity postMessage directly.
window.assistantIdentityChanged = () =>
window.BusymateAI?.identityChanged?.() ?? Promise.resolve(false);
// Call after YOUR product completes logout. Without this the signed-out
// visitor keeps a verified chat and the previous transcript until the tab
// closes — a privacy defect, not a missing nicety.
window.assistantSignedOut = () =>
window.BusymateAI?.signedOut?.("signed_out");
</script>
<script
src="https://your-assistant.busymate.ai/embed/v1.js"
data-assistant="your-assistant"
data-label="Ask mate"
async></script>Öffnet ein angemeldeter Nutzer die Adresse Ihres Assistenten oder Ihre eigene Domain, übergeben Sie das Anmelde-Token im URL-Fragment. Die Seite löscht es vor dem Austausch.
// Full-page open with identity in the URL FRAGMENT — never sent in the
// request line, referrer, or logs; the destination strips it before exchange.
function newLaunchNonce() {
const bytes = new Uint8Array(32);
crypto.getRandomValues(bytes);
return btoa(String.fromCharCode(...bytes))
.replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, "");
}
const nonce = newLaunchNonce();
const accessToken = await getProductAccessToken(); // YOUR existing auth helper
if (!accessToken) throw new Error("Sign in before opening an identified assistant");
const returnTo = new URL(location.href); returnTo.search = ""; returnTo.hash = "";
const response = await fetch("https://YOUR-PRODUCT-DOMAIN/api/bmai/identity", {
method: "POST", credentials: "include", cache: "no-store",
headers: { "content-type": "application/json", authorization: "Bearer " + accessToken },
body: JSON.stringify({ nonce, returnTo: returnTo.href }),
});
if (response.status === 401) throw new Error("Sign in before opening an identified assistant");
if (!response.ok) throw new Error("AI identity mint failed (" + response.status + ")");
const identity = await response.json();
if (typeof identity.token !== "string" || typeof identity.nonce !== "string") {
throw new Error("AI identity mint returned an invalid response");
}
if (identity.nonce !== nonce) throw new Error("AI identity nonce mismatch");
const url = new URL("https://your-assistant.busymate.ai/");
url.hash = new URLSearchParams({
bmai_token: identity.token,
bmai_nonce: identity.nonce,
}).toString();
location.assign(url);04iPhone
Fixiere die Version des Swift-Pakets. Verbinde dein authentifiziertes Backend und ergänze die native Mikrofonberechtigung mithilfe des Plattformleitfadens und der Beispiel-App.
iOS: Installation, Konfiguration und Demo
// Swift Package: https://github.com/serebano/busymate-ai-sdk-ios.git (exact 1.0.2)
// Full lifecycle + demo: https://busymate.ai/docs/guides/ios-sdk
import WebKit
import BusymateAI
@MainActor
func installAssistant(
on webView: WKWebView,
account: @escaping () -> String?,
mint: @escaping @MainActor (BusymateBridge.MintRequest) async throws -> BusymateBridge.MintToken?
) {
BusymateBridge.install(on: webView, config: .init(
assistant: "your-assistant",
origins: ["https://your-assistant.busymate.ai"],
account: account,
mint: mint
))
// mint calls YOUR authenticated backend with request.nonce; never cache tokens.
// Backend endpoint: https://YOUR-PRODUCT-DOMAIN/api/bmai/identity
webView.load(URLRequest(url: URL(string: "https://your-assistant.busymate.ai/?channel=ios")!))
}
// Microphone: declare NSMicrophoneUsageDescription; install and retain
// BusymateMicrophone before load, and forward WKUIDelegate media permission.
// Call BusymateBridge.accountChanged() on login/logout/account changes.05Android
Fixiere die Version der Android-Bibliothek. Installiere sie vor dem Laden des Chats und folge dem Leitfaden zu Activity-Lebenszyklus, Mikrofon und Wiederherstellung des Renderers.
Android: Installation, Konfiguration und Demo
// Gradle installation + lifecycle: https://busymate.ai/docs/guides/android-sdk
// Source: https://github.com/serebano/busymate-ai-sdk-android/tree/1.0.2
import android.webkit.WebView
import ai.busymate.bridge.BusymateBridge
fun installAssistant(
webView: WebView,
account: () -> String?,
mint: (Map<String, Any?>, (BusymateBridge.MintResult) -> Unit) -> Unit
) {
BusymateBridge.install(webView, BusymateBridge.Config(
assistant = "your-assistant",
origins = listOf("https://your-assistant.busymate.ai"),
account = account,
mint = mint
))
// mint calls YOUR authenticated backend with request["nonce"], then done(result).
// Backend endpoint: https://YOUR-PRODUCT-DOMAIN/api/bmai/identity
webView.loadUrl("https://your-assistant.busymate.ai/?channel=android")
}
// Microphone: declare INTERNET + RECORD_AUDIO; construct and retain
// BusymateMicrophone in Activity.onCreate BEFORE STARTED/loadUrl; forward
// WebChromeClient.onPermissionRequest. See the guide for renderer recovery.
// Call BusymateBridge.accountChanged() on login/logout/account changes.06Desktop
Die offiziellen SDKs für macOS, Windows, Electron, Linux und Tauri laden den gehosteten Chat in einer isolierten WebView, beantworten Identitätsanfragen über die privilegierte Host-Schicht und öffnen sichere URLs extern. Pinne die SDK-Version und binde dein authentifiziertes Backend wie auf Mobilgeräten an.
Desktop: Installation, Konfiguration und Beispiel-Apps
// Official desktop SDK for your platform — macOS, Windows, Electron, Linux or Tauri:
// https://github.com/serebano/busymate-ai-sdk-electron (and -macos, -windows, -linux, -tauri).
// Every SDK takes these settings and installs the identity bridge before the first load.
const chatOptions = {
url: "https://your-assistant.busymate.ai/?channel=desktop_sdk", // the window's top-level page
assistant: "your-assistant",
account: () => productAuth.currentUserId(), // null when signed out
// YOUR authenticated backend signs { token, nonce } for request.nonce.
mint: (request) => productAuth.mintAssistantIdentity(request),
};07MCP-Tools
Veröffentlichen Sie vollständige Schemata bei der Discovery. Geben Sie jedem Tool eine von drei Zugriffsstufen, markieren Sie die Änderungen, die eine Bestätigungskarte brauchen, und prüfen Sie die Autorisierung bei jedem Aufruf erneut.
Jeder im Chat darf es aufrufen. Preise, Status, Funktionen.
Braucht einen angemeldeten Nutzer. Bestellstatus, Kontoauskünfte.
Handelt im Auftrag des angemeldeten Nutzers über ein eingegrenztes Actor-Token oder die eigene OAuth-Berechtigung des Nutzers.
Jede Änderung wird auf dem Server bestätigt. Tools, die Sie in confirm_tools eintragen, halten vor der Ausführung an einer Bestätigungskarte an; ebenso jeder Tool-Name, den der Assistent nicht kennt. Widget-Frames führen nie eine Änderung aus.
MCP endpoint ............ https://YOUR-DOMAIN/mcp
RFC 8707 resource ....... https://YOUR-DOMAIN/mcp (the token is audience-bound to this)
AS metadata (RFC 8414) .. https://YOUR-DOMAIN/.well-known/oauth-authorization-server
Resource meta (RFC 9728) https://YOUR-DOMAIN/.well-known/oauth-protected-resource
Client registration ..... Dynamic (RFC 7591) — public client, no secret
PKCE .................... S256 required (RFC 7636)
Authorization response .. iss parameter checked (RFC 9207)
Grants .................. authorization_code + refresh_token
Delegated tools/call .... no bearer -> 401; user derived from the bearer,
NEVER from an account id in tool arguments
Customer experience ..... one separate Authorize account tools action is expected;
use signed_actor_token instead for automatic SSO// POST https://YOUR-DOMAIN/mcp
// Authorization: Bearer <the per-user OAuth token mate obtained>
{
"jsonrpc": "2.0",
"id": 12,
"method": "tools/call",
"params": { "name": "get_my_account", "arguments": {} }
}
// Your server verifies the bearer, derives the user from its signed subject,
// and returns ONLY that user's data.Dieselben Protokolle gelten, ob die Plattform Client zu Ihrem Server ist oder Server für Ihren MCP-Client.
REST-API und Webhooks
Ein workspace-begrenzter API-Schlüssel authentifiziert sowohl die REST-Endpunkte als auch den MCP-Server. Listen Sie Gespräche auf und lesen Sie sie, posten Sie eine Operatorantwort, oder abonnieren Sie einen Webhook, anstatt abzufragen.
Erstellen Sie einen Schlüssel in Konsole → API keys und senden Sie ihn als Bearer-Token.
curl https://busymate.ai/api/v1/conversations \
-H "Authorization: Bearer bmai_sk_..."Vollständige Referenz: der API-Leitfaden, Webhooks, das OpenAPI-Dokument.
08Übergabe und Insights
Ein Kunde bittet um einen Menschen, ein Tool schlägt fehl, eine Rückerstattung liegt über Ihrem Limit, ein Stichwort taucht auf, oder ein beliebiges Ereignis, das Sie festlegen.
Eine Inbox; Zuweisung von Hand, reihum oder an die Person mit den wenigsten offenen Chats; Hinweise in der App, per Web Push, APNs und persönlichem Telegram.
Das Gespräch mitlesen, mit dem Kontext einsteigen, im selben Chat antworten; der Assistent nimmt keine Änderungen vor, solange ein Mensch aktiv ist.
Wiederkehrende Fragen, fehlendes Wissen und gescheiterte Wege, gruppiert aus echten Gesprächen, mit Links zu den Belegen.
09Workspace-Login
Konfigurieren Sie Login- und Konto-URLs des Workspace in der Konsole. Ein Gast, der Anmelden wählt, verlässt den Frame, authentifiziert sich in Ihrem Produkt und kehrt genau zur Ausgangs-URL zurück. Ihr Backend liefert dann ein einmaliges Anmelde-Token; Busymate AI erhält nie das Passwort des Nutzers oder Ihren Signaturschlüssel.
Eine Änderung berührt immer nur die eigenen Daten des angemeldeten Nutzers. Konto-Tools nehmen den Kunden aus dem delegierten Actor, prüfen die Autorisierung bei jedem Aufruf erneut und fragen bei den Änderungen nach, die Sie festlegen.
10Start-Checkliste
Bereit, Ihren Workspace einzurichten?
Die Integrationsseite der Konsole erzeugt aus Ihren veröffentlichten Einstellungen den Code und die Einstellungen für jede Oberfläche.
WebMCP
WebMCP ist der Entwurf der W3C Web Machine Learning Community Group für Seiten, die ihre eigenen Aktionen als Tools auflisten. Drei Wege hinein, von der kleinsten Änderung bis zur vollständigen Kontrolle.
book_appointment, check_order_status, start_return — ein Tool, ein Zweck.
"nächsten Dienstag um zehn", "Express" — niemals eine interne ID, die der Assistent raten muss.
Bieten Sie die Tools an, die diese Seite ausführen kann; melden Sie sie ab, wenn die Seite weitergeht.
Eine Buchung, eine Zahlung, eine Rücksendung: kennzeichnen Sie sie, und der Kunde bestätigt vor der Ausführung.
Die Bestätigung bleibt beim Kunden. Tools laufen im Browser des Besuchers auf Ihrer Origin. Ein Tool, das Sie als consequential markieren, stoppt bei einer Bestätigung, die der Kunde sieht; exposedTo beschränkt, welche Origins ein Tool überhaupt sehen dürfen.
Die kleinste Änderung: ein Name und eine einzeilige Beschreibung auf einem Formular, das Sie bereits haben. Der Browser macht daraus ein Tool; das Formular bleibt sichtbar und funktioniert weiterhin für alle.
<form action="/book" toolname="book_appointment"
tooldescription="Book an appointment for a date, a time and a service."
toolautosubmit>
<input name="date" type="date" toolparamdescription="The day, e.g. next Tuesday">
<input name="time" type="time" toolparamdescription="The start time">
<select name="service" toolparamdescription="Which service to book">
<option>Consultation</option>
<option>Follow-up</option>
</select>
<button type="submit">Book</button>
</form>Vollständige Kontrolle: die Browser-API. Feature-Erkennung — Browser ohne WebMCP erhalten die Seite einfach wie heute. Chrome 149 und Edge 150 tragen sie als Origin Trial; Firefox und Safari überprüfen den Vorschlag.
// The browser API (draft). Load the polyfill BEFORE this file so every browser has it
// (it stands down where the browser is native):
// <script src="https://busymate.ai/webmcp/polyfill-1.0.1.js" integrity="sha384-pLZ5lO3gwZIn8Nim+hDrUQY+bvpliRtZhrS1O1OGRFB3lvoW0sZ71DUFHIk3m+DG" crossorigin="anonymous"></script>
const ctx = document.modelContext ?? navigator.modelContext;
if (!ctx) throw new Error("no WebMCP registry: the polyfill did not load");
ctx?.registerTool({
name: "start_return",
description: "Start a return for a delivered order. Asks the customer to confirm first.",
inputSchema: { type: "object", properties: { orderNumber: { type: "string", description: "The order number, as printed on the receipt" } }, required: ["orderNumber"] },
annotations: { consequentialHint: true },
execute: async ({ orderNumber }) => startReturn(orderNumber),
}, { exposedTo: ["self"] });Wo der Assistent bereits installiert ist, listet ein Aufruf Ihre Tools für ihn und jeden anderen Assistenten, der den Browser besucht — auf der Browser-API, wo sie existiert, und über die eigene Bridge des Assistenten überall sonst.
// One call, both transports: the browser's own WebMCP where it exists,
// and the assistant's bridge everywhere else (Safari, Firefox, app WebViews).
BusymateAI.registerPageTools([
{
name: "check_order_status",
description: "Look up an order by its number and say where it is.",
inputSchema: {
type: "object",
properties: { orderNumber: { type: "string", description: "The order number, as printed on the receipt" } },
required: ["orderNumber"],
additionalProperties: false,
},
annotations: { readOnlyHint: true },
execute: async ({ orderNumber }) => (await fetch(`/api/orders/${orderNumber}`)).json(),
},
]);Die Anleitung zur Einführung und das Copy-Paste-PromptDie verständliche Seite für Ihr Team
Management-MCP
Management-Tools über MCP mit OAuth 2.1. Der Client öffnet beim ersten Verbindungsaufbau einen Browser zum Anmelden; nichts wird eingefügt.
https://busymate.ai/mcp| Client | Verbindungsmethode |
|---|---|
| Claude | Füge den Connector aus Claudes Connector-Verzeichnis hinzu und melde dich an – nichts einzufügen. |
| ChatGPT and Codex | Die App ist bei OpenAI in Prüfung und noch nicht gelistet. |
| Claude Code (CLI) | Führen Sie den Befehl unten aus — der Browser übernimmt die OAuth-Anmeldung. |
| Cursor | Fügen Sie den mcp.json-Eintrag unten in Cursors MCP-Einstellungen ein. |
| Andere MCP-Clients | Geben Sie dem Client den Endpoint unten; OAuth 2.1 Discovery und PKCE kümmern sich um den Rest. |
Das Konto, mit dem Sie sich anmelden, bestimmt, welche Workspaces der Client verwalten darf. Jede Änderung fragt nach einer Bestätigung.
claude mcp add --transport http busymate-ai https://busymate.ai/mcpCursor, Claude Desktop und jeder Client, der eine mcp.json liest, akzeptieren diesen Eintrag; Clients, die eine Remote-URL erwarten, nehmen den Endpunkt oben.
{
"mcpServers": {
"busymate-ai": {
"type": "http",
"url": "https://busymate.ai/mcp"
}
}
}Neueste Änderungen
Build 1624
G4: with a workspace's pii read masking ON, the Inbox thread translation and the email copilot (Console and MCP summarize_email_thread, suggest_email_reply, translate_email, and the Console copilot on an email conversation) now reads the mail thread masked, so drafts and summaries cannot quote raw card numbers, IBANs or national ids. With the setting off nothing changes.
Build 1623
G4: with a workspace's pii read masking ON, the transcript Markdown export (Console and MCP) now masks the Handoff header row, and the MCP draft_tenant_support_reply copilot reads the conversation masked like the Console copilot does. With the setting off both are unchanged. MCP activity records name the workspace and the result size. Each call an AI assistant makes to Busymate AI is now recorded with the workspace it targeted and how big its answer was, in bytes and rows. When a ChatGPT or Claude view shows no data, the cause can be found from the activity record alone.
Build 1622
The script tag now says, once in the browser console, which call replaces an old one. Identify and refreshIdentity on the embed script keep working. The first call of each prints one console note naming the call to use instead (identityChanged), so integrations can move to the same names as the Web SDK (getIdentity, identityChanged, signedOut, account). The old v1 client drop-ins under /sdk/v1 are served unchanged and now answer with a Deprecation header.