Busymate AI

المطوّرون

امنح مساعد الذكاء الاصطناعي أدوات حقيقية عبر MCP

امنح المساعد أدوات حقيقية عبر MCP، المعيار المفتوح لربط الذكاء الاصطناعي بأنظمتك. أطلقه على الويب وiOS وAndroid وسطح المكتب. وأدر كل شيء من أي عميل MCP.

claude mcp add --transport http busymate-ai https://busymate.ai/mcp
الطرفية$claude mcp add --transport http busymate-ai https://busymate.ai/mcpمتصلJSON-RPC 2.0 · tools/call{ "jsonrpc": "2.0", "id": 12, "method": "tools/call", "params": { "name": "get_my_account", "arguments": {} } }{ "jsonrpc": "2.0", "id": 12, "result": { "content": [{ "type": "text", "text": "…" }] } }

مداخل البدء

اختر من أين تبدأ

أضف المساعد إلى موقعك الإلكتروني

وسم script واحد على أي صفحة تسمح بها — ويعمل زر الدردشة ودردشة الزوار فورًا.

ضع دعم الذكاء الاصطناعي داخل تطبيق iOS

حمّل الدردشة في WKWebView؛ وجسر صغير من ثلاث رسائل يسجّل دخول مستخدميك.

ضع دعم الذكاء الاصطناعي داخل تطبيق Android

حمّل الدردشة في WebView؛ وواجهة JavaScript واحدة تسجّل دخول مستخدميك.

اربط خادم MCP الخاص بك كأدوات

يصبح خادم MCP الخاص بك هو إجراءات المساعد، نيابةً عن كل عميل.

أدر كل مساحة عمل من طرفيتك

شغّل المنصة من Claude Code أو Cursor أو أي عميل MCP عبر OAuth.

دع وكلاء الذكاء الاصطناعي يقرؤون موقعك

خريطة نصية بسيطة لموقعك على /llms.txt، مكتوبة لوكلاء الذكاء الاصطناعي.

01البدء السريع

كيف تتكامل الأجزاء

يبقى تطبيقك مصدر الحقيقة. ويتلقى المساعد رمزًا موقّعًا قصير الأجل يبيّن من الحاضر، ثم يستدعي أدواتك بصفته فاعلًا منفصلًا محدود الصلاحيات.

عملاؤكموقعك أو تطبيقكالمساعدأنظمتكإعداداتكتُطبَّق تلقائيًا

01

تطبيقك

يحتفظ بالهوية وبيانات الحساب؛ ويوقّع رمزًا صالحًا لدقيقتين يبيّن من سجّل الدخول.

02

المساعد

يطبّق إعدادات مساحة عملك: المحتوى، والنماذج، ومستويات الوصول إلى الأدوات، وخطوات التأكيد، والتحويل.

03

خادم MCP الخاص بك

يجيب عن الأدوات لمستخدم واحد في كل مرة، مستمدًّا هوية المستخدم من الرمز الحامل الموقّع — لا من وسائط الأداة أبدًا.

7 طرق للربط، ومساعد واحد: تضمين الويب · العملاء المسجّلون · iOS · Android · سطح المكتب · REST API · خادم MCP الخاص بك

YOUR HELP SITErobots-aware1–50 pagesIndexRetrieve for an answerwith a source

02العملاء المسجّلون

تعرّف على العميل المسجّل مسبقًا

لكي يثق المساعد بهوية السائل، توقّع نقطة وصول مصادَق عليها واحدة على خادمك رمزًا قصير الأجل (JWT بخوارزمية ES256) يحمل معرّف العميل الثابت لديك وبضعة حقول عرض آمنة.

لا يتجاوز عمر الرمز 120 ثانية، ويحمل رمز nonce ومعرّف jti لمرة واحدة، ويسمّي مساحة عملك. ولا يصل المفتاح الخاص ولا جلسة منتجك إلى المتصفح أو الدردشة إطلاقًا.

Your backendThe browserThe assistantsigns the tokenthe key never leavescarries itchecks your JWKS120s maxchecked
server/bmai-identity.tstypescript
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 });
});

الرمز يقول من الحاضر، لا ما يُسمح له بفعله. أبقِ الأرصدة والأجهزة والإعدادات وكل تغيير خلف أدوات لا تجيب إلا لمستخدم واحد.

03الويب والصفحة الكاملة

سكربت واحد لزر دردشة مضمّن

