feat: 添加 MCP Server 导航项

- 在 WorkspaceDestination 枚举中添加 mcpServer
- 更新侧边栏顺序:助手→任务→技能→节点→代理→MCP Server | ClawHub→密钥→AI Gateway
- 创建 McpServerPage 展示 MCP 服务器连接状态
- 更新 app_shell.dart 路由映射
This commit is contained in:
Haitao Pan 2026-03-13 22:32:02 +08:00
parent 99c6aa9115
commit e50bef97e4
4 changed files with 189 additions and 2 deletions

View File

@ -4,6 +4,7 @@ import 'package:flutter/material.dart';
import '../features/ai_gateway/ai_gateway_page.dart';
import '../features/assistant/assistant_page.dart';
import '../features/claw_hub/claw_hub_page.dart';
import '../features/mcp_server/mcp_server_page.dart';
import '../features/mobile/ios_mobile_shell.dart';
import '../features/modules/modules_page.dart';
import '../features/secrets/secrets_page.dart';
@ -340,6 +341,10 @@ class _AppShellState extends State<AppShell> {
onOpenDetail: onOpenDetail,
initialTab: ModulesTab.agents,
),
WorkspaceDestination.mcpServer => McpServerPage(
controller: widget.controller,
onOpenDetail: onOpenDetail,
),
WorkspaceDestination.clawHub => ClawHubPage(
controller: widget.controller,
onOpenDetail: onOpenDetail,

View File

@ -0,0 +1,172 @@
import 'package:flutter/material.dart';
import '../../app/app_controller.dart';
import '../../i18n/app_language.dart';
import '../../models/app_models.dart';
import '../../runtime/runtime_models.dart';
import '../../widgets/surface_card.dart';
import '../../widgets/top_bar.dart';
class McpServerPage extends StatelessWidget {
const McpServerPage({
super.key,
required this.controller,
required this.onOpenDetail,
});
final AppController controller;
final ValueChanged<DetailPanelData> onOpenDetail;
@override
Widget build(BuildContext context) {
final items = controller.connectors;
return AnimatedBuilder(
animation: controller,
builder: (context, _) {
return SingleChildScrollView(
padding: const EdgeInsets.fromLTRB(32, 32, 32, 8),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
TopBar(
title: 'MCP Server',
subtitle: appText(
'管理 MCP 服务器连接与工具配置。',
'Manage MCP server connections and tool configurations.',
),
trailing: Wrap(
spacing: 12,
runSpacing: 12,
children: [
SizedBox(
width: 220,
child: TextField(
decoration: InputDecoration(
hintText: appText('搜索服务器', 'Search servers'),
prefixIcon: Icon(Icons.search_rounded),
),
),
),
IconButton(
onPressed: () async {
await controller.connectorsController.refresh();
},
icon: const Icon(Icons.refresh_rounded),
),
],
),
),
const SizedBox(height: 24),
if (items.isEmpty)
SurfaceCard(
child: Text(
controller.connection.status ==
RuntimeConnectionStatus.connected
? appText(
'当前没有连接的 MCP 服务器。',
'No MCP servers connected.',
)
: appText(
'连接 Gateway 后可查看 MCP 服务器。',
'Connect a gateway to view MCP servers.',
),
),
)
else
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: items
.map(
(connector) => Padding(
padding: const EdgeInsets.only(bottom: 12),
child: SurfaceCard(
onTap: () => onOpenDetail(
DetailPanelData(
title: connector.label,
subtitle: appText('连接器', 'Connector'),
icon: Icons.dns_rounded,
status: StatusInfo(
connector.status,
connector.connected
? StatusTone.success
: StatusTone.neutral,
),
description: connector.detailLabel,
meta: connector.meta,
actions: [appText('配置', 'Configure')],
sections: [
DetailSection(
title: appText('详情', 'Details'),
items: [
DetailItem(
label: appText('ID', 'ID'),
value: connector.id,
),
DetailItem(
label: appText('状态', 'Status'),
value: connector.status,
),
DetailItem(
label: appText('已配置', 'Configured'),
value: connector.configured
? appText('', 'Yes')
: appText('', 'No'),
),
DetailItem(
label: appText('已启用', 'Enabled'),
value: connector.enabled
? appText('', 'Yes')
: appText('', 'No'),
),
],
),
],
),
),
child: Row(
children: [
Expanded(
flex: 4,
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Text(
connector.label,
style: Theme.of(context)
.textTheme
.titleMedium,
),
const SizedBox(height: 6),
Text(
connector.detailLabel,
style:
Theme.of(context).textTheme.bodySmall,
),
],
),
),
Expanded(
flex: 2,
child: Text(
connector.connected
? appText('已连接', 'Connected')
: appText('未连接', 'Disconnected'),
),
),
const Icon(Icons.chevron_right_rounded),
],
),
),
),
)
.toList(),
),
],
),
);
},
);
}
}

