From 5ab237138e780cefe4685949a4dbc09858145cf0 Mon Sep 17 00:00:00 2001 From: Hyu Date: Sun, 28 Jun 2026 01:42:08 +0800 Subject: [PATCH] feat(web): split MCP resources into tab --- .../home/mcp/components/mcp-form/MCPForm.tsx | 74 +++++++++++++++---- web/src/i18n/locales/en-US.ts | 2 + web/src/i18n/locales/es-ES.ts | 2 + web/src/i18n/locales/ja-JP.ts | 2 + web/src/i18n/locales/ru-RU.ts | 2 + web/src/i18n/locales/th-TH.ts | 2 + web/src/i18n/locales/vi-VN.ts | 2 + web/src/i18n/locales/zh-Hans.ts | 2 + web/src/i18n/locales/zh-Hant.ts | 2 + 9 files changed, 75 insertions(+), 15 deletions(-) diff --git a/web/src/app/home/mcp/components/mcp-form/MCPForm.tsx b/web/src/app/home/mcp/components/mcp-form/MCPForm.tsx index d229f8ddb..a33115723 100644 --- a/web/src/app/home/mcp/components/mcp-form/MCPForm.tsx +++ b/web/src/app/home/mcp/components/mcp-form/MCPForm.tsx @@ -246,7 +246,6 @@ function ToolsList({ tools, t }: { tools: MCPTool[]; t: TFunction }) { ); } -// Resources list component function ResourcesList({ resources, serverName, @@ -285,7 +284,7 @@ function ResourcesList({ }; return ( -
+
{resources.map((resource, index) => ( - {t('mcp.noToolsFound')} + {content === 'resources' + ? t('mcp.noResourcesFound') + : t('mcp.noToolsFound')}
); } @@ -362,6 +367,14 @@ function RuntimePanel({ !mcpTesting && runtimeInfo.status === MCPSessionStatus.CONNECTED; const tools = runtimeInfo.tools || []; const resources = runtimeInfo.resources || []; + const showTools = content === 'all' || content === 'tools'; + const showResources = content === 'all' || content === 'resources'; + const empty = + content === 'tools' + ? tools.length === 0 + : content === 'resources' + ? resources.length === 0 + : tools.length === 0 && resources.length === 0; return (
@@ -371,20 +384,26 @@ function RuntimePanel({
)} - {isConnected && tools.length > 0 && } + {isConnected && showTools && tools.length > 0 && ( + + )} - {isConnected && resources.length > 0 && ( + {isConnected && showResources && resources.length > 0 && (
-
- {t('mcp.resourceCount', { count: resources.length })} -
+ {content === 'all' && ( +
+ {t('mcp.resourceCount', { count: resources.length })} +
+ )}
)} - {isConnected && tools.length === 0 && resources.length === 0 && ( + {isConnected && empty && (
- {t('mcp.noToolsFound')} + {content === 'resources' + ? t('mcp.noResourcesFound') + : t('mcp.noToolsFound')}
)} @@ -1141,16 +1160,20 @@ const MCPForm = forwardRef(function MCPForm( ); // In edit mode the right side shows a tablist switching between the live - // Tools list and the Docs (README captured from LangBot Space at install). + // Tools/resources lists and the Docs (README captured from LangBot Space at install). // Create mode has neither, so it falls back to the bare runtime placeholder. - // The tool count lives in the tab label (only when connected); the panel + // Counts live in the tab labels (only when connected); the panel // body itself no longer repeats a title/subtitle. - const toolsConnected = + const runtimeConnected = !mcpTesting && runtimeInfo?.status === MCPSessionStatus.CONNECTED; const toolsCount = runtimeInfo?.tools?.length ?? 0; - const toolsTabLabel = toolsConnected + const resourcesCount = runtimeInfo?.resources?.length ?? 0; + const toolsTabLabel = runtimeConnected ? `${t('mcp.tabTools')} ${toolsCount}` : t('mcp.tabTools'); + const resourcesTabLabel = runtimeConnected + ? `${t('mcp.tabResources')} ${resourcesCount}` + : t('mcp.tabResources'); const detailPanel = isEditMode ? ( @@ -1161,6 +1184,9 @@ const MCPForm = forwardRef(function MCPForm( {toolsTabLabel} + + {resourcesTabLabel} + @@ -1169,7 +1195,25 @@ const MCPForm = forwardRef(function MCPForm( value="tools" className="mt-4 min-h-0 flex-1 overflow-y-auto" > - {runtimePanel} + + + + ) : ( diff --git a/web/src/i18n/locales/en-US.ts b/web/src/i18n/locales/en-US.ts index 6a76e990d..b275c905e 100644 --- a/web/src/i18n/locales/en-US.ts +++ b/web/src/i18n/locales/en-US.ts @@ -804,7 +804,9 @@ const enUS = { toolsFound: 'tools', unknownError: 'Unknown error', noToolsFound: 'No tools found', + noResourcesFound: 'No resources found', tabTools: 'Tools', + tabResources: 'Resources', tabDocs: 'Docs', noReadme: 'No documentation available', parseResultFailed: 'Failed to parse test result', diff --git a/web/src/i18n/locales/es-ES.ts b/web/src/i18n/locales/es-ES.ts index 0573b7f7f..85dd74b5e 100644 --- a/web/src/i18n/locales/es-ES.ts +++ b/web/src/i18n/locales/es-ES.ts @@ -818,7 +818,9 @@ const esES = { toolsFound: 'herramientas', unknownError: 'Error desconocido', noToolsFound: 'No se encontraron herramientas', + noResourcesFound: 'No se encontraron recursos', tabTools: 'Herramientas', + tabResources: 'Recursos', tabDocs: 'Documentación', noReadme: 'No hay documentación disponible', parseResultFailed: 'Error al analizar el resultado de la prueba', diff --git a/web/src/i18n/locales/ja-JP.ts b/web/src/i18n/locales/ja-JP.ts index a6fff83bd..35f0f6133 100644 --- a/web/src/i18n/locales/ja-JP.ts +++ b/web/src/i18n/locales/ja-JP.ts @@ -810,7 +810,9 @@ const jaJP = { toolsFound: '個のツール', unknownError: '不明なエラー', noToolsFound: 'ツールが見つかりません', + noResourcesFound: 'リソースが見つかりません', tabTools: 'ツール', + tabResources: 'リソース', tabDocs: 'ドキュメント', noReadme: 'ドキュメントがありません', parseResultFailed: 'テスト結果の解析に失敗しました', diff --git a/web/src/i18n/locales/ru-RU.ts b/web/src/i18n/locales/ru-RU.ts index 6cc012029..eddffd1b7 100644 --- a/web/src/i18n/locales/ru-RU.ts +++ b/web/src/i18n/locales/ru-RU.ts @@ -815,7 +815,9 @@ const ruRU = { toolsFound: 'инструментов', unknownError: 'Неизвестная ошибка', noToolsFound: 'Инструменты не найдены', + noResourcesFound: 'Ресурсы не найдены', tabTools: 'Инструменты', + tabResources: 'Ресурсы', tabDocs: 'Документация', noReadme: 'Документация отсутствует', parseResultFailed: 'Не удалось разобрать результат теста', diff --git a/web/src/i18n/locales/th-TH.ts b/web/src/i18n/locales/th-TH.ts index e2a83fb25..e72bc5f90 100644 --- a/web/src/i18n/locales/th-TH.ts +++ b/web/src/i18n/locales/th-TH.ts @@ -793,7 +793,9 @@ const thTH = { toolsFound: 'เครื่องมือ', unknownError: 'ข้อผิดพลาดที่ไม่ทราบสาเหตุ', noToolsFound: 'ไม่พบเครื่องมือ', + noResourcesFound: 'ไม่พบทรัพยากร', tabTools: 'เครื่องมือ', + tabResources: 'ทรัพยากร', tabDocs: 'เอกสาร', noReadme: 'ไม่มีเอกสาร', parseResultFailed: 'ไม่สามารถแยกวิเคราะห์ผลการทดสอบได้', diff --git a/web/src/i18n/locales/vi-VN.ts b/web/src/i18n/locales/vi-VN.ts index cb0d4490d..54f57af14 100644 --- a/web/src/i18n/locales/vi-VN.ts +++ b/web/src/i18n/locales/vi-VN.ts @@ -808,7 +808,9 @@ const viVN = { toolsFound: 'công cụ', unknownError: 'Lỗi không xác định', noToolsFound: 'Không tìm thấy công cụ nào', + noResourcesFound: 'Không tìm thấy tài nguyên nào', tabTools: 'Công cụ', + tabResources: 'Tài nguyên', tabDocs: 'Tài liệu', noReadme: 'Không có tài liệu', parseResultFailed: 'Phân tích kết quả kiểm tra thất bại', diff --git a/web/src/i18n/locales/zh-Hans.ts b/web/src/i18n/locales/zh-Hans.ts index 804a1ea6f..a69d2c8ce 100644 --- a/web/src/i18n/locales/zh-Hans.ts +++ b/web/src/i18n/locales/zh-Hans.ts @@ -771,7 +771,9 @@ const zhHans = { toolsFound: '个工具', unknownError: '未知错误', noToolsFound: '未找到任何工具', + noResourcesFound: '未找到任何资源', tabTools: '工具', + tabResources: '资源', tabDocs: '文档', noReadme: '暂无文档', parseResultFailed: '解析测试结果失败', diff --git a/web/src/i18n/locales/zh-Hant.ts b/web/src/i18n/locales/zh-Hant.ts index 9814ea3ad..d6280f842 100644 --- a/web/src/i18n/locales/zh-Hant.ts +++ b/web/src/i18n/locales/zh-Hant.ts @@ -770,7 +770,9 @@ const zhHant = { toolsFound: '個工具', unknownError: '未知錯誤', noToolsFound: '未找到任何工具', + noResourcesFound: '未找到任何資源', tabTools: '工具', + tabResources: '資源', tabDocs: '文件', noReadme: '暫無文件', parseResultFailed: '解析測試結果失敗',