تطلب حزمة SDK الهوية من خادمك عند الحاجة، وتعمل مع الزوار، وتُحدَّث بعد تسجيل الدخول والخروج، وتفتح الروابط الخارجية خارج الإطار، ولا تحتاج إلى ملفات تعريف ارتباط من جهات خارجية.

index.htmlhtml
<!-- 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>

افتح الدردشة بملء الصفحة على عنوانك

عندما يفتح مستخدم مسجّل عنوان مساعدك أو نطاقك المخصص، مرّر رمز تسجيل الدخول في جزء العنوان (fragment). وتمسحه الصفحة قبل التبادل.

open-assistant.tstypescript
// 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 مع جسر رسائل محدود

اسمح فقط بالرسائل الثلاث ذات الإصدارات: طلب الهوية، والرد على الهوية، والعنوان الخارجي. وأصدِر الهوية عبر عميل واجهة البرمجة المصادَق عليه الموجود أصلًا في التطبيق.

AssistantBridge.swiftswift
// 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 مع واجهة واحدة ضمن قائمة السماح

احصر التنقل في نطاق الذكاء الاصطناعي الخاص بمساحة العميل، وافتح الروابط الخارجية في متصفح النظام، ولا تعرض أساليب أصلية عامة.

AssistantBridge.ktkotlin
// 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.

06سطح المكتب

البروتوكول نفسه يناسب Electron وTauri والأغلفة الأصلية

استخدم WebView معزولًا، وامنع فتح نوافذ جديدة داخل العرض، وافتح العناوين الآمنة خارجيًا، وأجب عن طلبات الهوية عبر طبقة المضيف ذات الصلاحيات.

assistant-renderer.tstypescript
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" };
});

07أدوات MCP

امنح المساعد أدوات دون أن تمنحه قاعدة بيانات عملائك

انشر مخططات كاملة عند الاكتشاف. وامنح كل أداة أحد مستويات الوصول الثلاثة، وحدّد التغييرات التي تحتاج إلى بطاقة تأكيد، وأعد التحقق من الصلاحيات في كل استدعاء.

عام

يجوز لأي شخص يدردش استدعاؤه. الأسعار، والحالة، والميزات.

مُعرَّف

يتطلب مستخدمًا مسجّلًا. حالة الطلبات، وإجابات الحساب.

مفوَّض

يتصرف نيابةً عن المستخدم المسجّل عبر رمز فاعل محدود الصلاحيات أو عبر إذن OAuth الخاص بالمستخدم نفسه.

كل تغيير يُؤكَّد على الخادم. الأدوات التي تدرجها في confirm_tools تتوقف عند بطاقة تأكيد قبل تنفيذها؛ وكذلك أي اسم أداة لا يتعرّف عليه المساعد. ولا تنفّذ إطارات اللوحات أي تغيير إطلاقًا.

oauth-requirements.txttext
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
delegated-call.jsonjson
// 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.

ما تتحدث به المنصة

تنطبق مجموعة البروتوكولات نفسها سواء كانت المنصة عميلًا لخادمك أو خادمًا لعميل MCP لديك.

  • OAuth 2.1 مع PKCE (S256)؛ والعملاء العامّون يسجّلون ديناميكيًا (RFC 7591).
  • الاكتشاف عبر بيانات خادم التفويض (RFC 8414) وبيانات المورد المحمي (RFC 9728).
  • أنواع المنح: authorization_code وrefresh_token؛ واستجابة التفويض تحمل جهة الإصدار (RFC 9207).
  • مؤشرات الموارد (RFC 8707) عندما تكون المنصة هي عميل OAuth لخادم MCP الخاص بك.
  • تبادل الرموز (RFC 8693) حيثما كان مُعدًّا.

08التحويل والرؤى

اضبط قواعد تدخّل الإنسان

متى يحوّل المحادثة

عندما يطلب العميل التحدث إلى إنسان، أو تفشل أداة، أو يتجاوز مبلغ الاسترداد حدّك، أو تظهر كلمة مفتاحية، أو أي حدث تحدده أنت.

كيف يُبلَّغ فريقك

صندوق وارد واحد؛ والإسناد يدويًا أو بالتناوب أو لمن لديه أقل عدد من المحادثات المفتوحة؛ والتنبيهات داخل التطبيق وعبر Web Push وAPNs وTelegram الشخصي.

فريقك يتولى الأمر

