💄 style: improve mcp server type select and fix refresh mcp manifest issue (#7517)

* improve experience

* fix mcp manifest refresh issue

* improve description

* improve style

* add stdio mcp plugin

* improve experience

* fix tests

* fix tests
This commit is contained in:
Arvin Xu
2025-04-23 09:07:32 +08:00
committed by GitHub
parent 5cdf0e2146
commit 53d8eac3cf
28 changed files with 761 additions and 529 deletions
+4 -9
View File
@@ -21,21 +21,16 @@ module.exports = async ({ github, context, releaseUrl, version, tag }) => {
// Organize assets by platform
const macAssets = release.data.assets.filter(
(asset) =>
((asset.name.includes('.dmg') || asset.name.includes('.zip')) &&
!asset.name.includes('.blockmap')) ||
(asset.name.includes('latest-mac') && asset.name.endsWith('.yml')),
(asset.name.includes('.dmg') || asset.name.includes('.zip')) &&
!asset.name.includes('.blockmap'),
);
const winAssets = release.data.assets.filter(
(asset) =>
(asset.name.includes('.exe') && !asset.name.includes('.blockmap')) ||
(asset.name.includes('latest-win') && asset.name.endsWith('.yml')),
(asset) => asset.name.includes('.exe') && !asset.name.includes('.blockmap'),
);
const linuxAssets = release.data.assets.filter(
(asset) =>
(asset.name.includes('.AppImage') && !asset.name.includes('.blockmap')) ||
(asset.name.includes('latest-linux') && asset.name.endsWith('.yml')),
(asset) => asset.name.includes('.AppImage') && !asset.name.includes('.blockmap'),
);
// Generate combined download table
+31 -31
View File
@@ -34,37 +34,6 @@
"desc": "العلامة المميزة للبرنامج المساعد",
"label": "المعرف"
},
"mcp": {
"args": {
"desc": "قائمة المعلمات المرسلة إلى أمر STDIO",
"label": "معلمات الأمر",
"placeholder": "على سبيل المثال: --port 8080 --debug",
"tooltip": "اضغط على Enter بعد إدخال المعلمات أو استخدم الفاصلة/المسافة للفصل"
},
"command": {
"desc": "الملف القابل للتنفيذ أو البرنامج النصي لبدء مكون MCP STDIO",
"label": "الأمر",
"placeholder": "على سبيل المثال: python main.py أو /path/to/executable"
},
"endpoint": {
"desc": "أدخل عنوان خادم HTTP القابل للبث MCP الخاص بك",
"label": "عنوان URL لنقطة نهاية MCP"
},
"identifier": {
"desc": "حدد اسمًا لمكون MCP الخاص بك، يجب أن يكون باستخدام أحرف إنجليزية",
"invalid": "يمكنك إدخال أحرف إنجليزية، أرقام، والرمزين - و _ فقط",
"label": "اسم مكون MCP",
"placeholder": "على سبيل المثال: my-mcp-plugin"
},
"type": {
"desc": "اختر طريقة الاتصال لمكون MCP، النسخة على الويب تدعم فقط HTTP القابل للبث",
"label": "نوع مكون MCP"
},
"url": {
"desc": "أدخل عنوان نقطة نهاية مكون HTTP MCP الخاص بك",
"label": "عنوان URL لنقطة نهاية HTTP"
}
},
"mode": {
"mcp": "مكون MCP",
"mcpExp": "تجريبي",
@@ -76,6 +45,37 @@
"placeholder": "محرك البحث"
}
},
"mcp": {
"args": {
"desc": "قائمة المعلمات المرسلة إلى أمر STDIO",
"label": "معلمات الأمر",
"placeholder": "على سبيل المثال: --port 8080 --debug",
"tooltip": "اضغط على Enter بعد إدخال المعلمات أو استخدم الفاصلة/المسافة للفصل"
},
"command": {
"desc": "الملف القابل للتنفيذ أو البرنامج النصي المستخدم لبدء ملحق MCP STDIO",
"label": "الأمر",
"placeholder": "على سبيل المثال: python main.py أو /path/to/executable"
},
"endpoint": {
"desc": "أدخل عنوان خادم MCP Streamable HTTP الخاص بك",
"label": "عنوان URL لنقطة نهاية MCP"
},
"identifier": {
"desc": "حدد اسمًا لملحق MCP الخاص بك، يجب أن يكون باستخدام أحرف إنجليزية",
"invalid": "يمكنك إدخال أحرف إنجليزية، أرقام، والرمزين - و _ فقط",
"label": "اسم ملحق MCP",
"placeholder": "على سبيل المثال: my-mcp-plugin"
},
"type": {
"desc": "اختر طريقة الاتصال لملحق MCP، النسخة الويب تدعم فقط Streamable HTTP",
"label": "نوع ملحق MCP"
},
"url": {
"desc": "أدخل عنوان HTTP القابل للبث لخادم MCP الخاص بك، ولا ينتهي بـ /sse",
"label": "عنوان URL لنقطة نهاية HTTP"
}
},
"meta": {
"author": {
"desc": "مؤلف البرنامج المساعد",
+31 -31
View File
@@ -34,37 +34,6 @@
"desc": "Уникалният идентификатор на плъгина",
"label": "Идентификатор"
},
"mcp": {
"args": {
"desc": "Списък с параметри, предадени на STDIO командата",
"label": "Командни параметри",
"placeholder": "Например: --port 8080 --debug",
"tooltip": "Натиснете Enter след въвеждане на параметри или използвайте запетая/интервал за разделяне"
},
"command": {
"desc": "Изпълним файл или скрипт за стартиране на MCP STDIO плъгина",
"label": "Команда",
"placeholder": "Например: python main.py или /path/to/executable"
},
"endpoint": {
"desc": "Въведете адреса на вашия MCP Streamable HTTP сървър",
"label": "MCP Endpoint URL"
},
"identifier": {
"desc": "Определете име за вашия MCP плъгин, трябва да използвате английски символи",
"invalid": "Можете да въвеждате само английски символи, цифри, - и _",
"label": "Име на MCP плъгин",
"placeholder": "Например: my-mcp-plugin"
},
"type": {
"desc": "Изберете начина на комуникация на MCP плъгина, уеб версията поддържа само Streamable HTTP",
"label": "Тип на MCP плъгин"
},
"url": {
"desc": "Въведете адреса на вашия MCP HTTP плъгин",
"label": "HTTP Endpoint URL"
}
},
"mode": {
"mcp": "MCP плъгин",
"mcpExp": "Експериментален",
@@ -76,6 +45,37 @@
"placeholder": "Търсачка"
}
},
"mcp": {
"args": {
"desc": "Списък с параметри, предадени на STDIO командата",
"label": "Командни параметри",
"placeholder": "Например: --port 8080 --debug",
"tooltip": "Натиснете Enter след въвеждане на параметри или използвайте запетая/интервал за разделяне"
},
"command": {
"desc": "Изпълним файл или скрипт за стартиране на MCP STDIO плъгин",
"label": "Команда",
"placeholder": "Например: python main.py или /path/to/executable"
},
"endpoint": {
"desc": "Въведете адреса на вашия MCP Streamable HTTP Server",
"label": "MCP Endpoint URL"
},
"identifier": {
"desc": "Определете име за вашия MCP плъгин, трябва да използвате английски символи",
"invalid": "Можете да въвеждате само английски символи, цифри, - и _",
"label": "Име на MCP плъгин",
"placeholder": "Например: my-mcp-plugin"
},
"type": {
"desc": "Изберете начина на комуникация на MCP плъгина, уеб версията поддържа само Streamable HTTP",
"label": "Тип на MCP плъгин"
},
"url": {
"desc": "Въведете адреса на вашия MCP сървър Streamable HTTP, който не завършва с /sse",
"label": "HTTP Endpoint URL"
}
},
"meta": {
"author": {
"desc": "Авторът на плъгина",
+3 -8
View File
@@ -47,15 +47,10 @@
},
"mcp": {
"args": {
"desc": "Liste der Parameter, die an den STDIO-Befehl übergeben werden",
"label": "Befehlsparameter",
"placeholder": "z.B.: --port 8080 --debug",
"tooltip": "Drücken Sie die Eingabetaste oder verwenden Sie Kommas/Leerzeichen zur Trennung der Eingabeparameter"
"label": "Befehlsparameter"
},
"command": {
"desc": "Die ausführbare Datei oder das Skript zum Starten des MCP STDIO-Plugins",
"label": "Befehl",
"placeholder": "z.B.: python main.py oder /path/to/executable"
"label": "Befehl"
},
"endpoint": {
"desc": "Geben Sie die Adresse Ihres MCP Streamable HTTP Servers ein",
@@ -72,7 +67,7 @@
"label": "MCP-Plugin-Typ"
},
"url": {
"desc": "Geben Sie die Endpoint-Adresse Ihres MCP HTTP-Plugins ein",
"desc": "Geben Sie Ihre MCP-Server-Streamable-HTTP-Adresse ein, die nicht mit /sse endet",
"label": "HTTP Endpoint-URL"
}
},
+3 -8
View File
@@ -47,15 +47,10 @@
},
"mcp": {
"args": {
"desc": "List of parameters to pass to the STDIO command",
"label": "Command Parameters",
"placeholder": "e.g., --port 8080 --debug",
"tooltip": "Press Enter after entering parameters or separate with commas/spaces"
"label": "Command Parameters"
},
"command": {
"desc": "Executable file or script to start the MCP STDIO plugin",
"label": "Command",
"placeholder": "e.g., python main.py or /path/to/executable"
"label": "Command"
},
"endpoint": {
"desc": "Enter the address of your MCP Streamable HTTP Server",
@@ -72,7 +67,7 @@
"label": "MCP Plugin Type"
},
"url": {
"desc": "Enter the Endpoint address of your MCP HTTP plugin",
"desc": "Enter your MCP Server Streamable HTTP address, which should not end with /sse",
"label": "HTTP Endpoint URL"
}
},
+31 -31
View File
@@ -34,37 +34,6 @@
"desc": "Identificador único del complemento",
"label": "Identificador"
},
"mcp": {
"args": {
"desc": "Lista de parámetros a pasar al comando STDIO",
"label": "Parámetros del comando",
"placeholder": "Por ejemplo: --port 8080 --debug",
"tooltip": "Presiona enter después de ingresar los parámetros o usa comas/espacios para separarlos"
},
"command": {
"desc": "Archivo ejecutable o script para iniciar el plugin MCP STDIO",
"label": "Comando",
"placeholder": "Por ejemplo: python main.py o /ruta/al/ejecutable"
},
"endpoint": {
"desc": "Ingresa la dirección de tu servidor HTTP Streamable MCP",
"label": "URL del Endpoint MCP"
},
"identifier": {
"desc": "Especifica un nombre para tu plugin MCP, debe usar caracteres en inglés",
"invalid": "Solo se pueden ingresar caracteres en inglés, números, y los símbolos - y _",
"label": "Nombre del plugin MCP",
"placeholder": "Por ejemplo: my-mcp-plugin"
},
"type": {
"desc": "Selecciona el método de comunicación del plugin MCP, la versión web solo soporta HTTP Streamable",
"label": "Tipo de plugin MCP"
},
"url": {
"desc": "Ingresa la dirección del Endpoint de tu plugin HTTP MCP",
"label": "URL del Endpoint HTTP"
}
},
"mode": {
"mcp": "Plugin MCP",
"mcpExp": "Experimental",
@@ -76,6 +45,37 @@
"placeholder": "Buscar motor de búsqueda"
}
},
"mcp": {
"args": {
"desc": "Lista de parámetros a pasar al comando STDIO",
"label": "Parámetros del comando",
"placeholder": "Por ejemplo: --port 8080 --debug",
"tooltip": "Presiona enter o usa comas/espacios para separar los parámetros después de ingresarlos"
},
"command": {
"desc": "Archivo ejecutable o script para iniciar el complemento MCP STDIO",
"label": "Comando",
"placeholder": "Por ejemplo: python main.py o /ruta/al/ejecutable"
},
"endpoint": {
"desc": "Ingresa la dirección de tu servidor HTTP Streamable MCP",
"label": "URL del Endpoint MCP"
},
"identifier": {
"desc": "Especifica un nombre para tu complemento MCP, debe usar caracteres en inglés",
"invalid": "Solo se pueden ingresar caracteres en inglés, números, y los símbolos - y _",
"label": "Nombre del complemento MCP",
"placeholder": "Por ejemplo: my-mcp-plugin"
},
"type": {
"desc": "Selecciona el método de comunicación del complemento MCP, la versión web solo admite HTTP Streamable",
"label": "Tipo de complemento MCP"
},
"url": {
"desc": "Introduce la dirección HTTP transmitible de tu servidor MCP, que no debe terminar con /sse",
"label": "URL del Endpoint HTTP"
}
},
"meta": {
"author": {
"desc": "Autor del complemento",
+31 -31
View File
@@ -34,37 +34,6 @@
"desc": "شناسه‌ی یکتای افزونه",
"label": "شناسه"
},
"mcp": {
"args": {
"desc": "لیست پارامترهای منتقل شده به دستور STDIO",
"label": "پارامترهای دستور",
"placeholder": "برای مثال: --port 8080 --debug",
"tooltip": "پس از وارد کردن پارامترها، کلید Enter را فشار دهید یا از کاما/فاصله برای جداسازی استفاده کنید"
},
"command": {
"desc": "فایل اجرایی یا اسکریپتی که برای راه‌اندازی افزونه MCP STDIO استفاده می‌شود",
"label": "دستور",
"placeholder": "برای مثال: python main.py یا /path/to/executable"
},
"endpoint": {
"desc": "آدرس سرور HTTP Streamable MCP خود را وارد کنید",
"label": "آدرس URL Endpoint MCP"
},
"identifier": {
"desc": "برای افزونه MCP خود یک نام مشخص کنید، باید از کاراکترهای انگلیسی استفاده کنید",
"invalid": "فقط می‌توانید از کاراکترهای انگلیسی، اعداد، و دو علامت - و _ استفاده کنید",
"label": "نام افزونه MCP",
"placeholder": "برای مثال: my-mcp-plugin"
},
"type": {
"desc": "روش ارتباطی افزونه MCP را انتخاب کنید، نسخه وب فقط از Streamable HTTP پشتیبانی می‌کند",
"label": "نوع افزونه MCP"
},
"url": {
"desc": "آدرس Endpoint افزونه HTTP MCP خود را وارد کنید",
"label": "آدرس URL Endpoint HTTP"
}
},
"mode": {
"mcp": "افزونه MCP",
"mcpExp": "تجربی",
@@ -76,6 +45,37 @@
"placeholder": "موتور جستجو"
}
},
"mcp": {
"args": {
"desc": "لیست پارامترهای منتقل شده به دستور STDIO",
"label": "پارامترهای دستور",
"placeholder": "برای مثال: --port 8080 --debug",
"tooltip": "پس از وارد کردن پارامترها، Enter را بزنید یا از ویرگول/فاصله استفاده کنید"
},
"command": {
"desc": "فایل اجرایی یا اسکریپتی که برای راه‌اندازی افزونه MCP STDIO استفاده می‌شود",
"label": "دستور",
"placeholder": "برای مثال: python main.py یا /path/to/executable"
},
"endpoint": {
"desc": "آدرس سرور HTTP Streamable MCP خود را وارد کنید",
"label": "آدرس URL نقطه پایانی MCP"
},
"identifier": {
"desc": "برای افزونه MCP خود یک نام مشخص کنید، باید از کاراکترهای انگلیسی استفاده کنید",
"invalid": "فقط می‌توانید از کاراکترهای انگلیسی، اعداد، - و _ استفاده کنید",
"label": "نام افزونه MCP",
"placeholder": "برای مثال: my-mcp-plugin"
},
"type": {
"desc": "روش ارتباط افزونه MCP را انتخاب کنید، نسخه وب فقط از HTTP Streamable پشتیبانی می‌کند",
"label": "نوع افزونه MCP"
},
"url": {
"desc": "آدرس HTTP قابل پخش سرور MCP خود را وارد کنید، که با /sse پایان نمی‌یابد",
"label": "آدرس URL نقطه پایانی HTTP"
}
},
"meta": {
"author": {
"desc": "نویسنده افزونه",
+31 -31
View File
@@ -34,37 +34,6 @@
"desc": "Identifiant unique du plugin",
"label": "Identifiant"
},
"mcp": {
"args": {
"desc": "Liste des paramètres à passer à la commande STDIO",
"label": "Paramètres de commande",
"placeholder": "Par exemple : --port 8080 --debug",
"tooltip": "Appuyez sur Entrée après avoir saisi les paramètres ou utilisez une virgule/un espace pour les séparer"
},
"command": {
"desc": "Fichier exécutable ou script utilisé pour démarrer le plugin MCP STDIO",
"label": "Commande",
"placeholder": "Par exemple : python main.py ou /path/to/executable"
},
"endpoint": {
"desc": "Entrez l'adresse de votre serveur HTTP Streamable MCP",
"label": "URL de l'endpoint MCP"
},
"identifier": {
"desc": "Donnez un nom à votre plugin MCP, doit utiliser des caractères anglais",
"invalid": "Vous ne pouvez entrer que des caractères anglais, des chiffres, - et _",
"label": "Nom du plugin MCP",
"placeholder": "Par exemple : mon-plugin-mcp"
},
"type": {
"desc": "Choisissez le mode de communication du plugin MCP, la version web ne prend en charge que HTTP Streamable",
"label": "Type de plugin MCP"
},
"url": {
"desc": "Entrez l'adresse de l'endpoint de votre plugin HTTP MCP",
"label": "URL de l'endpoint HTTP"
}
},
"mode": {
"mcp": "Plugin MCP",
"mcpExp": "Expérimental",
@@ -76,6 +45,37 @@
"placeholder": "Moteur de recherche"
}
},
"mcp": {
"args": {
"desc": "Liste des paramètres à passer à la commande STDIO",
"label": "Paramètres de commande",
"placeholder": "Par exemple : --port 8080 --debug",
"tooltip": "Appuyez sur Entrée après avoir saisi les paramètres ou utilisez une virgule/un espace pour les séparer"
},
"command": {
"desc": "Fichier exécutable ou script utilisé pour démarrer le plugin MCP STDIO",
"label": "Commande",
"placeholder": "Par exemple : python main.py ou /path/to/executable"
},
"endpoint": {
"desc": "Entrez l'adresse de votre serveur HTTP Streamable MCP",
"label": "URL de l'endpoint MCP"
},
"identifier": {
"desc": "Donnez un nom à votre plugin MCP, en utilisant des caractères anglais",
"invalid": "Vous ne pouvez entrer que des caractères anglais, des chiffres, - et _",
"label": "Nom du plugin MCP",
"placeholder": "Par exemple : my-mcp-plugin"
},
"type": {
"desc": "Choisissez le mode de communication du plugin MCP, la version web ne prend en charge que le HTTP Streamable",
"label": "Type de plugin MCP"
},
"url": {
"desc": "Entrez l'adresse HTTP Streamable de votre serveur MCP, sans terminer par /sse",
"label": "URL de l'endpoint HTTP"
}
},
"meta": {
"author": {
"desc": "Auteur du plugin",
+31 -31
View File
@@ -34,37 +34,6 @@
"desc": "Identificatore univoco del plugin",
"label": "Identificatore"
},
"mcp": {
"args": {
"desc": "Elenco di parametri da passare al comando STDIO",
"label": "Parametri del comando",
"placeholder": "Ad esempio: --port 8080 --debug",
"tooltip": "Premi invio dopo aver inserito i parametri o separali con una virgola/spazio"
},
"command": {
"desc": "File eseguibile o script per avviare il plugin MCP STDIO",
"label": "Comando",
"placeholder": "Ad esempio: python main.py o /path/to/executable"
},
"endpoint": {
"desc": "Inserisci l'indirizzo del tuo server HTTP Streamable MCP",
"label": "URL Endpoint MCP"
},
"identifier": {
"desc": "Assegna un nome al tuo plugin MCP, deve utilizzare caratteri inglesi",
"invalid": "Puoi inserire solo caratteri inglesi, numeri, e i simboli - e _",
"label": "Nome del plugin MCP",
"placeholder": "Ad esempio: my-mcp-plugin"
},
"type": {
"desc": "Seleziona il metodo di comunicazione del plugin MCP, la versione web supporta solo Streamable HTTP",
"label": "Tipo di plugin MCP"
},
"url": {
"desc": "Inserisci l'indirizzo Endpoint del tuo plugin HTTP MCP",
"label": "URL Endpoint HTTP"
}
},
"mode": {
"mcp": "Plugin MCP",
"mcpExp": "Sperimentale",
@@ -76,6 +45,37 @@
"placeholder": "Motore di ricerca"
}
},
"mcp": {
"args": {
"desc": "Elenco dei parametri da passare al comando STDIO",
"label": "Parametri del comando",
"placeholder": "Ad esempio: --port 8080 --debug",
"tooltip": "Premi invio dopo aver inserito i parametri o separali con una virgola/spazio"
},
"command": {
"desc": "File eseguibile o script per avviare il plugin MCP STDIO",
"label": "Comando",
"placeholder": "Ad esempio: python main.py o /path/to/executable"
},
"endpoint": {
"desc": "Inserisci l'indirizzo del tuo server HTTP Streamable MCP",
"label": "URL Endpoint MCP"
},
"identifier": {
"desc": "Assegna un nome al tuo plugin MCP, deve utilizzare caratteri inglesi",
"invalid": "Puoi inserire solo caratteri inglesi, numeri, e i simboli - e _",
"label": "Nome del plugin MCP",
"placeholder": "Ad esempio: my-mcp-plugin"
},
"type": {
"desc": "Scegli il metodo di comunicazione del plugin MCP, la versione web supporta solo Streamable HTTP",
"label": "Tipo di plugin MCP"
},
"url": {
"desc": "Inserisci l'indirizzo HTTP Streamable del tuo server MCP, che non deve terminare con /sse",
"label": "URL Endpoint HTTP"
}
},
"meta": {
"author": {
"desc": "Autore del plugin",
+31 -31
View File
@@ -34,37 +34,6 @@
"desc": "プラグインの一意の識別子",
"label": "識別子"
},
"mcp": {
"args": {
"desc": "STDIO コマンドに渡すパラメータのリスト",
"label": "コマンドパラメータ",
"placeholder": "例:--port 8080 --debug",
"tooltip": "パラメータを入力したら Enter を押すか、カンマ/スペースで区切ってください"
},
"command": {
"desc": "MCP STDIO プラグインを起動するための実行可能ファイルまたはスクリプト",
"label": "コマンド",
"placeholder": "例:python main.py または /path/to/executable"
},
"endpoint": {
"desc": "あなたの MCP ストリーミング HTTP サーバーのアドレスを入力してください",
"label": "MCP エンドポイント URL"
},
"identifier": {
"desc": "あなたの MCP プラグインに名前を指定してください。英字を使用する必要があります",
"invalid": "英字、数字、- および _ のみ入力できます",
"label": "MCP プラグイン名",
"placeholder": "例:my-mcp-plugin"
},
"type": {
"desc": "MCP プラグインの通信方法を選択してください。ウェブ版はストリーミング HTTP のみサポートしています",
"label": "MCP プラグインタイプ"
},
"url": {
"desc": "あなたの MCP HTTP プラグインのエンドポイントアドレスを入力してください",
"label": "HTTP エンドポイント URL"
}
},
"mode": {
"mcp": "MCP プラグイン",
"mcpExp": "実験的",
@@ -76,6 +45,37 @@
"placeholder": "検索エンジン"
}
},
"mcp": {
"args": {
"desc": "STDIO コマンドに渡すパラメータのリスト",
"label": "コマンドパラメータ",
"placeholder": "例:--port 8080 --debug",
"tooltip": "パラメータを入力したら、Enter キーを押すか、カンマ/スペースで区切ってください"
},
"command": {
"desc": "MCP STDIO プラグインを起動するための実行可能ファイルまたはスクリプト",
"label": "コマンド",
"placeholder": "例:python main.py または /path/to/executable"
},
"endpoint": {
"desc": "あなたの MCP Streamable HTTP サーバーのアドレスを入力してください",
"label": "MCP エンドポイント URL"
},
"identifier": {
"desc": "あなたの MCP プラグインに名前を指定してください。英字を使用する必要があります",
"invalid": "英字、数字、- および _ のみを入力できます",
"label": "MCP プラグイン名",
"placeholder": "例:my-mcp-plugin"
},
"type": {
"desc": "MCP プラグインの通信方式を選択してください。ウェブ版は Streamable HTTP のみをサポートしています",
"label": "MCP プラグインタイプ"
},
"url": {
"desc": "あなたのMCPサーバーストリーミングHTTPアドレスを入力してください。/sseで終わることはありません",
"label": "HTTP エンドポイント URL"
}
},
"meta": {
"author": {
"desc": "プラグインの作者",
+3 -8
View File
@@ -47,15 +47,10 @@
},
"mcp": {
"args": {
"desc": "STDIO 명령에 전달할 매개변수 목록",
"label": "명령 매개변수",
"placeholder": "예: --port 8080 --debug",
"tooltip": "매개변수를 입력한 후 Enter 키를 누르거나 쉼표/공백으로 구분하세요"
"label": "명령 매개변수"
},
"command": {
"desc": "MCP STDIO 플러그인을 시작하는 실행 파일 또는 스크립트",
"label": "명령",
"placeholder": "예: python main.py 또는 /path/to/executable"
"label": "명령"
},
"endpoint": {
"desc": "당신의 MCP 스트리밍 HTTP 서버 주소를 입력하세요",
@@ -72,7 +67,7 @@
"label": "MCP 플러그인 유형"
},
"url": {
"desc": "당신의 MCP HTTP 플러그인의 엔드포인트 주소를 입력하세요",
"desc": "MCP 서버의 스트리밍 HTTP 주소를 입력하세요. /sse로 끝나지 않습니다.",
"label": "HTTP 엔드포인트 URL"
}
},
+31 -31
View File
@@ -34,37 +34,6 @@
"desc": "De unieke identificatie van de plug-in",
"label": "Identificatie"
},
"mcp": {
"args": {
"desc": "Lijst van parameters die aan het STDIO-commando worden doorgegeven",
"label": "Commando-parameters",
"placeholder": "Bijvoorbeeld: --port 8080 --debug",
"tooltip": "Druk op enter of gebruik komma's/spaties om parameters te scheiden"
},
"command": {
"desc": "Uitvoerbaar bestand of script om de MCP STDIO-plugin te starten",
"label": "Commando",
"placeholder": "Bijvoorbeeld: python main.py of /path/to/executable"
},
"endpoint": {
"desc": "Voer het adres van je MCP Streamable HTTP Server in",
"label": "MCP Endpoint URL"
},
"identifier": {
"desc": "Geef je MCP-plugin een naam, gebruik Engelse karakters",
"invalid": "Alleen Engelse karakters, cijfers, - en _ zijn toegestaan",
"label": "Naam van de MCP-plugin",
"placeholder": "Bijvoorbeeld: my-mcp-plugin"
},
"type": {
"desc": "Kies de communicatiemethode voor de MCP-plugin, de webversie ondersteunt alleen Streamable HTTP",
"label": "Type MCP-plugin"
},
"url": {
"desc": "Voer het Endpoint-adres van je MCP HTTP-plugin in",
"label": "HTTP Endpoint URL"
}
},
"mode": {
"mcp": "MCP-plugin",
"mcpExp": "Experimenteel",
@@ -76,6 +45,37 @@
"placeholder": "Zoekmachine"
}
},
"mcp": {
"args": {
"desc": "Lijst van parameters die aan het STDIO-commando worden doorgegeven",
"label": "Commando-parameters",
"placeholder": "Bijvoorbeeld: --port 8080 --debug",
"tooltip": "Druk op enter of gebruik een komma/spatie om de parameters te scheiden na invoer"
},
"command": {
"desc": "Uitvoerbaar bestand of script om de MCP STDIO-plugin te starten",
"label": "Commando",
"placeholder": "Bijvoorbeeld: python main.py of /path/to/executable"
},
"endpoint": {
"desc": "Voer het adres van je MCP Streamable HTTP Server in",
"label": "MCP Endpoint URL"
},
"identifier": {
"desc": "Geef je MCP-plugin een naam, gebruik Engelse karakters",
"invalid": "Alleen Engelse karakters, cijfers, - en _ zijn toegestaan",
"label": "MCP Plugin Naam",
"placeholder": "Bijvoorbeeld: my-mcp-plugin"
},
"type": {
"desc": "Kies de communicatiemethode voor de MCP-plugin, de webversie ondersteunt alleen Streamable HTTP",
"label": "MCP Plugin Type"
},
"url": {
"desc": "Voer je MCP Server Streamable HTTP-adres in, dit eindigt niet op /sse",
"label": "HTTP Endpoint URL"
}
},
"meta": {
"author": {
"desc": "De auteur van de plug-in",
+3 -8
View File
@@ -47,15 +47,10 @@
},
"mcp": {
"args": {
"desc": "Lista argumentów przekazywanych do polecenia STDIO",
"label": "Argumenty polecenia",
"placeholder": "Na przykład: --port 8080 --debug",
"tooltip": "Naciśnij Enter po wprowadzeniu argumentów lub użyj przecinka/spacji jako separatora"
"label": "Argumenty polecenia"
},
"command": {
"desc": "Wykonywalny plik lub skrypt do uruchomienia wtyczki MCP STDIO",
"label": "Polecenie",
"placeholder": "Na przykład: python main.py lub /path/to/executable"
"label": "Polecenie"
},
"endpoint": {
"desc": "Wprowadź adres swojego serwera MCP Streamable HTTP",
@@ -72,7 +67,7 @@
"label": "Typ wtyczki MCP"
},
"url": {
"desc": "Wprowadź adres punktu końcowego swojej wtyczki MCP HTTP",
"desc": "Wprowadź adres HTTP swojego serwera MCP Streamable, który nie kończy się na /sse",
"label": "URL punktu końcowego HTTP"
}
},
+31 -31
View File
@@ -34,37 +34,6 @@
"desc": "Identificador único do plugin",
"label": "Identificador"
},
"mcp": {
"args": {
"desc": "Lista de parâmetros a serem passados para o comando STDIO",
"label": "Parâmetros do comando",
"placeholder": "Por exemplo: --port 8080 --debug",
"tooltip": "Pressione Enter após inserir os parâmetros ou use vírgula/espaço para separar"
},
"command": {
"desc": "Arquivo executável ou script usado para iniciar o plugin MCP STDIO",
"label": "Comando",
"placeholder": "Por exemplo: python main.py ou /caminho/para/executável"
},
"endpoint": {
"desc": "Insira o endereço do seu Servidor HTTP Streamable MCP",
"label": "URL do Endpoint MCP"
},
"identifier": {
"desc": "Dê um nome ao seu plugin MCP, deve usar caracteres em inglês",
"invalid": "Somente caracteres em inglês, números, - e _ são permitidos",
"label": "Nome do plugin MCP",
"placeholder": "Por exemplo: meu-plugin-mcp"
},
"type": {
"desc": "Escolha o método de comunicação do plugin MCP, a versão web suporta apenas HTTP Streamable",
"label": "Tipo de plugin MCP"
},
"url": {
"desc": "Insira o endereço do Endpoint do seu plugin HTTP MCP",
"label": "URL do Endpoint HTTP"
}
},
"mode": {
"mcp": "Plugin MCP",
"mcpExp": "Experimental",
@@ -76,6 +45,37 @@
"placeholder": "Pesquisar mecanismo de busca"
}
},
"mcp": {
"args": {
"desc": "Lista de parâmetros a serem passados para o comando STDIO",
"label": "Parâmetros do comando",
"placeholder": "Por exemplo: --port 8080 --debug",
"tooltip": "Pressione Enter após inserir os parâmetros ou use vírgula/espaço para separar"
},
"command": {
"desc": "Arquivo executável ou script usado para iniciar o plugin MCP STDIO",
"label": "Comando",
"placeholder": "Por exemplo: python main.py ou /caminho/para/executável"
},
"endpoint": {
"desc": "Insira o endereço do seu Servidor HTTP Streamable MCP",
"label": "URL do Endpoint MCP"
},
"identifier": {
"desc": "Dê um nome ao seu plugin MCP, deve usar caracteres em inglês",
"invalid": "Somente caracteres em inglês, números, - e _ são permitidos",
"label": "Nome do plugin MCP",
"placeholder": "Por exemplo: meu-plugin-mcp"
},
"type": {
"desc": "Escolha o método de comunicação do plugin MCP, a versão web suporta apenas Streamable HTTP",
"label": "Tipo de plugin MCP"
},
"url": {
"desc": "Insira o endereço HTTP Streamable do seu servidor MCP, que não deve terminar com /sse",
"label": "URL do Endpoint HTTP"
}
},
"meta": {
"author": {
"desc": "Autor do plugin",
+31 -31
View File
@@ -34,37 +34,6 @@
"desc": "Уникальный идентификатор плагина",
"label": "Идентификатор"
},
"mcp": {
"args": {
"desc": "Список параметров, передаваемых в команду STDIO",
"label": "Параметры команды",
"placeholder": "Например: --port 8080 --debug",
"tooltip": "Нажмите Enter после ввода параметров или используйте запятую/пробел для разделения"
},
"command": {
"desc": "Исполняемый файл или скрипт для запуска MCP STDIO плагина",
"label": "Команда",
"placeholder": "Например: python main.py или /path/to/executable"
},
"endpoint": {
"desc": "Введите адрес вашего MCP Streamable HTTP сервера",
"label": "MCP Endpoint URL"
},
"identifier": {
"desc": "Укажите имя для вашего MCP плагина, необходимо использовать английские символы",
"invalid": "Можно вводить только английские буквы, цифры, символы - и _",
"label": "Имя MCP плагина",
"placeholder": "Например: my-mcp-plugin"
},
"type": {
"desc": "Выберите способ связи для MCP плагина, веб-версия поддерживает только Streamable HTTP",
"label": "Тип MCP плагина"
},
"url": {
"desc": "Введите адрес Endpoint вашего MCP HTTP плагина",
"label": "HTTP Endpoint URL"
}
},
"mode": {
"mcp": "MCP плагин",
"mcpExp": "Экспериментальный",
@@ -76,6 +45,37 @@
"placeholder": "Поиск в поисковике"
}
},
"mcp": {
"args": {
"desc": "Список параметров, передаваемых команде STDIO",
"label": "Параметры команды",
"placeholder": "Например: --port 8080 --debug",
"tooltip": "Нажмите Enter после ввода параметров или используйте запятую/пробел для разделения"
},
"command": {
"desc": "Исполняемый файл или скрипт для запуска плагина MCP STDIO",
"label": "Команда",
"placeholder": "Например: python main.py или /path/to/executable"
},
"endpoint": {
"desc": "Введите адрес вашего MCP Streamable HTTP Server",
"label": "URL-адрес MCP Endpoint"
},
"identifier": {
"desc": "Укажите имя для вашего MCP плагина, необходимо использовать английские символы",
"invalid": "Можно вводить только английские буквы, цифры, символы - и _",
"label": "Имя MCP плагина",
"placeholder": "Например: my-mcp-plugin"
},
"type": {
"desc": "Выберите способ связи для MCP плагина, веб-версия поддерживает только Streamable HTTP",
"label": "Тип MCP плагина"
},
"url": {
"desc": "Введите адрес вашего MCP Server Streamable HTTP, который не заканчивается на /sse",
"label": "URL-адрес HTTP Endpoint"
}
},
"meta": {
"author": {
"desc": "Автор плагина",
+31 -31
View File
@@ -34,37 +34,6 @@
"desc": "Eklenti için benzersiz tanımlayıcı",
"label": "Tanımlayıcı"
},
"mcp": {
"args": {
"desc": "STDIO komutuna iletilen parametreler listesi",
"label": "Komut Parametreleri",
"placeholder": "Örneğin: --port 8080 --debug",
"tooltip": "Parametreleri girdikten sonra enter tuşuna basın veya virgül/boşluk ile ayırın"
},
"command": {
"desc": "MCP STDIO eklentisini başlatmak için kullanılacak yürütülebilir dosya veya betik",
"label": "Komut",
"placeholder": "Örneğin: python main.py veya /path/to/executable"
},
"endpoint": {
"desc": "MCP Streamable HTTP Sunucunuzun adresini girin",
"label": "MCP Endpoint URL"
},
"identifier": {
"desc": "MCP eklentinize bir ad verin, İngilizce karakterler kullanmalısınız",
"invalid": "Sadece İngilizce karakterler, rakamlar, - ve _ bu iki sembolü girebilirsiniz",
"label": "MCP Eklenti Adı",
"placeholder": "Örneğin: my-mcp-plugin"
},
"type": {
"desc": "MCP eklentisinin iletişim yöntemini seçin, web sürümü yalnızca Streamable HTTP'yi destekler",
"label": "MCP Eklenti Türü"
},
"url": {
"desc": "MCP HTTP eklentinizin Endpoint adresini girin",
"label": "HTTP Endpoint URL"
}
},
"mode": {
"mcp": "MCP Eklentisi",
"mcpExp": "Deneysel",
@@ -76,6 +45,37 @@
"placeholder": "Arama Motoru"
}
},
"mcp": {
"args": {
"desc": "STDIO komutuna iletilecek parametreler listesi",
"label": "Komut Parametreleri",
"placeholder": "Örneğin: --port 8080 --debug",
"tooltip": "Parametreleri girdikten sonra Enter'a basın veya virgül/boşluk ile ayırın"
},
"command": {
"desc": "MCP STDIO eklentisini başlatmak için kullanılacak yürütülebilir dosya veya betik",
"label": "Komut",
"placeholder": "Örneğin: python main.py veya /path/to/executable"
},
"endpoint": {
"desc": "MCP Streamable HTTP Sunucunuzun adresini girin",
"label": "MCP Endpoint URL"
},
"identifier": {
"desc": "MCP eklentiniz için bir ad belirleyin, İngilizce karakterler kullanmalısınız",
"invalid": "Sadece İngilizce karakterler, rakamlar, - ve _ bu iki sembolü girebilirsiniz",
"label": "MCP Eklenti Adı",
"placeholder": "Örneğin: my-mcp-plugin"
},
"type": {
"desc": "MCP eklentisinin iletişim yöntemini seçin, web sürümü yalnızca Streamable HTTP'yi destekler",
"label": "MCP Eklenti Türü"
},
"url": {
"desc": "MCP Sunucu Akış HTTP adresinizi girin, /sse ile bitmemelidir",
"label": "HTTP Endpoint URL"
}
},
"meta": {
"author": {
"desc": "Eklentinin yazarı",
+3 -8
View File
@@ -47,15 +47,10 @@
},
"mcp": {
"args": {
"desc": "Danh sách các tham số được truyền cho lệnh STDIO",
"label": "Tham số lệnh",
"placeholder": "Ví dụ: --port 8080 --debug",
"tooltip": "Nhấn Enter sau khi nhập tham số hoặc sử dụng dấu phẩy/khoảng trắng để phân tách"
"label": "Tham số lệnh"
},
"command": {
"desc": "Tệp thực thi hoặc kịch bản để khởi động plugin MCP STDIO",
"label": "Lệnh",
"placeholder": "Ví dụ: python main.py hoặc /path/to/executable"
"label": "Lệnh"
},
"endpoint": {
"desc": "Nhập địa chỉ của máy chủ HTTP Streamable MCP của bạn",
@@ -72,7 +67,7 @@
"label": "Loại plugin MCP"
},
"url": {
"desc": "Nhập địa chỉ Điểm cuối HTTP của plugin MCP của bạn",
"desc": "Nhập địa chỉ HTTP Streamable của máy chủ MCP của bạn, không kết thúc bằng /sse",
"label": "URL Điểm cuối HTTP"
}
},
+14 -9
View File
@@ -47,15 +47,12 @@
},
"mcp": {
"args": {
"desc": "传递给 STDIO 命令的参数列表",
"label": "命令参数",
"placeholder": "例如:--port 8080 --debug",
"tooltip": "输入参数后按回车或使用逗号/空格分隔"
"desc": "传递给 STDIO 命令的参数列表,一般在这里输入 MCP 服务器名称",
"placeholder": "例如:mcp-hello-world"
},
"command": {
"desc": "用于启动 MCP STDIO 插件的可执行文件或脚本",
"label": "命令",
"placeholder": "例如:python main.py 或 /path/to/executable"
"label": "命令"
},
"endpoint": {
"desc": "输入你的 MCP Streamable HTTP Server 的地址",
@@ -69,11 +66,19 @@
},
"type": {
"desc": "选择 MCP 插件的通信方式,网页版只支持 Streamable HTTP",
"label": "MCP 插件类型"
"httpFeature1": "兼容网页版与桌面端",
"httpFeature2": "连接远程 MCP 服务端, 无需额外安装配置",
"httpShortDesc": "基于流式 HTTP 的通信协议",
"label": "MCP 插件类型",
"stdioFeature1": "更低的通信延迟, 适合本地执行",
"stdioFeature2": "通过系统标准输入输出通信,需在本地安装运行 MCP 服务端",
"stdioNotAvailable": "STDIO 模式仅在桌面版可用",
"stdioShortDesc": "基于标准输入输出的通信协议",
"title": "MCP 插件类型"
},
"url": {
"desc": "输入你的 MCP HTTP 插件的 Endpoint 地址",
"label": "HTTP Endpoint URL"
"desc": "输入你的 MCP Server Streamable HTTP 地址,不会以 /sse 结尾",
"label": "Streamable HTTP Endpoint URL"
}
},
"meta": {
+31 -31
View File
@@ -34,37 +34,6 @@
"desc": "外掛的唯一識別碼",
"label": "識別碼"
},
"mcp": {
"args": {
"desc": "傳遞給 STDIO 命令的參數列表",
"label": "命令參數",
"placeholder": "例如:--port 8080 --debug",
"tooltip": "輸入參數後按回車或使用逗號/空格分隔"
},
"command": {
"desc": "用於啟動 MCP STDIO 插件的可執行文件或腳本",
"label": "命令",
"placeholder": "例如:python main.py 或 /path/to/executable"
},
"endpoint": {
"desc": "輸入你的 MCP Streamable HTTP Server 的地址",
"label": "MCP Endpoint URL"
},
"identifier": {
"desc": "為你的 MCP 插件指定一個名稱,需要使用英文字符",
"invalid": "只能輸入英文字符、數字、- 和_ 這兩個符號",
"label": "MCP 插件名稱",
"placeholder": "例如:my-mcp-plugin"
},
"type": {
"desc": "選擇 MCP 插件的通信方式,網頁版只支持 Streamable HTTP",
"label": "MCP 插件類型"
},
"url": {
"desc": "輸入你的 MCP HTTP 插件的 Endpoint 地址",
"label": "HTTP Endpoint URL"
}
},
"mode": {
"mcp": "MCP 插件",
"mcpExp": "實驗性",
@@ -76,6 +45,37 @@
"placeholder": "搜尋引擎"
}
},
"mcp": {
"args": {
"desc": "傳遞給 STDIO 命令的參數列表",
"label": "命令參數",
"placeholder": "例如:--port 8080 --debug",
"tooltip": "輸入參數後按回車或使用逗號/空格分隔"
},
"command": {
"desc": "用於啟動 MCP STDIO 插件的可執行文件或腳本",
"label": "命令",
"placeholder": "例如:python main.py 或 /path/to/executable"
},
"endpoint": {
"desc": "輸入你的 MCP Streamable HTTP Server 的地址",
"label": "MCP Endpoint URL"
},
"identifier": {
"desc": "為你的 MCP 插件指定一個名稱,需要使用英文字符",
"invalid": "只能輸入英文字符、數字、- 和_ 這兩個符號",
"label": "MCP 插件名稱",
"placeholder": "例如:my-mcp-plugin"
},
"type": {
"desc": "選擇 MCP 插件的通信方式,網頁版只支持 Streamable HTTP",
"label": "MCP 插件類型"
},
"url": {
"desc": "輸入你的 MCP Server Streamable HTTP 地址,結尾不會有 /sse",
"label": "HTTP Endpoint URL"
}
},
"meta": {
"author": {
"desc": "外掛的作者",
@@ -0,0 +1,20 @@
import { Input, InputProps } from 'antd';
import { memo } from 'react';
interface ArgsInputProps extends Omit<InputProps, 'value' | 'onChange'> {
onChange?: (value: string[]) => void;
value?: string[];
}
const ArgsInput = memo<ArgsInputProps>(({ value, onChange, ...res }) => {
return (
<Input
onChange={(e) => {
onChange?.([e.target.value]);
}}
value={value?.[0]}
{...res}
/>
);
});
export default ArgsInput;
@@ -0,0 +1,176 @@
import { Icon } from '@lobehub/ui';
import { Typography } from 'antd';
import { createStyles } from 'antd-style';
import { CheckIcon, RouterIcon, TerminalIcon } from 'lucide-react';
import React, { memo } from 'react';
import { useTranslation } from 'react-i18next';
import { Center, Flexbox } from 'react-layout-kit';
import { isDesktop } from '@/const/version';
// Define styles using antd-style (moved from MCPManifestForm)
const useStyles = createStyles(({ token, css }) => ({
active: css`
border-color: ${token.colorPrimary};
&:hover {
border-color: ${token.colorPrimary};
}
`,
cardDescription: css`
font-size: ${token.fontSizeSM}px;
color: ${token.colorTextDescription};
`,
cardTitle: css`
font-weight: bold;
`,
checkIcon: css`
position: absolute;
inset-block-start: 12px;
inset-inline-end: 12px;
display: flex;
align-items: center;
justify-content: center;
width: 20px;
height: 20px;
border-radius: 50%;
color: ${token.colorBgContainer};
background-color: ${token.colorPrimary};
`,
container: css`
cursor: pointer;
position: relative;
width: 100%;
padding-block: 12px;
padding-inline: 16px;
border: 1px solid ${token.colorBorder};
border-radius: ${token.borderRadiusLG}px;
background-color: ${token.colorBgContainer};
transition:
border-color 0.3s ${token.motionEaseInOut},
box-shadow 0.3s ${token.motionEaseInOut};
&:hover {
border-color: ${token.colorPrimaryHover};
}
`,
disabled: css`
cursor: not-allowed;
border-color: ${token.colorBorder};
opacity: 0.6;
background-color: ${token.colorBgContainerDisabled};
&:hover {
border-color: ${token.colorBorder};
}
`,
featureIcon: css`
color: ${token.colorTextSecondary};
`,
featureItem: css`
display: flex;
gap: 8px;
align-items: center;
`,
featureText: css`
font-size: ${token.fontSizeSM}px;
color: ${token.colorTextSecondary};
`,
}));
// Helper component for feature list items (moved from MCPManifestForm)
const FeatureItem = memo(({ children }: { children: React.ReactNode }) => {
const { styles } = useStyles();
return (
<div className={styles.featureItem}>
<Center className={styles.featureIcon}>
<CheckIcon size={16} />
</Center>
<div className={styles.featureText}>{children}</div>
</div>
);
});
interface MCPTypeSelectProps {
onChange?: (value: string) => void;
value?: string;
}
const MCPTypeSelect = ({ value, onChange }: MCPTypeSelectProps) => {
const { t } = useTranslation('plugin');
const { styles, cx } = useStyles();
const handleSelect = (type: string) => {
onChange?.(type);
};
const data = [
{
description: t('dev.mcp.type.httpShortDesc'),
features: [t('dev.mcp.type.httpFeature1'), t('dev.mcp.type.httpFeature2')],
icon: RouterIcon,
label: 'Streamable HTTP',
value: 'http',
},
{
description: t('dev.mcp.type.stdioShortDesc'),
features: [t('dev.mcp.type.stdioFeature1'), t('dev.mcp.type.stdioFeature2')],
icon: TerminalIcon,
label: 'STDIO',
value: 'stdio',
},
];
return (
<Flexbox gap={16} horizontal width={'100%'}>
{data.map(({ label, description, features, value: itemValue, icon }) => {
const isActive = value === itemValue;
const disabled = itemValue === 'stdio' && !isDesktop;
return (
<Flexbox
className={cx(styles.container, isActive && styles.active, disabled && styles.disabled)}
gap={12}
key={itemValue}
onClick={disabled ? undefined : () => handleSelect(itemValue)}
style={{ flex: 1 }} // Make cards take equal width
>
<Center className={styles.checkIcon} style={{ opacity: isActive ? 1 : 0 }}>
<CheckIcon size={14} />
</Center>
<Flexbox align={'flex-start'} gap={12} horizontal>
<Center height={22}>
<Icon icon={icon} style={{ fontSize: 16 }} />
</Center>
<Flexbox>
<div className={styles.cardTitle}>{label}</div>
<div className={styles.cardDescription}>{description}</div>
</Flexbox>
</Flexbox>
<Flexbox gap={8}>
{features.map((feature) => (
<FeatureItem key={feature}>{feature}</FeatureItem>
))}
</Flexbox>
{disabled && (
<Typography.Text style={{ fontSize: 12, marginTop: 8 }} type="warning">
{t('dev.mcp.type.stdioNotAvailable')}
</Typography.Text>
)}
</Flexbox>
);
})}
{/* Streamable HTTP Card */}
</Flexbox>
);
};
export default MCPTypeSelect;
@@ -1,23 +1,52 @@
import {
SiBun,
SiDocker,
SiNodedotjs,
SiNpm,
SiPnpm,
SiPython,
} from '@icons-pack/react-simple-icons';
import { LobeChatPluginManifest } from '@lobehub/chat-plugin-sdk';
import { ActionIcon, FormItem } from '@lobehub/ui';
import { Form, FormInstance, Input, Radio, Select } from 'antd';
import { AutoComplete, Form, FormInstance, Input } from 'antd';
import { FileCode, RotateCwIcon } from 'lucide-react';
import { useState } from 'react';
import { FC, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { Flexbox } from 'react-layout-kit';
import ManifestPreviewer from '@/components/ManifestPreviewer';
import { isDesktop } from '@/const/version';
import { mcpService } from '@/services/mcp';
import { useToolStore } from '@/store/tool';
import { pluginSelectors } from '@/store/tool/selectors';
import { PluginInstallError } from '@/types/tool/plugin';
import ArgsInput from './ArgsInput';
import MCPTypeSelect from './MCPTypeSelect';
interface MCPManifestFormProps {
form: FormInstance;
isEditMode?: boolean;
}
// 定义预设的命令选项
const STDIO_COMMAND_OPTIONS: {
// 假设图标是 React 函数组件
color?: string;
icon?: FC<{ color?: string; size?: number }>;
value: string;
}[] = [
{ color: '#CB3837', icon: SiNpm, value: 'npx' },
{ color: '#CB3837', icon: SiNpm, value: 'npm' },
{ color: '#F69220', icon: SiPnpm, value: 'pnpm' },
{ color: '#F69220', icon: SiPnpm, value: 'pnpx' },
{ color: '#339933', icon: SiNodedotjs, value: 'node' },
{ color: '#efe2d2', icon: SiBun, value: 'bun' },
{ color: '#efe2d2', icon: SiBun, value: 'bunx' },
{ color: '#DE5FE9', icon: SiPython, value: 'uv' },
{ color: '#3776AB', icon: SiPython, value: 'python' },
{ color: '#2496ED', icon: SiDocker, value: 'docker' },
];
const MCPManifestForm = ({ form, isEditMode }: MCPManifestFormProps) => {
const { t } = useTranslation('plugin');
const mcpType = Form.useWatch(['customParams', 'mcp', 'type'], form);
@@ -25,9 +54,18 @@ const MCPManifestForm = ({ form, isEditMode }: MCPManifestFormProps) => {
const pluginIds = useToolStore(pluginSelectors.storeAndInstallPluginsIdList);
const HTTP_URL_KEY = ['customParams', 'mcp', 'url'];
const STDIO_COMMAND = ['customParams', 'mcp', 'command'];
const STDIO_ARGS = ['customParams', 'mcp', 'args'];
return (
<Form form={form} layout={'vertical'}>
<Flexbox gap={16}>
<Flexbox>
<Form.Item
label={t('dev.mcp.type.title')}
name={['customParams', 'mcp', 'type']}
rules={[{ required: true }]}
>
<MCPTypeSelect />
</Form.Item>
<Form.Item
extra={t('dev.mcp.identifier.desc')}
label={t('dev.mcp.identifier.label')}
@@ -38,7 +76,6 @@ const MCPManifestForm = ({ form, isEditMode }: MCPManifestFormProps) => {
message: t('dev.mcp.identifier.invalid'),
pattern: /^[\w-]+$/,
},
// 编辑模式下,不进行重复校验
isEditMode
? {}
: {
@@ -46,7 +83,6 @@ const MCPManifestForm = ({ form, isEditMode }: MCPManifestFormProps) => {
validator: async () => {
const id = form.getFieldValue('identifier');
if (!id) return true;
if (pluginIds.includes(id)) {
throw new Error('Duplicate');
}
@@ -57,21 +93,6 @@ const MCPManifestForm = ({ form, isEditMode }: MCPManifestFormProps) => {
<Input placeholder={t('dev.mcp.identifier.placeholder')} />
</Form.Item>
<Form.Item
extra={t('dev.mcp.type.desc')}
initialValue={'http'}
label={t('dev.mcp.type.label')}
name={['customParams', 'mcp', 'type']}
rules={[{ required: true }]}
>
<Radio.Group>
<Radio value={'http'}>Streamable HTTP</Radio>
<Radio disabled={!isDesktop} value={'stdio'}>
STDIO
</Radio>
</Radio.Group>
</Form.Item>
{mcpType === 'http' && (
<Form.Item
extra={
@@ -97,14 +118,12 @@ const MCPManifestForm = ({ form, isEditMode }: MCPManifestFormProps) => {
{
validator: async (_, value) => {
if (!value) return true;
try {
const data = await mcpService.getStreamableMcpServerManifest(
form.getFieldValue('identifier'),
value,
);
setManifest(data);
form.setFieldsValue({ identifier: data.identifier, manifest: data });
} catch (error) {
const err = error as PluginInstallError;
@@ -136,21 +155,64 @@ const MCPManifestForm = ({ form, isEditMode }: MCPManifestFormProps) => {
<Form.Item
extra={t('dev.mcp.command.desc')}
label={t('dev.mcp.command.label')}
name={['mcp', 'command']}
name={STDIO_COMMAND}
rules={[{ required: true }]}
>
<Input placeholder={t('dev.mcp.command.placeholder')} />
<AutoComplete
options={STDIO_COMMAND_OPTIONS.map(({ value, icon: Icon, color }) => ({
label: (
<Flexbox align={'center'} gap={8} horizontal>
{Icon && <Icon color={color} size={16} />}
{value}
</Flexbox>
),
value: value,
}))}
placeholder={t('dev.mcp.command.placeholder')}
/>
</Form.Item>
<Form.Item
extra={t('dev.mcp.args.desc')}
hasFeedback
label={t('dev.mcp.args.label')}
name={['mcp', 'args']}
tooltip={t('dev.mcp.args.tooltip')}
name={STDIO_ARGS}
rules={[
{ required: true },
{
validator: async (_, value) => {
if (!value) return true;
const name = form.getFieldValue('identifier');
if (!name) throw new Error('Please input mcp server name');
try {
const data = await mcpService.getStdioMcpServerManifest(
name,
form.getFieldValue(STDIO_COMMAND),
value,
);
setManifest(data);
form.setFieldsValue({ identifier: data.identifier, manifest: data });
} catch (error) {
const err = error as PluginInstallError;
throw t(`error.${err.message}`, { error: err.cause! });
}
},
},
]}
>
<Select
mode="tags"
<ArgsInput
placeholder={t('dev.mcp.args.placeholder')}
tokenSeparators={[',', ' ']}
suffix={
<ActionIcon
icon={RotateCwIcon}
onClick={(e) => {
e.stopPropagation();
form.validateFields([STDIO_ARGS]);
}}
size={'small'}
title={t('dev.meta.manifest.refresh')}
/>
}
/>
</Form.Item>
</>
@@ -1,61 +1,5 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`MCPClient > Stdio Transport (using SDK Mock Server) > should list tools via stdio 1`] = `
[
{
"description": "Echoes back a message with 'Hello' prefix",
"inputSchema": {
"$schema": "http://json-schema.org/draft-07/schema#",
"additionalProperties": false,
"properties": {
"message": {
"description": "The message to echo",
"type": "string",
},
},
"required": [
"message",
],
"type": "object",
},
"name": "echo",
},
{
"description": "Lists all available tools and methods",
"inputSchema": {
"$schema": "http://json-schema.org/draft-07/schema#",
"additionalProperties": false,
"properties": {},
"type": "object",
},
"name": "debug",
},
{
"description": "Adds two numbers",
"inputSchema": {
"$schema": "http://json-schema.org/draft-07/schema#",
"additionalProperties": false,
"properties": {
"a": {
"description": "The first number",
"type": "number",
},
"b": {
"description": "The second number",
"type": "number",
},
},
"required": [
"a",
"b",
],
"type": "object",
},
"name": "add",
},
]
`;
exports[`MCPClient > Stdio Transport > should list tools via stdio 1`] = `
[
{
+14 -7
View File
@@ -47,15 +47,14 @@ export default {
},
mcp: {
args: {
desc: '传递给 STDIO 命令的参数列表',
desc: '传递给 STDIO 命令的参数列表,一般在这里输入 MCP 服务器名称',
label: '命令参数',
placeholder: '例如:--port 8080 --debug',
tooltip: '输入参数后按回车或使用逗号/空格分隔',
placeholder: '例如:mcp-hello-world',
},
command: {
desc: '用于启动 MCP STDIO 插件的可执行文件或脚本',
desc: '用于启动 MCP STDIO Server 的可执行文件或脚本',
label: '命令',
placeholder: '例如:python main.py 或 /path/to/executable',
placeholder: '例如:npx / uv / docker 等',
},
endpoint: {
desc: '输入你的 MCP Streamable HTTP Server 的地址',
@@ -69,11 +68,19 @@ export default {
},
type: {
desc: '选择 MCP 插件的通信方式,网页版只支持 Streamable HTTP',
httpFeature1: '兼容网页版与桌面端',
httpFeature2: '连接远程 MCP 服务端, 无需额外安装配置',
httpShortDesc: '基于流式 HTTP 的通信协议',
label: 'MCP 插件类型',
stdioFeature1: '更低的通信延迟, 适合本地执行',
stdioFeature2: '通过系统标准输入输出通信,需在本地安装运行 MCP 服务端',
stdioNotAvailable: 'STDIO 模式仅在桌面版可用',
stdioShortDesc: '基于标准输入输出的通信协议',
title: 'MCP 插件类型',
},
url: {
desc: '输入你的 MCP HTTP 插件的 Endpoint 地址',
label: 'HTTP Endpoint URL',
desc: '输入你的 MCP Server Streamable HTTP 地址,不会以 /sse 结尾',
label: 'Streamable HTTP Endpoint URL',
},
},
meta: {
+6
View File
@@ -35,6 +35,12 @@ const checkStdioEnvironment = (params: z.infer<typeof mcpClientParamsSchema>) =>
const mcpProcedure = isServerMode ? authedProcedure : passwordProcedure;
export const mcpRouter = router({
getStdioMcpServerManifest: mcpProcedure.input(stdioParamsSchema).query(async ({ input }) => {
// Stdio check can be done here or rely on the service/client layer
checkStdioEnvironment(input);
return await mcpService.getStdioMcpServerManifest(input.name, input.command, input.args);
}),
getStreamableMcpServerManifest: mcpProcedure
.input(
z.object({
+19
View File
@@ -139,6 +139,25 @@ class MCPService {
): Promise<LobeChatPluginManifest> {
const tools = await this.listTools({ name: identifier, type: 'http', url }); // Get client using params
return {
api: tools,
identifier,
meta: {
avatar: 'MCP_AVATAR',
description: `${identifier} MCP server has ${tools.length} tools, like "${tools[0]?.name}"`,
title: identifier,
},
// TODO: temporary
type: 'mcp' as any,
};
}
async getStdioMcpServerManifest(
identifier: string,
command: string,
args: string[],
): Promise<LobeChatPluginManifest> {
const tools = await this.listTools({ args, command, name: identifier, type: 'stdio' }); // Get client using params
return {
api: tools,
identifier,
+13 -2
View File
@@ -1,12 +1,14 @@
import { toolsClient } from '@/libs/trpc/client';
import { getToolStoreState } from '@/store/tool';
import { pluginSelectors } from '@/store/tool/slices/plugin/selectors';
import { ChatToolPayload } from '@/types/message';
class MCPService {
async invokeMcpToolCall(payload: ChatToolPayload, { signal }: { signal?: AbortSignal }) {
const { pluginSelectors } = await import('@/store/tool/selectors');
const { getToolStoreState } = await import('@/store/tool/store');
const s = getToolStoreState();
const { identifier, arguments: args, apiName } = payload;
const plugin = pluginSelectors.getCustomPluginById(identifier)(s);
if (!plugin) return;
@@ -20,6 +22,15 @@ class MCPService {
async getStreamableMcpServerManifest(identifier: string, url: string) {
return toolsClient.mcp.getStreamableMcpServerManifest.query({ identifier, url });
}
async getStdioMcpServerManifest(identifier: string, command: string, args?: string[]) {
return toolsClient.mcp.getStdioMcpServerManifest.query({
args: args,
command,
name: identifier,
type: 'stdio',
});
}
}
export const mcpService = new MCPService();
+16 -4
View File
@@ -1,8 +1,10 @@
import { LobeChatPluginManifest } from '@lobehub/chat-plugin-sdk';
import { t } from 'i18next';
import { merge } from 'lodash-es';
import { StateCreator } from 'zustand/vanilla';
import { notification } from '@/components/AntdStaticMethods';
import { mcpService } from '@/services/mcp';
import { pluginService } from '@/services/plugin';
import { toolService } from '@/services/tool';
import { pluginHelpers } from '@/store/tool/helpers';
@@ -40,12 +42,22 @@ export const createCustomPluginSlice: StateCreator<
if (!plugin) return;
const { refreshPlugins, updateInstallLoadingState } = get();
try {
updateInstallLoadingState(id, true);
const manifest = await toolService.getToolManifest(
plugin.customParams?.manifestUrl,
plugin.customParams?.useProxy,
);
let manifest: LobeChatPluginManifest;
// mean this is a mcp plugin
if (!!plugin.customParams?.mcp) {
const url = plugin.customParams?.mcp?.url;
if (!url) return;
manifest = await mcpService.getStreamableMcpServerManifest(plugin.identifier, url);
} else {
manifest = await toolService.getToolManifest(
plugin.customParams?.manifestUrl,
plugin.customParams?.useProxy,
);
}
updateInstallLoadingState(id, false);
await pluginService.updatePluginManifest(id, manifest);