Dezvoltatori
Dați-i asistentului dumneavoastră AI instrumente reale, prin MCP
Dați-i asistentului instrumente reale prin MCP, standardul deschis pentru conectarea AI la sistemele dumneavoastră. Lansați-l pe web, iOS, Android și desktop. Administrați totul din orice client MCP.
claude mcp add --transport http busymate-ai https://busymate.ai/mcpCăi de intrare
Alegeți de unde începeți
Adăugați asistentul pe site-ul dumneavoastră
Un singur script tag pe orice pagină permiteți — launcherul și chatul pentru vizitatori funcționează imediat.
Puneți asistență AI în aplicația dumneavoastră iOS
Încărcați chatul într-un WKWebView; o punte mică, din trei mesaje, vă autentifică utilizatorii.
Puneți asistență AI în aplicația dumneavoastră Android
Încărcați chatul într-un WebView; o singură interfață JavaScript vă autentifică utilizatorii.
Conectați-vă serverul MCP ca instrumente
Propriul dumneavoastră server MCP devine acțiunile asistentului, în numele fiecărui client.
Administrați fiecare spațiu de lucru din terminal
Conduceți platforma din Claude Code, Cursor sau orice client MCP, prin OAuth.
Lăsați agenții AI să vă citească site-ul
O hartă text simplu a site-ului dumneavoastră la /llms.txt, scrisă pentru agenți AI.
01Start rapid
Cum se leagă totul
Aplicația dumneavoastră rămâne sursa de adevăr. Asistentul primește un token semnat, de scurtă durată, care spune cine este prezent, și vă apelează instrumentele ca actor separat, cu drepturi limitate.
01
Aplicația dumneavoastră
Păstrează identitatea și datele de cont; semnează un token de două minute care spune cine este autentificat.
02
Asistentul
Aplică setările spațiului dumneavoastră de lucru: conținut, modele, niveluri de acces la instrumente, pași de confirmare, preluare.
03
Serverul dumneavoastră MCP
Răspunde la instrumente pentru un singur utilizator o dată, luând utilizatorul din tokenul bearer al celui autentificat — niciodată din argumentele instrumentului.
7 moduri de conectare, un singur asistent: Embed web · Clienți autentificați · iOS · Android · Desktop · API REST · Serverul dumneavoastră MCP
02Clienți autentificați
Recunoașteți clientul deja autentificat
Pentru ca asistentul să poată avea încredere în cine îl întreabă, un singur endpoint autentificat din backendul dumneavoastră semnează un token de scurtă durată (un JWT ES256) cu id-ul stabil al clientului și câteva câmpuri sigure de afișare.
Tokenul trăiește cel mult 120 secunde, poartă un nonce unic și un jti și numește spațiul dumneavoastră de lucru. Cheia privată și sesiunea produsului dumneavoastră nu ajung niciodată în browser sau în 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": "00000000-0000-0000-0000-000000000000", // Your product's registered tenant claim
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("https://YOUR-PRODUCT-DOMAIN (set when you register the provider)")
.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 });
});Tokenul spune cine este acolo, nu ce are voie să facă. Țineți soldurile, dispozitivele, setările și fiecare modificare în spatele unor instrumente care răspund pentru un singur utilizator.
03Web și pagină întreagă
Un singur script pentru un launcher încorporat
SDK-ul cere identitatea backendului dumneavoastră atunci când are nevoie de una, funcționează pentru vizitatori, se reîmprospătează după autentificare și delogare, deschide linkurile externe în afara cadrului și nu are nevoie de cookie-uri terțe.
<!-- Floating "bro" 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, logout, access-token/session
// rotation, or account switch. Do not send an identity postMessage directly.
window.refreshAssistantIdentity = () =>
window.BusymateAI?.refreshIdentity?.() ?? Promise.resolve();
</script>
<script
src="https://your-assistant.busymate.ai/embed/v1.js"
data-assistant="your-assistant"
data-label="Ask bro"
async></script>Deschideți chatul pe pagină întreagă, la adresa dumneavoastră
Când un utilizator autentificat deschide adresa asistentului dumneavoastră sau domeniul propriu, transmiteți tokenul de autentificare în fragmentul URL-ului. Pagina îl șterge înainte de schimb.
// 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
WKWebView cu o punte de mesaje îngustă
Permiteți doar cele trei mesaje versionate: cerere de identitate, răspuns de identitate și URL extern. Emiteți identitatea prin clientul API autentificat existent al aplicației.
// SDK source: https://busymate.ai/sdk/v1/ios/BusymateAI.swift
// Load https://your-assistant.busymate.ai/?channel=ios in a WKWebView.
final class AssistantBridge: NSObject, WKScriptMessageHandler {
let webView: WKWebView
func userContentController(_ controller: WKUserContentController,
didReceive message: WKScriptMessage) {
guard message.name == "BusymateAI",
let body = message.body as? [String: Any],
body["type"] as? String == "busymate.ai.v1.identity_request"
else { return }
Task { // mint through YOUR authenticated API — never a key in the app
let identity = try await api.mintLaunchIdentity()
let payload: [String: Any] = [
"type": "busymate.ai.v1.identity",
"token": identity.token,
"nonce": identity.nonce,
]
let data = try JSONSerialization.data(withJSONObject: payload)
let json = String(decoding: data, as: UTF8.self)
await webView.evaluateJavaScript("window.postMessage(\(json), '*')")
}
}
}05Android
WebView cu o singură interfață permisă
Păstrează navigarea pe originea AI a tenantului, trimite linkurile externe în browserul sistemului și nu expune metode native generice.
// SDK source: https://busymate.ai/sdk/v1/android/BusymateAI.kt
// Load https://your-assistant.busymate.ai/?channel=android in a WebView.
class AssistantBridge(private val webView: WebView) {
@JavascriptInterface
fun postMessage(raw: String) {
val message = JSONObject(raw)
if (message.optString("type") != "busymate.ai.v1.identity_request") return
lifecycleScope.launch { // mint through YOUR authenticated API client
val identity = api.mintLaunchIdentity()
val response = JSONObject()
.put("type", "busymate.ai.v1.identity")
.put("token", identity.token)
.put("nonce", identity.nonce)
webView.evaluateJavascript(
"window.postMessage(${JSONObject.quote(response.toString())}, '*')", null
)
}
}
}
webView.settings.javaScriptEnabled = true
webView.addJavascriptInterface(AssistantBridge(webView), "BusymateAINative")
// SupportChatNative + support.chat.v1.* remain accepted for shipped apps.06Desktop
Același protocol se potrivește cu Electron, Tauri și shell-uri native
Folosiți un WebView izolat, blocați ferestrele noi în cadru, deschideți URL-urile sigure în exterior și răspundeți cererilor de identitate prin stratul privilegiat al aplicației.
import { mountBusymateAI } from "https://busymate.ai/sdk/v1/index.js";
// productAuth is a narrow preload/Tauri command bridge. It calls YOUR
// authenticated backend; no cookie, signing key, or refresh token is exposed
// to the renderer.
const assistant = await mountBusymateAI({
assistant: "your-assistant",
origin: "https://your-assistant.busymate.ai",
label: "Ask bro",
getIdentity: () => window.productAuth.mintAssistantIdentity(),
});
window.productAuth.onSessionChanged(() => assistant.refreshIdentity());
assistant.open();
// Electron main process (Tauri: use the equivalent shell/open allowlist):
mainWindow.webContents.setWindowOpenHandler(({ url }) => {
const target = new URL(url);
if (target.protocol === "https:" || target.protocol === "http:") {
void shell.openExternal(target.href);
}
return { action: "deny" };
});07Instrumente MCP
Dați-i asistentului instrumente fără să-i dați baza de date cu clienți
Publicați scheme complete la descoperire. Dați fiecărui instrument unul dintre cele trei niveluri de acces, marcați modificările care au nevoie de un card de confirmare și reverificați autorizarea la fiecare apel.
Public
Oricine conversează îl poate apela. Prețuri, stare, funcții.
Identificat
Necesită un utilizator autentificat. Starea comenzilor, răspunsuri despre cont.
Delegat
Acționează în numele utilizatorului autentificat, printr-un token de actor cu drepturi limitate sau prin permisiunea OAuth a utilizatorului însuși.
Fiecare modificare este confirmată pe server. Instrumentele pe care le enumerați în confirm_tools se opresc la un card de confirmare înainte să ruleze; la fel și orice nume de instrument pe care asistentul nu îl recunoaște. Cadrele widget nu execută niciodată o modificare.
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 bro 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.Ce vorbește platforma
Același set de protocoale se aplică indiferent dacă platforma este clientul serverului dumneavoastră sau serverul clientului dumneavoastră MCP.
- OAuth 2.1 cu PKCE (S256); clienții publici se înregistrează dinamic (RFC 7591).
- Descoperire prin metadatele serverului de autorizare (RFC 8414) și metadatele resursei protejate (RFC 9728).
- Grants: authorization_code și refresh_token; răspunsul de autorizare poartă issuer-ul (RFC 9207).
- Indicatori de resursă (RFC 8707) atunci când platforma este clientul OAuth către serverul dumneavoastră MCP.
- Schimb de tokenuri (RFC 8693) acolo unde este configurat.
08Preluare și analize
Stabiliți regulile pentru momentul în care intervine un om
Când predă discuția
Un client cere un om, un instrument eșuează, o rambursare depășește limita dumneavoastră, apare un cuvânt-cheie sau orice eveniment definit de dumneavoastră.
Cum este anunțată echipa dumneavoastră
Un singur Inbox; alocare manuală, pe rând sau către cel cu cele mai puține discuții deschise; alerte în aplicație, prin Web Push, APNs și Telegram personal.
Echipa dumneavoastră preia
Urmăriți conversația, intrați cu tot contextul, răspundeți în același chat; asistentul nu face nicio modificare cât timp un om este activ.
Analize
Întrebări repetate, cunoștințe lipsă și trasee eșuate, grupate din conversații reale, cu linkuri către dovezi.
09Login pentru spațiul de lucru
Păstrați-vă propria bază de utilizatori și propria autentificare
Configurați URL-urile de login și de cont ale spațiului de lucru în Consolă. Un vizitator care alege Autentificare părăsește cadrul, se autentifică în produsul dumneavoastră și revine exact la URL-ul de plecare. Backendul dumneavoastră furnizează apoi un token de autentificare de unică folosință; Busymate AI nu primește niciodată parola utilizatorului sau cheia dumneavoastră de semnare.
O modificare atinge întotdeauna doar datele proprii ale utilizatorului autentificat. Instrumentele de cont preiau clientul din actorul delegat, reverifică autorizarea la fiecare apel și cer confirmare pentru modificările pe care le configurați.
10Listă de verificare la lansare
Lista de verificare înainte de lansare
- 01Configurați brandingul, SEO, adresa web și întrebările sugerate.
- 02Înregistrați-vă autentificarea: issuer, JWKS, audiență, claims și vechimea tokenului.
- 03Conectați MCP, stabiliți nivelul de acces al fiecărui instrument, dovediți că citirile sunt limitate la propriul utilizator și că scrierile sunt confirmate.
- 04Stabiliți regulile de preluare, alocați oameni în Inbox, definiți programul și țintele de răspuns.
- 05Testați vizitatorii, utilizatorii autentificați, delogarea și schimbarea de cont, tokenurile reluate și un id de spațiu de lucru schimbat.
- 06Verificați chatul pe pagină întreagă, embedul, iOS, Android, desktopul, accesibilitatea și linkurile externe.
- 07Publicați doar versiunea pe care ați verificat-o; urmăriți starea conexiunilor și a domeniilor.
Sunteți gata să vă configurați spațiul de lucru?
Pagina Integrare din Consolă generează codul și setările pentru fiecare suprafață pornind de la setările dumneavoastră publicate.
MCP de administrare
Administrați fiecare spațiu de lucru din orice client MCP
218 instrumente de administrare prin MCP, cu OAuth 2.1. Clientul deschide o autentificare în browser la prima conectare; nu se lipește nimic manual.
Documente de descoperire
- Endpoint MCP
- https://busymate.ai/mcp
- Metadate ale serverului de autorizare (RFC 8414)
- https://busymate.ai/.well-known/oauth-authorization-server/mcp
- Metadate ale resursei protejate (RFC 9728)
- https://busymate.ai/.well-known/oauth-protected-resource/mcp
Contul cu care vă autentificați decide ce spații de lucru poate administra clientul. Fiecare modificare cere confirmare.
Claude Code
claude mcp add --transport http busymate-ai https://busymate.ai/mcpAdministrează platforma din orice client MCP
Cursor, Claude Desktop și orice client care citește un mcp.json acceptă această intrare; clienții care primesc un URL remote folosesc endpointul de mai sus.
{
"mcpServers": {
"platform-management": {
"type": "http",
"url": "https://busymate.ai/mcp"
}
}
}Ultimele modificări
Ce a fost lansat
Conectați primul instrument chiar astăzi
Înregistrați-vă serverul MCP, alegeți cine poate folosi fiecare instrument, publicați. Asistentul îl poate folosi în același minut.