View File

@ -2,18 +2,19 @@ import 'package:flutter/material.dart';
import '../i18n/app_language.dart';
enum WorkspaceDestination {
enum WorkspaceDestination {
assistant,
tasks,
skills,
nodes,
agents,
mcpServer,
clawHub,
secrets,
aiGateway,
settings,
account,
}
}
extension WorkspaceDestinationCopy on WorkspaceDestination {
String get label => switch (this) {
@ -22,6 +23,7 @@ extension WorkspaceDestinationCopy on WorkspaceDestination {
WorkspaceDestination.skills => appText('技能', 'Skills'),
WorkspaceDestination.nodes => appText('节点', 'Nodes'),
WorkspaceDestination.agents => appText('代理', 'Agents'),
WorkspaceDestination.mcpServer => 'MCP Server',
WorkspaceDestination.clawHub => 'ClawHub',
WorkspaceDestination.secrets => appText('密钥', 'Secrets'),
WorkspaceDestination.aiGateway => 'AI Gateway',
@ -35,6 +37,7 @@ extension WorkspaceDestinationCopy on WorkspaceDestination {
WorkspaceDestination.skills => Icons.auto_awesome_rounded,
WorkspaceDestination.nodes => Icons.developer_board_rounded,
WorkspaceDestination.agents => Icons.hub_rounded,
WorkspaceDestination.mcpServer => Icons.dns_rounded,
WorkspaceDestination.clawHub => Icons.extension_rounded,
WorkspaceDestination.secrets => Icons.key_rounded,
WorkspaceDestination.aiGateway => Icons.smart_toy_rounded,
@ -63,6 +66,10 @@ extension WorkspaceDestinationCopy on WorkspaceDestination {
'管理代理实例,配置行为与能力。',
'Manage agent instances, configure behaviors and capabilities.',
),
WorkspaceDestination.mcpServer => appText(
'管理 MCP 服务器连接与工具配置。',
'Manage MCP server connections and tool configurations.',
),
WorkspaceDestination.clawHub => appText(
'浏览和安装技能包、代理模板与连接器。',
'Browse and install skill packages, agent templates and connectors.',

View File

@ -43,6 +43,7 @@ class SidebarNavigation extends StatelessWidget {
WorkspaceDestination.skills,
WorkspaceDestination.nodes,
WorkspaceDestination.agents,
WorkspaceDestination.mcpServer,
WorkspaceDestination.clawHub,
WorkspaceDestination.secrets,
WorkspaceDestination.aiGateway,
@ -258,6 +259,7 @@ class _SidebarNavItemState extends State<SidebarNavItem> {
WorkspaceDestination.skills => Icons.auto_awesome_rounded,
WorkspaceDestination.nodes => Icons.developer_board_rounded,
WorkspaceDestination.agents => Icons.hub_rounded,
WorkspaceDestination.mcpServer => Icons.dns_rounded,
WorkspaceDestination.clawHub => Icons.extension_rounded,
WorkspaceDestination.secrets => Icons.key_rounded,
WorkspaceDestination.aiGateway => Icons.smart_toy_rounded,
@ -273,6 +275,7 @@ class _SidebarNavItemState extends State<SidebarNavItem> {
WorkspaceDestination.skills => appText('技能', 'Skills'),
WorkspaceDestination.nodes => appText('节点', 'Nodes'),
WorkspaceDestination.agents => appText('代理', 'Agents'),
WorkspaceDestination.mcpServer => 'MCP Server',
WorkspaceDestination.clawHub => 'ClawHub',
WorkspaceDestination.secrets => appText('密钥', 'Secrets'),
WorkspaceDestination.aiGateway => 'AI Gateway',