refactor: mcp setting ui refactor
This commit is contained in:
parent
29f7da1a4c
commit
eddbae6f5e
@ -6,7 +6,7 @@ import React, { useEffect, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import styled from 'styled-components'
|
||||
|
||||
import { SettingContainer, SettingDivider, SettingTitle } from '..'
|
||||
import { SettingContainer, SettingDivider, SettingGroup, SettingTitle } from '..'
|
||||
|
||||
interface Props {
|
||||
server: MCPServer
|
||||
@ -163,70 +163,81 @@ const McpSettings: React.FC<Props> = ({ server }) => {
|
||||
}
|
||||
|
||||
return (
|
||||
<SettingContainer style={{ background: 'transparent' }}>
|
||||
<SettingTitle>
|
||||
<Flex align="center" gap={8}>
|
||||
<SettingContainer>
|
||||
<SettingGroup style={{ marginBottom: 0 }}>
|
||||
<SettingTitle>
|
||||
<ServerName>{server?.name}</ServerName>
|
||||
</Flex>
|
||||
<Switch
|
||||
value={server.isActive}
|
||||
key={server.id}
|
||||
loading={loadingServer === server.id}
|
||||
onChange={onToggleActive}
|
||||
/>
|
||||
</SettingTitle>
|
||||
<SettingDivider />
|
||||
<Form form={form} layout="vertical" onValuesChange={onFormValuesChange}>
|
||||
<Form.Item name="name" label={t('settings.mcp.name')} rules={[{ required: true, message: '' }]}>
|
||||
<Input placeholder={t('common.name')} />
|
||||
</Form.Item>
|
||||
<Form.Item name="description" label={t('settings.mcp.description')}>
|
||||
<TextArea rows={2} placeholder={t('common.description')} />
|
||||
</Form.Item>
|
||||
<Form.Item name="serverType" label={t('settings.mcp.type')} rules={[{ required: true }]} initialValue="stdio">
|
||||
<Radio.Group
|
||||
onChange={(e) => setServerType(e.target.value)}
|
||||
options={[
|
||||
{ label: 'SSE', value: 'sse' },
|
||||
{ label: 'STDIO', value: 'stdio' }
|
||||
]}
|
||||
/>
|
||||
</Form.Item>
|
||||
{serverType === 'sse' && (
|
||||
<Form.Item
|
||||
name="baseUrl"
|
||||
label={t('settings.mcp.url')}
|
||||
rules={[{ required: serverType === 'sse', message: '' }]}
|
||||
tooltip={t('settings.mcp.baseUrlTooltip')}>
|
||||
<Input placeholder="http://localhost:3000/sse" />
|
||||
<Flex align="center" gap={16}>
|
||||
<Switch
|
||||
value={server.isActive}
|
||||
key={server.id}
|
||||
loading={loadingServer === server.id}
|
||||
onChange={onToggleActive}
|
||||
/>
|
||||
<Button type="primary" size="small" onClick={onSave} loading={loading} disabled={!isFormChanged}>
|
||||
{t('common.save')}
|
||||
</Button>
|
||||
</Flex>
|
||||
</SettingTitle>
|
||||
<SettingDivider />
|
||||
<Form
|
||||
form={form}
|
||||
layout="vertical"
|
||||
onValuesChange={onFormValuesChange}
|
||||
style={{
|
||||
height: 'calc(100vh - var(--navbar-height) - 115px)',
|
||||
overflowY: 'auto',
|
||||
width: 'calc(100% + 10px)',
|
||||
paddingRight: '10px'
|
||||
}}>
|
||||
<Form.Item name="name" label={t('settings.mcp.name')} rules={[{ required: true, message: '' }]}>
|
||||
<Input placeholder={t('common.name')} />
|
||||
</Form.Item>
|
||||
)}
|
||||
{serverType === 'stdio' && (
|
||||
<>
|
||||
<Form.Item name="description" label={t('settings.mcp.description')}>
|
||||
<TextArea rows={2} placeholder={t('common.description')} />
|
||||
</Form.Item>
|
||||
<Form.Item name="serverType" label={t('settings.mcp.type')} rules={[{ required: true }]} initialValue="stdio">
|
||||
<Radio.Group
|
||||
onChange={(e) => setServerType(e.target.value)}
|
||||
options={[
|
||||
{ label: 'SSE', value: 'sse' },
|
||||
{ label: 'STDIO', value: 'stdio' }
|
||||
]}
|
||||
/>
|
||||
</Form.Item>
|
||||
{serverType === 'sse' && (
|
||||
<Form.Item
|
||||
name="command"
|
||||
label={t('settings.mcp.command')}
|
||||
rules={[{ required: serverType === 'stdio', message: '' }]}>
|
||||
<Input placeholder="uvx or npx" />
|
||||
name="baseUrl"
|
||||
label={t('settings.mcp.url')}
|
||||
rules={[{ required: serverType === 'sse', message: '' }]}
|
||||
tooltip={t('settings.mcp.baseUrlTooltip')}>
|
||||
<Input placeholder="http://localhost:3000/sse" />
|
||||
</Form.Item>
|
||||
)}
|
||||
{serverType === 'stdio' && (
|
||||
<>
|
||||
<Form.Item
|
||||
name="command"
|
||||
label={t('settings.mcp.command')}
|
||||
rules={[{ required: serverType === 'stdio', message: '' }]}>
|
||||
<Input placeholder="uvx or npx" />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name="args"
|
||||
label={t('settings.mcp.args')}
|
||||
tooltip={t('settings.mcp.argsTooltip')}
|
||||
rules={[{ required: serverType === 'stdio', message: '' }]}>
|
||||
<TextArea rows={3} placeholder={`arg1\narg2`} style={{ fontFamily: 'monospace' }} />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
name="args"
|
||||
label={t('settings.mcp.args')}
|
||||
tooltip={t('settings.mcp.argsTooltip')}
|
||||
rules={[{ required: serverType === 'stdio', message: '' }]}>
|
||||
<TextArea rows={3} placeholder={`arg1\narg2`} style={{ fontFamily: 'monospace' }} />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item name="env" label={t('settings.mcp.env')} tooltip={t('settings.mcp.envTooltip')}>
|
||||
<TextArea rows={3} placeholder={`KEY1=value1\nKEY2=value2`} style={{ fontFamily: 'monospace' }} />
|
||||
</Form.Item>
|
||||
</>
|
||||
)}
|
||||
<Button type="primary" onClick={onSave} loading={loading} disabled={!isFormChanged}>
|
||||
{t('common.save')}
|
||||
</Button>
|
||||
</Form>
|
||||
<Form.Item name="env" label={t('settings.mcp.env')} tooltip={t('settings.mcp.envTooltip')}>
|
||||
<TextArea rows={3} placeholder={`KEY1=value1\nKEY2=value2`} style={{ fontFamily: 'monospace' }} />
|
||||
</Form.Item>
|
||||
</>
|
||||
)}
|
||||
</Form>
|
||||
</SettingGroup>
|
||||
</SettingContainer>
|
||||
)
|
||||
}
|
||||
|
||||
@ -4,7 +4,7 @@ import { HStack } from '@renderer/components/Layout'
|
||||
import { useTheme } from '@renderer/context/ThemeProvider'
|
||||
import { useMCPServers } from '@renderer/hooks/useMCPServers'
|
||||
import type { MCPServer } from '@renderer/types'
|
||||
import { Button, Input, Space, Spin, Table, Tag, Typography } from 'antd'
|
||||
import { Button, Card, Flex, Input, Space, Spin, Tag, Typography } from 'antd'
|
||||
import { npxFinder } from 'npx-scope-finder'
|
||||
import { type FC, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@ -128,48 +128,22 @@ const NpxSearch: FC = () => {
|
||||
<Spin />
|
||||
</div>
|
||||
) : searchResults.length > 0 ? (
|
||||
<Table
|
||||
dataSource={searchResults}
|
||||
columns={[
|
||||
{
|
||||
title: t('settings.mcp.npx_list.package_name'),
|
||||
dataIndex: 'name',
|
||||
key: 'name',
|
||||
width: '200px'
|
||||
},
|
||||
{
|
||||
title: t('settings.mcp.npx_list.description'),
|
||||
key: 'description',
|
||||
ellipsis: true,
|
||||
render: (_, record: SearchResult) => (
|
||||
<Space direction="vertical" size="small" style={{ width: '100%' }}>
|
||||
<Text ellipsis={{ tooltip: true }}>{record.description}</Text>
|
||||
<Text ellipsis={{ tooltip: true }} type="secondary">
|
||||
{t('settings.mcp.npx_list.usage')}: {record.usage}
|
||||
</Text>
|
||||
<Paragraph ellipsis={{ tooltip: true }}>
|
||||
<Link href={record.npmLink} target="_blank" rel="noopener noreferrer">
|
||||
{record.npmLink}
|
||||
</Link>
|
||||
</Paragraph>
|
||||
</Space>
|
||||
)
|
||||
},
|
||||
{
|
||||
title: t('settings.mcp.npx_list.version'),
|
||||
dataIndex: 'version',
|
||||
key: 'version',
|
||||
width: '100px',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
title: t('settings.mcp.npx_list.actions'),
|
||||
key: 'actions',
|
||||
width: '80px',
|
||||
align: 'center',
|
||||
render: (_, record: SearchResult) => (
|
||||
searchResults.map((record) => (
|
||||
<Card
|
||||
size="small"
|
||||
key={record.npmLink}
|
||||
title={
|
||||
<Typography.Title level={5} style={{ margin: 0 }}>
|
||||
{record.name}
|
||||
</Typography.Title>
|
||||
}
|
||||
extra={
|
||||
<Flex>
|
||||
<Tag bordered={false} color="magenta">
|
||||
v{record.version}
|
||||
</Tag>
|
||||
<Button
|
||||
type="primary"
|
||||
type="text"
|
||||
icon={<PlusOutlined />}
|
||||
size="small"
|
||||
onClick={() => {
|
||||
@ -185,12 +159,21 @@ const NpxSearch: FC = () => {
|
||||
addMCPServer(tempServer)
|
||||
}}
|
||||
/>
|
||||
)
|
||||
}
|
||||
]}
|
||||
pagination={false}
|
||||
bordered
|
||||
/>
|
||||
</Flex>
|
||||
}>
|
||||
<Space direction="vertical" size="small">
|
||||
<Text ellipsis={{ tooltip: true }}>{record.description}</Text>
|
||||
<Text ellipsis={{ tooltip: true }} type="secondary">
|
||||
{t('settings.mcp.npx_list.usage')}: {record.usage}
|
||||
</Text>
|
||||
<Text ellipsis={{ tooltip: true }}>
|
||||
<Link href={record.npmLink} target="_blank" rel="noopener noreferrer">
|
||||
{record.npmLink}
|
||||
</Link>
|
||||
</Text>
|
||||
</Space>
|
||||
</Card>
|
||||
))
|
||||
) : null}
|
||||
</Space>
|
||||
</SettingGroup>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user