راقب المحادثة، وانضم إليها مع كامل السياق، ورد في الدردشة نفسها؛ ولا يجري المساعد أي تغييرات ما دام هناك إنسان نشط.

الرؤى

الأسئلة المتكررة، والمعرفة الناقصة، والمسارات الفاشلة، مجمّعة من محادثات حقيقية مع روابط إلى الأدلة.

09تسجيل الدخول لمساحة العمل

احتفظ بقاعدة مستخدميك ونظام المصادقة الخاص بك

اضبط عناوين تسجيل الدخول والحساب لمساحة العمل في لوحة التحكم. فالزائر الذي يختار تسجيل الدخول يغادر الإطار، ويصادق على منتجك، ثم يعود إلى العنوان الأصلي نفسه بالضبط. بعدها يوفّر خادمك رمز تسجيل دخول لمرة واحدة؛ ولا يتلقى Busymate AI أبدًا كلمة مرور المستخدم ولا مفتاح التوقيع لديك.

لا يمسّ أي تغيير سوى بيانات المستخدم المسجّل نفسه. تأخذ أدوات الحساب هوية العميل من الفاعل المفوَّض، وتعيد التحقق من الصلاحيات في كل استدعاء، وتطلب تأكيدًا على التغييرات التي تحددها أنت.

10قائمة تحقق الإطلاق

قائمة تحقق الإطلاق للإنتاج

  1. 01اضبط الهوية البصرية وتحسين محركات البحث وعنوانك على الويب والأسئلة المقترحة.
  2. 02سجّل نظام تسجيل الدخول لديك: جهة الإصدار، وJWKS، والجمهور، والادعاءات، وعمر الرمز.
  3. 03اربط MCP، وحدّد مستوى الوصول لكل أداة، وأثبت أن عمليات القراءة محصورة بصاحبها وأن عمليات الكتابة مؤكَّدة.
  4. 04اضبط قواعد التحويل، وعيّن فريق صندوق الوارد، وحدّد ساعات العمل وأهداف زمن الاستجابة.
  5. 05اختبر الزوار، والمستخدمين المسجّلين، وتسجيل الخروج وتبديل الحساب، والرموز المُعاد تشغيلها، ومعرّف مساحة عمل مُبدَّل.
  6. 06افحص الدردشة بملء الصفحة، والتضمين، وiOS، وAndroid، وسطح المكتب، وإمكانية الوصول، والروابط الخارجية.
  7. 07لا تنشر إلا النسخة التي فحصتها؛ وراقب صحة الاتصال والنطاق.

هل أنت مستعد لإعداد مساحة عملك؟

تنشئ صفحة التكامل في لوحة التحكم الشيفرة والإعدادات لكل واجهة انطلاقًا من إعداداتك المنشورة.

افتح لوحة التحكم

MCP الإداري

أدر كل مساحة عمل من أي عميل MCP

218 أداة إدارية عبر MCP مع OAuth 2.1. يفتح العميل صفحة تسجيل دخول في المتصفح عند أول اتصال؛ ولا شيء يُلصَق يدويًا.

مستندات الاكتشاف

نقطة وصول MCP
https://busymate.ai/mcp
بيانات خادم التفويض (RFC 8414)
https://busymate.ai/.well-known/oauth-authorization-server/mcp
بيانات المورد المحمي (RFC 9728)
https://busymate.ai/.well-known/oauth-protected-resource/mcp

الحساب الذي تسجّل الدخول به هو ما يحدد مساحات العمل التي يجوز للعميل إدارتها. وكل تغيير يطلب تأكيدًا.

Your MCP clientcreate_artifactJSON-RPCcreated: truehttps://your-assistant.busymate.ai/artifact/…VISIBILITYSitemapGallery

Claude Code

claude-code.shbash
claude mcp add --transport http busymate-ai https://busymate.ai/mcp

أدر المنصة من أي عميل MCP

يقبل Cursor وClaude Desktop وأي عميل يقرأ ملف mcp.json هذا الإدخال؛ أما العملاء الذين يقبلون عنوانًا بعيدًا فيأخذون نقطة الوصول أعلاه.

mcp.jsonjson
{
  "mcpServers": {
    "platform-management": {
      "type": "http",
      "url": "https://busymate.ai/mcp"
    }
  }
}

اربط أول أداة لديك اليوم

سجّل خادم MCP الخاص بك، واختر من يجوز له استخدام كل أداة، ثم انشر. ويمكن للمساعد استخدامها في الدقيقة نفسها.