feat(Inputbar, MCPToolsButton, AssistantMCPSettings): integrate active MCP server handling and UI updates

- Added active MCP server filtering in Inputbar for message sending.
- Updated MCPToolsButton to reflect availability of enabled MCPs.
- Refactored AssistantMCPSettings to streamline MCP server updates and adjusted UI styles for consistency.
This commit is contained in:
kangfenmao 2025-04-01 15:55:21 +08:00 committed by 亢奋猫
parent 8b9929cc7b
commit bfbfba13fe
3 changed files with 24 additions and 23 deletions

View File

@ -13,6 +13,7 @@ import TranslateButton from '@renderer/components/TranslateButton'
import { isFunctionCallingModel, isGenerateImageModel, isVisionModel, isWebSearchModel } from '@renderer/config/models'
import db from '@renderer/databases'
import { useAssistant } from '@renderer/hooks/useAssistant'
import { useMCPServers } from '@renderer/hooks/useMCPServers'
import { useMessageOperations, useTopicLoading } from '@renderer/hooks/useMessageOperations'
import { modelGenerating, useRuntime } from '@renderer/hooks/useRuntime'
import { useMessageStyle, useSettings } from '@renderer/hooks/useSettings'
@ -101,6 +102,7 @@ const Inputbar: FC<Props> = ({ assistant: _assistant, setActiveTopic, topic }) =
const isVision = useMemo(() => isVisionModel(model), [model])
const supportExts = useMemo(() => [...textExts, ...documentExts, ...(isVision ? imageExts : [])], [isVision])
const navigate = useNavigate()
const { activedMcpServers } = useMCPServers()
const showKnowledgeIcon = useSidebarIconShow('knowledge')
const showMCPToolsIcon = isFunctionCallingModel(model)
@ -148,7 +150,7 @@ const Inputbar: FC<Props> = ({ assistant: _assistant, setActiveTopic, topic }) =
// Reset to assistant knowledge mcp servers
useEffect(() => {
setEnabledMCPs(assistant.mcpServers || [])
}, [assistant])
}, [assistant.mcpServers])
const sendMessage = useCallback(async () => {
if (inputEmpty || loading) {
@ -179,8 +181,12 @@ const Inputbar: FC<Props> = ({ assistant: _assistant, setActiveTopic, topic }) =
userMessage.mentions = mentionModels
}
if (enabledMCPs) {
userMessage.enabledMCPs = enabledMCPs
if (isFunctionCallingModel(model)) {
if (!isEmpty(assistant.mcpServers) && !isEmpty(activedMcpServers)) {
userMessage.enabledMCPs = activedMcpServers.filter((server) =>
assistant.mcpServers?.some((s) => s.id === server.id)
)
}
}
userMessage.usage = await estimateMessageUsage(userMessage)
@ -202,13 +208,14 @@ const Inputbar: FC<Props> = ({ assistant: _assistant, setActiveTopic, topic }) =
console.error('Failed to send message:', error)
}
}, [
activedMcpServers,
assistant,
dispatch,
enabledMCPs,
files,
inputEmpty,
loading,
mentionModels,
model,
resizeTextArea,
selectedKnowledgeBases,
text,

View File

@ -19,6 +19,10 @@ const MCPToolsButton: FC<Props> = ({ enabledMCPs, toggelEnableMCP, ToolbarButton
const menuRef = useRef<HTMLDivElement>(null)
const { t } = useTranslation()
const availableMCPs = activedMcpServers.filter((server) => enabledMCPs.some((s) => s.id === server.id))
const buttonEnabled = availableMCPs.length > 0
const truncateText = (text: string, maxLength: number = 50) => {
if (!text || text.length <= maxLength) return text
return text.substring(0, maxLength) + '...'
@ -102,7 +106,7 @@ const MCPToolsButton: FC<Props> = ({ enabledMCPs, toggelEnableMCP, ToolbarButton
overlayClassName="mention-models-dropdown">
<Tooltip placement="top" title={t('settings.mcp.title')} arrow>
<ToolbarButton type="text" ref={dropdownRef}>
<CodeOutlined style={{ color: enabledMCPs.length > 0 ? 'var(--color-primary)' : 'var(--color-icon)' }} />
<CodeOutlined style={{ color: buttonEnabled ? 'var(--color-primary)' : 'var(--color-icon)' }} />
</ToolbarButton>
</Tooltip>
</Dropdown>

View File

@ -25,14 +25,14 @@ interface Props {
const AssistantMCPSettings: React.FC<Props> = ({ assistant, updateAssistant }) => {
const { t } = useTranslation()
const { mcpServers: allMcpServers } = useMCPServers()
const onUpdate = (ids: string[]) => {
const mcpServers = ids
.map((id) => allMcpServers.find((server) => server.id === id))
.filter((server): server is MCPServer => server !== undefined && server.isActive)
const _assistant = { ...assistant, mcpServers }
updateAssistant(_assistant)
updateAssistant({ ...assistant, mcpServers })
}
const handleServerToggle = (serverId: string) => {
@ -52,7 +52,7 @@ const AssistantMCPSettings: React.FC<Props> = ({ assistant, updateAssistant }) =
return (
<Container>
<HeaderContainer>
<Box style={{ fontWeight: 'bold', fontSize: '16px' }}>
<Box style={{ fontWeight: 'bold', fontSize: '14px' }}>
{t('assistants.settings.mcp.title')}
<Tooltip title={t('assistants.settings.mcp.description', 'Select MCP servers to use with this assistant')}>
<InfoIcon />
@ -111,9 +111,6 @@ const Container = styled.div`
flex: 1;
flex-direction: column;
overflow: hidden;
padding: 12px;
background-color: ${(props) => props.theme.colors?.background || '#f9f9f9'};
border-radius: 8px;
`
const HeaderContainer = styled.div`
@ -126,13 +123,13 @@ const HeaderContainer = styled.div`
const InfoIcon = styled(InfoCircleOutlined)`
margin-left: 6px;
font-size: 14px;
color: ${(props) => props.theme.colors?.textSecondary || '#8c8c8c'};
color: var(--color-text-2);
cursor: help;
`
const EnabledCount = styled.span`
font-size: 12px;
color: ${(props) => props.theme.colors?.textSecondary || '#8c8c8c'};
color: var(--color-text-2);
`
const EmptyContainer = styled.div`
@ -148,7 +145,6 @@ const ServerList = styled.div`
flex-direction: column;
gap: 8px;
overflow-y: auto;
padding: 4px;
`
const ServerItem = styled.div<{ isEnabled: boolean }>`
@ -157,15 +153,9 @@ const ServerItem = styled.div<{ isEnabled: boolean }>`
align-items: center;
padding: 12px 16px;
border-radius: 8px;
background-color: ${(props) => props.theme.colors?.cardBackground || '#fff'};
border: 1px solid ${(props) => props.theme.colors?.border || '#e6e6e6'};
background-color: var(--color-background-mute);
border: 1px solid var(--color-border);
transition: all 0.2s ease;
&:hover {
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
transform: translateY(-1px);
}
opacity: ${(props) => (props.isEnabled ? 1 : 0.7)};
`