diff --git a/frontend/src/features/agent/AgentView.vue b/frontend/src/features/agent/AgentView.vue
index 11ed477..283f44d 100644
--- a/frontend/src/features/agent/AgentView.vue
+++ b/frontend/src/features/agent/AgentView.vue
@@ -5,7 +5,8 @@ import { useAgentStore } from '@/stores/agent'
import { useProviderStore } from '@/stores/provider'
import { useSkillStore } from '@/stores/skill'
import type { AgentEvent } from '@/contracts'
-import { eventLabel, localizeDetails, permissionLabel, runStatusLabel, toolDescription, toolLabel } from './labels'
+import { eventLabel, localizeDetails, permissionLabel, runStatusLabel, toolLabel } from './labels'
+import ToolOption from './ToolOption.vue'
const route = useRoute()
const router = useRouter()
@@ -88,7 +89,7 @@ function eventText(event: AgentEvent) {
-
+
@@ -114,12 +115,7 @@ function eventText(event: AgentEvent) {
diff --git a/frontend/src/features/agent/labels.spec.ts b/frontend/src/features/agent/labels.spec.ts
index 123ac25..fcb568a 100644
--- a/frontend/src/features/agent/labels.spec.ts
+++ b/frontend/src/features/agent/labels.spec.ts
@@ -9,6 +9,21 @@ import {
} from './labels'
describe('智能体页面中文标签', () => {
+ it('按 MCP 远程工具名匹配中文,不依赖服务器 ID', () => {
+ for (const server of ['9ca7ee21603a', 'another-server']) {
+ expect(toolLabel(`mcp.${server}.web_search`)).toBe('网页搜索')
+ expect(toolLabel(`mcp.${server}.understand_image`)).toBe('图像理解')
+ expect(toolDescription(`mcp.${server}.web_search`, 'Search the web')).toContain('搜索关键词')
+ }
+ expect(toolLabel('text.uppercase')).toBe('文本转大写')
+ expect(toolDescription('text.uppercase', 'Convert input text to uppercase.')).toContain('大写')
+ })
+
+ it('保留服务端中文,未知工具不编造翻译或套用内置工具语义', () => {
+ expect(toolDescription('mcp.server.web_search', '仅搜索指定站点。')).toBe('仅搜索指定站点。')
+ expect(toolDescription('mcp.server.custom_action', 'Private action')).toContain('暂无中文说明')
+ expect(toolLabel('mcp.server.notes.delete')).toBe('MCP 工具 · notes.delete')
+ })
it('转换运行状态和事件名称', () => {
expect(runStatusLabel('waiting_permission')).toBe('等待授权')
expect(eventLabel('ToolCall')).toBe('调用工具')
diff --git a/frontend/src/features/agent/labels.ts b/frontend/src/features/agent/labels.ts
index c6646d6..0ed56b5 100644
--- a/frontend/src/features/agent/labels.ts
+++ b/frontend/src/features/agent/labels.ts
@@ -42,6 +42,7 @@ const toolLabels: Record = {
'tasks.list': '列出任务',
'attachments.read': '读取附件',
'audio.transcribe': '音频转写',
+ 'text.uppercase': '文本转大写',
}
const toolDescriptions: Record = {
@@ -58,7 +59,25 @@ const toolDescriptions: Record = {
'tasks.update': '更新已有任务。',
'tasks.list': '列出已持久化的任务。',
'attachments.read': '读取由宿主管理的 UTF-8 附件。',
- 'audio.transcribe': '读取音频附件已有的宿主转写结果。',
+ 'audio.transcribe': '将音频转写为文本,按模型路由使用 API 或本地后端。',
+ 'text.uppercase': '将输入文本中的字母转换为大写。',
+}
+
+// MCP IDs contain a server-specific namespace. Localize the remote tool name
+// for presentation only; requests must keep using the complete original ID.
+const mcpTools: Record = {
+ web_search: {
+ label: '网页搜索',
+ description: '搜索实时或外部网页信息。输入搜索关键词;结果包含标题、链接、摘要等信息。时效性问题可在关键词中加入日期,完整参数以服务原文为准。',
+ },
+ understand_image: {
+ label: '图像理解',
+ description: '根据提示词分析图片、描述内容或提取信息。输入分析要求和图片地址或本地路径;支持的格式与路径规则请查看服务原文。',
+ },
+}
+
+function mcpName(name: string): string | undefined {
+ return /^mcp\.[^.]+\.(.+)$/.exec(name)?.[1]
}
const permissionLabels: Record = {
@@ -105,10 +124,17 @@ export function eventLabel(event: AgentEventType): string {
}
export function toolLabel(name: string): string {
+ const remote = mcpName(name)
+ if (remote) return mcpTools[remote]?.label ?? `MCP 工具 · ${remote}`
return toolLabels[name] ?? name
}
export function toolDescription(name: string, fallback: string): string {
+ const remote = mcpName(name)
+ if (remote) {
+ if (/\p{Script=Han}/u.test(fallback)) return fallback
+ return mcpTools[remote]?.description ?? '暂无中文说明,请展开查看服务原文。'
+ }
return toolDescriptions[name] ?? fallback
}